--- /dev/null
+__pycache__
+*~
+#*
+uploads/
+env/
+logs/
\ No newline at end of file
--- /dev/null
+# Utilisation de Femtoblackweb
+
+ sudo apt install python3-venv
+ git clone XXX femtoblackweb
+ cd femtoblackweb
+ pyvenv env/
+ source env/bin/activate
+ pip3 install -r requirements.txt
+ python3 femtoblackweb.py
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from flask import Flask
+from femtoblackpool.simple_page import simple_page
+from flask import Flask, request, redirect, url_for, render_template, jsonify, abort, send_from_directory, session
+import os
+
+from werkzeug import secure_filename
+
+from datetime import datetime
+
+from flask.ext.socketio import SocketIO, emit, join_room, leave_room, close_room, rooms, disconnect
+# configuration
+
+# create our little application :)
+app = Flask(__name__)
+app.config.update({
+ 'DEBUG': True,
+ 'SECRET_KEY': 'Eheucahduugei3aiyau3kizua%',
+ 'USERNAME': 'admin',
+ 'PASSWORD': 'default',
+ 'UPLOAD_FOLDER': '/home/bot/flask/uploads',
+ 'MAX_CONTENT_LENGTH': 50 * 1024 * 1024
+})
+app.config.from_envvar('FLASKR_SETTINGS', silent=True)
+
+socketio = SocketIO(app)
+
+@app.errorhandler(404)
+def page_not_found(e):
+ return render_template('404.html'), 404
+
+@app.route('/')
+def index():
+ return render_template('index.html')
+
+@app.route('/upload', methods=['GET', 'POST'])
+def upload_file():
+
+ def allowed_file(filename):
+ ALLOWED_EXTENSIONS = ['mp3', 'ogg', 'flac']
+ return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
+
+ if request.method == 'POST':
+ f = request.files['file']
+
+ result = {
+ 'name': f.filename,
+ 'type': f.mimetype,
+ }
+
+ if allowed_file(f.filename):
+ filename = secure_filename(f.filename)
+ dst_file = os.path.join(app.config['UPLOAD_FOLDER'], filename)
+ f.save(dst_file)
+ result['size'] = os.path.getsize(dst_file)
+ else:
+ result['size'] = 0
+ result['error'] = 'Filetype not allowed'
+
+ return jsonify(files=[result])
+
+
+ return render_template('upload.html')
+
+@app.route('/download/<filename>')
+def download(filename):
+ return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
+
+@app.route('/analyze/<filename>')
+def analyze_file(filename):
+ f = os.path.join(app.config['UPLOAD_FOLDER'], filename)
+
+ if os.path.exists(f):
+ return render_template('analyze_file.html', filename=filename)
+
+ else:
+ abort(404)
+
+@app.route('/testio')
+def testio():
+ return render_template('testio.html')
+
+
+@socketio.on('my event', namespace='/test')
+def test_message(message):
+ session['receive_count'] = session.get('receive_count', 0) + 1
+ emit('my response',
+ {'data': message['data'], 'count': session['receive_count']})
+
+
+@socketio.on('my broadcast event', namespace='/test')
+def test_broadcast_message(message):
+ session['receive_count'] = session.get('receive_count', 0) + 1
+ emit('my response',
+ {'data': message['data'], 'count': session['receive_count']},
+ broadcast=True)
+
+
+@socketio.on('join', namespace='/test')
+def join(message):
+ join_room(message['room'])
+ session['receive_count'] = session.get('receive_count', 0) + 1
+ emit('my response',
+ {'data': 'In rooms: ' + ', '.join(rooms()),
+ 'count': session['receive_count']})
+
+
+@socketio.on('leave', namespace='/test')
+def leave(message):
+ leave_room(message['room'])
+ session['receive_count'] = session.get('receive_count', 0) + 1
+ emit('my response',
+ {'data': 'In rooms: ' + ', '.join(rooms()),
+ 'count': session['receive_count']})
+
+
+@socketio.on('close room', namespace='/test')
+def close(message):
+ session['receive_count'] = session.get('receive_count', 0) + 1
+ emit('my response', {'data': 'Room ' + message['room'] + ' is closing.',
+ 'count': session['receive_count']},
+ room=message['room'])
+ close_room(message['room'])
+
+
+@socketio.on('my room event', namespace='/test')
+def send_room_message(message):
+ session['receive_count'] = session.get('receive_count', 0) + 1
+ emit('my response',
+ {'data': message['data'], 'count': session['receive_count']},
+ room=message['room'])
+
+
+@socketio.on('disconnect request', namespace='/test')
+def disconnect_request():
+ session['receive_count'] = session.get('receive_count', 0) + 1
+ emit('my response',
+ {'data': 'Disconnected!', 'count': session['receive_count']})
+ disconnect()
+
+
+@socketio.on('connect', namespace='/test')
+def test_connect():
+ emit('my response', {'data': 'Connected', 'count': 0})
+
+
+@socketio.on('disconnect', namespace='/test')
+def test_disconnect():
+ print('Client disconnected', request.sid)
+
+
+
+
+if __name__ == "__main__":
+ socketio.run(app)
+ #app.run(debug=True)
--- /dev/null
+Flask==0.10.1
+Flask-SocketIO==1.0
+Jinja2==2.8
+MarkupSafe==0.23
+Werkzeug==0.10.4
+eventlet==0.17.4
+greenlet==0.4.9
+itsdangerous==0.24
+python-engineio==0.7.1
+python-socketio==0.6.1
+six==1.10.0
--- /dev/null
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+.btn-default,
+.btn-primary,
+.btn-success,
+.btn-info,
+.btn-warning,
+.btn-danger {
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+}
+.btn-default:active,
+.btn-primary:active,
+.btn-success:active,
+.btn-info:active,
+.btn-warning:active,
+.btn-danger:active,
+.btn-default.active,
+.btn-primary.active,
+.btn-success.active,
+.btn-info.active,
+.btn-warning.active,
+.btn-danger.active {
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn-default.disabled,
+.btn-primary.disabled,
+.btn-success.disabled,
+.btn-info.disabled,
+.btn-warning.disabled,
+.btn-danger.disabled,
+.btn-default[disabled],
+.btn-primary[disabled],
+.btn-success[disabled],
+.btn-info[disabled],
+.btn-warning[disabled],
+.btn-danger[disabled],
+fieldset[disabled] .btn-default,
+fieldset[disabled] .btn-primary,
+fieldset[disabled] .btn-success,
+fieldset[disabled] .btn-info,
+fieldset[disabled] .btn-warning,
+fieldset[disabled] .btn-danger {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn-default .badge,
+.btn-primary .badge,
+.btn-success .badge,
+.btn-info .badge,
+.btn-warning .badge,
+.btn-danger .badge {
+ text-shadow: none;
+}
+.btn:active,
+.btn.active {
+ background-image: none;
+}
+.btn-default {
+ text-shadow: 0 1px 0 #fff;
+ background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+ background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
+ background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #dbdbdb;
+ border-color: #ccc;
+}
+.btn-default:hover,
+.btn-default:focus {
+ background-color: #e0e0e0;
+ background-position: 0 -15px;
+}
+.btn-default:active,
+.btn-default.active {
+ background-color: #e0e0e0;
+ border-color: #dbdbdb;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+ background-color: #e0e0e0;
+ background-image: none;
+}
+.btn-primary {
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #245580;
+}
+.btn-primary:hover,
+.btn-primary:focus {
+ background-color: #265a88;
+ background-position: 0 -15px;
+}
+.btn-primary:active,
+.btn-primary.active {
+ background-color: #265a88;
+ border-color: #245580;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+ background-color: #265a88;
+ background-image: none;
+}
+.btn-success {
+ background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
+ background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
+ background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #3e8f3e;
+}
+.btn-success:hover,
+.btn-success:focus {
+ background-color: #419641;
+ background-position: 0 -15px;
+}
+.btn-success:active,
+.btn-success.active {
+ background-color: #419641;
+ border-color: #3e8f3e;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+ background-color: #419641;
+ background-image: none;
+}
+.btn-info {
+ background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+ background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
+ background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #28a4c9;
+}
+.btn-info:hover,
+.btn-info:focus {
+ background-color: #2aabd2;
+ background-position: 0 -15px;
+}
+.btn-info:active,
+.btn-info.active {
+ background-color: #2aabd2;
+ border-color: #28a4c9;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+ background-color: #2aabd2;
+ background-image: none;
+}
+.btn-warning {
+ background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+ background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
+ background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #e38d13;
+}
+.btn-warning:hover,
+.btn-warning:focus {
+ background-color: #eb9316;
+ background-position: 0 -15px;
+}
+.btn-warning:active,
+.btn-warning.active {
+ background-color: #eb9316;
+ border-color: #e38d13;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+ background-color: #eb9316;
+ background-image: none;
+}
+.btn-danger {
+ background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+ background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
+ background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #b92c28;
+}
+.btn-danger:hover,
+.btn-danger:focus {
+ background-color: #c12e2a;
+ background-position: 0 -15px;
+}
+.btn-danger:active,
+.btn-danger.active {
+ background-color: #c12e2a;
+ border-color: #b92c28;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+ background-color: #c12e2a;
+ background-image: none;
+}
+.thumbnail,
+.img-thumbnail {
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+ background-color: #e8e8e8;
+ background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+ background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+ background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+ background-repeat: repeat-x;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+ background-color: #2e6da4;
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+ background-repeat: repeat-x;
+}
+.navbar-default {
+ background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+ background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
+ background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .active > a {
+ background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+ background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
+ background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
+ background-repeat: repeat-x;
+ -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+}
+.navbar-brand,
+.navbar-nav > li > a {
+ text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
+}
+.navbar-inverse {
+ background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
+ background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
+ background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-radius: 4px;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .active > a {
+ background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+ background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
+ background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
+ background-repeat: repeat-x;
+ -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+ box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+}
+.navbar-inverse .navbar-brand,
+.navbar-inverse .navbar-nav > li > a {
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
+}
+.navbar-static-top,
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ border-radius: 0;
+}
+@media (max-width: 767px) {
+ .navbar .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #fff;
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+ background-repeat: repeat-x;
+ }
+}
+.alert {
+ text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+}
+.alert-success {
+ background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+ background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
+ background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #b2dba1;
+}
+.alert-info {
+ background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+ background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
+ background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #9acfea;
+}
+.alert-warning {
+ background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+ background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
+ background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #f5e79e;
+}
+.alert-danger {
+ background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+ background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
+ background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #dca7a7;
+}
+.progress {
+ background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+ background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
+ background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar {
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-success {
+ background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+ background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
+ background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-info {
+ background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+ background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
+ background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-warning {
+ background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+ background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
+ background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-danger {
+ background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+ background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
+ background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-striped {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.list-group {
+ border-radius: 4px;
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+ text-shadow: 0 -1px 0 #286090;
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #2b669a;
+}
+.list-group-item.active .badge,
+.list-group-item.active:hover .badge,
+.list-group-item.active:focus .badge {
+ text-shadow: none;
+}
+.panel {
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+}
+.panel-default > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+ background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+ background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-primary > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-success > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+ background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
+ background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-info > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+ background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
+ background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-warning > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+ background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
+ background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-danger > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+ background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
+ background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
+ background-repeat: repeat-x;
+}
+.well {
+ background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+ background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
+ background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #dcdcdc;
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+}
+/*# sourceMappingURL=bootstrap-theme.css.map */
--- /dev/null
+{"version":3,"sources":["bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAAA;;;;GAIG;ACeH;;;;;;EAME,yCAAA;EC2CA,4FAAA;EACQ,oFAAA;CFvDT;ACgBC;;;;;;;;;;;;ECsCA,yDAAA;EACQ,iDAAA;CFxCT;ACMC;;;;;;;;;;;;;;;;;;ECiCA,yBAAA;EACQ,iBAAA;CFnBT;AC/BD;;;;;;EAuBI,kBAAA;CDgBH;ACyBC;;EAEE,uBAAA;CDvBH;AC4BD;EErEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;EAuC2C,0BAAA;EAA2B,mBAAA;CDjBvE;ACpBC;;EAEE,0BAAA;EACA,6BAAA;CDsBH;ACnBC;;EAEE,0BAAA;EACA,sBAAA;CDqBH;ACfG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6BL;ACbD;EEtEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8DD;AC5DC;;EAEE,0BAAA;EACA,6BAAA;CD8DH;AC3DC;;EAEE,0BAAA;EACA,sBAAA;CD6DH;ACvDG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqEL;ACpDD;EEvEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CDsGD;ACpGC;;EAEE,0BAAA;EACA,6BAAA;CDsGH;ACnGC;;EAEE,0BAAA;EACA,sBAAA;CDqGH;AC/FG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6GL;AC3FD;EExEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8ID;AC5IC;;EAEE,0BAAA;EACA,6BAAA;CD8IH;AC3IC;;EAEE,0BAAA;EACA,sBAAA;CD6IH;ACvIG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqJL;AClID;EEzEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CDsLD;ACpLC;;EAEE,0BAAA;EACA,6BAAA;CDsLH;ACnLC;;EAEE,0BAAA;EACA,sBAAA;CDqLH;AC/KG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6LL;ACzKD;EE1EI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8ND;AC5NC;;EAEE,0BAAA;EACA,6BAAA;CD8NH;AC3NC;;EAEE,0BAAA;EACA,sBAAA;CD6NH;ACvNG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqOL;AC1MD;;EClCE,mDAAA;EACQ,2CAAA;CFgPT;ACrMD;;EE3FI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF0FF,0BAAA;CD2MD;ACzMD;;;EEhGI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFgGF,0BAAA;CD+MD;ACtMD;EE7GI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ECnBF,oEAAA;EH+HA,mBAAA;ECjEA,4FAAA;EACQ,oFAAA;CF8QT;ACjND;;EE7GI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ED2CF,yDAAA;EACQ,iDAAA;CFwRT;AC9MD;;EAEE,+CAAA;CDgND;AC5MD;EEhII,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ECnBF,oEAAA;EHkJA,mBAAA;CDkND;ACrND;;EEhII,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ED2CF,wDAAA;EACQ,gDAAA;CF+ST;AC/ND;;EAYI,0CAAA;CDuNH;AClND;;;EAGE,iBAAA;CDoND;AC/LD;EAfI;;;IAGE,YAAA;IE7JF,yEAAA;IACA,oEAAA;IACA,8FAAA;IAAA,uEAAA;IACA,4BAAA;IACA,uHAAA;GH+WD;CACF;AC3MD;EACE,8CAAA;EC3HA,2FAAA;EACQ,mFAAA;CFyUT;ACnMD;EEtLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CD+MD;AC1MD;EEvLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CDuND;ACjND;EExLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CD+ND;ACxND;EEzLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CDuOD;ACxND;EEjMI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH4ZH;ACrND;EE3MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHmaH;AC3ND;EE5MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH0aH;ACjOD;EE7MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHibH;ACvOD;EE9MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHwbH;AC7OD;EE/MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH+bH;AChPD;EElLI,8MAAA;EACA,yMAAA;EACA,sMAAA;CHqaH;AC5OD;EACE,mBAAA;EC9KA,mDAAA;EACQ,2CAAA;CF6ZT;AC7OD;;;EAGE,8BAAA;EEnOE,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFiOF,sBAAA;CDmPD;ACxPD;;;EAQI,kBAAA;CDqPH;AC3OD;ECnME,kDAAA;EACQ,0CAAA;CFibT;ACrOD;EE5PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHoeH;AC3OD;EE7PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH2eH;ACjPD;EE9PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHkfH;ACvPD;EE/PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHyfH;AC7PD;EEhQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHggBH;ACnQD;EEjQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHugBH;ACnQD;EExQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFsQF,sBAAA;EC3NA,0FAAA;EACQ,kFAAA;CFqeT","file":"bootstrap-theme.css","sourcesContent":["/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]}
\ No newline at end of file
--- /dev/null
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
\ No newline at end of file
--- /dev/null
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
+html {
+ font-family: sans-serif;
+ -webkit-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+}
+body {
+ margin: 0;
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+audio,
+canvas,
+progress,
+video {
+ display: inline-block;
+ vertical-align: baseline;
+}
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+[hidden],
+template {
+ display: none;
+}
+a {
+ background-color: transparent;
+}
+a:active,
+a:hover {
+ outline: 0;
+}
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+b,
+strong {
+ font-weight: bold;
+}
+dfn {
+ font-style: italic;
+}
+h1 {
+ margin: .67em 0;
+ font-size: 2em;
+}
+mark {
+ color: #000;
+ background: #ff0;
+}
+small {
+ font-size: 80%;
+}
+sub,
+sup {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+sup {
+ top: -.5em;
+}
+sub {
+ bottom: -.25em;
+}
+img {
+ border: 0;
+}
+svg:not(:root) {
+ overflow: hidden;
+}
+figure {
+ margin: 1em 40px;
+}
+hr {
+ height: 0;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+pre {
+ overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+ margin: 0;
+ font: inherit;
+ color: inherit;
+}
+button {
+ overflow: visible;
+}
+button,
+select {
+ text-transform: none;
+}
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button;
+ cursor: pointer;
+}
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
+input {
+ line-height: normal;
+}
+input[type="checkbox"],
+input[type="radio"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ padding: 0;
+}
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ -webkit-appearance: textfield;
+}
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+fieldset {
+ padding: .35em .625em .75em;
+ margin: 0 2px;
+ border: 1px solid #c0c0c0;
+}
+legend {
+ padding: 0;
+ border: 0;
+}
+textarea {
+ overflow: auto;
+}
+optgroup {
+ font-weight: bold;
+}
+table {
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+td,
+th {
+ padding: 0;
+}
+/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
+@media print {
+ *,
+ *:before,
+ *:after {
+ color: #000 !important;
+ text-shadow: none !important;
+ background: transparent !important;
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+ }
+ a,
+ a:visited {
+ text-decoration: underline;
+ }
+ a[href]:after {
+ content: " (" attr(href) ")";
+ }
+ abbr[title]:after {
+ content: " (" attr(title) ")";
+ }
+ a[href^="#"]:after,
+ a[href^="javascript:"]:after {
+ content: "";
+ }
+ pre,
+ blockquote {
+ border: 1px solid #999;
+
+ page-break-inside: avoid;
+ }
+ thead {
+ display: table-header-group;
+ }
+ tr,
+ img {
+ page-break-inside: avoid;
+ }
+ img {
+ max-width: 100% !important;
+ }
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3;
+ }
+ h2,
+ h3 {
+ page-break-after: avoid;
+ }
+ .navbar {
+ display: none;
+ }
+ .btn > .caret,
+ .dropup > .btn > .caret {
+ border-top-color: #000 !important;
+ }
+ .label {
+ border: 1px solid #000;
+ }
+ .table {
+ border-collapse: collapse !important;
+ }
+ .table td,
+ .table th {
+ background-color: #fff !important;
+ }
+ .table-bordered th,
+ .table-bordered td {
+ border: 1px solid #ddd !important;
+ }
+}
+@font-face {
+ font-family: 'Glyphicons Halflings';
+
+ src: url('../fonts/glyphicons-halflings-regular.eot');
+ src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+}
+.glyphicon {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+.glyphicon-asterisk:before {
+ content: "\2a";
+}
+.glyphicon-plus:before {
+ content: "\2b";
+}
+.glyphicon-euro:before,
+.glyphicon-eur:before {
+ content: "\20ac";
+}
+.glyphicon-minus:before {
+ content: "\2212";
+}
+.glyphicon-cloud:before {
+ content: "\2601";
+}
+.glyphicon-envelope:before {
+ content: "\2709";
+}
+.glyphicon-pencil:before {
+ content: "\270f";
+}
+.glyphicon-glass:before {
+ content: "\e001";
+}
+.glyphicon-music:before {
+ content: "\e002";
+}
+.glyphicon-search:before {
+ content: "\e003";
+}
+.glyphicon-heart:before {
+ content: "\e005";
+}
+.glyphicon-star:before {
+ content: "\e006";
+}
+.glyphicon-star-empty:before {
+ content: "\e007";
+}
+.glyphicon-user:before {
+ content: "\e008";
+}
+.glyphicon-film:before {
+ content: "\e009";
+}
+.glyphicon-th-large:before {
+ content: "\e010";
+}
+.glyphicon-th:before {
+ content: "\e011";
+}
+.glyphicon-th-list:before {
+ content: "\e012";
+}
+.glyphicon-ok:before {
+ content: "\e013";
+}
+.glyphicon-remove:before {
+ content: "\e014";
+}
+.glyphicon-zoom-in:before {
+ content: "\e015";
+}
+.glyphicon-zoom-out:before {
+ content: "\e016";
+}
+.glyphicon-off:before {
+ content: "\e017";
+}
+.glyphicon-signal:before {
+ content: "\e018";
+}
+.glyphicon-cog:before {
+ content: "\e019";
+}
+.glyphicon-trash:before {
+ content: "\e020";
+}
+.glyphicon-home:before {
+ content: "\e021";
+}
+.glyphicon-file:before {
+ content: "\e022";
+}
+.glyphicon-time:before {
+ content: "\e023";
+}
+.glyphicon-road:before {
+ content: "\e024";
+}
+.glyphicon-download-alt:before {
+ content: "\e025";
+}
+.glyphicon-download:before {
+ content: "\e026";
+}
+.glyphicon-upload:before {
+ content: "\e027";
+}
+.glyphicon-inbox:before {
+ content: "\e028";
+}
+.glyphicon-play-circle:before {
+ content: "\e029";
+}
+.glyphicon-repeat:before {
+ content: "\e030";
+}
+.glyphicon-refresh:before {
+ content: "\e031";
+}
+.glyphicon-list-alt:before {
+ content: "\e032";
+}
+.glyphicon-lock:before {
+ content: "\e033";
+}
+.glyphicon-flag:before {
+ content: "\e034";
+}
+.glyphicon-headphones:before {
+ content: "\e035";
+}
+.glyphicon-volume-off:before {
+ content: "\e036";
+}
+.glyphicon-volume-down:before {
+ content: "\e037";
+}
+.glyphicon-volume-up:before {
+ content: "\e038";
+}
+.glyphicon-qrcode:before {
+ content: "\e039";
+}
+.glyphicon-barcode:before {
+ content: "\e040";
+}
+.glyphicon-tag:before {
+ content: "\e041";
+}
+.glyphicon-tags:before {
+ content: "\e042";
+}
+.glyphicon-book:before {
+ content: "\e043";
+}
+.glyphicon-bookmark:before {
+ content: "\e044";
+}
+.glyphicon-print:before {
+ content: "\e045";
+}
+.glyphicon-camera:before {
+ content: "\e046";
+}
+.glyphicon-font:before {
+ content: "\e047";
+}
+.glyphicon-bold:before {
+ content: "\e048";
+}
+.glyphicon-italic:before {
+ content: "\e049";
+}
+.glyphicon-text-height:before {
+ content: "\e050";
+}
+.glyphicon-text-width:before {
+ content: "\e051";
+}
+.glyphicon-align-left:before {
+ content: "\e052";
+}
+.glyphicon-align-center:before {
+ content: "\e053";
+}
+.glyphicon-align-right:before {
+ content: "\e054";
+}
+.glyphicon-align-justify:before {
+ content: "\e055";
+}
+.glyphicon-list:before {
+ content: "\e056";
+}
+.glyphicon-indent-left:before {
+ content: "\e057";
+}
+.glyphicon-indent-right:before {
+ content: "\e058";
+}
+.glyphicon-facetime-video:before {
+ content: "\e059";
+}
+.glyphicon-picture:before {
+ content: "\e060";
+}
+.glyphicon-map-marker:before {
+ content: "\e062";
+}
+.glyphicon-adjust:before {
+ content: "\e063";
+}
+.glyphicon-tint:before {
+ content: "\e064";
+}
+.glyphicon-edit:before {
+ content: "\e065";
+}
+.glyphicon-share:before {
+ content: "\e066";
+}
+.glyphicon-check:before {
+ content: "\e067";
+}
+.glyphicon-move:before {
+ content: "\e068";
+}
+.glyphicon-step-backward:before {
+ content: "\e069";
+}
+.glyphicon-fast-backward:before {
+ content: "\e070";
+}
+.glyphicon-backward:before {
+ content: "\e071";
+}
+.glyphicon-play:before {
+ content: "\e072";
+}
+.glyphicon-pause:before {
+ content: "\e073";
+}
+.glyphicon-stop:before {
+ content: "\e074";
+}
+.glyphicon-forward:before {
+ content: "\e075";
+}
+.glyphicon-fast-forward:before {
+ content: "\e076";
+}
+.glyphicon-step-forward:before {
+ content: "\e077";
+}
+.glyphicon-eject:before {
+ content: "\e078";
+}
+.glyphicon-chevron-left:before {
+ content: "\e079";
+}
+.glyphicon-chevron-right:before {
+ content: "\e080";
+}
+.glyphicon-plus-sign:before {
+ content: "\e081";
+}
+.glyphicon-minus-sign:before {
+ content: "\e082";
+}
+.glyphicon-remove-sign:before {
+ content: "\e083";
+}
+.glyphicon-ok-sign:before {
+ content: "\e084";
+}
+.glyphicon-question-sign:before {
+ content: "\e085";
+}
+.glyphicon-info-sign:before {
+ content: "\e086";
+}
+.glyphicon-screenshot:before {
+ content: "\e087";
+}
+.glyphicon-remove-circle:before {
+ content: "\e088";
+}
+.glyphicon-ok-circle:before {
+ content: "\e089";
+}
+.glyphicon-ban-circle:before {
+ content: "\e090";
+}
+.glyphicon-arrow-left:before {
+ content: "\e091";
+}
+.glyphicon-arrow-right:before {
+ content: "\e092";
+}
+.glyphicon-arrow-up:before {
+ content: "\e093";
+}
+.glyphicon-arrow-down:before {
+ content: "\e094";
+}
+.glyphicon-share-alt:before {
+ content: "\e095";
+}
+.glyphicon-resize-full:before {
+ content: "\e096";
+}
+.glyphicon-resize-small:before {
+ content: "\e097";
+}
+.glyphicon-exclamation-sign:before {
+ content: "\e101";
+}
+.glyphicon-gift:before {
+ content: "\e102";
+}
+.glyphicon-leaf:before {
+ content: "\e103";
+}
+.glyphicon-fire:before {
+ content: "\e104";
+}
+.glyphicon-eye-open:before {
+ content: "\e105";
+}
+.glyphicon-eye-close:before {
+ content: "\e106";
+}
+.glyphicon-warning-sign:before {
+ content: "\e107";
+}
+.glyphicon-plane:before {
+ content: "\e108";
+}
+.glyphicon-calendar:before {
+ content: "\e109";
+}
+.glyphicon-random:before {
+ content: "\e110";
+}
+.glyphicon-comment:before {
+ content: "\e111";
+}
+.glyphicon-magnet:before {
+ content: "\e112";
+}
+.glyphicon-chevron-up:before {
+ content: "\e113";
+}
+.glyphicon-chevron-down:before {
+ content: "\e114";
+}
+.glyphicon-retweet:before {
+ content: "\e115";
+}
+.glyphicon-shopping-cart:before {
+ content: "\e116";
+}
+.glyphicon-folder-close:before {
+ content: "\e117";
+}
+.glyphicon-folder-open:before {
+ content: "\e118";
+}
+.glyphicon-resize-vertical:before {
+ content: "\e119";
+}
+.glyphicon-resize-horizontal:before {
+ content: "\e120";
+}
+.glyphicon-hdd:before {
+ content: "\e121";
+}
+.glyphicon-bullhorn:before {
+ content: "\e122";
+}
+.glyphicon-bell:before {
+ content: "\e123";
+}
+.glyphicon-certificate:before {
+ content: "\e124";
+}
+.glyphicon-thumbs-up:before {
+ content: "\e125";
+}
+.glyphicon-thumbs-down:before {
+ content: "\e126";
+}
+.glyphicon-hand-right:before {
+ content: "\e127";
+}
+.glyphicon-hand-left:before {
+ content: "\e128";
+}
+.glyphicon-hand-up:before {
+ content: "\e129";
+}
+.glyphicon-hand-down:before {
+ content: "\e130";
+}
+.glyphicon-circle-arrow-right:before {
+ content: "\e131";
+}
+.glyphicon-circle-arrow-left:before {
+ content: "\e132";
+}
+.glyphicon-circle-arrow-up:before {
+ content: "\e133";
+}
+.glyphicon-circle-arrow-down:before {
+ content: "\e134";
+}
+.glyphicon-globe:before {
+ content: "\e135";
+}
+.glyphicon-wrench:before {
+ content: "\e136";
+}
+.glyphicon-tasks:before {
+ content: "\e137";
+}
+.glyphicon-filter:before {
+ content: "\e138";
+}
+.glyphicon-briefcase:before {
+ content: "\e139";
+}
+.glyphicon-fullscreen:before {
+ content: "\e140";
+}
+.glyphicon-dashboard:before {
+ content: "\e141";
+}
+.glyphicon-paperclip:before {
+ content: "\e142";
+}
+.glyphicon-heart-empty:before {
+ content: "\e143";
+}
+.glyphicon-link:before {
+ content: "\e144";
+}
+.glyphicon-phone:before {
+ content: "\e145";
+}
+.glyphicon-pushpin:before {
+ content: "\e146";
+}
+.glyphicon-usd:before {
+ content: "\e148";
+}
+.glyphicon-gbp:before {
+ content: "\e149";
+}
+.glyphicon-sort:before {
+ content: "\e150";
+}
+.glyphicon-sort-by-alphabet:before {
+ content: "\e151";
+}
+.glyphicon-sort-by-alphabet-alt:before {
+ content: "\e152";
+}
+.glyphicon-sort-by-order:before {
+ content: "\e153";
+}
+.glyphicon-sort-by-order-alt:before {
+ content: "\e154";
+}
+.glyphicon-sort-by-attributes:before {
+ content: "\e155";
+}
+.glyphicon-sort-by-attributes-alt:before {
+ content: "\e156";
+}
+.glyphicon-unchecked:before {
+ content: "\e157";
+}
+.glyphicon-expand:before {
+ content: "\e158";
+}
+.glyphicon-collapse-down:before {
+ content: "\e159";
+}
+.glyphicon-collapse-up:before {
+ content: "\e160";
+}
+.glyphicon-log-in:before {
+ content: "\e161";
+}
+.glyphicon-flash:before {
+ content: "\e162";
+}
+.glyphicon-log-out:before {
+ content: "\e163";
+}
+.glyphicon-new-window:before {
+ content: "\e164";
+}
+.glyphicon-record:before {
+ content: "\e165";
+}
+.glyphicon-save:before {
+ content: "\e166";
+}
+.glyphicon-open:before {
+ content: "\e167";
+}
+.glyphicon-saved:before {
+ content: "\e168";
+}
+.glyphicon-import:before {
+ content: "\e169";
+}
+.glyphicon-export:before {
+ content: "\e170";
+}
+.glyphicon-send:before {
+ content: "\e171";
+}
+.glyphicon-floppy-disk:before {
+ content: "\e172";
+}
+.glyphicon-floppy-saved:before {
+ content: "\e173";
+}
+.glyphicon-floppy-remove:before {
+ content: "\e174";
+}
+.glyphicon-floppy-save:before {
+ content: "\e175";
+}
+.glyphicon-floppy-open:before {
+ content: "\e176";
+}
+.glyphicon-credit-card:before {
+ content: "\e177";
+}
+.glyphicon-transfer:before {
+ content: "\e178";
+}
+.glyphicon-cutlery:before {
+ content: "\e179";
+}
+.glyphicon-header:before {
+ content: "\e180";
+}
+.glyphicon-compressed:before {
+ content: "\e181";
+}
+.glyphicon-earphone:before {
+ content: "\e182";
+}
+.glyphicon-phone-alt:before {
+ content: "\e183";
+}
+.glyphicon-tower:before {
+ content: "\e184";
+}
+.glyphicon-stats:before {
+ content: "\e185";
+}
+.glyphicon-sd-video:before {
+ content: "\e186";
+}
+.glyphicon-hd-video:before {
+ content: "\e187";
+}
+.glyphicon-subtitles:before {
+ content: "\e188";
+}
+.glyphicon-sound-stereo:before {
+ content: "\e189";
+}
+.glyphicon-sound-dolby:before {
+ content: "\e190";
+}
+.glyphicon-sound-5-1:before {
+ content: "\e191";
+}
+.glyphicon-sound-6-1:before {
+ content: "\e192";
+}
+.glyphicon-sound-7-1:before {
+ content: "\e193";
+}
+.glyphicon-copyright-mark:before {
+ content: "\e194";
+}
+.glyphicon-registration-mark:before {
+ content: "\e195";
+}
+.glyphicon-cloud-download:before {
+ content: "\e197";
+}
+.glyphicon-cloud-upload:before {
+ content: "\e198";
+}
+.glyphicon-tree-conifer:before {
+ content: "\e199";
+}
+.glyphicon-tree-deciduous:before {
+ content: "\e200";
+}
+.glyphicon-cd:before {
+ content: "\e201";
+}
+.glyphicon-save-file:before {
+ content: "\e202";
+}
+.glyphicon-open-file:before {
+ content: "\e203";
+}
+.glyphicon-level-up:before {
+ content: "\e204";
+}
+.glyphicon-copy:before {
+ content: "\e205";
+}
+.glyphicon-paste:before {
+ content: "\e206";
+}
+.glyphicon-alert:before {
+ content: "\e209";
+}
+.glyphicon-equalizer:before {
+ content: "\e210";
+}
+.glyphicon-king:before {
+ content: "\e211";
+}
+.glyphicon-queen:before {
+ content: "\e212";
+}
+.glyphicon-pawn:before {
+ content: "\e213";
+}
+.glyphicon-bishop:before {
+ content: "\e214";
+}
+.glyphicon-knight:before {
+ content: "\e215";
+}
+.glyphicon-baby-formula:before {
+ content: "\e216";
+}
+.glyphicon-tent:before {
+ content: "\26fa";
+}
+.glyphicon-blackboard:before {
+ content: "\e218";
+}
+.glyphicon-bed:before {
+ content: "\e219";
+}
+.glyphicon-apple:before {
+ content: "\f8ff";
+}
+.glyphicon-erase:before {
+ content: "\e221";
+}
+.glyphicon-hourglass:before {
+ content: "\231b";
+}
+.glyphicon-lamp:before {
+ content: "\e223";
+}
+.glyphicon-duplicate:before {
+ content: "\e224";
+}
+.glyphicon-piggy-bank:before {
+ content: "\e225";
+}
+.glyphicon-scissors:before {
+ content: "\e226";
+}
+.glyphicon-bitcoin:before {
+ content: "\e227";
+}
+.glyphicon-btc:before {
+ content: "\e227";
+}
+.glyphicon-xbt:before {
+ content: "\e227";
+}
+.glyphicon-yen:before {
+ content: "\00a5";
+}
+.glyphicon-jpy:before {
+ content: "\00a5";
+}
+.glyphicon-ruble:before {
+ content: "\20bd";
+}
+.glyphicon-rub:before {
+ content: "\20bd";
+}
+.glyphicon-scale:before {
+ content: "\e230";
+}
+.glyphicon-ice-lolly:before {
+ content: "\e231";
+}
+.glyphicon-ice-lolly-tasted:before {
+ content: "\e232";
+}
+.glyphicon-education:before {
+ content: "\e233";
+}
+.glyphicon-option-horizontal:before {
+ content: "\e234";
+}
+.glyphicon-option-vertical:before {
+ content: "\e235";
+}
+.glyphicon-menu-hamburger:before {
+ content: "\e236";
+}
+.glyphicon-modal-window:before {
+ content: "\e237";
+}
+.glyphicon-oil:before {
+ content: "\e238";
+}
+.glyphicon-grain:before {
+ content: "\e239";
+}
+.glyphicon-sunglasses:before {
+ content: "\e240";
+}
+.glyphicon-text-size:before {
+ content: "\e241";
+}
+.glyphicon-text-color:before {
+ content: "\e242";
+}
+.glyphicon-text-background:before {
+ content: "\e243";
+}
+.glyphicon-object-align-top:before {
+ content: "\e244";
+}
+.glyphicon-object-align-bottom:before {
+ content: "\e245";
+}
+.glyphicon-object-align-horizontal:before {
+ content: "\e246";
+}
+.glyphicon-object-align-left:before {
+ content: "\e247";
+}
+.glyphicon-object-align-vertical:before {
+ content: "\e248";
+}
+.glyphicon-object-align-right:before {
+ content: "\e249";
+}
+.glyphicon-triangle-right:before {
+ content: "\e250";
+}
+.glyphicon-triangle-left:before {
+ content: "\e251";
+}
+.glyphicon-triangle-bottom:before {
+ content: "\e252";
+}
+.glyphicon-triangle-top:before {
+ content: "\e253";
+}
+.glyphicon-console:before {
+ content: "\e254";
+}
+.glyphicon-superscript:before {
+ content: "\e255";
+}
+.glyphicon-subscript:before {
+ content: "\e256";
+}
+.glyphicon-menu-left:before {
+ content: "\e257";
+}
+.glyphicon-menu-right:before {
+ content: "\e258";
+}
+.glyphicon-menu-down:before {
+ content: "\e259";
+}
+.glyphicon-menu-up:before {
+ content: "\e260";
+}
+* {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+*:before,
+*:after {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+html {
+ font-size: 10px;
+
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+body {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #333;
+ background-color: #fff;
+}
+input,
+button,
+select,
+textarea {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+a {
+ color: #337ab7;
+ text-decoration: none;
+}
+a:hover,
+a:focus {
+ color: #23527c;
+ text-decoration: underline;
+}
+a:focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+figure {
+ margin: 0;
+}
+img {
+ vertical-align: middle;
+}
+.img-responsive,
+.thumbnail > img,
+.thumbnail a > img,
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ display: block;
+ max-width: 100%;
+ height: auto;
+}
+.img-rounded {
+ border-radius: 6px;
+}
+.img-thumbnail {
+ display: inline-block;
+ max-width: 100%;
+ height: auto;
+ padding: 4px;
+ line-height: 1.42857143;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ -webkit-transition: all .2s ease-in-out;
+ -o-transition: all .2s ease-in-out;
+ transition: all .2s ease-in-out;
+}
+.img-circle {
+ border-radius: 50%;
+}
+hr {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 0;
+ border-top: 1px solid #eee;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ clip: auto;
+}
+[role="button"] {
+ cursor: pointer;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+ font-family: inherit;
+ font-weight: 500;
+ line-height: 1.1;
+ color: inherit;
+}
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small,
+.h1 small,
+.h2 small,
+.h3 small,
+.h4 small,
+.h5 small,
+.h6 small,
+h1 .small,
+h2 .small,
+h3 .small,
+h4 .small,
+h5 .small,
+h6 .small,
+.h1 .small,
+.h2 .small,
+.h3 .small,
+.h4 .small,
+.h5 .small,
+.h6 .small {
+ font-weight: normal;
+ line-height: 1;
+ color: #777;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+h1 small,
+.h1 small,
+h2 small,
+.h2 small,
+h3 small,
+.h3 small,
+h1 .small,
+.h1 .small,
+h2 .small,
+.h2 .small,
+h3 .small,
+.h3 .small {
+ font-size: 65%;
+}
+h4,
+.h4,
+h5,
+.h5,
+h6,
+.h6 {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+h4 small,
+.h4 small,
+h5 small,
+.h5 small,
+h6 small,
+.h6 small,
+h4 .small,
+.h4 .small,
+h5 .small,
+.h5 .small,
+h6 .small,
+.h6 .small {
+ font-size: 75%;
+}
+h1,
+.h1 {
+ font-size: 36px;
+}
+h2,
+.h2 {
+ font-size: 30px;
+}
+h3,
+.h3 {
+ font-size: 24px;
+}
+h4,
+.h4 {
+ font-size: 18px;
+}
+h5,
+.h5 {
+ font-size: 14px;
+}
+h6,
+.h6 {
+ font-size: 12px;
+}
+p {
+ margin: 0 0 10px;
+}
+.lead {
+ margin-bottom: 20px;
+ font-size: 16px;
+ font-weight: 300;
+ line-height: 1.4;
+}
+@media (min-width: 768px) {
+ .lead {
+ font-size: 21px;
+ }
+}
+small,
+.small {
+ font-size: 85%;
+}
+mark,
+.mark {
+ padding: .2em;
+ background-color: #fcf8e3;
+}
+.text-left {
+ text-align: left;
+}
+.text-right {
+ text-align: right;
+}
+.text-center {
+ text-align: center;
+}
+.text-justify {
+ text-align: justify;
+}
+.text-nowrap {
+ white-space: nowrap;
+}
+.text-lowercase {
+ text-transform: lowercase;
+}
+.text-uppercase {
+ text-transform: uppercase;
+}
+.text-capitalize {
+ text-transform: capitalize;
+}
+.text-muted {
+ color: #777;
+}
+.text-primary {
+ color: #337ab7;
+}
+a.text-primary:hover,
+a.text-primary:focus {
+ color: #286090;
+}
+.text-success {
+ color: #3c763d;
+}
+a.text-success:hover,
+a.text-success:focus {
+ color: #2b542c;
+}
+.text-info {
+ color: #31708f;
+}
+a.text-info:hover,
+a.text-info:focus {
+ color: #245269;
+}
+.text-warning {
+ color: #8a6d3b;
+}
+a.text-warning:hover,
+a.text-warning:focus {
+ color: #66512c;
+}
+.text-danger {
+ color: #a94442;
+}
+a.text-danger:hover,
+a.text-danger:focus {
+ color: #843534;
+}
+.bg-primary {
+ color: #fff;
+ background-color: #337ab7;
+}
+a.bg-primary:hover,
+a.bg-primary:focus {
+ background-color: #286090;
+}
+.bg-success {
+ background-color: #dff0d8;
+}
+a.bg-success:hover,
+a.bg-success:focus {
+ background-color: #c1e2b3;
+}
+.bg-info {
+ background-color: #d9edf7;
+}
+a.bg-info:hover,
+a.bg-info:focus {
+ background-color: #afd9ee;
+}
+.bg-warning {
+ background-color: #fcf8e3;
+}
+a.bg-warning:hover,
+a.bg-warning:focus {
+ background-color: #f7ecb5;
+}
+.bg-danger {
+ background-color: #f2dede;
+}
+a.bg-danger:hover,
+a.bg-danger:focus {
+ background-color: #e4b9b9;
+}
+.page-header {
+ padding-bottom: 9px;
+ margin: 40px 0 20px;
+ border-bottom: 1px solid #eee;
+}
+ul,
+ol {
+ margin-top: 0;
+ margin-bottom: 10px;
+}
+ul ul,
+ol ul,
+ul ol,
+ol ol {
+ margin-bottom: 0;
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+.list-inline {
+ padding-left: 0;
+ margin-left: -5px;
+ list-style: none;
+}
+.list-inline > li {
+ display: inline-block;
+ padding-right: 5px;
+ padding-left: 5px;
+}
+dl {
+ margin-top: 0;
+ margin-bottom: 20px;
+}
+dt,
+dd {
+ line-height: 1.42857143;
+}
+dt {
+ font-weight: bold;
+}
+dd {
+ margin-left: 0;
+}
+@media (min-width: 768px) {
+ .dl-horizontal dt {
+ float: left;
+ width: 160px;
+ overflow: hidden;
+ clear: left;
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ .dl-horizontal dd {
+ margin-left: 180px;
+ }
+}
+abbr[title],
+abbr[data-original-title] {
+ cursor: help;
+ border-bottom: 1px dotted #777;
+}
+.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+blockquote {
+ padding: 10px 20px;
+ margin: 0 0 20px;
+ font-size: 17.5px;
+ border-left: 5px solid #eee;
+}
+blockquote p:last-child,
+blockquote ul:last-child,
+blockquote ol:last-child {
+ margin-bottom: 0;
+}
+blockquote footer,
+blockquote small,
+blockquote .small {
+ display: block;
+ font-size: 80%;
+ line-height: 1.42857143;
+ color: #777;
+}
+blockquote footer:before,
+blockquote small:before,
+blockquote .small:before {
+ content: '\2014 \00A0';
+}
+.blockquote-reverse,
+blockquote.pull-right {
+ padding-right: 15px;
+ padding-left: 0;
+ text-align: right;
+ border-right: 5px solid #eee;
+ border-left: 0;
+}
+.blockquote-reverse footer:before,
+blockquote.pull-right footer:before,
+.blockquote-reverse small:before,
+blockquote.pull-right small:before,
+.blockquote-reverse .small:before,
+blockquote.pull-right .small:before {
+ content: '';
+}
+.blockquote-reverse footer:after,
+blockquote.pull-right footer:after,
+.blockquote-reverse small:after,
+blockquote.pull-right small:after,
+.blockquote-reverse .small:after,
+blockquote.pull-right .small:after {
+ content: '\00A0 \2014';
+}
+address {
+ margin-bottom: 20px;
+ font-style: normal;
+ line-height: 1.42857143;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+code {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #c7254e;
+ background-color: #f9f2f4;
+ border-radius: 4px;
+}
+kbd {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #fff;
+ background-color: #333;
+ border-radius: 3px;
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+}
+kbd kbd {
+ padding: 0;
+ font-size: 100%;
+ font-weight: bold;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+pre {
+ display: block;
+ padding: 9.5px;
+ margin: 0 0 10px;
+ font-size: 13px;
+ line-height: 1.42857143;
+ color: #333;
+ word-break: break-all;
+ word-wrap: break-word;
+ background-color: #f5f5f5;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+}
+pre code {
+ padding: 0;
+ font-size: inherit;
+ color: inherit;
+ white-space: pre-wrap;
+ background-color: transparent;
+ border-radius: 0;
+}
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll;
+}
+.container {
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+@media (min-width: 768px) {
+ .container {
+ width: 750px;
+ }
+}
+@media (min-width: 992px) {
+ .container {
+ width: 970px;
+ }
+}
+@media (min-width: 1200px) {
+ .container {
+ width: 1170px;
+ }
+}
+.container-fluid {
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+.row {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
+ position: relative;
+ min-height: 1px;
+ padding-right: 15px;
+ padding-left: 15px;
+}
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
+ float: left;
+}
+.col-xs-12 {
+ width: 100%;
+}
+.col-xs-11 {
+ width: 91.66666667%;
+}
+.col-xs-10 {
+ width: 83.33333333%;
+}
+.col-xs-9 {
+ width: 75%;
+}
+.col-xs-8 {
+ width: 66.66666667%;
+}
+.col-xs-7 {
+ width: 58.33333333%;
+}
+.col-xs-6 {
+ width: 50%;
+}
+.col-xs-5 {
+ width: 41.66666667%;
+}
+.col-xs-4 {
+ width: 33.33333333%;
+}
+.col-xs-3 {
+ width: 25%;
+}
+.col-xs-2 {
+ width: 16.66666667%;
+}
+.col-xs-1 {
+ width: 8.33333333%;
+}
+.col-xs-pull-12 {
+ right: 100%;
+}
+.col-xs-pull-11 {
+ right: 91.66666667%;
+}
+.col-xs-pull-10 {
+ right: 83.33333333%;
+}
+.col-xs-pull-9 {
+ right: 75%;
+}
+.col-xs-pull-8 {
+ right: 66.66666667%;
+}
+.col-xs-pull-7 {
+ right: 58.33333333%;
+}
+.col-xs-pull-6 {
+ right: 50%;
+}
+.col-xs-pull-5 {
+ right: 41.66666667%;
+}
+.col-xs-pull-4 {
+ right: 33.33333333%;
+}
+.col-xs-pull-3 {
+ right: 25%;
+}
+.col-xs-pull-2 {
+ right: 16.66666667%;
+}
+.col-xs-pull-1 {
+ right: 8.33333333%;
+}
+.col-xs-pull-0 {
+ right: auto;
+}
+.col-xs-push-12 {
+ left: 100%;
+}
+.col-xs-push-11 {
+ left: 91.66666667%;
+}
+.col-xs-push-10 {
+ left: 83.33333333%;
+}
+.col-xs-push-9 {
+ left: 75%;
+}
+.col-xs-push-8 {
+ left: 66.66666667%;
+}
+.col-xs-push-7 {
+ left: 58.33333333%;
+}
+.col-xs-push-6 {
+ left: 50%;
+}
+.col-xs-push-5 {
+ left: 41.66666667%;
+}
+.col-xs-push-4 {
+ left: 33.33333333%;
+}
+.col-xs-push-3 {
+ left: 25%;
+}
+.col-xs-push-2 {
+ left: 16.66666667%;
+}
+.col-xs-push-1 {
+ left: 8.33333333%;
+}
+.col-xs-push-0 {
+ left: auto;
+}
+.col-xs-offset-12 {
+ margin-left: 100%;
+}
+.col-xs-offset-11 {
+ margin-left: 91.66666667%;
+}
+.col-xs-offset-10 {
+ margin-left: 83.33333333%;
+}
+.col-xs-offset-9 {
+ margin-left: 75%;
+}
+.col-xs-offset-8 {
+ margin-left: 66.66666667%;
+}
+.col-xs-offset-7 {
+ margin-left: 58.33333333%;
+}
+.col-xs-offset-6 {
+ margin-left: 50%;
+}
+.col-xs-offset-5 {
+ margin-left: 41.66666667%;
+}
+.col-xs-offset-4 {
+ margin-left: 33.33333333%;
+}
+.col-xs-offset-3 {
+ margin-left: 25%;
+}
+.col-xs-offset-2 {
+ margin-left: 16.66666667%;
+}
+.col-xs-offset-1 {
+ margin-left: 8.33333333%;
+}
+.col-xs-offset-0 {
+ margin-left: 0;
+}
+@media (min-width: 768px) {
+ .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
+ float: left;
+ }
+ .col-sm-12 {
+ width: 100%;
+ }
+ .col-sm-11 {
+ width: 91.66666667%;
+ }
+ .col-sm-10 {
+ width: 83.33333333%;
+ }
+ .col-sm-9 {
+ width: 75%;
+ }
+ .col-sm-8 {
+ width: 66.66666667%;
+ }
+ .col-sm-7 {
+ width: 58.33333333%;
+ }
+ .col-sm-6 {
+ width: 50%;
+ }
+ .col-sm-5 {
+ width: 41.66666667%;
+ }
+ .col-sm-4 {
+ width: 33.33333333%;
+ }
+ .col-sm-3 {
+ width: 25%;
+ }
+ .col-sm-2 {
+ width: 16.66666667%;
+ }
+ .col-sm-1 {
+ width: 8.33333333%;
+ }
+ .col-sm-pull-12 {
+ right: 100%;
+ }
+ .col-sm-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-sm-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-sm-pull-9 {
+ right: 75%;
+ }
+ .col-sm-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-sm-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-sm-pull-6 {
+ right: 50%;
+ }
+ .col-sm-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-sm-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-sm-pull-3 {
+ right: 25%;
+ }
+ .col-sm-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-sm-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-sm-pull-0 {
+ right: auto;
+ }
+ .col-sm-push-12 {
+ left: 100%;
+ }
+ .col-sm-push-11 {
+ left: 91.66666667%;
+ }
+ .col-sm-push-10 {
+ left: 83.33333333%;
+ }
+ .col-sm-push-9 {
+ left: 75%;
+ }
+ .col-sm-push-8 {
+ left: 66.66666667%;
+ }
+ .col-sm-push-7 {
+ left: 58.33333333%;
+ }
+ .col-sm-push-6 {
+ left: 50%;
+ }
+ .col-sm-push-5 {
+ left: 41.66666667%;
+ }
+ .col-sm-push-4 {
+ left: 33.33333333%;
+ }
+ .col-sm-push-3 {
+ left: 25%;
+ }
+ .col-sm-push-2 {
+ left: 16.66666667%;
+ }
+ .col-sm-push-1 {
+ left: 8.33333333%;
+ }
+ .col-sm-push-0 {
+ left: auto;
+ }
+ .col-sm-offset-12 {
+ margin-left: 100%;
+ }
+ .col-sm-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-sm-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-sm-offset-9 {
+ margin-left: 75%;
+ }
+ .col-sm-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-sm-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-sm-offset-6 {
+ margin-left: 50%;
+ }
+ .col-sm-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-sm-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-sm-offset-3 {
+ margin-left: 25%;
+ }
+ .col-sm-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-sm-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-sm-offset-0 {
+ margin-left: 0;
+ }
+}
+@media (min-width: 992px) {
+ .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
+ float: left;
+ }
+ .col-md-12 {
+ width: 100%;
+ }
+ .col-md-11 {
+ width: 91.66666667%;
+ }
+ .col-md-10 {
+ width: 83.33333333%;
+ }
+ .col-md-9 {
+ width: 75%;
+ }
+ .col-md-8 {
+ width: 66.66666667%;
+ }
+ .col-md-7 {
+ width: 58.33333333%;
+ }
+ .col-md-6 {
+ width: 50%;
+ }
+ .col-md-5 {
+ width: 41.66666667%;
+ }
+ .col-md-4 {
+ width: 33.33333333%;
+ }
+ .col-md-3 {
+ width: 25%;
+ }
+ .col-md-2 {
+ width: 16.66666667%;
+ }
+ .col-md-1 {
+ width: 8.33333333%;
+ }
+ .col-md-pull-12 {
+ right: 100%;
+ }
+ .col-md-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-md-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-md-pull-9 {
+ right: 75%;
+ }
+ .col-md-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-md-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-md-pull-6 {
+ right: 50%;
+ }
+ .col-md-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-md-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-md-pull-3 {
+ right: 25%;
+ }
+ .col-md-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-md-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-md-pull-0 {
+ right: auto;
+ }
+ .col-md-push-12 {
+ left: 100%;
+ }
+ .col-md-push-11 {
+ left: 91.66666667%;
+ }
+ .col-md-push-10 {
+ left: 83.33333333%;
+ }
+ .col-md-push-9 {
+ left: 75%;
+ }
+ .col-md-push-8 {
+ left: 66.66666667%;
+ }
+ .col-md-push-7 {
+ left: 58.33333333%;
+ }
+ .col-md-push-6 {
+ left: 50%;
+ }
+ .col-md-push-5 {
+ left: 41.66666667%;
+ }
+ .col-md-push-4 {
+ left: 33.33333333%;
+ }
+ .col-md-push-3 {
+ left: 25%;
+ }
+ .col-md-push-2 {
+ left: 16.66666667%;
+ }
+ .col-md-push-1 {
+ left: 8.33333333%;
+ }
+ .col-md-push-0 {
+ left: auto;
+ }
+ .col-md-offset-12 {
+ margin-left: 100%;
+ }
+ .col-md-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-md-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-md-offset-9 {
+ margin-left: 75%;
+ }
+ .col-md-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-md-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-md-offset-6 {
+ margin-left: 50%;
+ }
+ .col-md-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-md-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-md-offset-3 {
+ margin-left: 25%;
+ }
+ .col-md-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-md-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-md-offset-0 {
+ margin-left: 0;
+ }
+}
+@media (min-width: 1200px) {
+ .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
+ float: left;
+ }
+ .col-lg-12 {
+ width: 100%;
+ }
+ .col-lg-11 {
+ width: 91.66666667%;
+ }
+ .col-lg-10 {
+ width: 83.33333333%;
+ }
+ .col-lg-9 {
+ width: 75%;
+ }
+ .col-lg-8 {
+ width: 66.66666667%;
+ }
+ .col-lg-7 {
+ width: 58.33333333%;
+ }
+ .col-lg-6 {
+ width: 50%;
+ }
+ .col-lg-5 {
+ width: 41.66666667%;
+ }
+ .col-lg-4 {
+ width: 33.33333333%;
+ }
+ .col-lg-3 {
+ width: 25%;
+ }
+ .col-lg-2 {
+ width: 16.66666667%;
+ }
+ .col-lg-1 {
+ width: 8.33333333%;
+ }
+ .col-lg-pull-12 {
+ right: 100%;
+ }
+ .col-lg-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-lg-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-lg-pull-9 {
+ right: 75%;
+ }
+ .col-lg-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-lg-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-lg-pull-6 {
+ right: 50%;
+ }
+ .col-lg-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-lg-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-lg-pull-3 {
+ right: 25%;
+ }
+ .col-lg-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-lg-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-lg-pull-0 {
+ right: auto;
+ }
+ .col-lg-push-12 {
+ left: 100%;
+ }
+ .col-lg-push-11 {
+ left: 91.66666667%;
+ }
+ .col-lg-push-10 {
+ left: 83.33333333%;
+ }
+ .col-lg-push-9 {
+ left: 75%;
+ }
+ .col-lg-push-8 {
+ left: 66.66666667%;
+ }
+ .col-lg-push-7 {
+ left: 58.33333333%;
+ }
+ .col-lg-push-6 {
+ left: 50%;
+ }
+ .col-lg-push-5 {
+ left: 41.66666667%;
+ }
+ .col-lg-push-4 {
+ left: 33.33333333%;
+ }
+ .col-lg-push-3 {
+ left: 25%;
+ }
+ .col-lg-push-2 {
+ left: 16.66666667%;
+ }
+ .col-lg-push-1 {
+ left: 8.33333333%;
+ }
+ .col-lg-push-0 {
+ left: auto;
+ }
+ .col-lg-offset-12 {
+ margin-left: 100%;
+ }
+ .col-lg-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-lg-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-lg-offset-9 {
+ margin-left: 75%;
+ }
+ .col-lg-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-lg-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-lg-offset-6 {
+ margin-left: 50%;
+ }
+ .col-lg-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-lg-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-lg-offset-3 {
+ margin-left: 25%;
+ }
+ .col-lg-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-lg-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-lg-offset-0 {
+ margin-left: 0;
+ }
+}
+table {
+ background-color: transparent;
+}
+caption {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ color: #777;
+ text-align: left;
+}
+th {
+ text-align: left;
+}
+.table {
+ width: 100%;
+ max-width: 100%;
+ margin-bottom: 20px;
+}
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+ padding: 8px;
+ line-height: 1.42857143;
+ vertical-align: top;
+ border-top: 1px solid #ddd;
+}
+.table > thead > tr > th {
+ vertical-align: bottom;
+ border-bottom: 2px solid #ddd;
+}
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.table > thead:first-child > tr:first-child > td {
+ border-top: 0;
+}
+.table > tbody + tbody {
+ border-top: 2px solid #ddd;
+}
+.table .table {
+ background-color: #fff;
+}
+.table-condensed > thead > tr > th,
+.table-condensed > tbody > tr > th,
+.table-condensed > tfoot > tr > th,
+.table-condensed > thead > tr > td,
+.table-condensed > tbody > tr > td,
+.table-condensed > tfoot > tr > td {
+ padding: 5px;
+}
+.table-bordered {
+ border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > tbody > tr > th,
+.table-bordered > tfoot > tr > th,
+.table-bordered > thead > tr > td,
+.table-bordered > tbody > tr > td,
+.table-bordered > tfoot > tr > td {
+ border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > thead > tr > td {
+ border-bottom-width: 2px;
+}
+.table-striped > tbody > tr:nth-of-type(odd) {
+ background-color: #f9f9f9;
+}
+.table-hover > tbody > tr:hover {
+ background-color: #f5f5f5;
+}
+table col[class*="col-"] {
+ position: static;
+ display: table-column;
+ float: none;
+}
+table td[class*="col-"],
+table th[class*="col-"] {
+ position: static;
+ display: table-cell;
+ float: none;
+}
+.table > thead > tr > td.active,
+.table > tbody > tr > td.active,
+.table > tfoot > tr > td.active,
+.table > thead > tr > th.active,
+.table > tbody > tr > th.active,
+.table > tfoot > tr > th.active,
+.table > thead > tr.active > td,
+.table > tbody > tr.active > td,
+.table > tfoot > tr.active > td,
+.table > thead > tr.active > th,
+.table > tbody > tr.active > th,
+.table > tfoot > tr.active > th {
+ background-color: #f5f5f5;
+}
+.table-hover > tbody > tr > td.active:hover,
+.table-hover > tbody > tr > th.active:hover,
+.table-hover > tbody > tr.active:hover > td,
+.table-hover > tbody > tr:hover > .active,
+.table-hover > tbody > tr.active:hover > th {
+ background-color: #e8e8e8;
+}
+.table > thead > tr > td.success,
+.table > tbody > tr > td.success,
+.table > tfoot > tr > td.success,
+.table > thead > tr > th.success,
+.table > tbody > tr > th.success,
+.table > tfoot > tr > th.success,
+.table > thead > tr.success > td,
+.table > tbody > tr.success > td,
+.table > tfoot > tr.success > td,
+.table > thead > tr.success > th,
+.table > tbody > tr.success > th,
+.table > tfoot > tr.success > th {
+ background-color: #dff0d8;
+}
+.table-hover > tbody > tr > td.success:hover,
+.table-hover > tbody > tr > th.success:hover,
+.table-hover > tbody > tr.success:hover > td,
+.table-hover > tbody > tr:hover > .success,
+.table-hover > tbody > tr.success:hover > th {
+ background-color: #d0e9c6;
+}
+.table > thead > tr > td.info,
+.table > tbody > tr > td.info,
+.table > tfoot > tr > td.info,
+.table > thead > tr > th.info,
+.table > tbody > tr > th.info,
+.table > tfoot > tr > th.info,
+.table > thead > tr.info > td,
+.table > tbody > tr.info > td,
+.table > tfoot > tr.info > td,
+.table > thead > tr.info > th,
+.table > tbody > tr.info > th,
+.table > tfoot > tr.info > th {
+ background-color: #d9edf7;
+}
+.table-hover > tbody > tr > td.info:hover,
+.table-hover > tbody > tr > th.info:hover,
+.table-hover > tbody > tr.info:hover > td,
+.table-hover > tbody > tr:hover > .info,
+.table-hover > tbody > tr.info:hover > th {
+ background-color: #c4e3f3;
+}
+.table > thead > tr > td.warning,
+.table > tbody > tr > td.warning,
+.table > tfoot > tr > td.warning,
+.table > thead > tr > th.warning,
+.table > tbody > tr > th.warning,
+.table > tfoot > tr > th.warning,
+.table > thead > tr.warning > td,
+.table > tbody > tr.warning > td,
+.table > tfoot > tr.warning > td,
+.table > thead > tr.warning > th,
+.table > tbody > tr.warning > th,
+.table > tfoot > tr.warning > th {
+ background-color: #fcf8e3;
+}
+.table-hover > tbody > tr > td.warning:hover,
+.table-hover > tbody > tr > th.warning:hover,
+.table-hover > tbody > tr.warning:hover > td,
+.table-hover > tbody > tr:hover > .warning,
+.table-hover > tbody > tr.warning:hover > th {
+ background-color: #faf2cc;
+}
+.table > thead > tr > td.danger,
+.table > tbody > tr > td.danger,
+.table > tfoot > tr > td.danger,
+.table > thead > tr > th.danger,
+.table > tbody > tr > th.danger,
+.table > tfoot > tr > th.danger,
+.table > thead > tr.danger > td,
+.table > tbody > tr.danger > td,
+.table > tfoot > tr.danger > td,
+.table > thead > tr.danger > th,
+.table > tbody > tr.danger > th,
+.table > tfoot > tr.danger > th {
+ background-color: #f2dede;
+}
+.table-hover > tbody > tr > td.danger:hover,
+.table-hover > tbody > tr > th.danger:hover,
+.table-hover > tbody > tr.danger:hover > td,
+.table-hover > tbody > tr:hover > .danger,
+.table-hover > tbody > tr.danger:hover > th {
+ background-color: #ebcccc;
+}
+.table-responsive {
+ min-height: .01%;
+ overflow-x: auto;
+}
+@media screen and (max-width: 767px) {
+ .table-responsive {
+ width: 100%;
+ margin-bottom: 15px;
+ overflow-y: hidden;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ border: 1px solid #ddd;
+ }
+ .table-responsive > .table {
+ margin-bottom: 0;
+ }
+ .table-responsive > .table > thead > tr > th,
+ .table-responsive > .table > tbody > tr > th,
+ .table-responsive > .table > tfoot > tr > th,
+ .table-responsive > .table > thead > tr > td,
+ .table-responsive > .table > tbody > tr > td,
+ .table-responsive > .table > tfoot > tr > td {
+ white-space: nowrap;
+ }
+ .table-responsive > .table-bordered {
+ border: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:first-child,
+ .table-responsive > .table-bordered > tbody > tr > th:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+ .table-responsive > .table-bordered > thead > tr > td:first-child,
+ .table-responsive > .table-bordered > tbody > tr > td:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:last-child,
+ .table-responsive > .table-bordered > tbody > tr > th:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+ .table-responsive > .table-bordered > thead > tr > td:last-child,
+ .table-responsive > .table-bordered > tbody > tr > td:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+ }
+ .table-responsive > .table-bordered > tbody > tr:last-child > th,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > th,
+ .table-responsive > .table-bordered > tbody > tr:last-child > td,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+ border-bottom: 0;
+ }
+}
+fieldset {
+ min-width: 0;
+ padding: 0;
+ margin: 0;
+ border: 0;
+}
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: 20px;
+ font-size: 21px;
+ line-height: inherit;
+ color: #333;
+ border: 0;
+ border-bottom: 1px solid #e5e5e5;
+}
+label {
+ display: inline-block;
+ max-width: 100%;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+input[type="search"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+input[type="radio"],
+input[type="checkbox"] {
+ margin: 4px 0 0;
+ margin-top: 1px \9;
+ line-height: normal;
+}
+input[type="file"] {
+ display: block;
+}
+input[type="range"] {
+ display: block;
+ width: 100%;
+}
+select[multiple],
+select[size] {
+ height: auto;
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+output {
+ display: block;
+ padding-top: 7px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555;
+}
+.form-control {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555;
+ background-color: #fff;
+ background-image: none;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+.form-control:focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+}
+.form-control::-moz-placeholder {
+ color: #999;
+ opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+ color: #999;
+}
+.form-control::-webkit-input-placeholder {
+ color: #999;
+}
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+ background-color: #eee;
+ opacity: 1;
+}
+.form-control[disabled],
+fieldset[disabled] .form-control {
+ cursor: not-allowed;
+}
+textarea.form-control {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-appearance: none;
+}
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ input[type="date"].form-control,
+ input[type="time"].form-control,
+ input[type="datetime-local"].form-control,
+ input[type="month"].form-control {
+ line-height: 34px;
+ }
+ input[type="date"].input-sm,
+ input[type="time"].input-sm,
+ input[type="datetime-local"].input-sm,
+ input[type="month"].input-sm,
+ .input-group-sm input[type="date"],
+ .input-group-sm input[type="time"],
+ .input-group-sm input[type="datetime-local"],
+ .input-group-sm input[type="month"] {
+ line-height: 30px;
+ }
+ input[type="date"].input-lg,
+ input[type="time"].input-lg,
+ input[type="datetime-local"].input-lg,
+ input[type="month"].input-lg,
+ .input-group-lg input[type="date"],
+ .input-group-lg input[type="time"],
+ .input-group-lg input[type="datetime-local"],
+ .input-group-lg input[type="month"] {
+ line-height: 46px;
+ }
+}
+.form-group {
+ margin-bottom: 15px;
+}
+.radio,
+.checkbox {
+ position: relative;
+ display: block;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.radio label,
+.checkbox label {
+ min-height: 20px;
+ padding-left: 20px;
+ margin-bottom: 0;
+ font-weight: normal;
+ cursor: pointer;
+}
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+ position: absolute;
+ margin-top: 4px \9;
+ margin-left: -20px;
+}
+.radio + .radio,
+.checkbox + .checkbox {
+ margin-top: -5px;
+}
+.radio-inline,
+.checkbox-inline {
+ position: relative;
+ display: inline-block;
+ padding-left: 20px;
+ margin-bottom: 0;
+ font-weight: normal;
+ vertical-align: middle;
+ cursor: pointer;
+}
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+ margin-top: 0;
+ margin-left: 10px;
+}
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"].disabled,
+input[type="checkbox"].disabled,
+fieldset[disabled] input[type="radio"],
+fieldset[disabled] input[type="checkbox"] {
+ cursor: not-allowed;
+}
+.radio-inline.disabled,
+.checkbox-inline.disabled,
+fieldset[disabled] .radio-inline,
+fieldset[disabled] .checkbox-inline {
+ cursor: not-allowed;
+}
+.radio.disabled label,
+.checkbox.disabled label,
+fieldset[disabled] .radio label,
+fieldset[disabled] .checkbox label {
+ cursor: not-allowed;
+}
+.form-control-static {
+ min-height: 34px;
+ padding-top: 7px;
+ padding-bottom: 7px;
+ margin-bottom: 0;
+}
+.form-control-static.input-lg,
+.form-control-static.input-sm {
+ padding-right: 0;
+ padding-left: 0;
+}
+.input-sm {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+select.input-sm {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.input-sm,
+select[multiple].input-sm {
+ height: auto;
+}
+.form-group-sm .form-control {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.form-group-sm select.form-control {
+ height: 30px;
+ line-height: 30px;
+}
+.form-group-sm textarea.form-control,
+.form-group-sm select[multiple].form-control {
+ height: auto;
+}
+.form-group-sm .form-control-static {
+ height: 30px;
+ min-height: 32px;
+ padding: 6px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+}
+.input-lg {
+ height: 46px;
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+select.input-lg {
+ height: 46px;
+ line-height: 46px;
+}
+textarea.input-lg,
+select[multiple].input-lg {
+ height: auto;
+}
+.form-group-lg .form-control {
+ height: 46px;
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+.form-group-lg select.form-control {
+ height: 46px;
+ line-height: 46px;
+}
+.form-group-lg textarea.form-control,
+.form-group-lg select[multiple].form-control {
+ height: auto;
+}
+.form-group-lg .form-control-static {
+ height: 46px;
+ min-height: 38px;
+ padding: 11px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+}
+.has-feedback {
+ position: relative;
+}
+.has-feedback .form-control {
+ padding-right: 42.5px;
+}
+.form-control-feedback {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 2;
+ display: block;
+ width: 34px;
+ height: 34px;
+ line-height: 34px;
+ text-align: center;
+ pointer-events: none;
+}
+.input-lg + .form-control-feedback,
+.input-group-lg + .form-control-feedback,
+.form-group-lg .form-control + .form-control-feedback {
+ width: 46px;
+ height: 46px;
+ line-height: 46px;
+}
+.input-sm + .form-control-feedback,
+.input-group-sm + .form-control-feedback,
+.form-group-sm .form-control + .form-control-feedback {
+ width: 30px;
+ height: 30px;
+ line-height: 30px;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline,
+.has-success.radio label,
+.has-success.checkbox label,
+.has-success.radio-inline label,
+.has-success.checkbox-inline label {
+ color: #3c763d;
+}
+.has-success .form-control {
+ border-color: #3c763d;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-success .form-control:focus {
+ border-color: #2b542c;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+}
+.has-success .input-group-addon {
+ color: #3c763d;
+ background-color: #dff0d8;
+ border-color: #3c763d;
+}
+.has-success .form-control-feedback {
+ color: #3c763d;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline,
+.has-warning.radio label,
+.has-warning.checkbox label,
+.has-warning.radio-inline label,
+.has-warning.checkbox-inline label {
+ color: #8a6d3b;
+}
+.has-warning .form-control {
+ border-color: #8a6d3b;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-warning .form-control:focus {
+ border-color: #66512c;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+}
+.has-warning .input-group-addon {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+ border-color: #8a6d3b;
+}
+.has-warning .form-control-feedback {
+ color: #8a6d3b;
+}
+.has-error .help-block,
+.has-error .control-label,
+.has-error .radio,
+.has-error .checkbox,
+.has-error .radio-inline,
+.has-error .checkbox-inline,
+.has-error.radio label,
+.has-error.checkbox label,
+.has-error.radio-inline label,
+.has-error.checkbox-inline label {
+ color: #a94442;
+}
+.has-error .form-control {
+ border-color: #a94442;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-error .form-control:focus {
+ border-color: #843534;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+}
+.has-error .input-group-addon {
+ color: #a94442;
+ background-color: #f2dede;
+ border-color: #a94442;
+}
+.has-error .form-control-feedback {
+ color: #a94442;
+}
+.has-feedback label ~ .form-control-feedback {
+ top: 25px;
+}
+.has-feedback label.sr-only ~ .form-control-feedback {
+ top: 0;
+}
+.help-block {
+ display: block;
+ margin-top: 5px;
+ margin-bottom: 10px;
+ color: #737373;
+}
+@media (min-width: 768px) {
+ .form-inline .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .form-inline .form-control-static {
+ display: inline-block;
+ }
+ .form-inline .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .form-inline .input-group .input-group-addon,
+ .form-inline .input-group .input-group-btn,
+ .form-inline .input-group .form-control {
+ width: auto;
+ }
+ .form-inline .input-group > .form-control {
+ width: 100%;
+ }
+ .form-inline .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio,
+ .form-inline .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio label,
+ .form-inline .checkbox label {
+ padding-left: 0;
+ }
+ .form-inline .radio input[type="radio"],
+ .form-inline .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .form-inline .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+ padding-top: 7px;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+ min-height: 27px;
+}
+.form-horizontal .form-group {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .control-label {
+ padding-top: 7px;
+ margin-bottom: 0;
+ text-align: right;
+ }
+}
+.form-horizontal .has-feedback .form-control-feedback {
+ right: 15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-lg .control-label {
+ padding-top: 14.333333px;
+ font-size: 18px;
+ }
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-sm .control-label {
+ padding-top: 6px;
+ font-size: 12px;
+ }
+}
+.btn {
+ display: inline-block;
+ padding: 6px 12px;
+ margin-bottom: 0;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 1.42857143;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: middle;
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ cursor: pointer;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ background-image: none;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus,
+.btn.focus,
+.btn:active.focus,
+.btn.active.focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+.btn:hover,
+.btn:focus,
+.btn.focus {
+ color: #333;
+ text-decoration: none;
+}
+.btn:active,
+.btn.active {
+ background-image: none;
+ outline: 0;
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+ cursor: not-allowed;
+ filter: alpha(opacity=65);
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ opacity: .65;
+}
+a.btn.disabled,
+fieldset[disabled] a.btn {
+ pointer-events: none;
+}
+.btn-default {
+ color: #333;
+ background-color: #fff;
+ border-color: #ccc;
+}
+.btn-default:focus,
+.btn-default.focus {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #8c8c8c;
+}
+.btn-default:hover {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #adadad;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #adadad;
+}
+.btn-default:active:hover,
+.btn-default.active:hover,
+.open > .dropdown-toggle.btn-default:hover,
+.btn-default:active:focus,
+.btn-default.active:focus,
+.open > .dropdown-toggle.btn-default:focus,
+.btn-default:active.focus,
+.btn-default.active.focus,
+.open > .dropdown-toggle.btn-default.focus {
+ color: #333;
+ background-color: #d4d4d4;
+ border-color: #8c8c8c;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ background-image: none;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+ background-color: #fff;
+ border-color: #ccc;
+}
+.btn-default .badge {
+ color: #fff;
+ background-color: #333;
+}
+.btn-primary {
+ color: #fff;
+ background-color: #337ab7;
+ border-color: #2e6da4;
+}
+.btn-primary:focus,
+.btn-primary.focus {
+ color: #fff;
+ background-color: #286090;
+ border-color: #122b40;
+}
+.btn-primary:hover {
+ color: #fff;
+ background-color: #286090;
+ border-color: #204d74;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ color: #fff;
+ background-color: #286090;
+ border-color: #204d74;
+}
+.btn-primary:active:hover,
+.btn-primary.active:hover,
+.open > .dropdown-toggle.btn-primary:hover,
+.btn-primary:active:focus,
+.btn-primary.active:focus,
+.open > .dropdown-toggle.btn-primary:focus,
+.btn-primary:active.focus,
+.btn-primary.active.focus,
+.open > .dropdown-toggle.btn-primary.focus {
+ color: #fff;
+ background-color: #204d74;
+ border-color: #122b40;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ background-image: none;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+ background-color: #337ab7;
+ border-color: #2e6da4;
+}
+.btn-primary .badge {
+ color: #337ab7;
+ background-color: #fff;
+}
+.btn-success {
+ color: #fff;
+ background-color: #5cb85c;
+ border-color: #4cae4c;
+}
+.btn-success:focus,
+.btn-success.focus {
+ color: #fff;
+ background-color: #449d44;
+ border-color: #255625;
+}
+.btn-success:hover {
+ color: #fff;
+ background-color: #449d44;
+ border-color: #398439;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ color: #fff;
+ background-color: #449d44;
+ border-color: #398439;
+}
+.btn-success:active:hover,
+.btn-success.active:hover,
+.open > .dropdown-toggle.btn-success:hover,
+.btn-success:active:focus,
+.btn-success.active:focus,
+.open > .dropdown-toggle.btn-success:focus,
+.btn-success:active.focus,
+.btn-success.active.focus,
+.open > .dropdown-toggle.btn-success.focus {
+ color: #fff;
+ background-color: #398439;
+ border-color: #255625;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ background-image: none;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+ background-color: #5cb85c;
+ border-color: #4cae4c;
+}
+.btn-success .badge {
+ color: #5cb85c;
+ background-color: #fff;
+}
+.btn-info {
+ color: #fff;
+ background-color: #5bc0de;
+ border-color: #46b8da;
+}
+.btn-info:focus,
+.btn-info.focus {
+ color: #fff;
+ background-color: #31b0d5;
+ border-color: #1b6d85;
+}
+.btn-info:hover {
+ color: #fff;
+ background-color: #31b0d5;
+ border-color: #269abc;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ color: #fff;
+ background-color: #31b0d5;
+ border-color: #269abc;
+}
+.btn-info:active:hover,
+.btn-info.active:hover,
+.open > .dropdown-toggle.btn-info:hover,
+.btn-info:active:focus,
+.btn-info.active:focus,
+.open > .dropdown-toggle.btn-info:focus,
+.btn-info:active.focus,
+.btn-info.active.focus,
+.open > .dropdown-toggle.btn-info.focus {
+ color: #fff;
+ background-color: #269abc;
+ border-color: #1b6d85;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ background-image: none;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+ background-color: #5bc0de;
+ border-color: #46b8da;
+}
+.btn-info .badge {
+ color: #5bc0de;
+ background-color: #fff;
+}
+.btn-warning {
+ color: #fff;
+ background-color: #f0ad4e;
+ border-color: #eea236;
+}
+.btn-warning:focus,
+.btn-warning.focus {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #985f0d;
+}
+.btn-warning:hover {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #d58512;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #d58512;
+}
+.btn-warning:active:hover,
+.btn-warning.active:hover,
+.open > .dropdown-toggle.btn-warning:hover,
+.btn-warning:active:focus,
+.btn-warning.active:focus,
+.open > .dropdown-toggle.btn-warning:focus,
+.btn-warning:active.focus,
+.btn-warning.active.focus,
+.open > .dropdown-toggle.btn-warning.focus {
+ color: #fff;
+ background-color: #d58512;
+ border-color: #985f0d;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ background-image: none;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+ background-color: #f0ad4e;
+ border-color: #eea236;
+}
+.btn-warning .badge {
+ color: #f0ad4e;
+ background-color: #fff;
+}
+.btn-danger {
+ color: #fff;
+ background-color: #d9534f;
+ border-color: #d43f3a;
+}
+.btn-danger:focus,
+.btn-danger.focus {
+ color: #fff;
+ background-color: #c9302c;
+ border-color: #761c19;
+}
+.btn-danger:hover {
+ color: #fff;
+ background-color: #c9302c;
+ border-color: #ac2925;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ color: #fff;
+ background-color: #c9302c;
+ border-color: #ac2925;
+}
+.btn-danger:active:hover,
+.btn-danger.active:hover,
+.open > .dropdown-toggle.btn-danger:hover,
+.btn-danger:active:focus,
+.btn-danger.active:focus,
+.open > .dropdown-toggle.btn-danger:focus,
+.btn-danger:active.focus,
+.btn-danger.active.focus,
+.open > .dropdown-toggle.btn-danger.focus {
+ color: #fff;
+ background-color: #ac2925;
+ border-color: #761c19;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ background-image: none;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+ background-color: #d9534f;
+ border-color: #d43f3a;
+}
+.btn-danger .badge {
+ color: #d9534f;
+ background-color: #fff;
+}
+.btn-link {
+ font-weight: normal;
+ color: #337ab7;
+ border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link.active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+ background-color: transparent;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+ border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+ color: #23527c;
+ text-decoration: underline;
+ background-color: transparent;
+}
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+ color: #777;
+ text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+ padding: 1px 5px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.btn-block {
+ display: block;
+ width: 100%;
+}
+.btn-block + .btn-block {
+ margin-top: 5px;
+}
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+ width: 100%;
+}
+.fade {
+ opacity: 0;
+ -webkit-transition: opacity .15s linear;
+ -o-transition: opacity .15s linear;
+ transition: opacity .15s linear;
+}
+.fade.in {
+ opacity: 1;
+}
+.collapse {
+ display: none;
+}
+.collapse.in {
+ display: block;
+}
+tr.collapse.in {
+ display: table-row;
+}
+tbody.collapse.in {
+ display: table-row-group;
+}
+.collapsing {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ -webkit-transition-timing-function: ease;
+ -o-transition-timing-function: ease;
+ transition-timing-function: ease;
+ -webkit-transition-duration: .35s;
+ -o-transition-duration: .35s;
+ transition-duration: .35s;
+ -webkit-transition-property: height, visibility;
+ -o-transition-property: height, visibility;
+ transition-property: height, visibility;
+}
+.caret {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-left: 2px;
+ vertical-align: middle;
+ border-top: 4px dashed;
+ border-top: 4px solid \9;
+ border-right: 4px solid transparent;
+ border-left: 4px solid transparent;
+}
+.dropup,
+.dropdown {
+ position: relative;
+}
+.dropdown-toggle:focus {
+ outline: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 160px;
+ padding: 5px 0;
+ margin: 2px 0 0;
+ font-size: 14px;
+ text-align: left;
+ list-style: none;
+ background-color: #fff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, .15);
+ border-radius: 4px;
+ -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+}
+.dropdown-menu.pull-right {
+ right: 0;
+ left: auto;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 9px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.dropdown-menu > li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: 1.42857143;
+ color: #333;
+ white-space: nowrap;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+ color: #262626;
+ text-decoration: none;
+ background-color: #f5f5f5;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+ color: #fff;
+ text-decoration: none;
+ background-color: #337ab7;
+ outline: 0;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ color: #777;
+}
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ text-decoration: none;
+ cursor: not-allowed;
+ background-color: transparent;
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+}
+.open > .dropdown-menu {
+ display: block;
+}
+.open > a {
+ outline: 0;
+}
+.dropdown-menu-right {
+ right: 0;
+ left: auto;
+}
+.dropdown-menu-left {
+ right: auto;
+ left: 0;
+}
+.dropdown-header {
+ display: block;
+ padding: 3px 20px;
+ font-size: 12px;
+ line-height: 1.42857143;
+ color: #777;
+ white-space: nowrap;
+}
+.dropdown-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 990;
+}
+.pull-right > .dropdown-menu {
+ right: 0;
+ left: auto;
+}
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+ content: "";
+ border-top: 0;
+ border-bottom: 4px dashed;
+ border-bottom: 4px solid \9;
+}
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 2px;
+}
+@media (min-width: 768px) {
+ .navbar-right .dropdown-menu {
+ right: 0;
+ left: auto;
+ }
+ .navbar-right .dropdown-menu-left {
+ right: auto;
+ left: 0;
+ }
+}
+.btn-group,
+.btn-group-vertical {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+ position: relative;
+ float: left;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus,
+.btn-group > .btn:active,
+.btn-group-vertical > .btn:active,
+.btn-group > .btn.active,
+.btn-group-vertical > .btn.active {
+ z-index: 2;
+}
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+ margin-left: -1px;
+}
+.btn-toolbar {
+ margin-left: -5px;
+}
+.btn-toolbar .btn,
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+ float: left;
+}
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+ margin-left: 5px;
+}
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+ border-radius: 0;
+}
+.btn-group > .btn:first-child {
+ margin-left: 0;
+}
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group > .btn-group {
+ float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+.btn-group > .btn + .dropdown-toggle {
+ padding-right: 8px;
+ padding-left: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+ padding-right: 12px;
+ padding-left: 12px;
+}
+.btn-group.open .dropdown-toggle {
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn .caret {
+ margin-left: 0;
+}
+.btn-lg .caret {
+ border-width: 5px 5px 0;
+ border-bottom-width: 0;
+}
+.dropup .btn-lg .caret {
+ border-width: 0 5px 5px;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+ display: block;
+ float: none;
+ width: 100%;
+ max-width: 100%;
+}
+.btn-group-vertical > .btn-group > .btn {
+ float: none;
+}
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+ margin-top: -1px;
+ margin-left: 0;
+}
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ border-bottom-left-radius: 4px;
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.btn-group-justified {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+ border-collapse: separate;
+}
+.btn-group-justified > .btn,
+.btn-group-justified > .btn-group {
+ display: table-cell;
+ float: none;
+ width: 1%;
+}
+.btn-group-justified > .btn-group .btn {
+ width: 100%;
+}
+.btn-group-justified > .btn-group .dropdown-menu {
+ left: auto;
+}
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+ position: absolute;
+ clip: rect(0, 0, 0, 0);
+ pointer-events: none;
+}
+.input-group {
+ position: relative;
+ display: table;
+ border-collapse: separate;
+}
+.input-group[class*="col-"] {
+ float: none;
+ padding-right: 0;
+ padding-left: 0;
+}
+.input-group .form-control {
+ position: relative;
+ z-index: 2;
+ float: left;
+ width: 100%;
+ margin-bottom: 0;
+}
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+ height: 46px;
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+select.input-group-lg > .form-control,
+select.input-group-lg > .input-group-addon,
+select.input-group-lg > .input-group-btn > .btn {
+ height: 46px;
+ line-height: 46px;
+}
+textarea.input-group-lg > .form-control,
+textarea.input-group-lg > .input-group-addon,
+textarea.input-group-lg > .input-group-btn > .btn,
+select[multiple].input-group-lg > .form-control,
+select[multiple].input-group-lg > .input-group-addon,
+select[multiple].input-group-lg > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+select.input-group-sm > .form-control,
+select.input-group-sm > .input-group-addon,
+select.input-group-sm > .input-group-btn > .btn {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.input-group-sm > .form-control,
+textarea.input-group-sm > .input-group-addon,
+textarea.input-group-sm > .input-group-btn > .btn,
+select[multiple].input-group-sm > .form-control,
+select[multiple].input-group-sm > .input-group-addon,
+select[multiple].input-group-sm > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+ display: table-cell;
+}
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.input-group-addon,
+.input-group-btn {
+ width: 1%;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+.input-group-addon {
+ padding: 6px 12px;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 1;
+ color: #555;
+ text-align: center;
+ background-color: #eee;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+}
+.input-group-addon.input-sm {
+ padding: 5px 10px;
+ font-size: 12px;
+ border-radius: 3px;
+}
+.input-group-addon.input-lg {
+ padding: 10px 16px;
+ font-size: 18px;
+ border-radius: 6px;
+}
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+ margin-top: 0;
+}
+.input-group .form-control:first-child,
+.input-group-addon:first-child,
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
+.input-group-btn:first-child > .dropdown-toggle,
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.input-group-addon:first-child {
+ border-right: 0;
+}
+.input-group .form-control:last-child,
+.input-group-addon:last-child,
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
+.input-group-btn:last-child > .dropdown-toggle,
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.input-group-addon:last-child {
+ border-left: 0;
+}
+.input-group-btn {
+ position: relative;
+ font-size: 0;
+ white-space: nowrap;
+}
+.input-group-btn > .btn {
+ position: relative;
+}
+.input-group-btn > .btn + .btn {
+ margin-left: -1px;
+}
+.input-group-btn > .btn:hover,
+.input-group-btn > .btn:focus,
+.input-group-btn > .btn:active {
+ z-index: 2;
+}
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group {
+ margin-right: -1px;
+}
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group {
+ z-index: 2;
+ margin-left: -1px;
+}
+.nav {
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.nav > li {
+ position: relative;
+ display: block;
+}
+.nav > li > a {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+}
+.nav > li > a:hover,
+.nav > li > a:focus {
+ text-decoration: none;
+ background-color: #eee;
+}
+.nav > li.disabled > a {
+ color: #777;
+}
+.nav > li.disabled > a:hover,
+.nav > li.disabled > a:focus {
+ color: #777;
+ text-decoration: none;
+ cursor: not-allowed;
+ background-color: transparent;
+}
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+ background-color: #eee;
+ border-color: #337ab7;
+}
+.nav .nav-divider {
+ height: 1px;
+ margin: 9px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.nav > li > a > img {
+ max-width: none;
+}
+.nav-tabs {
+ border-bottom: 1px solid #ddd;
+}
+.nav-tabs > li {
+ float: left;
+ margin-bottom: -1px;
+}
+.nav-tabs > li > a {
+ margin-right: 2px;
+ line-height: 1.42857143;
+ border: 1px solid transparent;
+ border-radius: 4px 4px 0 0;
+}
+.nav-tabs > li > a:hover {
+ border-color: #eee #eee #ddd;
+}
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+ color: #555;
+ cursor: default;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-bottom-color: transparent;
+}
+.nav-tabs.nav-justified {
+ width: 100%;
+ border-bottom: 0;
+}
+.nav-tabs.nav-justified > li {
+ float: none;
+}
+.nav-tabs.nav-justified > li > a {
+ margin-bottom: 5px;
+ text-align: center;
+}
+.nav-tabs.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-tabs.nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs.nav-justified > li > a {
+ margin-right: 0;
+ border-radius: 4px;
+}
+.nav-tabs.nav-justified > .active > a,
+.nav-tabs.nav-justified > .active > a:hover,
+.nav-tabs.nav-justified > .active > a:focus {
+ border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li > a {
+ border-bottom: 1px solid #ddd;
+ border-radius: 4px 4px 0 0;
+ }
+ .nav-tabs.nav-justified > .active > a,
+ .nav-tabs.nav-justified > .active > a:hover,
+ .nav-tabs.nav-justified > .active > a:focus {
+ border-bottom-color: #fff;
+ }
+}
+.nav-pills > li {
+ float: left;
+}
+.nav-pills > li > a {
+ border-radius: 4px;
+}
+.nav-pills > li + li {
+ margin-left: 2px;
+}
+.nav-pills > li.active > a,
+.nav-pills > li.active > a:hover,
+.nav-pills > li.active > a:focus {
+ color: #fff;
+ background-color: #337ab7;
+}
+.nav-stacked > li {
+ float: none;
+}
+.nav-stacked > li + li {
+ margin-top: 2px;
+ margin-left: 0;
+}
+.nav-justified {
+ width: 100%;
+}
+.nav-justified > li {
+ float: none;
+}
+.nav-justified > li > a {
+ margin-bottom: 5px;
+ text-align: center;
+}
+.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs-justified {
+ border-bottom: 0;
+}
+.nav-tabs-justified > li > a {
+ margin-right: 0;
+ border-radius: 4px;
+}
+.nav-tabs-justified > .active > a,
+.nav-tabs-justified > .active > a:hover,
+.nav-tabs-justified > .active > a:focus {
+ border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs-justified > li > a {
+ border-bottom: 1px solid #ddd;
+ border-radius: 4px 4px 0 0;
+ }
+ .nav-tabs-justified > .active > a,
+ .nav-tabs-justified > .active > a:hover,
+ .nav-tabs-justified > .active > a:focus {
+ border-bottom-color: #fff;
+ }
+}
+.tab-content > .tab-pane {
+ display: none;
+}
+.tab-content > .active {
+ display: block;
+}
+.nav-tabs .dropdown-menu {
+ margin-top: -1px;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.navbar {
+ position: relative;
+ min-height: 50px;
+ margin-bottom: 20px;
+ border: 1px solid transparent;
+}
+@media (min-width: 768px) {
+ .navbar {
+ border-radius: 4px;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-header {
+ float: left;
+ }
+}
+.navbar-collapse {
+ padding-right: 15px;
+ padding-left: 15px;
+ overflow-x: visible;
+ -webkit-overflow-scrolling: touch;
+ border-top: 1px solid transparent;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+}
+.navbar-collapse.in {
+ overflow-y: auto;
+}
+@media (min-width: 768px) {
+ .navbar-collapse {
+ width: auto;
+ border-top: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+ .navbar-collapse.collapse {
+ display: block !important;
+ height: auto !important;
+ padding-bottom: 0;
+ overflow: visible !important;
+ }
+ .navbar-collapse.in {
+ overflow-y: visible;
+ }
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-static-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+.navbar-fixed-top .navbar-collapse,
+.navbar-fixed-bottom .navbar-collapse {
+ max-height: 340px;
+}
+@media (max-device-width: 480px) and (orientation: landscape) {
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ max-height: 200px;
+ }
+}
+.container > .navbar-header,
+.container-fluid > .navbar-header,
+.container > .navbar-collapse,
+.container-fluid > .navbar-collapse {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+@media (min-width: 768px) {
+ .container > .navbar-header,
+ .container-fluid > .navbar-header,
+ .container > .navbar-collapse,
+ .container-fluid > .navbar-collapse {
+ margin-right: 0;
+ margin-left: 0;
+ }
+}
+.navbar-static-top {
+ z-index: 1000;
+ border-width: 0 0 1px;
+}
+@media (min-width: 768px) {
+ .navbar-static-top {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ position: fixed;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+}
+@media (min-width: 768px) {
+ .navbar-fixed-top,
+ .navbar-fixed-bottom {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top {
+ top: 0;
+ border-width: 0 0 1px;
+}
+.navbar-fixed-bottom {
+ bottom: 0;
+ margin-bottom: 0;
+ border-width: 1px 0 0;
+}
+.navbar-brand {
+ float: left;
+ height: 50px;
+ padding: 15px 15px;
+ font-size: 18px;
+ line-height: 20px;
+}
+.navbar-brand:hover,
+.navbar-brand:focus {
+ text-decoration: none;
+}
+.navbar-brand > img {
+ display: block;
+}
+@media (min-width: 768px) {
+ .navbar > .container .navbar-brand,
+ .navbar > .container-fluid .navbar-brand {
+ margin-left: -15px;
+ }
+}
+.navbar-toggle {
+ position: relative;
+ float: right;
+ padding: 9px 10px;
+ margin-top: 8px;
+ margin-right: 15px;
+ margin-bottom: 8px;
+ background-color: transparent;
+ background-image: none;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.navbar-toggle:focus {
+ outline: 0;
+}
+.navbar-toggle .icon-bar {
+ display: block;
+ width: 22px;
+ height: 2px;
+ border-radius: 1px;
+}
+.navbar-toggle .icon-bar + .icon-bar {
+ margin-top: 4px;
+}
+@media (min-width: 768px) {
+ .navbar-toggle {
+ display: none;
+ }
+}
+.navbar-nav {
+ margin: 7.5px -15px;
+}
+.navbar-nav > li > a {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ line-height: 20px;
+}
+@media (max-width: 767px) {
+ .navbar-nav .open .dropdown-menu {
+ position: static;
+ float: none;
+ width: auto;
+ margin-top: 0;
+ background-color: transparent;
+ border: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+ .navbar-nav .open .dropdown-menu > li > a,
+ .navbar-nav .open .dropdown-menu .dropdown-header {
+ padding: 5px 15px 5px 25px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a {
+ line-height: 20px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-nav .open .dropdown-menu > li > a:focus {
+ background-image: none;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-nav {
+ float: left;
+ margin: 0;
+ }
+ .navbar-nav > li {
+ float: left;
+ }
+ .navbar-nav > li > a {
+ padding-top: 15px;
+ padding-bottom: 15px;
+ }
+}
+.navbar-form {
+ padding: 10px 15px;
+ margin-top: 8px;
+ margin-right: -15px;
+ margin-bottom: 8px;
+ margin-left: -15px;
+ border-top: 1px solid transparent;
+ border-bottom: 1px solid transparent;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+}
+@media (min-width: 768px) {
+ .navbar-form .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control-static {
+ display: inline-block;
+ }
+ .navbar-form .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .navbar-form .input-group .input-group-addon,
+ .navbar-form .input-group .input-group-btn,
+ .navbar-form .input-group .form-control {
+ width: auto;
+ }
+ .navbar-form .input-group > .form-control {
+ width: 100%;
+ }
+ .navbar-form .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio,
+ .navbar-form .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio label,
+ .navbar-form .checkbox label {
+ padding-left: 0;
+ }
+ .navbar-form .radio input[type="radio"],
+ .navbar-form .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .navbar-form .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+@media (max-width: 767px) {
+ .navbar-form .form-group {
+ margin-bottom: 5px;
+ }
+ .navbar-form .form-group:last-child {
+ margin-bottom: 0;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-form {
+ width: auto;
+ padding-top: 0;
+ padding-bottom: 0;
+ margin-right: 0;
+ margin-left: 0;
+ border: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+}
+.navbar-nav > li > .dropdown-menu {
+ margin-top: 0;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
+ margin-bottom: 0;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.navbar-btn {
+ margin-top: 8px;
+ margin-bottom: 8px;
+}
+.navbar-btn.btn-sm {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.navbar-btn.btn-xs {
+ margin-top: 14px;
+ margin-bottom: 14px;
+}
+.navbar-text {
+ margin-top: 15px;
+ margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+ .navbar-text {
+ float: left;
+ margin-right: 15px;
+ margin-left: 15px;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-left {
+ float: left !important;
+ }
+ .navbar-right {
+ float: right !important;
+ margin-right: -15px;
+ }
+ .navbar-right ~ .navbar-right {
+ margin-right: 0;
+ }
+}
+.navbar-default {
+ background-color: #f8f8f8;
+ border-color: #e7e7e7;
+}
+.navbar-default .navbar-brand {
+ color: #777;
+}
+.navbar-default .navbar-brand:hover,
+.navbar-default .navbar-brand:focus {
+ color: #5e5e5e;
+ background-color: transparent;
+}
+.navbar-default .navbar-text {
+ color: #777;
+}
+.navbar-default .navbar-nav > li > a {
+ color: #777;
+}
+.navbar-default .navbar-nav > li > a:hover,
+.navbar-default .navbar-nav > li > a:focus {
+ color: #333;
+ background-color: transparent;
+}
+.navbar-default .navbar-nav > .active > a,
+.navbar-default .navbar-nav > .active > a:hover,
+.navbar-default .navbar-nav > .active > a:focus {
+ color: #555;
+ background-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .disabled > a,
+.navbar-default .navbar-nav > .disabled > a:hover,
+.navbar-default .navbar-nav > .disabled > a:focus {
+ color: #ccc;
+ background-color: transparent;
+}
+.navbar-default .navbar-toggle {
+ border-color: #ddd;
+}
+.navbar-default .navbar-toggle:hover,
+.navbar-default .navbar-toggle:focus {
+ background-color: #ddd;
+}
+.navbar-default .navbar-toggle .icon-bar {
+ background-color: #888;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+ border-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .open > a:hover,
+.navbar-default .navbar-nav > .open > a:focus {
+ color: #555;
+ background-color: #e7e7e7;
+}
+@media (max-width: 767px) {
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+ color: #777;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #333;
+ background-color: transparent;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #555;
+ background-color: #e7e7e7;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #ccc;
+ background-color: transparent;
+ }
+}
+.navbar-default .navbar-link {
+ color: #777;
+}
+.navbar-default .navbar-link:hover {
+ color: #333;
+}
+.navbar-default .btn-link {
+ color: #777;
+}
+.navbar-default .btn-link:hover,
+.navbar-default .btn-link:focus {
+ color: #333;
+}
+.navbar-default .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-default .btn-link:hover,
+.navbar-default .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-default .btn-link:focus {
+ color: #ccc;
+}
+.navbar-inverse {
+ background-color: #222;
+ border-color: #080808;
+}
+.navbar-inverse .navbar-brand {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+ color: #fff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-text {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-nav > li > a {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+ color: #fff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+ color: #fff;
+ background-color: #080808;
+}
+.navbar-inverse .navbar-nav > .disabled > a,
+.navbar-inverse .navbar-nav > .disabled > a:hover,
+.navbar-inverse .navbar-nav > .disabled > a:focus {
+ color: #444;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-toggle {
+ border-color: #333;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+ background-color: #333;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+ background-color: #fff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+ border-color: #101010;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+ color: #fff;
+ background-color: #080808;
+}
+@media (max-width: 767px) {
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
+ border-color: #080808;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
+ background-color: #080808;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+ color: #9d9d9d;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #fff;
+ background-color: transparent;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #fff;
+ background-color: #080808;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #444;
+ background-color: transparent;
+ }
+}
+.navbar-inverse .navbar-link {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-link:hover {
+ color: #fff;
+}
+.navbar-inverse .btn-link {
+ color: #9d9d9d;
+}
+.navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link:focus {
+ color: #fff;
+}
+.navbar-inverse .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-inverse .btn-link:focus {
+ color: #444;
+}
+.breadcrumb {
+ padding: 8px 15px;
+ margin-bottom: 20px;
+ list-style: none;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+}
+.breadcrumb > li {
+ display: inline-block;
+}
+.breadcrumb > li + li:before {
+ padding: 0 5px;
+ color: #ccc;
+ content: "/\00a0";
+}
+.breadcrumb > .active {
+ color: #777;
+}
+.pagination {
+ display: inline-block;
+ padding-left: 0;
+ margin: 20px 0;
+ border-radius: 4px;
+}
+.pagination > li {
+ display: inline;
+}
+.pagination > li > a,
+.pagination > li > span {
+ position: relative;
+ float: left;
+ padding: 6px 12px;
+ margin-left: -1px;
+ line-height: 1.42857143;
+ color: #337ab7;
+ text-decoration: none;
+ background-color: #fff;
+ border: 1px solid #ddd;
+}
+.pagination > li:first-child > a,
+.pagination > li:first-child > span {
+ margin-left: 0;
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+.pagination > li:last-child > a,
+.pagination > li:last-child > span {
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+}
+.pagination > li > a:hover,
+.pagination > li > span:hover,
+.pagination > li > a:focus,
+.pagination > li > span:focus {
+ z-index: 3;
+ color: #23527c;
+ background-color: #eee;
+ border-color: #ddd;
+}
+.pagination > .active > a,
+.pagination > .active > span,
+.pagination > .active > a:hover,
+.pagination > .active > span:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span:focus {
+ z-index: 2;
+ color: #fff;
+ cursor: default;
+ background-color: #337ab7;
+ border-color: #337ab7;
+}
+.pagination > .disabled > span,
+.pagination > .disabled > span:hover,
+.pagination > .disabled > span:focus,
+.pagination > .disabled > a,
+.pagination > .disabled > a:hover,
+.pagination > .disabled > a:focus {
+ color: #777;
+ cursor: not-allowed;
+ background-color: #fff;
+ border-color: #ddd;
+}
+.pagination-lg > li > a,
+.pagination-lg > li > span {
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+}
+.pagination-lg > li:first-child > a,
+.pagination-lg > li:first-child > span {
+ border-top-left-radius: 6px;
+ border-bottom-left-radius: 6px;
+}
+.pagination-lg > li:last-child > a,
+.pagination-lg > li:last-child > span {
+ border-top-right-radius: 6px;
+ border-bottom-right-radius: 6px;
+}
+.pagination-sm > li > a,
+.pagination-sm > li > span {
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+}
+.pagination-sm > li:first-child > a,
+.pagination-sm > li:first-child > span {
+ border-top-left-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.pagination-sm > li:last-child > a,
+.pagination-sm > li:last-child > span {
+ border-top-right-radius: 3px;
+ border-bottom-right-radius: 3px;
+}
+.pager {
+ padding-left: 0;
+ margin: 20px 0;
+ text-align: center;
+ list-style: none;
+}
+.pager li {
+ display: inline;
+}
+.pager li > a,
+.pager li > span {
+ display: inline-block;
+ padding: 5px 14px;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 15px;
+}
+.pager li > a:hover,
+.pager li > a:focus {
+ text-decoration: none;
+ background-color: #eee;
+}
+.pager .next > a,
+.pager .next > span {
+ float: right;
+}
+.pager .previous > a,
+.pager .previous > span {
+ float: left;
+}
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+ color: #777;
+ cursor: not-allowed;
+ background-color: #fff;
+}
+.label {
+ display: inline;
+ padding: .2em .6em .3em;
+ font-size: 75%;
+ font-weight: bold;
+ line-height: 1;
+ color: #fff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: .25em;
+}
+a.label:hover,
+a.label:focus {
+ color: #fff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.label:empty {
+ display: none;
+}
+.btn .label {
+ position: relative;
+ top: -1px;
+}
+.label-default {
+ background-color: #777;
+}
+.label-default[href]:hover,
+.label-default[href]:focus {
+ background-color: #5e5e5e;
+}
+.label-primary {
+ background-color: #337ab7;
+}
+.label-primary[href]:hover,
+.label-primary[href]:focus {
+ background-color: #286090;
+}
+.label-success {
+ background-color: #5cb85c;
+}
+.label-success[href]:hover,
+.label-success[href]:focus {
+ background-color: #449d44;
+}
+.label-info {
+ background-color: #5bc0de;
+}
+.label-info[href]:hover,
+.label-info[href]:focus {
+ background-color: #31b0d5;
+}
+.label-warning {
+ background-color: #f0ad4e;
+}
+.label-warning[href]:hover,
+.label-warning[href]:focus {
+ background-color: #ec971f;
+}
+.label-danger {
+ background-color: #d9534f;
+}
+.label-danger[href]:hover,
+.label-danger[href]:focus {
+ background-color: #c9302c;
+}
+.badge {
+ display: inline-block;
+ min-width: 10px;
+ padding: 3px 7px;
+ font-size: 12px;
+ font-weight: bold;
+ line-height: 1;
+ color: #fff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: middle;
+ background-color: #777;
+ border-radius: 10px;
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.btn-xs .badge,
+.btn-group-xs > .btn .badge {
+ top: 0;
+ padding: 1px 5px;
+}
+a.badge:hover,
+a.badge:focus {
+ color: #fff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+ color: #337ab7;
+ background-color: #fff;
+}
+.list-group-item > .badge {
+ float: right;
+}
+.list-group-item > .badge + .badge {
+ margin-right: 5px;
+}
+.nav-pills > li > a > .badge {
+ margin-left: 3px;
+}
+.jumbotron {
+ padding-top: 30px;
+ padding-bottom: 30px;
+ margin-bottom: 30px;
+ color: inherit;
+ background-color: #eee;
+}
+.jumbotron h1,
+.jumbotron .h1 {
+ color: inherit;
+}
+.jumbotron p {
+ margin-bottom: 15px;
+ font-size: 21px;
+ font-weight: 200;
+}
+.jumbotron > hr {
+ border-top-color: #d5d5d5;
+}
+.container .jumbotron,
+.container-fluid .jumbotron {
+ border-radius: 6px;
+}
+.jumbotron .container {
+ max-width: 100%;
+}
+@media screen and (min-width: 768px) {
+ .jumbotron {
+ padding-top: 48px;
+ padding-bottom: 48px;
+ }
+ .container .jumbotron,
+ .container-fluid .jumbotron {
+ padding-right: 60px;
+ padding-left: 60px;
+ }
+ .jumbotron h1,
+ .jumbotron .h1 {
+ font-size: 63px;
+ }
+}
+.thumbnail {
+ display: block;
+ padding: 4px;
+ margin-bottom: 20px;
+ line-height: 1.42857143;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ -webkit-transition: border .2s ease-in-out;
+ -o-transition: border .2s ease-in-out;
+ transition: border .2s ease-in-out;
+}
+.thumbnail > img,
+.thumbnail a > img {
+ margin-right: auto;
+ margin-left: auto;
+}
+a.thumbnail:hover,
+a.thumbnail:focus,
+a.thumbnail.active {
+ border-color: #337ab7;
+}
+.thumbnail .caption {
+ padding: 9px;
+ color: #333;
+}
+.alert {
+ padding: 15px;
+ margin-bottom: 20px;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.alert h4 {
+ margin-top: 0;
+ color: inherit;
+}
+.alert .alert-link {
+ font-weight: bold;
+}
+.alert > p,
+.alert > ul {
+ margin-bottom: 0;
+}
+.alert > p + p {
+ margin-top: 5px;
+}
+.alert-dismissable,
+.alert-dismissible {
+ padding-right: 35px;
+}
+.alert-dismissable .close,
+.alert-dismissible .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ color: inherit;
+}
+.alert-success {
+ color: #3c763d;
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+}
+.alert-success hr {
+ border-top-color: #c9e2b3;
+}
+.alert-success .alert-link {
+ color: #2b542c;
+}
+.alert-info {
+ color: #31708f;
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+}
+.alert-info hr {
+ border-top-color: #a6e1ec;
+}
+.alert-info .alert-link {
+ color: #245269;
+}
+.alert-warning {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+ border-color: #faebcc;
+}
+.alert-warning hr {
+ border-top-color: #f7e1b5;
+}
+.alert-warning .alert-link {
+ color: #66512c;
+}
+.alert-danger {
+ color: #a94442;
+ background-color: #f2dede;
+ border-color: #ebccd1;
+}
+.alert-danger hr {
+ border-top-color: #e4b9c0;
+}
+.alert-danger .alert-link {
+ color: #843534;
+}
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@-o-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+.progress {
+ height: 20px;
+ margin-bottom: 20px;
+ overflow: hidden;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+}
+.progress-bar {
+ float: left;
+ width: 0;
+ height: 100%;
+ font-size: 12px;
+ line-height: 20px;
+ color: #fff;
+ text-align: center;
+ background-color: #337ab7;
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+ -webkit-transition: width .6s ease;
+ -o-transition: width .6s ease;
+ transition: width .6s ease;
+}
+.progress-striped .progress-bar,
+.progress-bar-striped {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ -webkit-background-size: 40px 40px;
+ background-size: 40px 40px;
+}
+.progress.active .progress-bar,
+.progress-bar.active {
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
+ -o-animation: progress-bar-stripes 2s linear infinite;
+ animation: progress-bar-stripes 2s linear infinite;
+}
+.progress-bar-success {
+ background-color: #5cb85c;
+}
+.progress-striped .progress-bar-success {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-info {
+ background-color: #5bc0de;
+}
+.progress-striped .progress-bar-info {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-warning {
+ background-color: #f0ad4e;
+}
+.progress-striped .progress-bar-warning {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-danger {
+ background-color: #d9534f;
+}
+.progress-striped .progress-bar-danger {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.media {
+ margin-top: 15px;
+}
+.media:first-child {
+ margin-top: 0;
+}
+.media,
+.media-body {
+ overflow: hidden;
+ zoom: 1;
+}
+.media-body {
+ width: 10000px;
+}
+.media-object {
+ display: block;
+}
+.media-object.img-thumbnail {
+ max-width: none;
+}
+.media-right,
+.media > .pull-right {
+ padding-left: 10px;
+}
+.media-left,
+.media > .pull-left {
+ padding-right: 10px;
+}
+.media-left,
+.media-right,
+.media-body {
+ display: table-cell;
+ vertical-align: top;
+}
+.media-middle {
+ vertical-align: middle;
+}
+.media-bottom {
+ vertical-align: bottom;
+}
+.media-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.media-list {
+ padding-left: 0;
+ list-style: none;
+}
+.list-group {
+ padding-left: 0;
+ margin-bottom: 20px;
+}
+.list-group-item {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+ margin-bottom: -1px;
+ background-color: #fff;
+ border: 1px solid #ddd;
+}
+.list-group-item:first-child {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+.list-group-item:last-child {
+ margin-bottom: 0;
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+a.list-group-item,
+button.list-group-item {
+ color: #555;
+}
+a.list-group-item .list-group-item-heading,
+button.list-group-item .list-group-item-heading {
+ color: #333;
+}
+a.list-group-item:hover,
+button.list-group-item:hover,
+a.list-group-item:focus,
+button.list-group-item:focus {
+ color: #555;
+ text-decoration: none;
+ background-color: #f5f5f5;
+}
+button.list-group-item {
+ width: 100%;
+ text-align: left;
+}
+.list-group-item.disabled,
+.list-group-item.disabled:hover,
+.list-group-item.disabled:focus {
+ color: #777;
+ cursor: not-allowed;
+ background-color: #eee;
+}
+.list-group-item.disabled .list-group-item-heading,
+.list-group-item.disabled:hover .list-group-item-heading,
+.list-group-item.disabled:focus .list-group-item-heading {
+ color: inherit;
+}
+.list-group-item.disabled .list-group-item-text,
+.list-group-item.disabled:hover .list-group-item-text,
+.list-group-item.disabled:focus .list-group-item-text {
+ color: #777;
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+ z-index: 2;
+ color: #fff;
+ background-color: #337ab7;
+ border-color: #337ab7;
+}
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small,
+.list-group-item.active:hover .list-group-item-heading > .small,
+.list-group-item.active:focus .list-group-item-heading > .small {
+ color: inherit;
+}
+.list-group-item.active .list-group-item-text,
+.list-group-item.active:hover .list-group-item-text,
+.list-group-item.active:focus .list-group-item-text {
+ color: #c7ddef;
+}
+.list-group-item-success {
+ color: #3c763d;
+ background-color: #dff0d8;
+}
+a.list-group-item-success,
+button.list-group-item-success {
+ color: #3c763d;
+}
+a.list-group-item-success .list-group-item-heading,
+button.list-group-item-success .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-success:hover,
+button.list-group-item-success:hover,
+a.list-group-item-success:focus,
+button.list-group-item-success:focus {
+ color: #3c763d;
+ background-color: #d0e9c6;
+}
+a.list-group-item-success.active,
+button.list-group-item-success.active,
+a.list-group-item-success.active:hover,
+button.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus,
+button.list-group-item-success.active:focus {
+ color: #fff;
+ background-color: #3c763d;
+ border-color: #3c763d;
+}
+.list-group-item-info {
+ color: #31708f;
+ background-color: #d9edf7;
+}
+a.list-group-item-info,
+button.list-group-item-info {
+ color: #31708f;
+}
+a.list-group-item-info .list-group-item-heading,
+button.list-group-item-info .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-info:hover,
+button.list-group-item-info:hover,
+a.list-group-item-info:focus,
+button.list-group-item-info:focus {
+ color: #31708f;
+ background-color: #c4e3f3;
+}
+a.list-group-item-info.active,
+button.list-group-item-info.active,
+a.list-group-item-info.active:hover,
+button.list-group-item-info.active:hover,
+a.list-group-item-info.active:focus,
+button.list-group-item-info.active:focus {
+ color: #fff;
+ background-color: #31708f;
+ border-color: #31708f;
+}
+.list-group-item-warning {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+}
+a.list-group-item-warning,
+button.list-group-item-warning {
+ color: #8a6d3b;
+}
+a.list-group-item-warning .list-group-item-heading,
+button.list-group-item-warning .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-warning:hover,
+button.list-group-item-warning:hover,
+a.list-group-item-warning:focus,
+button.list-group-item-warning:focus {
+ color: #8a6d3b;
+ background-color: #faf2cc;
+}
+a.list-group-item-warning.active,
+button.list-group-item-warning.active,
+a.list-group-item-warning.active:hover,
+button.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus,
+button.list-group-item-warning.active:focus {
+ color: #fff;
+ background-color: #8a6d3b;
+ border-color: #8a6d3b;
+}
+.list-group-item-danger {
+ color: #a94442;
+ background-color: #f2dede;
+}
+a.list-group-item-danger,
+button.list-group-item-danger {
+ color: #a94442;
+}
+a.list-group-item-danger .list-group-item-heading,
+button.list-group-item-danger .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-danger:hover,
+button.list-group-item-danger:hover,
+a.list-group-item-danger:focus,
+button.list-group-item-danger:focus {
+ color: #a94442;
+ background-color: #ebcccc;
+}
+a.list-group-item-danger.active,
+button.list-group-item-danger.active,
+a.list-group-item-danger.active:hover,
+button.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus,
+button.list-group-item-danger.active:focus {
+ color: #fff;
+ background-color: #a94442;
+ border-color: #a94442;
+}
+.list-group-item-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.list-group-item-text {
+ margin-bottom: 0;
+ line-height: 1.3;
+}
+.panel {
+ margin-bottom: 20px;
+ background-color: #fff;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+}
+.panel-body {
+ padding: 15px;
+}
+.panel-heading {
+ padding: 10px 15px;
+ border-bottom: 1px solid transparent;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel-heading > .dropdown .dropdown-toggle {
+ color: inherit;
+}
+.panel-title {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-size: 16px;
+ color: inherit;
+}
+.panel-title > a,
+.panel-title > small,
+.panel-title > .small,
+.panel-title > small > a,
+.panel-title > .small > a {
+ color: inherit;
+}
+.panel-footer {
+ padding: 10px 15px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #ddd;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .list-group,
+.panel > .panel-collapse > .list-group {
+ margin-bottom: 0;
+}
+.panel > .list-group .list-group-item,
+.panel > .panel-collapse > .list-group .list-group-item {
+ border-width: 1px 0;
+ border-radius: 0;
+}
+.panel > .list-group:first-child .list-group-item:first-child,
+.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {
+ border-top: 0;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel > .list-group:last-child .list-group-item:last-child,
+.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {
+ border-bottom: 0;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.panel-heading + .list-group .list-group-item:first-child {
+ border-top-width: 0;
+}
+.list-group + .panel-footer {
+ border-top-width: 0;
+}
+.panel > .table,
+.panel > .table-responsive > .table,
+.panel > .panel-collapse > .table {
+ margin-bottom: 0;
+}
+.panel > .table caption,
+.panel > .table-responsive > .table caption,
+.panel > .panel-collapse > .table caption {
+ padding-right: 15px;
+ padding-left: 15px;
+}
+.panel > .table:first-child,
+.panel > .table-responsive:first-child > .table:first-child {
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
+ border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
+ border-top-right-radius: 3px;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
+ border-bottom-right-radius: 3px;
+}
+.panel > .panel-body + .table,
+.panel > .panel-body + .table-responsive,
+.panel > .table + .panel-body,
+.panel > .table-responsive + .panel-body {
+ border-top: 1px solid #ddd;
+}
+.panel > .table > tbody:first-child > tr:first-child th,
+.panel > .table > tbody:first-child > tr:first-child td {
+ border-top: 0;
+}
+.panel > .table-bordered,
+.panel > .table-responsive > .table-bordered {
+ border: 0;
+}
+.panel > .table-bordered > thead > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
+.panel > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-bordered > thead > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
+.panel > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-bordered > tfoot > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+}
+.panel > .table-bordered > thead > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
+.panel > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-bordered > thead > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
+.panel > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-bordered > tfoot > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+}
+.panel > .table-bordered > thead > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
+.panel > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-bordered > thead > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
+.panel > .table-bordered > tbody > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
+ border-bottom: 0;
+}
+.panel > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-bordered > tfoot > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
+ border-bottom: 0;
+}
+.panel > .table-responsive {
+ margin-bottom: 0;
+ border: 0;
+}
+.panel-group {
+ margin-bottom: 20px;
+}
+.panel-group .panel {
+ margin-bottom: 0;
+ border-radius: 4px;
+}
+.panel-group .panel + .panel {
+ margin-top: 5px;
+}
+.panel-group .panel-heading {
+ border-bottom: 0;
+}
+.panel-group .panel-heading + .panel-collapse > .panel-body,
+.panel-group .panel-heading + .panel-collapse > .list-group {
+ border-top: 1px solid #ddd;
+}
+.panel-group .panel-footer {
+ border-top: 0;
+}
+.panel-group .panel-footer + .panel-collapse .panel-body {
+ border-bottom: 1px solid #ddd;
+}
+.panel-default {
+ border-color: #ddd;
+}
+.panel-default > .panel-heading {
+ color: #333;
+ background-color: #f5f5f5;
+ border-color: #ddd;
+}
+.panel-default > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #ddd;
+}
+.panel-default > .panel-heading .badge {
+ color: #f5f5f5;
+ background-color: #333;
+}
+.panel-default > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #ddd;
+}
+.panel-primary {
+ border-color: #337ab7;
+}
+.panel-primary > .panel-heading {
+ color: #fff;
+ background-color: #337ab7;
+ border-color: #337ab7;
+}
+.panel-primary > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #337ab7;
+}
+.panel-primary > .panel-heading .badge {
+ color: #337ab7;
+ background-color: #fff;
+}
+.panel-primary > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #337ab7;
+}
+.panel-success {
+ border-color: #d6e9c6;
+}
+.panel-success > .panel-heading {
+ color: #3c763d;
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+}
+.panel-success > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #d6e9c6;
+}
+.panel-success > .panel-heading .badge {
+ color: #dff0d8;
+ background-color: #3c763d;
+}
+.panel-success > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #d6e9c6;
+}
+.panel-info {
+ border-color: #bce8f1;
+}
+.panel-info > .panel-heading {
+ color: #31708f;
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+}
+.panel-info > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #bce8f1;
+}
+.panel-info > .panel-heading .badge {
+ color: #d9edf7;
+ background-color: #31708f;
+}
+.panel-info > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #bce8f1;
+}
+.panel-warning {
+ border-color: #faebcc;
+}
+.panel-warning > .panel-heading {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+ border-color: #faebcc;
+}
+.panel-warning > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #faebcc;
+}
+.panel-warning > .panel-heading .badge {
+ color: #fcf8e3;
+ background-color: #8a6d3b;
+}
+.panel-warning > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #faebcc;
+}
+.panel-danger {
+ border-color: #ebccd1;
+}
+.panel-danger > .panel-heading {
+ color: #a94442;
+ background-color: #f2dede;
+ border-color: #ebccd1;
+}
+.panel-danger > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #ebccd1;
+}
+.panel-danger > .panel-heading .badge {
+ color: #f2dede;
+ background-color: #a94442;
+}
+.panel-danger > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #ebccd1;
+}
+.embed-responsive {
+ position: relative;
+ display: block;
+ height: 0;
+ padding: 0;
+ overflow: hidden;
+}
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: 0;
+}
+.embed-responsive-16by9 {
+ padding-bottom: 56.25%;
+}
+.embed-responsive-4by3 {
+ padding-bottom: 75%;
+}
+.well {
+ min-height: 20px;
+ padding: 19px;
+ margin-bottom: 20px;
+ background-color: #f5f5f5;
+ border: 1px solid #e3e3e3;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+}
+.well blockquote {
+ border-color: #ddd;
+ border-color: rgba(0, 0, 0, .15);
+}
+.well-lg {
+ padding: 24px;
+ border-radius: 6px;
+}
+.well-sm {
+ padding: 9px;
+ border-radius: 3px;
+}
+.close {
+ float: right;
+ font-size: 21px;
+ font-weight: bold;
+ line-height: 1;
+ color: #000;
+ text-shadow: 0 1px 0 #fff;
+ filter: alpha(opacity=20);
+ opacity: .2;
+}
+.close:hover,
+.close:focus {
+ color: #000;
+ text-decoration: none;
+ cursor: pointer;
+ filter: alpha(opacity=50);
+ opacity: .5;
+}
+button.close {
+ -webkit-appearance: none;
+ padding: 0;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+}
+.modal-open {
+ overflow: hidden;
+}
+.modal {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1050;
+ display: none;
+ overflow: hidden;
+ -webkit-overflow-scrolling: touch;
+ outline: 0;
+}
+.modal.fade .modal-dialog {
+ -webkit-transition: -webkit-transform .3s ease-out;
+ -o-transition: -o-transform .3s ease-out;
+ transition: transform .3s ease-out;
+ -webkit-transform: translate(0, -25%);
+ -ms-transform: translate(0, -25%);
+ -o-transform: translate(0, -25%);
+ transform: translate(0, -25%);
+}
+.modal.in .modal-dialog {
+ -webkit-transform: translate(0, 0);
+ -ms-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ transform: translate(0, 0);
+}
+.modal-open .modal {
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 10px;
+}
+.modal-content {
+ position: relative;
+ background-color: #fff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #999;
+ border: 1px solid rgba(0, 0, 0, .2);
+ border-radius: 6px;
+ outline: 0;
+ -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+ box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+}
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1040;
+ background-color: #000;
+}
+.modal-backdrop.fade {
+ filter: alpha(opacity=0);
+ opacity: 0;
+}
+.modal-backdrop.in {
+ filter: alpha(opacity=50);
+ opacity: .5;
+}
+.modal-header {
+ min-height: 16.42857143px;
+ padding: 15px;
+ border-bottom: 1px solid #e5e5e5;
+}
+.modal-header .close {
+ margin-top: -2px;
+}
+.modal-title {
+ margin: 0;
+ line-height: 1.42857143;
+}
+.modal-body {
+ position: relative;
+ padding: 15px;
+}
+.modal-footer {
+ padding: 15px;
+ text-align: right;
+ border-top: 1px solid #e5e5e5;
+}
+.modal-footer .btn + .btn {
+ margin-bottom: 0;
+ margin-left: 5px;
+}
+.modal-footer .btn-group .btn + .btn {
+ margin-left: -1px;
+}
+.modal-footer .btn-block + .btn-block {
+ margin-left: 0;
+}
+.modal-scrollbar-measure {
+ position: absolute;
+ top: -9999px;
+ width: 50px;
+ height: 50px;
+ overflow: scroll;
+}
+@media (min-width: 768px) {
+ .modal-dialog {
+ width: 600px;
+ margin: 30px auto;
+ }
+ .modal-content {
+ -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+ box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+ }
+ .modal-sm {
+ width: 300px;
+ }
+}
+@media (min-width: 992px) {
+ .modal-lg {
+ width: 900px;
+ }
+}
+.tooltip {
+ position: absolute;
+ z-index: 1070;
+ display: block;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1.42857143;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ letter-spacing: normal;
+ word-break: normal;
+ word-spacing: normal;
+ word-wrap: normal;
+ white-space: normal;
+ filter: alpha(opacity=0);
+ opacity: 0;
+
+ line-break: auto;
+}
+.tooltip.in {
+ filter: alpha(opacity=90);
+ opacity: .9;
+}
+.tooltip.top {
+ padding: 5px 0;
+ margin-top: -3px;
+}
+.tooltip.right {
+ padding: 0 5px;
+ margin-left: 3px;
+}
+.tooltip.bottom {
+ padding: 5px 0;
+ margin-top: 3px;
+}
+.tooltip.left {
+ padding: 0 5px;
+ margin-left: -3px;
+}
+.tooltip-inner {
+ max-width: 200px;
+ padding: 3px 8px;
+ color: #fff;
+ text-align: center;
+ background-color: #000;
+ border-radius: 4px;
+}
+.tooltip-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+.tooltip.top .tooltip-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000;
+}
+.tooltip.top-left .tooltip-arrow {
+ right: 5px;
+ bottom: 0;
+ margin-bottom: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000;
+}
+.tooltip.top-right .tooltip-arrow {
+ bottom: 0;
+ left: 5px;
+ margin-bottom: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000;
+}
+.tooltip.right .tooltip-arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ border-width: 5px 5px 5px 0;
+ border-right-color: #000;
+}
+.tooltip.left .tooltip-arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ border-width: 5px 0 5px 5px;
+ border-left-color: #000;
+}
+.tooltip.bottom .tooltip-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000;
+}
+.tooltip.bottom-left .tooltip-arrow {
+ top: 0;
+ right: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000;
+}
+.tooltip.bottom-right .tooltip-arrow {
+ top: 0;
+ left: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000;
+}
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1060;
+ display: none;
+ max-width: 276px;
+ padding: 1px;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1.42857143;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ letter-spacing: normal;
+ word-break: normal;
+ word-spacing: normal;
+ word-wrap: normal;
+ white-space: normal;
+ background-color: #fff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, .2);
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+
+ line-break: auto;
+}
+.popover.top {
+ margin-top: -10px;
+}
+.popover.right {
+ margin-left: 10px;
+}
+.popover.bottom {
+ margin-top: 10px;
+}
+.popover.left {
+ margin-left: -10px;
+}
+.popover-title {
+ padding: 8px 14px;
+ margin: 0;
+ font-size: 14px;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ border-radius: 5px 5px 0 0;
+}
+.popover-content {
+ padding: 9px 14px;
+}
+.popover > .arrow,
+.popover > .arrow:after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+.popover > .arrow {
+ border-width: 11px;
+}
+.popover > .arrow:after {
+ content: "";
+ border-width: 10px;
+}
+.popover.top > .arrow {
+ bottom: -11px;
+ left: 50%;
+ margin-left: -11px;
+ border-top-color: #999;
+ border-top-color: rgba(0, 0, 0, .25);
+ border-bottom-width: 0;
+}
+.popover.top > .arrow:after {
+ bottom: 1px;
+ margin-left: -10px;
+ content: " ";
+ border-top-color: #fff;
+ border-bottom-width: 0;
+}
+.popover.right > .arrow {
+ top: 50%;
+ left: -11px;
+ margin-top: -11px;
+ border-right-color: #999;
+ border-right-color: rgba(0, 0, 0, .25);
+ border-left-width: 0;
+}
+.popover.right > .arrow:after {
+ bottom: -10px;
+ left: 1px;
+ content: " ";
+ border-right-color: #fff;
+ border-left-width: 0;
+}
+.popover.bottom > .arrow {
+ top: -11px;
+ left: 50%;
+ margin-left: -11px;
+ border-top-width: 0;
+ border-bottom-color: #999;
+ border-bottom-color: rgba(0, 0, 0, .25);
+}
+.popover.bottom > .arrow:after {
+ top: 1px;
+ margin-left: -10px;
+ content: " ";
+ border-top-width: 0;
+ border-bottom-color: #fff;
+}
+.popover.left > .arrow {
+ top: 50%;
+ right: -11px;
+ margin-top: -11px;
+ border-right-width: 0;
+ border-left-color: #999;
+ border-left-color: rgba(0, 0, 0, .25);
+}
+.popover.left > .arrow:after {
+ right: 1px;
+ bottom: -10px;
+ content: " ";
+ border-right-width: 0;
+ border-left-color: #fff;
+}
+.carousel {
+ position: relative;
+}
+.carousel-inner {
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+}
+.carousel-inner > .item {
+ position: relative;
+ display: none;
+ -webkit-transition: .6s ease-in-out left;
+ -o-transition: .6s ease-in-out left;
+ transition: .6s ease-in-out left;
+}
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ line-height: 1;
+}
+@media all and (transform-3d), (-webkit-transform-3d) {
+ .carousel-inner > .item {
+ -webkit-transition: -webkit-transform .6s ease-in-out;
+ -o-transition: -o-transform .6s ease-in-out;
+ transition: transform .6s ease-in-out;
+
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-perspective: 1000px;
+ perspective: 1000px;
+ }
+ .carousel-inner > .item.next,
+ .carousel-inner > .item.active.right {
+ left: 0;
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ }
+ .carousel-inner > .item.prev,
+ .carousel-inner > .item.active.left {
+ left: 0;
+ -webkit-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0);
+ }
+ .carousel-inner > .item.next.left,
+ .carousel-inner > .item.prev.right,
+ .carousel-inner > .item.active {
+ left: 0;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ }
+}
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ display: block;
+}
+.carousel-inner > .active {
+ left: 0;
+}
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+.carousel-inner > .next {
+ left: 100%;
+}
+.carousel-inner > .prev {
+ left: -100%;
+}
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+ left: 0;
+}
+.carousel-inner > .active.left {
+ left: -100%;
+}
+.carousel-inner > .active.right {
+ left: 100%;
+}
+.carousel-control {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 15%;
+ font-size: 20px;
+ color: #fff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+ filter: alpha(opacity=50);
+ opacity: .5;
+}
+.carousel-control.left {
+ background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+ background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+ background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001)));
+ background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+ background-repeat: repeat-x;
+}
+.carousel-control.right {
+ right: 0;
+ left: auto;
+ background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+ background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+ background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5)));
+ background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+ background-repeat: repeat-x;
+}
+.carousel-control:hover,
+.carousel-control:focus {
+ color: #fff;
+ text-decoration: none;
+ filter: alpha(opacity=90);
+ outline: 0;
+ opacity: .9;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-left,
+.carousel-control .glyphicon-chevron-right {
+ position: absolute;
+ top: 50%;
+ z-index: 5;
+ display: inline-block;
+ margin-top: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .glyphicon-chevron-left {
+ left: 50%;
+ margin-left: -10px;
+}
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-right {
+ right: 50%;
+ margin-right: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+ width: 20px;
+ height: 20px;
+ font-family: serif;
+ line-height: 1;
+}
+.carousel-control .icon-prev:before {
+ content: '\2039';
+}
+.carousel-control .icon-next:before {
+ content: '\203a';
+}
+.carousel-indicators {
+ position: absolute;
+ bottom: 10px;
+ left: 50%;
+ z-index: 15;
+ width: 60%;
+ padding-left: 0;
+ margin-left: -30%;
+ text-align: center;
+ list-style: none;
+}
+.carousel-indicators li {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ margin: 1px;
+ text-indent: -999px;
+ cursor: pointer;
+ background-color: #000 \9;
+ background-color: rgba(0, 0, 0, 0);
+ border: 1px solid #fff;
+ border-radius: 10px;
+}
+.carousel-indicators .active {
+ width: 12px;
+ height: 12px;
+ margin: 0;
+ background-color: #fff;
+}
+.carousel-caption {
+ position: absolute;
+ right: 15%;
+ bottom: 20px;
+ left: 15%;
+ z-index: 10;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ color: #fff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+}
+.carousel-caption .btn {
+ text-shadow: none;
+}
+@media screen and (min-width: 768px) {
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-prev,
+ .carousel-control .icon-next {
+ width: 30px;
+ height: 30px;
+ margin-top: -15px;
+ font-size: 30px;
+ }
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .icon-prev {
+ margin-left: -15px;
+ }
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-next {
+ margin-right: -15px;
+ }
+ .carousel-caption {
+ right: 20%;
+ left: 20%;
+ padding-bottom: 30px;
+ }
+ .carousel-indicators {
+ bottom: 20px;
+ }
+}
+.clearfix:before,
+.clearfix:after,
+.dl-horizontal dd:before,
+.dl-horizontal dd:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after,
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after,
+.btn-toolbar:before,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:before,
+.btn-group-vertical > .btn-group:after,
+.nav:before,
+.nav:after,
+.navbar:before,
+.navbar:after,
+.navbar-header:before,
+.navbar-header:after,
+.navbar-collapse:before,
+.navbar-collapse:after,
+.pager:before,
+.pager:after,
+.panel-body:before,
+.panel-body:after,
+.modal-footer:before,
+.modal-footer:after {
+ display: table;
+ content: " ";
+}
+.clearfix:after,
+.dl-horizontal dd:after,
+.container:after,
+.container-fluid:after,
+.row:after,
+.form-horizontal .form-group:after,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:after,
+.nav:after,
+.navbar:after,
+.navbar-header:after,
+.navbar-collapse:after,
+.pager:after,
+.panel-body:after,
+.modal-footer:after {
+ clear: both;
+}
+.center-block {
+ display: block;
+ margin-right: auto;
+ margin-left: auto;
+}
+.pull-right {
+ float: right !important;
+}
+.pull-left {
+ float: left !important;
+}
+.hide {
+ display: none !important;
+}
+.show {
+ display: block !important;
+}
+.invisible {
+ visibility: hidden;
+}
+.text-hide {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+.hidden {
+ display: none !important;
+}
+.affix {
+ position: fixed;
+}
+@-ms-viewport {
+ width: device-width;
+}
+.visible-xs,
+.visible-sm,
+.visible-md,
+.visible-lg {
+ display: none !important;
+}
+.visible-xs-block,
+.visible-xs-inline,
+.visible-xs-inline-block,
+.visible-sm-block,
+.visible-sm-inline,
+.visible-sm-inline-block,
+.visible-md-block,
+.visible-md-inline,
+.visible-md-inline-block,
+.visible-lg-block,
+.visible-lg-inline,
+.visible-lg-inline-block {
+ display: none !important;
+}
+@media (max-width: 767px) {
+ .visible-xs {
+ display: block !important;
+ }
+ table.visible-xs {
+ display: table !important;
+ }
+ tr.visible-xs {
+ display: table-row !important;
+ }
+ th.visible-xs,
+ td.visible-xs {
+ display: table-cell !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-block {
+ display: block !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline {
+ display: inline !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm {
+ display: block !important;
+ }
+ table.visible-sm {
+ display: table !important;
+ }
+ tr.visible-sm {
+ display: table-row !important;
+ }
+ th.visible-sm,
+ td.visible-sm {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-block {
+ display: block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md {
+ display: block !important;
+ }
+ table.visible-md {
+ display: table !important;
+ }
+ tr.visible-md {
+ display: table-row !important;
+ }
+ th.visible-md,
+ td.visible-md {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-block {
+ display: block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg {
+ display: block !important;
+ }
+ table.visible-lg {
+ display: table !important;
+ }
+ tr.visible-lg {
+ display: table-row !important;
+ }
+ th.visible-lg,
+ td.visible-lg {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-block {
+ display: block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (max-width: 767px) {
+ .hidden-xs {
+ display: none !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .hidden-sm {
+ display: none !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .hidden-md {
+ display: none !important;
+ }
+}
+@media (min-width: 1200px) {
+ .hidden-lg {
+ display: none !important;
+ }
+}
+.visible-print {
+ display: none !important;
+}
+@media print {
+ .visible-print {
+ display: block !important;
+ }
+ table.visible-print {
+ display: table !important;
+ }
+ tr.visible-print {
+ display: table-row !important;
+ }
+ th.visible-print,
+ td.visible-print {
+ display: table-cell !important;
+ }
+}
+.visible-print-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-block {
+ display: block !important;
+ }
+}
+.visible-print-inline {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline {
+ display: inline !important;
+ }
+}
+.visible-print-inline-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline-block {
+ display: inline-block !important;
+ }
+}
+@media print {
+ .hidden-print {
+ display: none !important;
+ }
+}
+/*# sourceMappingURL=bootstrap.css.map */
--- /dev/null
+{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4EAA4E;ACG5E;EACE,wBAAA;EACA,2BAAA;EACA,+BAAA;CDDD;ACQD;EACE,UAAA;CDND;ACmBD;;;;;;;;;;;;;EAaE,eAAA;CDjBD;ACyBD;;;;EAIE,sBAAA;EACA,yBAAA;CDvBD;AC+BD;EACE,cAAA;EACA,UAAA;CD7BD;ACqCD;;EAEE,cAAA;CDnCD;AC6CD;EACE,8BAAA;CD3CD;ACmDD;;EAEE,WAAA;CDjDD;AC2DD;EACE,0BAAA;CDzDD;ACgED;;EAEE,kBAAA;CD9DD;ACqED;EACE,mBAAA;CDnED;AC2ED;EACE,eAAA;EACA,iBAAA;CDzED;ACgFD;EACE,iBAAA;EACA,YAAA;CD9ED;ACqFD;EACE,eAAA;CDnFD;AC0FD;;EAEE,eAAA;EACA,eAAA;EACA,mBAAA;EACA,yBAAA;CDxFD;AC2FD;EACE,YAAA;CDzFD;AC4FD;EACE,gBAAA;CD1FD;ACoGD;EACE,UAAA;CDlGD;ACyGD;EACE,iBAAA;CDvGD;ACiHD;EACE,iBAAA;CD/GD;ACsHD;EACE,gCAAA;KAAA,6BAAA;UAAA,wBAAA;EACA,UAAA;CDpHD;AC2HD;EACE,eAAA;CDzHD;ACgID;;;;EAIE,kCAAA;EACA,eAAA;CD9HD;ACgJD;;;;;EAKE,eAAA;EACA,cAAA;EACA,UAAA;CD9ID;ACqJD;EACE,kBAAA;CDnJD;AC6JD;;EAEE,qBAAA;CD3JD;ACsKD;;;;EAIE,2BAAA;EACA,gBAAA;CDpKD;AC2KD;;EAEE,gBAAA;CDzKD;ACgLD;;EAEE,UAAA;EACA,WAAA;CD9KD;ACsLD;EACE,oBAAA;CDpLD;AC+LD;;EAEE,+BAAA;KAAA,4BAAA;UAAA,uBAAA;EACA,WAAA;CD7LD;ACsMD;;EAEE,aAAA;CDpMD;AC4MD;EACE,8BAAA;EACA,gCAAA;KAAA,6BAAA;UAAA,wBAAA;CD1MD;ACmND;;EAEE,yBAAA;CDjND;ACwND;EACE,0BAAA;EACA,cAAA;EACA,+BAAA;CDtND;AC8ND;EACE,UAAA;EACA,WAAA;CD5ND;ACmOD;EACE,eAAA;CDjOD;ACyOD;EACE,kBAAA;CDvOD;ACiPD;EACE,0BAAA;EACA,kBAAA;CD/OD;ACkPD;;EAEE,WAAA;CDhPD;AACD,qFAAqF;AElFrF;EA7FI;;;IAGI,mCAAA;IACA,uBAAA;IACA,oCAAA;YAAA,4BAAA;IACA,6BAAA;GFkLL;EE/KC;;IAEI,2BAAA;GFiLL;EE9KC;IACI,6BAAA;GFgLL;EE7KC;IACI,8BAAA;GF+KL;EE1KC;;IAEI,YAAA;GF4KL;EEzKC;;IAEI,uBAAA;IACA,yBAAA;GF2KL;EExKC;IACI,4BAAA;GF0KL;EEvKC;;IAEI,yBAAA;GFyKL;EEtKC;IACI,2BAAA;GFwKL;EErKC;;;IAGI,WAAA;IACA,UAAA;GFuKL;EEpKC;;IAEI,wBAAA;GFsKL;EEhKC;IACI,cAAA;GFkKL;EEhKC;;IAGQ,kCAAA;GFiKT;EE9JC;IACI,uBAAA;GFgKL;EE7JC;IACI,qCAAA;GF+JL;EEhKC;;IAKQ,kCAAA;GF+JT;EE5JC;;IAGQ,kCAAA;GF6JT;CACF;AGnPD;EACE,oCAAA;EACA,sDAAA;EACA,gYAAA;CHqPD;AG7OD;EACE,mBAAA;EACA,SAAA;EACA,sBAAA;EACA,oCAAA;EACA,mBAAA;EACA,oBAAA;EACA,eAAA;EACA,oCAAA;EACA,mCAAA;CH+OD;AG3OmC;EAAW,eAAA;CH8O9C;AG7OmC;EAAW,eAAA;CHgP9C;AG9OmC;;EAAW,iBAAA;CHkP9C;AGjPmC;EAAW,iBAAA;CHoP9C;AGnPmC;EAAW,iBAAA;CHsP9C;AGrPmC;EAAW,iBAAA;CHwP9C;AGvPmC;EAAW,iBAAA;CH0P9C;AGzPmC;EAAW,iBAAA;CH4P9C;AG3PmC;EAAW,iBAAA;CH8P9C;AG7PmC;EAAW,iBAAA;CHgQ9C;AG/PmC;EAAW,iBAAA;CHkQ9C;AGjQmC;EAAW,iBAAA;CHoQ9C;AGnQmC;EAAW,iBAAA;CHsQ9C;AGrQmC;EAAW,iBAAA;CHwQ9C;AGvQmC;EAAW,iBAAA;CH0Q9C;AGzQmC;EAAW,iBAAA;CH4Q9C;AG3QmC;EAAW,iBAAA;CH8Q9C;AG7QmC;EAAW,iBAAA;CHgR9C;AG/QmC;EAAW,iBAAA;CHkR9C;AGjRmC;EAAW,iBAAA;CHoR9C;AGnRmC;EAAW,iBAAA;CHsR9C;AGrRmC;EAAW,iBAAA;CHwR9C;AGvRmC;EAAW,iBAAA;CH0R9C;AGzRmC;EAAW,iBAAA;CH4R9C;AG3RmC;EAAW,iBAAA;CH8R9C;AG7RmC;EAAW,iBAAA;CHgS9C;AG/RmC;EAAW,iBAAA;CHkS9C;AGjSmC;EAAW,iBAAA;CHoS9C;AGnSmC;EAAW,iBAAA;CHsS9C;AGrSmC;EAAW,iBAAA;CHwS9C;AGvSmC;EAAW,iBAAA;CH0S9C;AGzSmC;EAAW,iBAAA;CH4S9C;AG3SmC;EAAW,iBAAA;CH8S9C;AG7SmC;EAAW,iBAAA;CHgT9C;AG/SmC;EAAW,iBAAA;CHkT9C;AGjTmC;EAAW,iBAAA;CHoT9C;AGnTmC;EAAW,iBAAA;CHsT9C;AGrTmC;EAAW,iBAAA;CHwT9C;AGvTmC;EAAW,iBAAA;CH0T9C;AGzTmC;EAAW,iBAAA;CH4T9C;AG3TmC;EAAW,iBAAA;CH8T9C;AG7TmC;EAAW,iBAAA;CHgU9C;AG/TmC;EAAW,iBAAA;CHkU9C;AGjUmC;EAAW,iBAAA;CHoU9C;AGnUmC;EAAW,iBAAA;CHsU9C;AGrUmC;EAAW,iBAAA;CHwU9C;AGvUmC;EAAW,iBAAA;CH0U9C;AGzUmC;EAAW,iBAAA;CH4U9C;AG3UmC;EAAW,iBAAA;CH8U9C;AG7UmC;EAAW,iBAAA;CHgV9C;AG/UmC;EAAW,iBAAA;CHkV9C;AGjVmC;EAAW,iBAAA;CHoV9C;AGnVmC;EAAW,iBAAA;CHsV9C;AGrVmC;EAAW,iBAAA;CHwV9C;AGvVmC;EAAW,iBAAA;CH0V9C;AGzVmC;EAAW,iBAAA;CH4V9C;AG3VmC;EAAW,iBAAA;CH8V9C;AG7VmC;EAAW,iBAAA;CHgW9C;AG/VmC;EAAW,iBAAA;CHkW9C;AGjWmC;EAAW,iBAAA;CHoW9C;AGnWmC;EAAW,iBAAA;CHsW9C;AGrWmC;EAAW,iBAAA;CHwW9C;AGvWmC;EAAW,iBAAA;CH0W9C;AGzWmC;EAAW,iBAAA;CH4W9C;AG3WmC;EAAW,iBAAA;CH8W9C;AG7WmC;EAAW,iBAAA;CHgX9C;AG/WmC;EAAW,iBAAA;CHkX9C;AGjXmC;EAAW,iBAAA;CHoX9C;AGnXmC;EAAW,iBAAA;CHsX9C;AGrXmC;EAAW,iBAAA;CHwX9C;AGvXmC;EAAW,iBAAA;CH0X9C;AGzXmC;EAAW,iBAAA;CH4X9C;AG3XmC;EAAW,iBAAA;CH8X9C;AG7XmC;EAAW,iBAAA;CHgY9C;AG/XmC;EAAW,iBAAA;CHkY9C;AGjYmC;EAAW,iBAAA;CHoY9C;AGnYmC;EAAW,iBAAA;CHsY9C;AGrYmC;EAAW,iBAAA;CHwY9C;AGvYmC;EAAW,iBAAA;CH0Y9C;AGzYmC;EAAW,iBAAA;CH4Y9C;AG3YmC;EAAW,iBAAA;CH8Y9C;AG7YmC;EAAW,iBAAA;CHgZ9C;AG/YmC;EAAW,iBAAA;CHkZ9C;AGjZmC;EAAW,iBAAA;CHoZ9C;AGnZmC;EAAW,iBAAA;CHsZ9C;AGrZmC;EAAW,iBAAA;CHwZ9C;AGvZmC;EAAW,iBAAA;CH0Z9C;AGzZmC;EAAW,iBAAA;CH4Z9C;AG3ZmC;EAAW,iBAAA;CH8Z9C;AG7ZmC;EAAW,iBAAA;CHga9C;AG/ZmC;EAAW,iBAAA;CHka9C;AGjamC;EAAW,iBAAA;CHoa9C;AGnamC;EAAW,iBAAA;CHsa9C;AGramC;EAAW,iBAAA;CHwa9C;AGvamC;EAAW,iBAAA;CH0a9C;AGzamC;EAAW,iBAAA;CH4a9C;AG3amC;EAAW,iBAAA;CH8a9C;AG7amC;EAAW,iBAAA;CHgb9C;AG/amC;EAAW,iBAAA;CHkb9C;AGjbmC;EAAW,iBAAA;CHob9C;AGnbmC;EAAW,iBAAA;CHsb9C;AGrbmC;EAAW,iBAAA;CHwb9C;AGvbmC;EAAW,iBAAA;CH0b9C;AGzbmC;EAAW,iBAAA;CH4b9C;AG3bmC;EAAW,iBAAA;CH8b9C;AG7bmC;EAAW,iBAAA;CHgc9C;AG/bmC;EAAW,iBAAA;CHkc9C;AGjcmC;EAAW,iBAAA;CHoc9C;AGncmC;EAAW,iBAAA;CHsc9C;AGrcmC;EAAW,iBAAA;CHwc9C;AGvcmC;EAAW,iBAAA;CH0c9C;AGzcmC;EAAW,iBAAA;CH4c9C;AG3cmC;EAAW,iBAAA;CH8c9C;AG7cmC;EAAW,iBAAA;CHgd9C;AG/cmC;EAAW,iBAAA;CHkd9C;AGjdmC;EAAW,iBAAA;CHod9C;AGndmC;EAAW,iBAAA;CHsd9C;AGrdmC;EAAW,iBAAA;CHwd9C;AGvdmC;EAAW,iBAAA;CH0d9C;AGzdmC;EAAW,iBAAA;CH4d9C;AG3dmC;EAAW,iBAAA;CH8d9C;AG7dmC;EAAW,iBAAA;CHge9C;AG/dmC;EAAW,iBAAA;CHke9C;AGjemC;EAAW,iBAAA;CHoe9C;AGnemC;EAAW,iBAAA;CHse9C;AGremC;EAAW,iBAAA;CHwe9C;AGvemC;EAAW,iBAAA;CH0e9C;AGzemC;EAAW,iBAAA;CH4e9C;AG3emC;EAAW,iBAAA;CH8e9C;AG7emC;EAAW,iBAAA;CHgf9C;AG/emC;EAAW,iBAAA;CHkf9C;AGjfmC;EAAW,iBAAA;CHof9C;AGnfmC;EAAW,iBAAA;CHsf9C;AGrfmC;EAAW,iBAAA;CHwf9C;AGvfmC;EAAW,iBAAA;CH0f9C;AGzfmC;EAAW,iBAAA;CH4f9C;AG3fmC;EAAW,iBAAA;CH8f9C;AG7fmC;EAAW,iBAAA;CHggB9C;AG/fmC;EAAW,iBAAA;CHkgB9C;AGjgBmC;EAAW,iBAAA;CHogB9C;AGngBmC;EAAW,iBAAA;CHsgB9C;AGrgBmC;EAAW,iBAAA;CHwgB9C;AGvgBmC;EAAW,iBAAA;CH0gB9C;AGzgBmC;EAAW,iBAAA;CH4gB9C;AG3gBmC;EAAW,iBAAA;CH8gB9C;AG7gBmC;EAAW,iBAAA;CHghB9C;AG/gBmC;EAAW,iBAAA;CHkhB9C;AGjhBmC;EAAW,iBAAA;CHohB9C;AGnhBmC;EAAW,iBAAA;CHshB9C;AGrhBmC;EAAW,iBAAA;CHwhB9C;AGvhBmC;EAAW,iBAAA;CH0hB9C;AGzhBmC;EAAW,iBAAA;CH4hB9C;AG3hBmC;EAAW,iBAAA;CH8hB9C;AG7hBmC;EAAW,iBAAA;CHgiB9C;AG/hBmC;EAAW,iBAAA;CHkiB9C;AGjiBmC;EAAW,iBAAA;CHoiB9C;AGniBmC;EAAW,iBAAA;CHsiB9C;AGriBmC;EAAW,iBAAA;CHwiB9C;AGviBmC;EAAW,iBAAA;CH0iB9C;AGziBmC;EAAW,iBAAA;CH4iB9C;AG3iBmC;EAAW,iBAAA;CH8iB9C;AG7iBmC;EAAW,iBAAA;CHgjB9C;AG/iBmC;EAAW,iBAAA;CHkjB9C;AGjjBmC;EAAW,iBAAA;CHojB9C;AGnjBmC;EAAW,iBAAA;CHsjB9C;AGrjBmC;EAAW,iBAAA;CHwjB9C;AGvjBmC;EAAW,iBAAA;CH0jB9C;AGzjBmC;EAAW,iBAAA;CH4jB9C;AG3jBmC;EAAW,iBAAA;CH8jB9C;AG7jBmC;EAAW,iBAAA;CHgkB9C;AG/jBmC;EAAW,iBAAA;CHkkB9C;AGjkBmC;EAAW,iBAAA;CHokB9C;AGnkBmC;EAAW,iBAAA;CHskB9C;AGrkBmC;EAAW,iBAAA;CHwkB9C;AGvkBmC;EAAW,iBAAA;CH0kB9C;AGzkBmC;EAAW,iBAAA;CH4kB9C;AG3kBmC;EAAW,iBAAA;CH8kB9C;AG7kBmC;EAAW,iBAAA;CHglB9C;AG/kBmC;EAAW,iBAAA;CHklB9C;AGjlBmC;EAAW,iBAAA;CHolB9C;AGnlBmC;EAAW,iBAAA;CHslB9C;AGrlBmC;EAAW,iBAAA;CHwlB9C;AGvlBmC;EAAW,iBAAA;CH0lB9C;AGzlBmC;EAAW,iBAAA;CH4lB9C;AG3lBmC;EAAW,iBAAA;CH8lB9C;AG7lBmC;EAAW,iBAAA;CHgmB9C;AG/lBmC;EAAW,iBAAA;CHkmB9C;AGjmBmC;EAAW,iBAAA;CHomB9C;AGnmBmC;EAAW,iBAAA;CHsmB9C;AGrmBmC;EAAW,iBAAA;CHwmB9C;AGvmBmC;EAAW,iBAAA;CH0mB9C;AGzmBmC;EAAW,iBAAA;CH4mB9C;AG3mBmC;EAAW,iBAAA;CH8mB9C;AG7mBmC;EAAW,iBAAA;CHgnB9C;AG/mBmC;EAAW,iBAAA;CHknB9C;AGjnBmC;EAAW,iBAAA;CHonB9C;AGnnBmC;EAAW,iBAAA;CHsnB9C;AGrnBmC;EAAW,iBAAA;CHwnB9C;AGvnBmC;EAAW,iBAAA;CH0nB9C;AGznBmC;EAAW,iBAAA;CH4nB9C;AG3nBmC;EAAW,iBAAA;CH8nB9C;AG7nBmC;EAAW,iBAAA;CHgoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AGvoBmC;EAAW,iBAAA;CH0oB9C;AGzoBmC;EAAW,iBAAA;CH4oB9C;AG3oBmC;EAAW,iBAAA;CH8oB9C;AG7oBmC;EAAW,iBAAA;CHgpB9C;AG/oBmC;EAAW,iBAAA;CHkpB9C;AGjpBmC;EAAW,iBAAA;CHopB9C;AGnpBmC;EAAW,iBAAA;CHspB9C;AGrpBmC;EAAW,iBAAA;CHwpB9C;AGvpBmC;EAAW,iBAAA;CH0pB9C;AGzpBmC;EAAW,iBAAA;CH4pB9C;AG3pBmC;EAAW,iBAAA;CH8pB9C;AG7pBmC;EAAW,iBAAA;CHgqB9C;AG/pBmC;EAAW,iBAAA;CHkqB9C;AGjqBmC;EAAW,iBAAA;CHoqB9C;AGnqBmC;EAAW,iBAAA;CHsqB9C;AGrqBmC;EAAW,iBAAA;CHwqB9C;AGvqBmC;EAAW,iBAAA;CH0qB9C;AGzqBmC;EAAW,iBAAA;CH4qB9C;AG3qBmC;EAAW,iBAAA;CH8qB9C;AG7qBmC;EAAW,iBAAA;CHgrB9C;AG/qBmC;EAAW,iBAAA;CHkrB9C;AGjrBmC;EAAW,iBAAA;CHorB9C;AGnrBmC;EAAW,iBAAA;CHsrB9C;AGrrBmC;EAAW,iBAAA;CHwrB9C;AGvrBmC;EAAW,iBAAA;CH0rB9C;AGzrBmC;EAAW,iBAAA;CH4rB9C;AG3rBmC;EAAW,iBAAA;CH8rB9C;AG7rBmC;EAAW,iBAAA;CHgsB9C;AG/rBmC;EAAW,iBAAA;CHksB9C;AGjsBmC;EAAW,iBAAA;CHosB9C;AGnsBmC;EAAW,iBAAA;CHssB9C;AGrsBmC;EAAW,iBAAA;CHwsB9C;AGvsBmC;EAAW,iBAAA;CH0sB9C;AGzsBmC;EAAW,iBAAA;CH4sB9C;AG3sBmC;EAAW,iBAAA;CH8sB9C;AG7sBmC;EAAW,iBAAA;CHgtB9C;AG/sBmC;EAAW,iBAAA;CHktB9C;AGjtBmC;EAAW,iBAAA;CHotB9C;AGntBmC;EAAW,iBAAA;CHstB9C;AGrtBmC;EAAW,iBAAA;CHwtB9C;AGvtBmC;EAAW,iBAAA;CH0tB9C;AGztBmC;EAAW,iBAAA;CH4tB9C;AG3tBmC;EAAW,iBAAA;CH8tB9C;AG7tBmC;EAAW,iBAAA;CHguB9C;AG/tBmC;EAAW,iBAAA;CHkuB9C;AGjuBmC;EAAW,iBAAA;CHouB9C;AGnuBmC;EAAW,iBAAA;CHsuB9C;AGruBmC;EAAW,iBAAA;CHwuB9C;AGvuBmC;EAAW,iBAAA;CH0uB9C;AGzuBmC;EAAW,iBAAA;CH4uB9C;AG3uBmC;EAAW,iBAAA;CH8uB9C;AG7uBmC;EAAW,iBAAA;CHgvB9C;AIthCD;ECgEE,+BAAA;EACG,4BAAA;EACK,uBAAA;CLy9BT;AIxhCD;;EC6DE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL+9BT;AIthCD;EACE,gBAAA;EACA,8CAAA;CJwhCD;AIrhCD;EACE,4DAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,0BAAA;CJuhCD;AInhCD;;;;EAIE,qBAAA;EACA,mBAAA;EACA,qBAAA;CJqhCD;AI/gCD;EACE,eAAA;EACA,sBAAA;CJihCD;AI/gCC;;EAEE,eAAA;EACA,2BAAA;CJihCH;AI9gCC;EErDA,qBAAA;EAEA,2CAAA;EACA,qBAAA;CNqkCD;AIxgCD;EACE,UAAA;CJ0gCD;AIpgCD;EACE,uBAAA;CJsgCD;AIlgCD;;;;;EGvEE,eAAA;EACA,gBAAA;EACA,aAAA;CPglCD;AItgCD;EACE,mBAAA;CJwgCD;AIlgCD;EACE,aAAA;EACA,wBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;EC6FA,yCAAA;EACK,oCAAA;EACG,iCAAA;EEvLR,sBAAA;EACA,gBAAA;EACA,aAAA;CPgmCD;AIlgCD;EACE,mBAAA;CJogCD;AI9/BD;EACE,iBAAA;EACA,oBAAA;EACA,UAAA;EACA,8BAAA;CJggCD;AIx/BD;EACE,mBAAA;EACA,WAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,iBAAA;EACA,uBAAA;EACA,UAAA;CJ0/BD;AIl/BC;;EAEE,iBAAA;EACA,YAAA;EACA,aAAA;EACA,UAAA;EACA,kBAAA;EACA,WAAA;CJo/BH;AIz+BD;EACE,gBAAA;CJ2+BD;AQloCD;;;;;;;;;;;;EAEE,qBAAA;EACA,iBAAA;EACA,iBAAA;EACA,eAAA;CR8oCD;AQnpCD;;;;;;;;;;;;;;;;;;;;;;;;EASI,oBAAA;EACA,eAAA;EACA,eAAA;CRoqCH;AQhqCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRqqCD;AQzqCD;;;;;;;;;;;;EAQI,eAAA;CR+qCH;AQ5qCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRirCD;AQrrCD;;;;;;;;;;;;EAQI,eAAA;CR2rCH;AQvrCD;;EAAU,gBAAA;CR2rCT;AQ1rCD;;EAAU,gBAAA;CR8rCT;AQ7rCD;;EAAU,gBAAA;CRisCT;AQhsCD;;EAAU,gBAAA;CRosCT;AQnsCD;;EAAU,gBAAA;CRusCT;AQtsCD;;EAAU,gBAAA;CR0sCT;AQpsCD;EACE,iBAAA;CRssCD;AQnsCD;EACE,oBAAA;EACA,gBAAA;EACA,iBAAA;EACA,iBAAA;CRqsCD;AQhsCD;EAAA;IAFI,gBAAA;GRssCD;CACF;AQ9rCD;;EAEE,eAAA;CRgsCD;AQ7rCD;;EAEE,0BAAA;EACA,cAAA;CR+rCD;AQ3rCD;EAAuB,iBAAA;CR8rCtB;AQ7rCD;EAAuB,kBAAA;CRgsCtB;AQ/rCD;EAAuB,mBAAA;CRksCtB;AQjsCD;EAAuB,oBAAA;CRosCtB;AQnsCD;EAAuB,oBAAA;CRssCtB;AQnsCD;EAAuB,0BAAA;CRssCtB;AQrsCD;EAAuB,0BAAA;CRwsCtB;AQvsCD;EAAuB,2BAAA;CR0sCtB;AQvsCD;EACE,eAAA;CRysCD;AQvsCD;ECrGE,eAAA;CT+yCD;AS9yCC;;EAEE,eAAA;CTgzCH;AQ3sCD;ECxGE,eAAA;CTszCD;ASrzCC;;EAEE,eAAA;CTuzCH;AQ/sCD;EC3GE,eAAA;CT6zCD;AS5zCC;;EAEE,eAAA;CT8zCH;AQntCD;EC9GE,eAAA;CTo0CD;ASn0CC;;EAEE,eAAA;CTq0CH;AQvtCD;ECjHE,eAAA;CT20CD;AS10CC;;EAEE,eAAA;CT40CH;AQvtCD;EAGE,YAAA;EE3HA,0BAAA;CVm1CD;AUl1CC;;EAEE,0BAAA;CVo1CH;AQztCD;EE9HE,0BAAA;CV01CD;AUz1CC;;EAEE,0BAAA;CV21CH;AQ7tCD;EEjIE,0BAAA;CVi2CD;AUh2CC;;EAEE,0BAAA;CVk2CH;AQjuCD;EEpIE,0BAAA;CVw2CD;AUv2CC;;EAEE,0BAAA;CVy2CH;AQruCD;EEvIE,0BAAA;CV+2CD;AU92CC;;EAEE,0BAAA;CVg3CH;AQpuCD;EACE,oBAAA;EACA,oBAAA;EACA,iCAAA;CRsuCD;AQ9tCD;;EAEE,cAAA;EACA,oBAAA;CRguCD;AQnuCD;;;;EAMI,iBAAA;CRmuCH;AQ5tCD;EACE,gBAAA;EACA,iBAAA;CR8tCD;AQ1tCD;EALE,gBAAA;EACA,iBAAA;EAMA,kBAAA;CR6tCD;AQ/tCD;EAKI,sBAAA;EACA,kBAAA;EACA,mBAAA;CR6tCH;AQxtCD;EACE,cAAA;EACA,oBAAA;CR0tCD;AQxtCD;;EAEE,wBAAA;CR0tCD;AQxtCD;EACE,kBAAA;CR0tCD;AQxtCD;EACE,eAAA;CR0tCD;AQjsCD;EAAA;IAVM,YAAA;IACA,aAAA;IACA,YAAA;IACA,kBAAA;IGtNJ,iBAAA;IACA,wBAAA;IACA,oBAAA;GXs6CC;EQ3sCH;IAHM,mBAAA;GRitCH;CACF;AQxsCD;;EAGE,aAAA;EACA,kCAAA;CRysCD;AQvsCD;EACE,eAAA;EA9IqB,0BAAA;CRw1CtB;AQrsCD;EACE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,+BAAA;CRusCD;AQlsCG;;;EACE,iBAAA;CRssCL;AQhtCD;;;EAmBI,eAAA;EACA,eAAA;EACA,wBAAA;EACA,eAAA;CRksCH;AQhsCG;;;EACE,uBAAA;CRosCL;AQ5rCD;;EAEE,oBAAA;EACA,gBAAA;EACA,gCAAA;EACA,eAAA;EACA,kBAAA;CR8rCD;AQxrCG;;;;;;EAAW,YAAA;CRgsCd;AQ/rCG;;;;;;EACE,uBAAA;CRssCL;AQhsCD;EACE,oBAAA;EACA,mBAAA;EACA,wBAAA;CRksCD;AYx+CD;;;;EAIE,+DAAA;CZ0+CD;AYt+CD;EACE,iBAAA;EACA,eAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CZw+CD;AYp+CD;EACE,iBAAA;EACA,eAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;EACA,uDAAA;UAAA,+CAAA;CZs+CD;AY5+CD;EASI,WAAA;EACA,gBAAA;EACA,kBAAA;EACA,yBAAA;UAAA,iBAAA;CZs+CH;AYj+CD;EACE,eAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,sBAAA;EACA,sBAAA;EACA,eAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;CZm+CD;AY9+CD;EAeI,WAAA;EACA,mBAAA;EACA,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,iBAAA;CZk+CH;AY79CD;EACE,kBAAA;EACA,mBAAA;CZ+9CD;AazhDD;ECHE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;Cd+hDD;AazhDC;EAAA;IAFE,aAAA;Gb+hDD;CACF;Aa3hDC;EAAA;IAFE,aAAA;GbiiDD;CACF;Aa7hDD;EAAA;IAFI,cAAA;GbmiDD;CACF;Aa1hDD;ECvBE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;CdojDD;AavhDD;ECvBE,mBAAA;EACA,oBAAA;CdijDD;AejjDG;EACE,mBAAA;EAEA,gBAAA;EAEA,mBAAA;EACA,oBAAA;CfijDL;AejiDG;EACE,YAAA;CfmiDL;Ae5hDC;EACE,YAAA;Cf8hDH;Ae/hDC;EACE,oBAAA;CfiiDH;AeliDC;EACE,oBAAA;CfoiDH;AeriDC;EACE,WAAA;CfuiDH;AexiDC;EACE,oBAAA;Cf0iDH;Ae3iDC;EACE,oBAAA;Cf6iDH;Ae9iDC;EACE,WAAA;CfgjDH;AejjDC;EACE,oBAAA;CfmjDH;AepjDC;EACE,oBAAA;CfsjDH;AevjDC;EACE,WAAA;CfyjDH;Ae1jDC;EACE,oBAAA;Cf4jDH;Ae7jDC;EACE,mBAAA;Cf+jDH;AejjDC;EACE,YAAA;CfmjDH;AepjDC;EACE,oBAAA;CfsjDH;AevjDC;EACE,oBAAA;CfyjDH;Ae1jDC;EACE,WAAA;Cf4jDH;Ae7jDC;EACE,oBAAA;Cf+jDH;AehkDC;EACE,oBAAA;CfkkDH;AenkDC;EACE,WAAA;CfqkDH;AetkDC;EACE,oBAAA;CfwkDH;AezkDC;EACE,oBAAA;Cf2kDH;Ae5kDC;EACE,WAAA;Cf8kDH;Ae/kDC;EACE,oBAAA;CfilDH;AellDC;EACE,mBAAA;CfolDH;AehlDC;EACE,YAAA;CfklDH;AelmDC;EACE,WAAA;CfomDH;AermDC;EACE,mBAAA;CfumDH;AexmDC;EACE,mBAAA;Cf0mDH;Ae3mDC;EACE,UAAA;Cf6mDH;Ae9mDC;EACE,mBAAA;CfgnDH;AejnDC;EACE,mBAAA;CfmnDH;AepnDC;EACE,UAAA;CfsnDH;AevnDC;EACE,mBAAA;CfynDH;Ae1nDC;EACE,mBAAA;Cf4nDH;Ae7nDC;EACE,UAAA;Cf+nDH;AehoDC;EACE,mBAAA;CfkoDH;AenoDC;EACE,kBAAA;CfqoDH;AejoDC;EACE,WAAA;CfmoDH;AernDC;EACE,kBAAA;CfunDH;AexnDC;EACE,0BAAA;Cf0nDH;Ae3nDC;EACE,0BAAA;Cf6nDH;Ae9nDC;EACE,iBAAA;CfgoDH;AejoDC;EACE,0BAAA;CfmoDH;AepoDC;EACE,0BAAA;CfsoDH;AevoDC;EACE,iBAAA;CfyoDH;Ae1oDC;EACE,0BAAA;Cf4oDH;Ae7oDC;EACE,0BAAA;Cf+oDH;AehpDC;EACE,iBAAA;CfkpDH;AenpDC;EACE,0BAAA;CfqpDH;AetpDC;EACE,yBAAA;CfwpDH;AezpDC;EACE,gBAAA;Cf2pDH;Aa3pDD;EElCI;IACE,YAAA;GfgsDH;EezrDD;IACE,YAAA;Gf2rDD;Ee5rDD;IACE,oBAAA;Gf8rDD;Ee/rDD;IACE,oBAAA;GfisDD;EelsDD;IACE,WAAA;GfosDD;EersDD;IACE,oBAAA;GfusDD;EexsDD;IACE,oBAAA;Gf0sDD;Ee3sDD;IACE,WAAA;Gf6sDD;Ee9sDD;IACE,oBAAA;GfgtDD;EejtDD;IACE,oBAAA;GfmtDD;EeptDD;IACE,WAAA;GfstDD;EevtDD;IACE,oBAAA;GfytDD;Ee1tDD;IACE,mBAAA;Gf4tDD;Ee9sDD;IACE,YAAA;GfgtDD;EejtDD;IACE,oBAAA;GfmtDD;EeptDD;IACE,oBAAA;GfstDD;EevtDD;IACE,WAAA;GfytDD;Ee1tDD;IACE,oBAAA;Gf4tDD;Ee7tDD;IACE,oBAAA;Gf+tDD;EehuDD;IACE,WAAA;GfkuDD;EenuDD;IACE,oBAAA;GfquDD;EetuDD;IACE,oBAAA;GfwuDD;EezuDD;IACE,WAAA;Gf2uDD;Ee5uDD;IACE,oBAAA;Gf8uDD;Ee/uDD;IACE,mBAAA;GfivDD;Ee7uDD;IACE,YAAA;Gf+uDD;Ee/vDD;IACE,WAAA;GfiwDD;EelwDD;IACE,mBAAA;GfowDD;EerwDD;IACE,mBAAA;GfuwDD;EexwDD;IACE,UAAA;Gf0wDD;Ee3wDD;IACE,mBAAA;Gf6wDD;Ee9wDD;IACE,mBAAA;GfgxDD;EejxDD;IACE,UAAA;GfmxDD;EepxDD;IACE,mBAAA;GfsxDD;EevxDD;IACE,mBAAA;GfyxDD;Ee1xDD;IACE,UAAA;Gf4xDD;Ee7xDD;IACE,mBAAA;Gf+xDD;EehyDD;IACE,kBAAA;GfkyDD;Ee9xDD;IACE,WAAA;GfgyDD;EelxDD;IACE,kBAAA;GfoxDD;EerxDD;IACE,0BAAA;GfuxDD;EexxDD;IACE,0BAAA;Gf0xDD;Ee3xDD;IACE,iBAAA;Gf6xDD;Ee9xDD;IACE,0BAAA;GfgyDD;EejyDD;IACE,0BAAA;GfmyDD;EepyDD;IACE,iBAAA;GfsyDD;EevyDD;IACE,0BAAA;GfyyDD;Ee1yDD;IACE,0BAAA;Gf4yDD;Ee7yDD;IACE,iBAAA;Gf+yDD;EehzDD;IACE,0BAAA;GfkzDD;EenzDD;IACE,yBAAA;GfqzDD;EetzDD;IACE,gBAAA;GfwzDD;CACF;AahzDD;EE3CI;IACE,YAAA;Gf81DH;Eev1DD;IACE,YAAA;Gfy1DD;Ee11DD;IACE,oBAAA;Gf41DD;Ee71DD;IACE,oBAAA;Gf+1DD;Eeh2DD;IACE,WAAA;Gfk2DD;Een2DD;IACE,oBAAA;Gfq2DD;Eet2DD;IACE,oBAAA;Gfw2DD;Eez2DD;IACE,WAAA;Gf22DD;Ee52DD;IACE,oBAAA;Gf82DD;Ee/2DD;IACE,oBAAA;Gfi3DD;Eel3DD;IACE,WAAA;Gfo3DD;Eer3DD;IACE,oBAAA;Gfu3DD;Eex3DD;IACE,mBAAA;Gf03DD;Ee52DD;IACE,YAAA;Gf82DD;Ee/2DD;IACE,oBAAA;Gfi3DD;Eel3DD;IACE,oBAAA;Gfo3DD;Eer3DD;IACE,WAAA;Gfu3DD;Eex3DD;IACE,oBAAA;Gf03DD;Ee33DD;IACE,oBAAA;Gf63DD;Ee93DD;IACE,WAAA;Gfg4DD;Eej4DD;IACE,oBAAA;Gfm4DD;Eep4DD;IACE,oBAAA;Gfs4DD;Eev4DD;IACE,WAAA;Gfy4DD;Ee14DD;IACE,oBAAA;Gf44DD;Ee74DD;IACE,mBAAA;Gf+4DD;Ee34DD;IACE,YAAA;Gf64DD;Ee75DD;IACE,WAAA;Gf+5DD;Eeh6DD;IACE,mBAAA;Gfk6DD;Een6DD;IACE,mBAAA;Gfq6DD;Eet6DD;IACE,UAAA;Gfw6DD;Eez6DD;IACE,mBAAA;Gf26DD;Ee56DD;IACE,mBAAA;Gf86DD;Ee/6DD;IACE,UAAA;Gfi7DD;Eel7DD;IACE,mBAAA;Gfo7DD;Eer7DD;IACE,mBAAA;Gfu7DD;Eex7DD;IACE,UAAA;Gf07DD;Ee37DD;IACE,mBAAA;Gf67DD;Ee97DD;IACE,kBAAA;Gfg8DD;Ee57DD;IACE,WAAA;Gf87DD;Eeh7DD;IACE,kBAAA;Gfk7DD;Een7DD;IACE,0BAAA;Gfq7DD;Eet7DD;IACE,0BAAA;Gfw7DD;Eez7DD;IACE,iBAAA;Gf27DD;Ee57DD;IACE,0BAAA;Gf87DD;Ee/7DD;IACE,0BAAA;Gfi8DD;Eel8DD;IACE,iBAAA;Gfo8DD;Eer8DD;IACE,0BAAA;Gfu8DD;Eex8DD;IACE,0BAAA;Gf08DD;Ee38DD;IACE,iBAAA;Gf68DD;Ee98DD;IACE,0BAAA;Gfg9DD;Eej9DD;IACE,yBAAA;Gfm9DD;Eep9DD;IACE,gBAAA;Gfs9DD;CACF;Aa38DD;EE9CI;IACE,YAAA;Gf4/DH;Eer/DD;IACE,YAAA;Gfu/DD;Eex/DD;IACE,oBAAA;Gf0/DD;Ee3/DD;IACE,oBAAA;Gf6/DD;Ee9/DD;IACE,WAAA;GfggED;EejgED;IACE,oBAAA;GfmgED;EepgED;IACE,oBAAA;GfsgED;EevgED;IACE,WAAA;GfygED;Ee1gED;IACE,oBAAA;Gf4gED;Ee7gED;IACE,oBAAA;Gf+gED;EehhED;IACE,WAAA;GfkhED;EenhED;IACE,oBAAA;GfqhED;EethED;IACE,mBAAA;GfwhED;Ee1gED;IACE,YAAA;Gf4gED;Ee7gED;IACE,oBAAA;Gf+gED;EehhED;IACE,oBAAA;GfkhED;EenhED;IACE,WAAA;GfqhED;EethED;IACE,oBAAA;GfwhED;EezhED;IACE,oBAAA;Gf2hED;Ee5hED;IACE,WAAA;Gf8hED;Ee/hED;IACE,oBAAA;GfiiED;EeliED;IACE,oBAAA;GfoiED;EeriED;IACE,WAAA;GfuiED;EexiED;IACE,oBAAA;Gf0iED;Ee3iED;IACE,mBAAA;Gf6iED;EeziED;IACE,YAAA;Gf2iED;Ee3jED;IACE,WAAA;Gf6jED;Ee9jED;IACE,mBAAA;GfgkED;EejkED;IACE,mBAAA;GfmkED;EepkED;IACE,UAAA;GfskED;EevkED;IACE,mBAAA;GfykED;Ee1kED;IACE,mBAAA;Gf4kED;Ee7kED;IACE,UAAA;Gf+kED;EehlED;IACE,mBAAA;GfklED;EenlED;IACE,mBAAA;GfqlED;EetlED;IACE,UAAA;GfwlED;EezlED;IACE,mBAAA;Gf2lED;Ee5lED;IACE,kBAAA;Gf8lED;Ee1lED;IACE,WAAA;Gf4lED;Ee9kED;IACE,kBAAA;GfglED;EejlED;IACE,0BAAA;GfmlED;EeplED;IACE,0BAAA;GfslED;EevlED;IACE,iBAAA;GfylED;Ee1lED;IACE,0BAAA;Gf4lED;Ee7lED;IACE,0BAAA;Gf+lED;EehmED;IACE,iBAAA;GfkmED;EenmED;IACE,0BAAA;GfqmED;EetmED;IACE,0BAAA;GfwmED;EezmED;IACE,iBAAA;Gf2mED;Ee5mED;IACE,0BAAA;Gf8mED;Ee/mED;IACE,yBAAA;GfinED;EelnED;IACE,gBAAA;GfonED;CACF;AgBxrED;EACE,8BAAA;ChB0rED;AgBxrED;EACE,iBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;ChB0rED;AgBxrED;EACE,iBAAA;ChB0rED;AgBprED;EACE,YAAA;EACA,gBAAA;EACA,oBAAA;ChBsrED;AgBzrED;;;;;;EAWQ,aAAA;EACA,wBAAA;EACA,oBAAA;EACA,8BAAA;ChBsrEP;AgBpsED;EAoBI,uBAAA;EACA,iCAAA;ChBmrEH;AgBxsED;;;;;;EA8BQ,cAAA;ChBkrEP;AgBhtED;EAoCI,8BAAA;ChB+qEH;AgBntED;EAyCI,0BAAA;ChB6qEH;AgBtqED;;;;;;EAOQ,aAAA;ChBuqEP;AgB5pED;EACE,0BAAA;ChB8pED;AgB/pED;;;;;;EAQQ,0BAAA;ChB+pEP;AgBvqED;;EAeM,yBAAA;ChB4pEL;AgBlpED;EAEI,0BAAA;ChBmpEH;AgB1oED;EAEI,0BAAA;ChB2oEH;AgBloED;EACE,iBAAA;EACA,YAAA;EACA,sBAAA;ChBooED;AgB/nEG;;EACE,iBAAA;EACA,YAAA;EACA,oBAAA;ChBkoEL;AiB9wEC;;;;;;;;;;;;EAOI,0BAAA;CjBqxEL;AiB/wEC;;;;;EAMI,0BAAA;CjBgxEL;AiBnyEC;;;;;;;;;;;;EAOI,0BAAA;CjB0yEL;AiBpyEC;;;;;EAMI,0BAAA;CjBqyEL;AiBxzEC;;;;;;;;;;;;EAOI,0BAAA;CjB+zEL;AiBzzEC;;;;;EAMI,0BAAA;CjB0zEL;AiB70EC;;;;;;;;;;;;EAOI,0BAAA;CjBo1EL;AiB90EC;;;;;EAMI,0BAAA;CjB+0EL;AiBl2EC;;;;;;;;;;;;EAOI,0BAAA;CjBy2EL;AiBn2EC;;;;;EAMI,0BAAA;CjBo2EL;AgBltED;EACE,iBAAA;EACA,kBAAA;ChBotED;AgBvpED;EAAA;IA1DI,YAAA;IACA,oBAAA;IACA,mBAAA;IACA,6CAAA;IACA,0BAAA;GhBqtED;EgB/pEH;IAlDM,iBAAA;GhBotEH;EgBlqEH;;;;;;IAzCY,oBAAA;GhBmtET;EgB1qEH;IAjCM,UAAA;GhB8sEH;EgB7qEH;;;;;;IAxBY,eAAA;GhB6sET;EgBrrEH;;;;;;IApBY,gBAAA;GhBitET;EgB7rEH;;;;IAPY,iBAAA;GhB0sET;CACF;AkBp6ED;EACE,WAAA;EACA,UAAA;EACA,UAAA;EAIA,aAAA;ClBm6ED;AkBh6ED;EACE,eAAA;EACA,YAAA;EACA,WAAA;EACA,oBAAA;EACA,gBAAA;EACA,qBAAA;EACA,eAAA;EACA,UAAA;EACA,iCAAA;ClBk6ED;AkB/5ED;EACE,sBAAA;EACA,gBAAA;EACA,mBAAA;EACA,kBAAA;ClBi6ED;AkBt5ED;Eb4BE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL63ET;AkBt5ED;;EAEE,gBAAA;EACA,mBAAA;EACA,oBAAA;ClBw5ED;AkBr5ED;EACE,eAAA;ClBu5ED;AkBn5ED;EACE,eAAA;EACA,YAAA;ClBq5ED;AkBj5ED;;EAEE,aAAA;ClBm5ED;AkB/4ED;;;EZvEE,qBAAA;EAEA,2CAAA;EACA,qBAAA;CN09ED;AkB/4ED;EACE,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;ClBi5ED;AkBv3ED;EACE,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,0BAAA;EACA,uBAAA;EACA,0BAAA;EACA,mBAAA;EbxDA,yDAAA;EACQ,iDAAA;EAyHR,uFAAA;EACK,0EAAA;EACG,uEAAA;CL0zET;AmBl8EC;EACE,sBAAA;EACA,WAAA;EdUF,uFAAA;EACQ,+EAAA;CL27ET;AK15EC;EACE,eAAA;EACA,WAAA;CL45EH;AK15EC;EAA0B,eAAA;CL65E3B;AK55EC;EAAgC,eAAA;CL+5EjC;AkB/3EC;;;EAGE,0BAAA;EACA,WAAA;ClBi4EH;AkB93EC;;EAEE,oBAAA;ClBg4EH;AkB53EC;EACE,aAAA;ClB83EH;AkBl3ED;EACE,yBAAA;ClBo3ED;AkB50ED;EAtBI;;;;IACE,kBAAA;GlBw2EH;EkBr2EC;;;;;;;;IAEE,kBAAA;GlB62EH;EkB12EC;;;;;;;;IAEE,kBAAA;GlBk3EH;CACF;AkBx2ED;EACE,oBAAA;ClB02ED;AkBl2ED;;EAEE,mBAAA;EACA,eAAA;EACA,iBAAA;EACA,oBAAA;ClBo2ED;AkBz2ED;;EAQI,iBAAA;EACA,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,gBAAA;ClBq2EH;AkBl2ED;;;;EAIE,mBAAA;EACA,mBAAA;EACA,mBAAA;ClBo2ED;AkBj2ED;;EAEE,iBAAA;ClBm2ED;AkB/1ED;;EAEE,mBAAA;EACA,sBAAA;EACA,mBAAA;EACA,iBAAA;EACA,uBAAA;EACA,oBAAA;EACA,gBAAA;ClBi2ED;AkB/1ED;;EAEE,cAAA;EACA,kBAAA;ClBi2ED;AkBx1EC;;;;;;EAGE,oBAAA;ClB61EH;AkBv1EC;;;;EAEE,oBAAA;ClB21EH;AkBr1EC;;;;EAGI,oBAAA;ClBw1EL;AkB70ED;EAEE,iBAAA;EACA,oBAAA;EAEA,iBAAA;EACA,iBAAA;ClB60ED;AkB30EC;;EAEE,gBAAA;EACA,iBAAA;ClB60EH;AkBh0ED;EC7PE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnBgkFD;AmB9jFC;EACE,aAAA;EACA,kBAAA;CnBgkFH;AmB7jFC;;EAEE,aAAA;CnB+jFH;AkB50ED;EAEI,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;ClB60EH;AkBn1ED;EASI,aAAA;EACA,kBAAA;ClB60EH;AkBv1ED;;EAcI,aAAA;ClB60EH;AkB31ED;EAiBI,aAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;ClB60EH;AkBz0ED;ECzRE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBqmFD;AmBnmFC;EACE,aAAA;EACA,kBAAA;CnBqmFH;AmBlmFC;;EAEE,aAAA;CnBomFH;AkBr1ED;EAEI,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;ClBs1EH;AkB51ED;EASI,aAAA;EACA,kBAAA;ClBs1EH;AkBh2ED;;EAcI,aAAA;ClBs1EH;AkBp2ED;EAiBI,aAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;ClBs1EH;AkB70ED;EAEE,mBAAA;ClB80ED;AkBh1ED;EAMI,sBAAA;ClB60EH;AkBz0ED;EACE,mBAAA;EACA,OAAA;EACA,SAAA;EACA,WAAA;EACA,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,mBAAA;EACA,qBAAA;ClB20ED;AkBz0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClB20ED;AkBz0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClB20ED;AkBv0ED;;;;;;;;;;ECpZI,eAAA;CnBuuFH;AkBn1ED;EChZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLwrFT;AmBtuFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL6rFT;AkB71ED;ECtYI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBsuFH;AkBl2ED;EChYI,eAAA;CnBquFH;AkBl2ED;;;;;;;;;;ECvZI,eAAA;CnBqwFH;AkB92ED;ECnZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLstFT;AmBpwFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL2tFT;AkBx3ED;ECzYI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBowFH;AkB73ED;ECnYI,eAAA;CnBmwFH;AkB73ED;;;;;;;;;;EC1ZI,eAAA;CnBmyFH;AkBz4ED;ECtZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLovFT;AmBlyFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CLyvFT;AkBn5ED;EC5YI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBkyFH;AkBx5ED;ECtYI,eAAA;CnBiyFH;AkBp5EC;EACG,UAAA;ClBs5EJ;AkBp5EC;EACG,OAAA;ClBs5EJ;AkB54ED;EACE,eAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;ClB84ED;AkB3zED;EAAA;IA9DM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlB63EH;EkBj0EH;IAvDM,sBAAA;IACA,YAAA;IACA,uBAAA;GlB23EH;EkBt0EH;IAhDM,sBAAA;GlBy3EH;EkBz0EH;IA5CM,sBAAA;IACA,uBAAA;GlBw3EH;EkB70EH;;;IAtCQ,YAAA;GlBw3EL;EkBl1EH;IAhCM,YAAA;GlBq3EH;EkBr1EH;IA5BM,iBAAA;IACA,uBAAA;GlBo3EH;EkBz1EH;;IApBM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlBi3EH;EkBh2EH;;IAdQ,gBAAA;GlBk3EL;EkBp2EH;;IATM,mBAAA;IACA,eAAA;GlBi3EH;EkBz2EH;IAHM,OAAA;GlB+2EH;CACF;AkBr2ED;;;;EASI,cAAA;EACA,iBAAA;EACA,iBAAA;ClBk2EH;AkB72ED;;EAiBI,iBAAA;ClBg2EH;AkBj3ED;EJhhBE,mBAAA;EACA,oBAAA;Cdo4FD;AkB90EC;EAAA;IAVI,kBAAA;IACA,iBAAA;IACA,iBAAA;GlB41EH;CACF;AkB53ED;EAwCI,YAAA;ClBu1EH;AkBz0EC;EAAA;IAJM,yBAAA;IACA,gBAAA;GlBi1EL;CACF;AkBv0EC;EAAA;IAJM,iBAAA;IACA,gBAAA;GlB+0EL;CACF;AoBl6FD;EACE,sBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;EACA,uBAAA;EACA,+BAAA;MAAA,2BAAA;EACA,gBAAA;EACA,uBAAA;EACA,8BAAA;EACA,oBAAA;EC6CA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,mBAAA;EhB4JA,0BAAA;EACG,uBAAA;EACC,sBAAA;EACI,kBAAA;CL6tFT;AoBr6FG;;;;;;EdrBF,qBAAA;EAEA,2CAAA;EACA,qBAAA;CNi8FD;AoBz6FC;;;EAGE,eAAA;EACA,sBAAA;CpB26FH;AoBx6FC;;EAEE,WAAA;EACA,uBAAA;Ef2BF,yDAAA;EACQ,iDAAA;CLg5FT;AoBx6FC;;;EAGE,oBAAA;EE7CF,cAAA;EAGA,0BAAA;EjB8DA,yBAAA;EACQ,iBAAA;CLy5FT;AoBx6FG;;EAEE,qBAAA;CpB06FL;AoBj6FD;EC3DE,eAAA;EACA,0BAAA;EACA,sBAAA;CrB+9FD;AqB79FC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB+9FP;AqB79FC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB+9FP;AqB79FC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB+9FP;AqB79FG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBq+FT;AqBl+FC;;;EAGE,uBAAA;CrBo+FH;AqB/9FG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrB6+FT;AoB/9FD;ECTI,eAAA;EACA,0BAAA;CrB2+FH;AoBh+FD;EC9DE,eAAA;EACA,0BAAA;EACA,sBAAA;CrBiiGD;AqB/hGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBiiGP;AqB/hGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBiiGP;AqB/hGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBiiGP;AqB/hGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBuiGT;AqBpiGC;;;EAGE,uBAAA;CrBsiGH;AqBjiGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrB+iGT;AoB9hGD;ECZI,eAAA;EACA,0BAAA;CrB6iGH;AoB9hGD;EClEE,eAAA;EACA,0BAAA;EACA,sBAAA;CrBmmGD;AqBjmGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBmmGP;AqBjmGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBmmGP;AqBjmGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBmmGP;AqBjmGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBymGT;AqBtmGC;;;EAGE,uBAAA;CrBwmGH;AqBnmGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrBinGT;AoB5lGD;EChBI,eAAA;EACA,0BAAA;CrB+mGH;AoB5lGD;ECtEE,eAAA;EACA,0BAAA;EACA,sBAAA;CrBqqGD;AqBnqGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBqqGP;AqBnqGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBqqGP;AqBnqGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBqqGP;AqBnqGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB2qGT;AqBxqGC;;;EAGE,uBAAA;CrB0qGH;AqBrqGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrBmrGT;AoB1pGD;ECpBI,eAAA;EACA,0BAAA;CrBirGH;AoB1pGD;EC1EE,eAAA;EACA,0BAAA;EACA,sBAAA;CrBuuGD;AqBruGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBuuGP;AqBruGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBuuGP;AqBruGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBuuGP;AqBruGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB6uGT;AqB1uGC;;;EAGE,uBAAA;CrB4uGH;AqBvuGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrBqvGT;AoBxtGD;ECxBI,eAAA;EACA,0BAAA;CrBmvGH;AoBxtGD;EC9EE,eAAA;EACA,0BAAA;EACA,sBAAA;CrByyGD;AqBvyGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrByyGP;AqBvyGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrByyGP;AqBvyGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrByyGP;AqBvyGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB+yGT;AqB5yGC;;;EAGE,uBAAA;CrB8yGH;AqBzyGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrBuzGT;AoBtxGD;EC5BI,eAAA;EACA,0BAAA;CrBqzGH;AoBjxGD;EACE,eAAA;EACA,oBAAA;EACA,iBAAA;CpBmxGD;AoBjxGC;;;;;EAKE,8BAAA;EfnCF,yBAAA;EACQ,iBAAA;CLuzGT;AoBlxGC;;;;EAIE,0BAAA;CpBoxGH;AoBlxGC;;EAEE,eAAA;EACA,2BAAA;EACA,8BAAA;CpBoxGH;AoBhxGG;;;;EAEE,eAAA;EACA,sBAAA;CpBoxGL;AoB3wGD;;ECrEE,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CrBo1GD;AoB9wGD;;ECzEE,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrB21GD;AoBjxGD;;EC7EE,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrBk2GD;AoBhxGD;EACE,eAAA;EACA,YAAA;CpBkxGD;AoB9wGD;EACE,gBAAA;CpBgxGD;AoBzwGC;;;EACE,YAAA;CpB6wGH;AuBv6GD;EACE,WAAA;ElBoLA,yCAAA;EACK,oCAAA;EACG,iCAAA;CLsvGT;AuB16GC;EACE,WAAA;CvB46GH;AuBx6GD;EACE,cAAA;CvB06GD;AuBx6GC;EAAY,eAAA;CvB26Gb;AuB16GC;EAAY,mBAAA;CvB66Gb;AuB56GC;EAAY,yBAAA;CvB+6Gb;AuB56GD;EACE,mBAAA;EACA,UAAA;EACA,iBAAA;ElBuKA,gDAAA;EACQ,2CAAA;KAAA,wCAAA;EAOR,mCAAA;EACQ,8BAAA;KAAA,2BAAA;EAGR,yCAAA;EACQ,oCAAA;KAAA,iCAAA;CLgwGT;AwB18GD;EACE,sBAAA;EACA,SAAA;EACA,UAAA;EACA,iBAAA;EACA,uBAAA;EACA,uBAAA;EACA,yBAAA;EACA,oCAAA;EACA,mCAAA;CxB48GD;AwBx8GD;;EAEE,mBAAA;CxB08GD;AwBt8GD;EACE,WAAA;CxBw8GD;AwBp8GD;EACE,mBAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,YAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,0BAAA;EACA,0BAAA;EACA,sCAAA;EACA,mBAAA;EnBsBA,oDAAA;EACQ,4CAAA;EmBrBR,qCAAA;UAAA,6BAAA;CxBu8GD;AwBl8GC;EACE,SAAA;EACA,WAAA;CxBo8GH;AwB79GD;ECzBE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBy/GD;AwBn+GD;EAmCI,eAAA;EACA,kBAAA;EACA,YAAA;EACA,oBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxBm8GH;AwB77GC;;EAEE,sBAAA;EACA,eAAA;EACA,0BAAA;CxB+7GH;AwBz7GC;;;EAGE,eAAA;EACA,sBAAA;EACA,WAAA;EACA,0BAAA;CxB27GH;AwBl7GC;;;EAGE,eAAA;CxBo7GH;AwBh7GC;;EAEE,sBAAA;EACA,8BAAA;EACA,uBAAA;EE3GF,oEAAA;EF6GE,oBAAA;CxBk7GH;AwB76GD;EAGI,eAAA;CxB66GH;AwBh7GD;EAQI,WAAA;CxB26GH;AwBn6GD;EACE,WAAA;EACA,SAAA;CxBq6GD;AwB75GD;EACE,QAAA;EACA,YAAA;CxB+5GD;AwB35GD;EACE,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxB65GD;AwBz5GD;EACE,gBAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;EACA,OAAA;EACA,aAAA;CxB25GD;AwBv5GD;EACE,SAAA;EACA,WAAA;CxBy5GD;AwBj5GD;;EAII,cAAA;EACA,0BAAA;EACA,4BAAA;EACA,YAAA;CxBi5GH;AwBx5GD;;EAWI,UAAA;EACA,aAAA;EACA,mBAAA;CxBi5GH;AwB53GD;EAXE;IApEA,WAAA;IACA,SAAA;GxB+8GC;EwB54GD;IA1DA,QAAA;IACA,YAAA;GxBy8GC;CACF;A2BzlHD;;EAEE,mBAAA;EACA,sBAAA;EACA,uBAAA;C3B2lHD;A2B/lHD;;EAMI,mBAAA;EACA,YAAA;C3B6lHH;A2B3lHG;;;;;;;;EAIE,WAAA;C3BimHL;A2B3lHD;;;;EAKI,kBAAA;C3B4lHH;A2BvlHD;EACE,kBAAA;C3BylHD;A2B1lHD;;;EAOI,YAAA;C3BwlHH;A2B/lHD;;;EAYI,iBAAA;C3BwlHH;A2BplHD;EACE,iBAAA;C3BslHD;A2BllHD;EACE,eAAA;C3BolHD;A2BnlHC;EClDA,8BAAA;EACG,2BAAA;C5BwoHJ;A2BllHD;;EC/CE,6BAAA;EACG,0BAAA;C5BqoHJ;A2BjlHD;EACE,YAAA;C3BmlHD;A2BjlHD;EACE,iBAAA;C3BmlHD;A2BjlHD;;ECnEE,8BAAA;EACG,2BAAA;C5BwpHJ;A2BhlHD;ECjEE,6BAAA;EACG,0BAAA;C5BopHJ;A2B/kHD;;EAEE,WAAA;C3BilHD;A2BhkHD;EACE,kBAAA;EACA,mBAAA;C3BkkHD;A2BhkHD;EACE,mBAAA;EACA,oBAAA;C3BkkHD;A2B7jHD;EtB/CE,yDAAA;EACQ,iDAAA;CL+mHT;A2B7jHC;EtBnDA,yBAAA;EACQ,iBAAA;CLmnHT;A2B1jHD;EACE,eAAA;C3B4jHD;A2BzjHD;EACE,wBAAA;EACA,uBAAA;C3B2jHD;A2BxjHD;EACE,wBAAA;C3B0jHD;A2BnjHD;;;EAII,eAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;C3BojHH;A2B3jHD;EAcM,YAAA;C3BgjHL;A2B9jHD;;;;EAsBI,iBAAA;EACA,eAAA;C3B8iHH;A2BziHC;EACE,iBAAA;C3B2iHH;A2BziHC;EACE,6BAAA;ECpKF,8BAAA;EACC,6BAAA;C5BgtHF;A2B1iHC;EACE,+BAAA;EChLF,2BAAA;EACC,0BAAA;C5B6tHF;A2B1iHD;EACE,iBAAA;C3B4iHD;A2B1iHD;;EC/KE,8BAAA;EACC,6BAAA;C5B6tHF;A2BziHD;EC7LE,2BAAA;EACC,0BAAA;C5ByuHF;A2BriHD;EACE,eAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;C3BuiHD;A2B3iHD;;EAOI,YAAA;EACA,oBAAA;EACA,UAAA;C3BwiHH;A2BjjHD;EAYI,YAAA;C3BwiHH;A2BpjHD;EAgBI,WAAA;C3BuiHH;A2BthHD;;;;EAKM,mBAAA;EACA,uBAAA;EACA,qBAAA;C3BuhHL;A6BjwHD;EACE,mBAAA;EACA,eAAA;EACA,0BAAA;C7BmwHD;A6BhwHC;EACE,YAAA;EACA,gBAAA;EACA,iBAAA;C7BkwHH;A6B3wHD;EAeI,mBAAA;EACA,WAAA;EAKA,YAAA;EAEA,YAAA;EACA,iBAAA;C7B0vHH;A6BjvHD;;;EV8BE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBwtHD;AmBttHC;;;EACE,aAAA;EACA,kBAAA;CnB0tHH;AmBvtHC;;;;;;EAEE,aAAA;CnB6tHH;A6BnwHD;;;EVyBE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnB+uHD;AmB7uHC;;;EACE,aAAA;EACA,kBAAA;CnBivHH;AmB9uHC;;;;;;EAEE,aAAA;CnBovHH;A6BjxHD;;;EAGE,oBAAA;C7BmxHD;A6BjxHC;;;EACE,iBAAA;C7BqxHH;A6BjxHD;;EAEE,UAAA;EACA,oBAAA;EACA,uBAAA;C7BmxHD;A6B9wHD;EACE,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;C7BgxHD;A6B7wHC;EACE,kBAAA;EACA,gBAAA;EACA,mBAAA;C7B+wHH;A6B7wHC;EACE,mBAAA;EACA,gBAAA;EACA,mBAAA;C7B+wHH;A6BnyHD;;EA0BI,cAAA;C7B6wHH;A6BxwHD;;;;;;;EDhGE,8BAAA;EACG,2BAAA;C5Bi3HJ;A6BzwHD;EACE,gBAAA;C7B2wHD;A6BzwHD;;;;;;;EDpGE,6BAAA;EACG,0BAAA;C5Bs3HJ;A6B1wHD;EACE,eAAA;C7B4wHD;A6BvwHD;EACE,mBAAA;EAGA,aAAA;EACA,oBAAA;C7BuwHD;A6B5wHD;EAUI,mBAAA;C7BqwHH;A6B/wHD;EAYM,kBAAA;C7BswHL;A6BnwHG;;;EAGE,WAAA;C7BqwHL;A6BhwHC;;EAGI,mBAAA;C7BiwHL;A6B9vHC;;EAGI,WAAA;EACA,kBAAA;C7B+vHL;A8B15HD;EACE,iBAAA;EACA,gBAAA;EACA,iBAAA;C9B45HD;A8B/5HD;EAOI,mBAAA;EACA,eAAA;C9B25HH;A8Bn6HD;EAWM,mBAAA;EACA,eAAA;EACA,mBAAA;C9B25HL;A8B15HK;;EAEE,sBAAA;EACA,0BAAA;C9B45HP;A8Bv5HG;EACE,eAAA;C9By5HL;A8Bv5HK;;EAEE,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,oBAAA;C9By5HP;A8Bl5HG;;;EAGE,0BAAA;EACA,sBAAA;C9Bo5HL;A8B77HD;ELHE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBm8HD;A8Bn8HD;EA0DI,gBAAA;C9B44HH;A8Bn4HD;EACE,iCAAA;C9Bq4HD;A8Bt4HD;EAGI,YAAA;EAEA,oBAAA;C9Bq4HH;A8B14HD;EASM,kBAAA;EACA,wBAAA;EACA,8BAAA;EACA,2BAAA;C9Bo4HL;A8Bn4HK;EACE,sCAAA;C9Bq4HP;A8B/3HK;;;EAGE,eAAA;EACA,0BAAA;EACA,0BAAA;EACA,iCAAA;EACA,gBAAA;C9Bi4HP;A8B53HC;EAqDA,YAAA;EA8BA,iBAAA;C9B6yHD;A8Bh4HC;EAwDE,YAAA;C9B20HH;A8Bn4HC;EA0DI,mBAAA;EACA,mBAAA;C9B40HL;A8Bv4HC;EAgEE,UAAA;EACA,WAAA;C9B00HH;A8B9zHD;EAAA;IAPM,oBAAA;IACA,UAAA;G9By0HH;E8Bn0HH;IAJQ,iBAAA;G9B00HL;CACF;A8Bp5HC;EAuFE,gBAAA;EACA,mBAAA;C9Bg0HH;A8Bx5HC;;;EA8FE,0BAAA;C9B+zHH;A8BjzHD;EAAA;IATM,iCAAA;IACA,2BAAA;G9B8zHH;E8BtzHH;;;IAHM,6BAAA;G9B8zHH;CACF;A8B/5HD;EAEI,YAAA;C9Bg6HH;A8Bl6HD;EAMM,mBAAA;C9B+5HL;A8Br6HD;EASM,iBAAA;C9B+5HL;A8B15HK;;;EAGE,eAAA;EACA,0BAAA;C9B45HP;A8Bp5HD;EAEI,YAAA;C9Bq5HH;A8Bv5HD;EAIM,gBAAA;EACA,eAAA;C9Bs5HL;A8B14HD;EACE,YAAA;C9B44HD;A8B74HD;EAII,YAAA;C9B44HH;A8Bh5HD;EAMM,mBAAA;EACA,mBAAA;C9B64HL;A8Bp5HD;EAYI,UAAA;EACA,WAAA;C9B24HH;A8B/3HD;EAAA;IAPM,oBAAA;IACA,UAAA;G9B04HH;E8Bp4HH;IAJQ,iBAAA;G9B24HL;CACF;A8Bn4HD;EACE,iBAAA;C9Bq4HD;A8Bt4HD;EAKI,gBAAA;EACA,mBAAA;C9Bo4HH;A8B14HD;;;EAYI,0BAAA;C9Bm4HH;A8Br3HD;EAAA;IATM,iCAAA;IACA,2BAAA;G9Bk4HH;E8B13HH;;;IAHM,6BAAA;G9Bk4HH;CACF;A8Bz3HD;EAEI,cAAA;C9B03HH;A8B53HD;EAKI,eAAA;C9B03HH;A8Bj3HD;EAEE,iBAAA;EF3OA,2BAAA;EACC,0BAAA;C5B8lIF;A+BxlID;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,8BAAA;C/B0lID;A+BllID;EAAA;IAFI,mBAAA;G/BwlID;CACF;A+BzkID;EAAA;IAFI,YAAA;G/B+kID;CACF;A+BjkID;EACE,oBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,2DAAA;UAAA,mDAAA;EAEA,kCAAA;C/BkkID;A+BhkIC;EACE,iBAAA;C/BkkIH;A+BtiID;EAAA;IAxBI,YAAA;IACA,cAAA;IACA,yBAAA;YAAA,iBAAA;G/BkkID;E+BhkIC;IACE,0BAAA;IACA,wBAAA;IACA,kBAAA;IACA,6BAAA;G/BkkIH;E+B/jIC;IACE,oBAAA;G/BikIH;E+B5jIC;;;IAGE,gBAAA;IACA,iBAAA;G/B8jIH;CACF;A+B1jID;;EAGI,kBAAA;C/B2jIH;A+BtjIC;EAAA;;IAFI,kBAAA;G/B6jIH;CACF;A+BpjID;;;;EAII,oBAAA;EACA,mBAAA;C/BsjIH;A+BhjIC;EAAA;;;;IAHI,gBAAA;IACA,eAAA;G/B0jIH;CACF;A+B9iID;EACE,cAAA;EACA,sBAAA;C/BgjID;A+B3iID;EAAA;IAFI,iBAAA;G/BijID;CACF;A+B7iID;;EAEE,gBAAA;EACA,SAAA;EACA,QAAA;EACA,cAAA;C/B+iID;A+BziID;EAAA;;IAFI,iBAAA;G/BgjID;CACF;A+B9iID;EACE,OAAA;EACA,sBAAA;C/BgjID;A+B9iID;EACE,UAAA;EACA,iBAAA;EACA,sBAAA;C/BgjID;A+B1iID;EACE,YAAA;EACA,mBAAA;EACA,gBAAA;EACA,kBAAA;EACA,aAAA;C/B4iID;A+B1iIC;;EAEE,sBAAA;C/B4iIH;A+BrjID;EAaI,eAAA;C/B2iIH;A+BliID;EALI;;IAEE,mBAAA;G/B0iIH;CACF;A+BhiID;EACE,mBAAA;EACA,aAAA;EACA,mBAAA;EACA,kBAAA;EC9LA,gBAAA;EACA,mBAAA;ED+LA,8BAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;C/BmiID;A+B/hIC;EACE,WAAA;C/BiiIH;A+B/iID;EAmBI,eAAA;EACA,YAAA;EACA,YAAA;EACA,mBAAA;C/B+hIH;A+BrjID;EAyBI,gBAAA;C/B+hIH;A+BzhID;EAAA;IAFI,cAAA;G/B+hID;CACF;A+BthID;EACE,oBAAA;C/BwhID;A+BzhID;EAII,kBAAA;EACA,qBAAA;EACA,kBAAA;C/BwhIH;A+B5/HC;EAAA;IAtBI,iBAAA;IACA,YAAA;IACA,YAAA;IACA,cAAA;IACA,8BAAA;IACA,UAAA;IACA,yBAAA;YAAA,iBAAA;G/BshIH;E+BtgID;;IAbM,2BAAA;G/BuhIL;E+B1gID;IAVM,kBAAA;G/BuhIL;E+BthIK;;IAEE,uBAAA;G/BwhIP;CACF;A+BtgID;EAAA;IAXI,YAAA;IACA,UAAA;G/BqhID;E+B3gIH;IAPM,YAAA;G/BqhIH;E+B9gIH;IALQ,kBAAA;IACA,qBAAA;G/BshIL;CACF;A+B3gID;EACE,mBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,qCAAA;E1B9NA,6FAAA;EACQ,qFAAA;E2B/DR,gBAAA;EACA,mBAAA;ChC4yID;AkB5xHD;EAAA;IA9DM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlB81HH;EkBlyHH;IAvDM,sBAAA;IACA,YAAA;IACA,uBAAA;GlB41HH;EkBvyHH;IAhDM,sBAAA;GlB01HH;EkB1yHH;IA5CM,sBAAA;IACA,uBAAA;GlBy1HH;EkB9yHH;;;IAtCQ,YAAA;GlBy1HL;EkBnzHH;IAhCM,YAAA;GlBs1HH;EkBtzHH;IA5BM,iBAAA;IACA,uBAAA;GlBq1HH;EkB1zHH;;IApBM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlBk1HH;EkBj0HH;;IAdQ,gBAAA;GlBm1HL;EkBr0HH;;IATM,mBAAA;IACA,eAAA;GlBk1HH;EkB10HH;IAHM,OAAA;GlBg1HH;CACF;A+BpjIC;EAAA;IANI,mBAAA;G/B8jIH;E+B5jIG;IACE,iBAAA;G/B8jIL;CACF;A+B7iID;EAAA;IARI,YAAA;IACA,UAAA;IACA,eAAA;IACA,gBAAA;IACA,eAAA;IACA,kBAAA;I1BzPF,yBAAA;IACQ,iBAAA;GLmzIP;CACF;A+BnjID;EACE,cAAA;EHpUA,2BAAA;EACC,0BAAA;C5B03IF;A+BnjID;EACE,iBAAA;EHzUA,6BAAA;EACC,4BAAA;EAOD,8BAAA;EACC,6BAAA;C5By3IF;A+B/iID;EChVE,gBAAA;EACA,mBAAA;ChCk4ID;A+BhjIC;ECnVA,iBAAA;EACA,oBAAA;ChCs4ID;A+BjjIC;ECtVA,iBAAA;EACA,oBAAA;ChC04ID;A+B3iID;EChWE,iBAAA;EACA,oBAAA;ChC84ID;A+BviID;EAAA;IAJI,YAAA;IACA,kBAAA;IACA,mBAAA;G/B+iID;CACF;A+BlhID;EAhBE;IExWA,uBAAA;GjC84IC;E+BriID;IE5WA,wBAAA;IF8WE,oBAAA;G/BuiID;E+BziID;IAKI,gBAAA;G/BuiIH;CACF;A+B9hID;EACE,0BAAA;EACA,sBAAA;C/BgiID;A+BliID;EAKI,eAAA;C/BgiIH;A+B/hIG;;EAEE,eAAA;EACA,8BAAA;C/BiiIL;A+B1iID;EAcI,eAAA;C/B+hIH;A+B7iID;EAmBM,eAAA;C/B6hIL;A+B3hIK;;EAEE,eAAA;EACA,8BAAA;C/B6hIP;A+BzhIK;;;EAGE,eAAA;EACA,0BAAA;C/B2hIP;A+BvhIK;;;EAGE,eAAA;EACA,8BAAA;C/ByhIP;A+BjkID;EA8CI,sBAAA;C/BshIH;A+BrhIG;;EAEE,0BAAA;C/BuhIL;A+BxkID;EAoDM,0BAAA;C/BuhIL;A+B3kID;;EA0DI,sBAAA;C/BqhIH;A+B9gIK;;;EAGE,0BAAA;EACA,eAAA;C/BghIP;A+B/+HC;EAAA;IAzBQ,eAAA;G/B4gIP;E+B3gIO;;IAEE,eAAA;IACA,8BAAA;G/B6gIT;E+BzgIO;;;IAGE,eAAA;IACA,0BAAA;G/B2gIT;E+BvgIO;;;IAGE,eAAA;IACA,8BAAA;G/BygIT;CACF;A+B3mID;EA8GI,eAAA;C/BggIH;A+B//HG;EACE,eAAA;C/BigIL;A+BjnID;EAqHI,eAAA;C/B+/HH;A+B9/HG;;EAEE,eAAA;C/BggIL;A+B5/HK;;;;EAEE,eAAA;C/BggIP;A+Bx/HD;EACE,0BAAA;EACA,sBAAA;C/B0/HD;A+B5/HD;EAKI,eAAA;C/B0/HH;A+Bz/HG;;EAEE,eAAA;EACA,8BAAA;C/B2/HL;A+BpgID;EAcI,eAAA;C/By/HH;A+BvgID;EAmBM,eAAA;C/Bu/HL;A+Br/HK;;EAEE,eAAA;EACA,8BAAA;C/Bu/HP;A+Bn/HK;;;EAGE,eAAA;EACA,0BAAA;C/Bq/HP;A+Bj/HK;;;EAGE,eAAA;EACA,8BAAA;C/Bm/HP;A+B3hID;EA+CI,sBAAA;C/B++HH;A+B9+HG;;EAEE,0BAAA;C/Bg/HL;A+BliID;EAqDM,0BAAA;C/Bg/HL;A+BriID;;EA2DI,sBAAA;C/B8+HH;A+Bx+HK;;;EAGE,0BAAA;EACA,eAAA;C/B0+HP;A+Bn8HC;EAAA;IA/BQ,sBAAA;G/Bs+HP;E+Bv8HD;IA5BQ,0BAAA;G/Bs+HP;E+B18HD;IAzBQ,eAAA;G/Bs+HP;E+Br+HO;;IAEE,eAAA;IACA,8BAAA;G/Bu+HT;E+Bn+HO;;;IAGE,eAAA;IACA,0BAAA;G/Bq+HT;E+Bj+HO;;;IAGE,eAAA;IACA,8BAAA;G/Bm+HT;CACF;A+B3kID;EA+GI,eAAA;C/B+9HH;A+B99HG;EACE,eAAA;C/Bg+HL;A+BjlID;EAsHI,eAAA;C/B89HH;A+B79HG;;EAEE,eAAA;C/B+9HL;A+B39HK;;;;EAEE,eAAA;C/B+9HP;AkCzmJD;EACE,kBAAA;EACA,oBAAA;EACA,iBAAA;EACA,0BAAA;EACA,mBAAA;ClC2mJD;AkChnJD;EAQI,sBAAA;ClC2mJH;AkCnnJD;EAWM,kBAAA;EACA,eAAA;EACA,eAAA;ClC2mJL;AkCxnJD;EAkBI,eAAA;ClCymJH;AmC7nJD;EACE,sBAAA;EACA,gBAAA;EACA,eAAA;EACA,mBAAA;CnC+nJD;AmCnoJD;EAOI,gBAAA;CnC+nJH;AmCtoJD;;EAUM,mBAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,sBAAA;EACA,eAAA;EACA,0BAAA;EACA,0BAAA;EACA,kBAAA;CnCgoJL;AmC9nJG;;EAGI,eAAA;EPXN,+BAAA;EACG,4BAAA;C5B2oJJ;AmC7nJG;;EPvBF,gCAAA;EACG,6BAAA;C5BwpJJ;AmCxnJG;;;;EAEE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,sBAAA;CnC4nJL;AmCtnJG;;;;;;EAGE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,sBAAA;EACA,gBAAA;CnC2nJL;AmClrJD;;;;;;EAkEM,eAAA;EACA,0BAAA;EACA,sBAAA;EACA,oBAAA;CnCwnJL;AmC/mJD;;EC3EM,mBAAA;EACA,gBAAA;EACA,uBAAA;CpC8rJL;AoC5rJG;;ERKF,+BAAA;EACG,4BAAA;C5B2rJJ;AoC3rJG;;ERTF,gCAAA;EACG,6BAAA;C5BwsJJ;AmC1nJD;;EChFM,kBAAA;EACA,gBAAA;EACA,iBAAA;CpC8sJL;AoC5sJG;;ERKF,+BAAA;EACG,4BAAA;C5B2sJJ;AoC3sJG;;ERTF,gCAAA;EACG,6BAAA;C5BwtJJ;AqC3tJD;EACE,gBAAA;EACA,eAAA;EACA,iBAAA;EACA,mBAAA;CrC6tJD;AqCjuJD;EAOI,gBAAA;CrC6tJH;AqCpuJD;;EAUM,sBAAA;EACA,kBAAA;EACA,0BAAA;EACA,0BAAA;EACA,oBAAA;CrC8tJL;AqC5uJD;;EAmBM,sBAAA;EACA,0BAAA;CrC6tJL;AqCjvJD;;EA2BM,aAAA;CrC0tJL;AqCrvJD;;EAkCM,YAAA;CrCutJL;AqCzvJD;;;;EA2CM,eAAA;EACA,0BAAA;EACA,oBAAA;CrCotJL;AsClwJD;EACE,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,kBAAA;EACA,eAAA;EACA,eAAA;EACA,mBAAA;EACA,oBAAA;EACA,yBAAA;EACA,qBAAA;CtCowJD;AsChwJG;;EAEE,eAAA;EACA,sBAAA;EACA,gBAAA;CtCkwJL;AsC7vJC;EACE,cAAA;CtC+vJH;AsC3vJC;EACE,mBAAA;EACA,UAAA;CtC6vJH;AsCtvJD;ECtCE,0BAAA;CvC+xJD;AuC5xJG;;EAEE,0BAAA;CvC8xJL;AsCzvJD;EC1CE,0BAAA;CvCsyJD;AuCnyJG;;EAEE,0BAAA;CvCqyJL;AsC5vJD;EC9CE,0BAAA;CvC6yJD;AuC1yJG;;EAEE,0BAAA;CvC4yJL;AsC/vJD;EClDE,0BAAA;CvCozJD;AuCjzJG;;EAEE,0BAAA;CvCmzJL;AsClwJD;ECtDE,0BAAA;CvC2zJD;AuCxzJG;;EAEE,0BAAA;CvC0zJL;AsCrwJD;EC1DE,0BAAA;CvCk0JD;AuC/zJG;;EAEE,0BAAA;CvCi0JL;AwCn0JD;EACE,sBAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,eAAA;EACA,uBAAA;EACA,oBAAA;EACA,mBAAA;EACA,0BAAA;EACA,oBAAA;CxCq0JD;AwCl0JC;EACE,cAAA;CxCo0JH;AwCh0JC;EACE,mBAAA;EACA,UAAA;CxCk0JH;AwC/zJC;;EAEE,OAAA;EACA,iBAAA;CxCi0JH;AwC5zJG;;EAEE,eAAA;EACA,sBAAA;EACA,gBAAA;CxC8zJL;AwCzzJC;;EAEE,eAAA;EACA,0BAAA;CxC2zJH;AwCxzJC;EACE,aAAA;CxC0zJH;AwCvzJC;EACE,kBAAA;CxCyzJH;AwCtzJC;EACE,iBAAA;CxCwzJH;AyCl3JD;EACE,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,eAAA;EACA,0BAAA;CzCo3JD;AyCz3JD;;EASI,eAAA;CzCo3JH;AyC73JD;EAaI,oBAAA;EACA,gBAAA;EACA,iBAAA;CzCm3JH;AyCl4JD;EAmBI,0BAAA;CzCk3JH;AyC/2JC;;EAEE,mBAAA;CzCi3JH;AyCz4JD;EA4BI,gBAAA;CzCg3JH;AyC91JD;EAAA;IAdI,kBAAA;IACA,qBAAA;GzCg3JD;EyC92JC;;IAEE,mBAAA;IACA,oBAAA;GzCg3JH;EyCx2JH;;IAHM,gBAAA;GzC+2JH;CACF;A0C15JD;EACE,eAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;ErCiLA,4CAAA;EACK,uCAAA;EACG,oCAAA;CL4uJT;A0Ct6JD;;EAaI,kBAAA;EACA,mBAAA;C1C65JH;A0Cz5JC;;;EAGE,sBAAA;C1C25JH;A0Ch7JD;EA0BI,aAAA;EACA,eAAA;C1Cy5JH;A2Cl7JD;EACE,cAAA;EACA,oBAAA;EACA,8BAAA;EACA,mBAAA;C3Co7JD;A2Cx7JD;EAQI,cAAA;EAEA,eAAA;C3Ck7JH;A2C57JD;EAeI,kBAAA;C3Cg7JH;A2C/7JD;;EAqBI,iBAAA;C3C86JH;A2Cn8JD;EAyBI,gBAAA;C3C66JH;A2Cr6JD;;EAEE,oBAAA;C3Cu6JD;A2Cz6JD;;EAMI,mBAAA;EACA,UAAA;EACA,aAAA;EACA,eAAA;C3Cu6JH;A2C/5JD;ECvDE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Cy9JD;A2Cp6JD;EClDI,0BAAA;C5Cy9JH;A2Cv6JD;EC/CI,eAAA;C5Cy9JH;A2Ct6JD;EC3DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Co+JD;A2C36JD;ECtDI,0BAAA;C5Co+JH;A2C96JD;ECnDI,eAAA;C5Co+JH;A2C76JD;EC/DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C++JD;A2Cl7JD;EC1DI,0BAAA;C5C++JH;A2Cr7JD;ECvDI,eAAA;C5C++JH;A2Cp7JD;ECnEE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C0/JD;A2Cz7JD;EC9DI,0BAAA;C5C0/JH;A2C57JD;EC3DI,eAAA;C5C0/JH;A6C5/JD;EACE;IAAQ,4BAAA;G7C+/JP;E6C9/JD;IAAQ,yBAAA;G7CigKP;CACF;A6C9/JD;EACE;IAAQ,4BAAA;G7CigKP;E6ChgKD;IAAQ,yBAAA;G7CmgKP;CACF;A6CtgKD;EACE;IAAQ,4BAAA;G7CigKP;E6ChgKD;IAAQ,yBAAA;G7CmgKP;CACF;A6C5/JD;EACE,iBAAA;EACA,aAAA;EACA,oBAAA;EACA,0BAAA;EACA,mBAAA;ExCsCA,uDAAA;EACQ,+CAAA;CLy9JT;A6C3/JD;EACE,YAAA;EACA,UAAA;EACA,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;ExCyBA,uDAAA;EACQ,+CAAA;EAyHR,oCAAA;EACK,+BAAA;EACG,4BAAA;CL62JT;A6Cx/JD;;ECCI,8MAAA;EACA,yMAAA;EACA,sMAAA;EDAF,mCAAA;UAAA,2BAAA;C7C4/JD;A6Cr/JD;;ExC5CE,2DAAA;EACK,sDAAA;EACG,mDAAA;CLqiKT;A6Cl/JD;EErEE,0BAAA;C/C0jKD;A+CvjKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C0gKH;A6Ct/JD;EEzEE,0BAAA;C/CkkKD;A+C/jKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9CkhKH;A6C1/JD;EE7EE,0BAAA;C/C0kKD;A+CvkKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C0hKH;A6C9/JD;EEjFE,0BAAA;C/CklKD;A+C/kKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9CkiKH;AgD1lKD;EAEE,iBAAA;ChD2lKD;AgDzlKC;EACE,cAAA;ChD2lKH;AgDvlKD;;EAEE,QAAA;EACA,iBAAA;ChDylKD;AgDtlKD;EACE,eAAA;ChDwlKD;AgDrlKD;EACE,eAAA;ChDulKD;AgDplKC;EACE,gBAAA;ChDslKH;AgDllKD;;EAEE,mBAAA;ChDolKD;AgDjlKD;;EAEE,oBAAA;ChDmlKD;AgDhlKD;;;EAGE,oBAAA;EACA,oBAAA;ChDklKD;AgD/kKD;EACE,uBAAA;ChDilKD;AgD9kKD;EACE,uBAAA;ChDglKD;AgD5kKD;EACE,cAAA;EACA,mBAAA;ChD8kKD;AgDxkKD;EACE,gBAAA;EACA,iBAAA;ChD0kKD;AiDjoKD;EAEE,oBAAA;EACA,gBAAA;CjDkoKD;AiD1nKD;EACE,mBAAA;EACA,eAAA;EACA,mBAAA;EAEA,oBAAA;EACA,0BAAA;EACA,0BAAA;CjD2nKD;AiDxnKC;ErB3BA,6BAAA;EACC,4BAAA;C5BspKF;AiDznKC;EACE,iBAAA;ErBvBF,gCAAA;EACC,+BAAA;C5BmpKF;AiDlnKD;;EAEE,eAAA;CjDonKD;AiDtnKD;;EAKI,eAAA;CjDqnKH;AiDjnKC;;;;EAEE,sBAAA;EACA,eAAA;EACA,0BAAA;CjDqnKH;AiDjnKD;EACE,YAAA;EACA,iBAAA;CjDmnKD;AiD9mKC;;;EAGE,0BAAA;EACA,eAAA;EACA,oBAAA;CjDgnKH;AiDrnKC;;;EASI,eAAA;CjDinKL;AiD1nKC;;;EAYI,eAAA;CjDmnKL;AiD9mKC;;;EAGE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,sBAAA;CjDgnKH;AiDtnKC;;;;;;;;;EAYI,eAAA;CjDqnKL;AiDjoKC;;;EAeI,eAAA;CjDunKL;AkDztKC;EACE,eAAA;EACA,0BAAA;ClD2tKH;AkDztKG;;EAEE,eAAA;ClD2tKL;AkD7tKG;;EAKI,eAAA;ClD4tKP;AkDztKK;;;;EAEE,eAAA;EACA,0BAAA;ClD6tKP;AkD3tKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDguKP;AkDtvKC;EACE,eAAA;EACA,0BAAA;ClDwvKH;AkDtvKG;;EAEE,eAAA;ClDwvKL;AkD1vKG;;EAKI,eAAA;ClDyvKP;AkDtvKK;;;;EAEE,eAAA;EACA,0BAAA;ClD0vKP;AkDxvKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD6vKP;AkDnxKC;EACE,eAAA;EACA,0BAAA;ClDqxKH;AkDnxKG;;EAEE,eAAA;ClDqxKL;AkDvxKG;;EAKI,eAAA;ClDsxKP;AkDnxKK;;;;EAEE,eAAA;EACA,0BAAA;ClDuxKP;AkDrxKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD0xKP;AkDhzKC;EACE,eAAA;EACA,0BAAA;ClDkzKH;AkDhzKG;;EAEE,eAAA;ClDkzKL;AkDpzKG;;EAKI,eAAA;ClDmzKP;AkDhzKK;;;;EAEE,eAAA;EACA,0BAAA;ClDozKP;AkDlzKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDuzKP;AiDttKD;EACE,cAAA;EACA,mBAAA;CjDwtKD;AiDttKD;EACE,iBAAA;EACA,iBAAA;CjDwtKD;AmDl1KD;EACE,oBAAA;EACA,0BAAA;EACA,8BAAA;EACA,mBAAA;E9C0DA,kDAAA;EACQ,0CAAA;CL2xKT;AmDj1KD;EACE,cAAA;CnDm1KD;AmD90KD;EACE,mBAAA;EACA,qCAAA;EvBpBA,6BAAA;EACC,4BAAA;C5Bq2KF;AmDp1KD;EAMI,eAAA;CnDi1KH;AmD50KD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,eAAA;CnD80KD;AmDl1KD;;;;;EAWI,eAAA;CnD80KH;AmDz0KD;EACE,mBAAA;EACA,0BAAA;EACA,8BAAA;EvBxCA,gCAAA;EACC,+BAAA;C5Bo3KF;AmDn0KD;;EAGI,iBAAA;CnDo0KH;AmDv0KD;;EAMM,oBAAA;EACA,iBAAA;CnDq0KL;AmDj0KG;;EAEI,cAAA;EvBvEN,6BAAA;EACC,4BAAA;C5B24KF;AmD/zKG;;EAEI,iBAAA;EvBvEN,gCAAA;EACC,+BAAA;C5By4KF;AmDx1KD;EvB1DE,2BAAA;EACC,0BAAA;C5Bq5KF;AmD3zKD;EAEI,oBAAA;CnD4zKH;AmDzzKD;EACE,oBAAA;CnD2zKD;AmDnzKD;;;EAII,iBAAA;CnDozKH;AmDxzKD;;;EAOM,mBAAA;EACA,oBAAA;CnDszKL;AmD9zKD;;EvBzGE,6BAAA;EACC,4BAAA;C5B26KF;AmDn0KD;;;;EAmBQ,4BAAA;EACA,6BAAA;CnDszKP;AmD10KD;;;;;;;;EAwBU,4BAAA;CnD4zKT;AmDp1KD;;;;;;;;EA4BU,6BAAA;CnDk0KT;AmD91KD;;EvBjGE,gCAAA;EACC,+BAAA;C5Bm8KF;AmDn2KD;;;;EAyCQ,+BAAA;EACA,gCAAA;CnDg0KP;AmD12KD;;;;;;;;EA8CU,+BAAA;CnDs0KT;AmDp3KD;;;;;;;;EAkDU,gCAAA;CnD40KT;AmD93KD;;;;EA2DI,8BAAA;CnDy0KH;AmDp4KD;;EA+DI,cAAA;CnDy0KH;AmDx4KD;;EAmEI,UAAA;CnDy0KH;AmD54KD;;;;;;;;;;;;EA0EU,eAAA;CnDg1KT;AmD15KD;;;;;;;;;;;;EA8EU,gBAAA;CnD01KT;AmDx6KD;;;;;;;;EAuFU,iBAAA;CnD21KT;AmDl7KD;;;;;;;;EAgGU,iBAAA;CnD41KT;AmD57KD;EAsGI,UAAA;EACA,iBAAA;CnDy1KH;AmD/0KD;EACE,oBAAA;CnDi1KD;AmDl1KD;EAKI,iBAAA;EACA,mBAAA;CnDg1KH;AmDt1KD;EASM,gBAAA;CnDg1KL;AmDz1KD;EAcI,iBAAA;CnD80KH;AmD51KD;;EAkBM,8BAAA;CnD80KL;AmDh2KD;EAuBI,cAAA;CnD40KH;AmDn2KD;EAyBM,iCAAA;CnD60KL;AmDt0KD;EC1PE,sBAAA;CpDmkLD;AoDjkLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDmkLH;AoDtkLC;EAMI,0BAAA;CpDmkLL;AoDzkLC;EASI,eAAA;EACA,0BAAA;CpDmkLL;AoDhkLC;EAEI,6BAAA;CpDikLL;AmDr1KD;EC7PE,sBAAA;CpDqlLD;AoDnlLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDqlLH;AoDxlLC;EAMI,0BAAA;CpDqlLL;AoD3lLC;EASI,eAAA;EACA,0BAAA;CpDqlLL;AoDllLC;EAEI,6BAAA;CpDmlLL;AmDp2KD;EChQE,sBAAA;CpDumLD;AoDrmLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDumLH;AoD1mLC;EAMI,0BAAA;CpDumLL;AoD7mLC;EASI,eAAA;EACA,0BAAA;CpDumLL;AoDpmLC;EAEI,6BAAA;CpDqmLL;AmDn3KD;ECnQE,sBAAA;CpDynLD;AoDvnLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDynLH;AoD5nLC;EAMI,0BAAA;CpDynLL;AoD/nLC;EASI,eAAA;EACA,0BAAA;CpDynLL;AoDtnLC;EAEI,6BAAA;CpDunLL;AmDl4KD;ECtQE,sBAAA;CpD2oLD;AoDzoLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD2oLH;AoD9oLC;EAMI,0BAAA;CpD2oLL;AoDjpLC;EASI,eAAA;EACA,0BAAA;CpD2oLL;AoDxoLC;EAEI,6BAAA;CpDyoLL;AmDj5KD;ECzQE,sBAAA;CpD6pLD;AoD3pLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD6pLH;AoDhqLC;EAMI,0BAAA;CpD6pLL;AoDnqLC;EASI,eAAA;EACA,0BAAA;CpD6pLL;AoD1pLC;EAEI,6BAAA;CpD2pLL;AqD3qLD;EACE,mBAAA;EACA,eAAA;EACA,UAAA;EACA,WAAA;EACA,iBAAA;CrD6qLD;AqDlrLD;;;;;EAYI,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,aAAA;EACA,YAAA;EACA,UAAA;CrD6qLH;AqDxqLD;EACE,uBAAA;CrD0qLD;AqDtqLD;EACE,oBAAA;CrDwqLD;AsDnsLD;EACE,iBAAA;EACA,cAAA;EACA,oBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;EjDwDA,wDAAA;EACQ,gDAAA;CL8oLT;AsD7sLD;EASI,mBAAA;EACA,kCAAA;CtDusLH;AsDlsLD;EACE,cAAA;EACA,mBAAA;CtDosLD;AsDlsLD;EACE,aAAA;EACA,mBAAA;CtDosLD;AuD1tLD;EACE,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,eAAA;EACA,6BAAA;EjCRA,aAAA;EAGA,0BAAA;CtBmuLD;AuD3tLC;;EAEE,eAAA;EACA,sBAAA;EACA,gBAAA;EjCfF,aAAA;EAGA,0BAAA;CtB2uLD;AuDvtLC;EACE,WAAA;EACA,gBAAA;EACA,wBAAA;EACA,UAAA;EACA,yBAAA;CvDytLH;AwD9uLD;EACE,iBAAA;CxDgvLD;AwD5uLD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,kCAAA;EAIA,WAAA;CxD2uLD;AwDxuLC;EnD+GA,sCAAA;EACI,kCAAA;EACC,iCAAA;EACG,8BAAA;EAkER,oDAAA;EAEK,0CAAA;EACG,oCAAA;CL2jLT;AwD9uLC;EnD2GA,mCAAA;EACI,+BAAA;EACC,8BAAA;EACG,2BAAA;CLsoLT;AwDlvLD;EACE,mBAAA;EACA,iBAAA;CxDovLD;AwDhvLD;EACE,mBAAA;EACA,YAAA;EACA,aAAA;CxDkvLD;AwD9uLD;EACE,mBAAA;EACA,0BAAA;EACA,0BAAA;EACA,qCAAA;EACA,mBAAA;EnDaA,iDAAA;EACQ,yCAAA;EmDZR,qCAAA;UAAA,6BAAA;EAEA,WAAA;CxDgvLD;AwD5uLD;EACE,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,0BAAA;CxD8uLD;AwD5uLC;ElCrEA,WAAA;EAGA,yBAAA;CtBkzLD;AwD/uLC;ElCtEA,aAAA;EAGA,0BAAA;CtBszLD;AwD9uLD;EACE,cAAA;EACA,iCAAA;EACA,0BAAA;CxDgvLD;AwD7uLD;EACE,iBAAA;CxD+uLD;AwD3uLD;EACE,UAAA;EACA,wBAAA;CxD6uLD;AwDxuLD;EACE,mBAAA;EACA,cAAA;CxD0uLD;AwDtuLD;EACE,cAAA;EACA,kBAAA;EACA,8BAAA;CxDwuLD;AwD3uLD;EAQI,iBAAA;EACA,iBAAA;CxDsuLH;AwD/uLD;EAaI,kBAAA;CxDquLH;AwDlvLD;EAiBI,eAAA;CxDouLH;AwD/tLD;EACE,mBAAA;EACA,aAAA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;CxDiuLD;AwD/sLD;EAZE;IACE,aAAA;IACA,kBAAA;GxD8tLD;EwD5tLD;InDvEA,kDAAA;IACQ,0CAAA;GLsyLP;EwD3tLD;IAAY,aAAA;GxD8tLX;CACF;AwDztLD;EAFE;IAAY,aAAA;GxD+tLX;CACF;AyD92LD;EACE,mBAAA;EACA,cAAA;EACA,eAAA;ECRA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;EDHA,gBAAA;EnCVA,WAAA;EAGA,yBAAA;CtBq4LD;AyD13LC;EnCdA,aAAA;EAGA,0BAAA;CtBy4LD;AyD73LC;EAAW,iBAAA;EAAmB,eAAA;CzDi4L/B;AyDh4LC;EAAW,iBAAA;EAAmB,eAAA;CzDo4L/B;AyDn4LC;EAAW,gBAAA;EAAmB,eAAA;CzDu4L/B;AyDt4LC;EAAW,kBAAA;EAAmB,eAAA;CzD04L/B;AyDt4LD;EACE,iBAAA;EACA,iBAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;EACA,mBAAA;CzDw4LD;AyDp4LD;EACE,mBAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;CzDs4LD;AyDl4LC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,0BAAA;CzDo4LH;AyDl4LC;EACE,UAAA;EACA,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,0BAAA;CzDo4LH;AyDl4LC;EACE,UAAA;EACA,UAAA;EACA,oBAAA;EACA,wBAAA;EACA,0BAAA;CzDo4LH;AyDl4LC;EACE,SAAA;EACA,QAAA;EACA,iBAAA;EACA,4BAAA;EACA,4BAAA;CzDo4LH;AyDl4LC;EACE,SAAA;EACA,SAAA;EACA,iBAAA;EACA,4BAAA;EACA,2BAAA;CzDo4LH;AyDl4LC;EACE,OAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,6BAAA;CzDo4LH;AyDl4LC;EACE,OAAA;EACA,WAAA;EACA,iBAAA;EACA,wBAAA;EACA,6BAAA;CzDo4LH;AyDl4LC;EACE,OAAA;EACA,UAAA;EACA,iBAAA;EACA,wBAAA;EACA,6BAAA;CzDo4LH;A2Dj+LD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EDXA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;ECAA,gBAAA;EAEA,0BAAA;EACA,qCAAA;UAAA,6BAAA;EACA,0BAAA;EACA,qCAAA;EACA,mBAAA;EtD8CA,kDAAA;EACQ,0CAAA;CLi8LT;A2D5+LC;EAAY,kBAAA;C3D++Lb;A2D9+LC;EAAY,kBAAA;C3Di/Lb;A2Dh/LC;EAAY,iBAAA;C3Dm/Lb;A2Dl/LC;EAAY,mBAAA;C3Dq/Lb;A2Dl/LD;EACE,UAAA;EACA,kBAAA;EACA,gBAAA;EACA,0BAAA;EACA,iCAAA;EACA,2BAAA;C3Do/LD;A2Dj/LD;EACE,kBAAA;C3Dm/LD;A2D3+LC;;EAEE,mBAAA;EACA,eAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;C3D6+LH;A2D1+LD;EACE,mBAAA;C3D4+LD;A2D1+LD;EACE,mBAAA;EACA,YAAA;C3D4+LD;A2Dx+LC;EACE,UAAA;EACA,mBAAA;EACA,uBAAA;EACA,0BAAA;EACA,sCAAA;EACA,cAAA;C3D0+LH;A2Dz+LG;EACE,aAAA;EACA,YAAA;EACA,mBAAA;EACA,uBAAA;EACA,0BAAA;C3D2+LL;A2Dx+LC;EACE,SAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,4BAAA;EACA,wCAAA;C3D0+LH;A2Dz+LG;EACE,aAAA;EACA,UAAA;EACA,cAAA;EACA,qBAAA;EACA,4BAAA;C3D2+LL;A2Dx+LC;EACE,UAAA;EACA,mBAAA;EACA,oBAAA;EACA,6BAAA;EACA,yCAAA;EACA,WAAA;C3D0+LH;A2Dz+LG;EACE,aAAA;EACA,SAAA;EACA,mBAAA;EACA,oBAAA;EACA,6BAAA;C3D2+LL;A2Dv+LC;EACE,SAAA;EACA,aAAA;EACA,kBAAA;EACA,sBAAA;EACA,2BAAA;EACA,uCAAA;C3Dy+LH;A2Dx+LG;EACE,aAAA;EACA,WAAA;EACA,sBAAA;EACA,2BAAA;EACA,cAAA;C3D0+LL;A4DnmMD;EACE,mBAAA;C5DqmMD;A4DlmMD;EACE,mBAAA;EACA,iBAAA;EACA,YAAA;C5DomMD;A4DvmMD;EAMI,cAAA;EACA,mBAAA;EvD6KF,0CAAA;EACK,qCAAA;EACG,kCAAA;CLw7LT;A4D9mMD;;EAcM,eAAA;C5DomML;A4D1kMC;EAAA;IvDiKA,uDAAA;IAEK,6CAAA;IACG,uCAAA;IA7JR,oCAAA;IAEQ,4BAAA;IA+GR,4BAAA;IAEQ,oBAAA;GL69LP;E4DxmMG;;IvDmHJ,2CAAA;IACQ,mCAAA;IuDjHF,QAAA;G5D2mML;E4DzmMG;;IvD8GJ,4CAAA;IACQ,oCAAA;IuD5GF,QAAA;G5D4mML;E4D1mMG;;;IvDyGJ,wCAAA;IACQ,gCAAA;IuDtGF,QAAA;G5D6mML;CACF;A4DnpMD;;;EA6CI,eAAA;C5D2mMH;A4DxpMD;EAiDI,QAAA;C5D0mMH;A4D3pMD;;EAsDI,mBAAA;EACA,OAAA;EACA,YAAA;C5DymMH;A4DjqMD;EA4DI,WAAA;C5DwmMH;A4DpqMD;EA+DI,YAAA;C5DwmMH;A4DvqMD;;EAmEI,QAAA;C5DwmMH;A4D3qMD;EAuEI,YAAA;C5DumMH;A4D9qMD;EA0EI,WAAA;C5DumMH;A4D/lMD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EtC9FA,aAAA;EAGA,0BAAA;EsC6FA,gBAAA;EACA,eAAA;EACA,mBAAA;EACA,0CAAA;C5DkmMD;A4D7lMC;EdlGE,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9CksMH;A4DjmMC;EACE,WAAA;EACA,SAAA;EdvGA,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9C2sMH;A4DnmMC;;EAEE,WAAA;EACA,eAAA;EACA,sBAAA;EtCtHF,aAAA;EAGA,0BAAA;CtB0tMD;A4DpoMD;;;;EAsCI,mBAAA;EACA,SAAA;EACA,kBAAA;EACA,WAAA;EACA,sBAAA;C5DomMH;A4D9oMD;;EA8CI,UAAA;EACA,mBAAA;C5DomMH;A4DnpMD;;EAmDI,WAAA;EACA,oBAAA;C5DomMH;A4DxpMD;;EAwDI,YAAA;EACA,aAAA;EACA,eAAA;EACA,mBAAA;C5DomMH;A4D/lMG;EACE,iBAAA;C5DimML;A4D7lMG;EACE,iBAAA;C5D+lML;A4DrlMD;EACE,mBAAA;EACA,aAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;C5DulMD;A4DhmMD;EAYI,sBAAA;EACA,YAAA;EACA,aAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;EACA,oBAAA;EACA,gBAAA;EAWA,0BAAA;EACA,mCAAA;C5D6kMH;A4D5mMD;EAkCI,UAAA;EACA,YAAA;EACA,aAAA;EACA,0BAAA;C5D6kMH;A4DtkMD;EACE,mBAAA;EACA,UAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,eAAA;EACA,mBAAA;EACA,0CAAA;C5DwkMD;A4DvkMC;EACE,kBAAA;C5DykMH;A4DhiMD;EAhCE;;;;IAKI,YAAA;IACA,aAAA;IACA,kBAAA;IACA,gBAAA;G5DkkMH;E4D1kMD;;IAYI,mBAAA;G5DkkMH;E4D9kMD;;IAgBI,oBAAA;G5DkkMH;E4D7jMD;IACE,UAAA;IACA,WAAA;IACA,qBAAA;G5D+jMD;E4D3jMD;IACE,aAAA;G5D6jMD;CACF;A6D3zMC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,aAAA;EACA,eAAA;C7Dy1MH;A6Dv1MC;;;;;;;;;;;;;;;EACE,YAAA;C7Du2MH;AiC/2MD;E6BRE,eAAA;EACA,kBAAA;EACA,mBAAA;C9D03MD;AiCj3MD;EACE,wBAAA;CjCm3MD;AiCj3MD;EACE,uBAAA;CjCm3MD;AiC32MD;EACE,yBAAA;CjC62MD;AiC32MD;EACE,0BAAA;CjC62MD;AiC32MD;EACE,mBAAA;CjC62MD;AiC32MD;E8BzBE,YAAA;EACA,mBAAA;EACA,kBAAA;EACA,8BAAA;EACA,UAAA;C/Du4MD;AiCz2MD;EACE,yBAAA;CjC22MD;AiCp2MD;EACE,gBAAA;CjCs2MD;AgEv4MD;EACE,oBAAA;ChEy4MD;AgEn4MD;;;;ECdE,yBAAA;CjEu5MD;AgEl4MD;;;;;;;;;;;;EAYE,yBAAA;ChEo4MD;AgE73MD;EAAA;IChDE,0BAAA;GjEi7MC;EiEh7MD;IAAU,0BAAA;GjEm7MT;EiEl7MD;IAAU,8BAAA;GjEq7MT;EiEp7MD;;IACU,+BAAA;GjEu7MT;CACF;AgEv4MD;EAAA;IAFI,0BAAA;GhE64MD;CACF;AgEv4MD;EAAA;IAFI,2BAAA;GhE64MD;CACF;AgEv4MD;EAAA;IAFI,iCAAA;GhE64MD;CACF;AgEt4MD;EAAA;ICrEE,0BAAA;GjE+8MC;EiE98MD;IAAU,0BAAA;GjEi9MT;EiEh9MD;IAAU,8BAAA;GjEm9MT;EiEl9MD;;IACU,+BAAA;GjEq9MT;CACF;AgEh5MD;EAAA;IAFI,0BAAA;GhEs5MD;CACF;AgEh5MD;EAAA;IAFI,2BAAA;GhEs5MD;CACF;AgEh5MD;EAAA;IAFI,iCAAA;GhEs5MD;CACF;AgE/4MD;EAAA;IC1FE,0BAAA;GjE6+MC;EiE5+MD;IAAU,0BAAA;GjE++MT;EiE9+MD;IAAU,8BAAA;GjEi/MT;EiEh/MD;;IACU,+BAAA;GjEm/MT;CACF;AgEz5MD;EAAA;IAFI,0BAAA;GhE+5MD;CACF;AgEz5MD;EAAA;IAFI,2BAAA;GhE+5MD;CACF;AgEz5MD;EAAA;IAFI,iCAAA;GhE+5MD;CACF;AgEx5MD;EAAA;IC/GE,0BAAA;GjE2gNC;EiE1gND;IAAU,0BAAA;GjE6gNT;EiE5gND;IAAU,8BAAA;GjE+gNT;EiE9gND;;IACU,+BAAA;GjEihNT;CACF;AgEl6MD;EAAA;IAFI,0BAAA;GhEw6MD;CACF;AgEl6MD;EAAA;IAFI,2BAAA;GhEw6MD;CACF;AgEl6MD;EAAA;IAFI,iCAAA;GhEw6MD;CACF;AgEj6MD;EAAA;IC5HE,yBAAA;GjEiiNC;CACF;AgEj6MD;EAAA;ICjIE,yBAAA;GjEsiNC;CACF;AgEj6MD;EAAA;ICtIE,yBAAA;GjE2iNC;CACF;AgEj6MD;EAAA;IC3IE,yBAAA;GjEgjNC;CACF;AgE95MD;ECnJE,yBAAA;CjEojND;AgE35MD;EAAA;ICjKE,0BAAA;GjEgkNC;EiE/jND;IAAU,0BAAA;GjEkkNT;EiEjkND;IAAU,8BAAA;GjEokNT;EiEnkND;;IACU,+BAAA;GjEskNT;CACF;AgEz6MD;EACE,yBAAA;ChE26MD;AgEt6MD;EAAA;IAFI,0BAAA;GhE46MD;CACF;AgE16MD;EACE,yBAAA;ChE46MD;AgEv6MD;EAAA;IAFI,2BAAA;GhE66MD;CACF;AgE36MD;EACE,yBAAA;ChE66MD;AgEx6MD;EAAA;IAFI,iCAAA;GhE86MD;CACF;AgEv6MD;EAAA;ICpLE,yBAAA;GjE+lNC;CACF","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\2a\";\n}\n.glyphicon-plus:before {\n content: \"\\2b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #ffffff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #ffffff;\n background-color: #333333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #dddddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #dddddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #dddddd;\n}\n.table .table {\n background-color: #ffffff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #dddddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #ffffff;\n background-image: none;\n border: 1px solid #cccccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999999;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 14.333333px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333333;\n background-color: #ffffff;\n border-color: #cccccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #ffffff;\n border-color: #cccccc;\n}\n.btn-default .badge {\n color: #ffffff;\n background-color: #333333;\n}\n.btn-primary {\n color: #ffffff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #ffffff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #ffffff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #ffffff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #ffffff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.btn-success {\n color: #ffffff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #ffffff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #ffffff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #ffffff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #ffffff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #ffffff;\n}\n.btn-info {\n color: #ffffff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #ffffff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #ffffff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #ffffff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #ffffff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #ffffff;\n}\n.btn-warning {\n color: #ffffff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #ffffff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #ffffff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #ffffff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #ffffff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #ffffff;\n}\n.btn-danger {\n color: #ffffff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #ffffff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #ffffff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #ffffff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #ffffff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #ffffff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #ffffff;\n border: 1px solid #cccccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #ffffff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-bottom-left-radius: 4px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #dddddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #dddddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #dddddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #ffffff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #ffffff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #dddddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #ffffff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #cccccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #dddddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #dddddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #cccccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777777;\n}\n.navbar-default .navbar-link:hover {\n color: #333333;\n}\n.navbar-default .btn-link {\n color: #777777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #cccccc;\n}\n.navbar-inverse {\n background-color: #222222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #ffffff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #ffffff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #ffffff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #ffffff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #ffffff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #ffffff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #ffffff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #ffffff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #ffffff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #cccccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 3;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #dddddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 2;\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #ffffff;\n border-color: #dddddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #ffffff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #ffffff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #ffffff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #ffffff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #ffffff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #ffffff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #ffffff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #dddddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #dddddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #dddddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #dddddd;\n}\n.panel-default {\n border-color: #dddddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #dddddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #dddddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #dddddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000000;\n text-shadow: 0 1px 0 #ffffff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #ffffff;\n border: 1px solid #999999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n min-height: 16.42857143px;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #ffffff;\n text-align: center;\n background-color: #000000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #ffffff;\n background-clip: padding-box;\n border: 1px solid #cccccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #ffffff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #ffffff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #ffffff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #ffffff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #ffffff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #ffffff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #ffffff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #ffffff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #ffffff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -15px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -15px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @grid-float-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655\n }\n\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned. As a workaround, we\n// set a pixel line-height that matches the given height of the input, but only\n// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848\n//\n// Note that as of 8.3, iOS doesn't support `datetime` or `week`.\n\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"datetime-local\"],\n input[type=\"month\"] {\n &.form-control {\n line-height: @input-height-base;\n }\n\n &.input-sm,\n .input-group-sm & {\n line-height: @input-height-small;\n }\n\n &.input-lg,\n .input-group-lg & {\n line-height: @input-height-large;\n }\n }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: @form-group-margin-bottom;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n\n label {\n min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n// Some special care is needed because <label>s don't inherit their parent's `cursor`.\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n &[disabled],\n &.disabled,\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n}\n// These classes are used directly on <label>s\n.radio-inline,\n.checkbox-inline {\n &.disabled,\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n}\n// These classes are used on elements with <label> descendants\n.radio,\n.checkbox {\n &.disabled,\n fieldset[disabled] & {\n label {\n cursor: @cursor-disabled;\n }\n }\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n // Size it appropriately next to real form controls\n padding-top: (@padding-base-vertical + 1);\n padding-bottom: (@padding-base-vertical + 1);\n // Remove default margin from `p`\n margin-bottom: 0;\n min-height: (@line-height-computed + @font-size-base);\n\n &.input-lg,\n &.input-sm {\n padding-left: 0;\n padding-right: 0;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n//\n// The `.form-group-* form-control` variations are sadly duplicated to avoid the\n// issue documented in https://github.com/twbs/bootstrap/issues/15074.\n\n.input-sm {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small);\n}\n.form-group-sm {\n .form-control {\n height: @input-height-small;\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n line-height: @line-height-small;\n border-radius: @input-border-radius-small;\n }\n select.form-control {\n height: @input-height-small;\n line-height: @input-height-small;\n }\n textarea.form-control,\n select[multiple].form-control {\n height: auto;\n }\n .form-control-static {\n height: @input-height-small;\n min-height: (@line-height-computed + @font-size-small);\n padding: (@padding-small-vertical + 1) @padding-small-horizontal;\n font-size: @font-size-small;\n line-height: @line-height-small;\n }\n}\n\n.input-lg {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large);\n}\n.form-group-lg {\n .form-control {\n height: @input-height-large;\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-large;\n border-radius: @input-border-radius-large;\n }\n select.form-control {\n height: @input-height-large;\n line-height: @input-height-large;\n }\n textarea.form-control,\n select[multiple].form-control {\n height: auto;\n }\n .form-control-static {\n height: @input-height-large;\n min-height: (@line-height-computed + @font-size-large);\n padding: (@padding-large-vertical + 1) @padding-large-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-large;\n }\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n}\n// Feedback icon (requires .glyphicon classes)\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2; // Ensure icon is above input groups\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: @input-height-large;\n height: @input-height-large;\n line-height: @input-height-large;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: @input-height-small;\n height: @input-height-small;\n line-height: @input-height-small;\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n// Reposition feedback icon if input has visible label above\n.has-feedback label {\n\n & ~ .form-control-feedback {\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n }\n &.sr-only ~ .form-control-feedback {\n top: 0;\n }\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n display: block; // account for any element using help-block\n margin-top: 5px;\n margin-bottom: 10px;\n color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n // Kick in the inline\n @media (min-width: @screen-sm-min) {\n // Inline-block all the things for \"inline\"\n .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // In navbar-form, allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n\n // Make static controls behave like regular ones\n .form-control-static {\n display: inline-block;\n }\n\n .input-group {\n display: inline-table;\n vertical-align: middle;\n\n .input-group-addon,\n .input-group-btn,\n .form-control {\n width: auto;\n }\n }\n\n // Input groups need that 100% width though\n .input-group > .form-control {\n width: 100%;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match.\n .radio,\n .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n\n label {\n padding-left: 0;\n }\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n\n // Re-override the feedback icon.\n .has-feedback .form-control-feedback {\n top: 0;\n }\n }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n // Consistent vertical alignment of radios and checkboxes\n //\n // Labels also get some reset styles, but that is scoped to a media query below.\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n // Reset spacing and right align labels, but scope to media queries so that\n // labels on narrow viewports stack the same as a default form example.\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n right: floor((@grid-gutter-width / 2));\n }\n\n // Form group sizes\n //\n // Quick utility class for applying `.input-lg` and `.input-sm` styles to the\n // inputs and labels within a `.form-group`.\n .form-group-lg {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: ((@padding-large-vertical * @line-height-large) + 1);\n font-size: @font-size-large;\n }\n }\n }\n .form-group-sm {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: (@padding-small-vertical + 1);\n font-size: @font-size-small;\n }\n }\n }\n}\n","// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n // Color the label and help text\n .help-block,\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline,\n &.radio label,\n &.checkbox label,\n &.radio-inline label,\n &.checkbox-inline label {\n color: @text-color;\n }\n // Set the border and box shadow on specific inputs to match\n .form-control {\n border-color: @border-color;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n &:focus {\n border-color: darken(@border-color, 10%);\n @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n .box-shadow(@shadow);\n }\n }\n // Set validation states also for addons\n .input-group-addon {\n color: @text-color;\n border-color: @border-color;\n background-color: @background-color;\n }\n // Optional feedback icon\n .form-control-feedback {\n color: @text-color;\n }\n}\n\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-border-focus` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n.form-control-focus(@color: @input-border-focus) {\n @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n &:focus {\n border-color: @color;\n outline: 0;\n .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `<a>` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n border-top-right-radius: @btn-border-radius-base;\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n border-bottom-left-radius: @btn-border-radius-base;\n .border-top-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @border-radius-base;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n // No need to set list-style: none; since .list-group-item is block level\n margin-bottom: 20px;\n padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n // Place the border on the list items and negative margin up for better styling\n margin-bottom: -1px;\n background-color: @list-group-bg;\n border: 1px solid @list-group-border;\n\n // Round the first and last items\n &:first-child {\n .border-top-radius(@list-group-border-radius);\n }\n &:last-child {\n margin-bottom: 0;\n .border-bottom-radius(@list-group-border-radius);\n }\n}\n\n\n// Interactive list items\n//\n// Use anchor or button elements instead of `li`s or `div`s to create interactive items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item,\nbutton.list-group-item {\n color: @list-group-link-color;\n\n .list-group-item-heading {\n color: @list-group-link-heading-color;\n }\n\n // Hover state\n &:hover,\n &:focus {\n text-decoration: none;\n color: @list-group-link-hover-color;\n background-color: @list-group-hover-bg;\n }\n}\n\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n\n.list-group-item {\n // Disabled state\n &.disabled,\n &.disabled:hover,\n &.disabled:focus {\n background-color: @list-group-disabled-bg;\n color: @list-group-disabled-color;\n cursor: @cursor-disabled;\n\n // Force color to inherit for custom content\n .list-group-item-heading {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-disabled-text-color;\n }\n }\n\n // Active class on item itself, not parent\n &.active,\n &.active:hover,\n &.active:focus {\n z-index: 2; // Place active items above their siblings for proper border styling\n color: @list-group-active-color;\n background-color: @list-group-active-bg;\n border-color: @list-group-active-border;\n\n // Force color to inherit for custom content\n .list-group-item-heading,\n .list-group-item-heading > small,\n .list-group-item-heading > .small {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-active-text-color;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n","// List Groups\n\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a&,\n button& {\n color: @color;\n\n .list-group-item-heading {\n color: inherit;\n }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\n }\n }\n}\n","//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n margin-bottom: @line-height-computed;\n background-color: @panel-bg;\n border: 1px solid transparent;\n border-radius: @panel-border-radius;\n .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n padding: @panel-body-padding;\n &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n padding: @panel-heading-padding;\n border-bottom: 1px solid transparent;\n .border-top-radius((@panel-border-radius - 1));\n\n > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: ceil((@font-size-base * 1.125));\n color: inherit;\n\n > a,\n > small,\n > .small,\n > small > a,\n > .small > a {\n color: inherit;\n }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n padding: @panel-footer-padding;\n background-color: @panel-footer-bg;\n border-top: 1px solid @panel-inner-border;\n .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n > .list-group,\n > .panel-collapse > .list-group {\n margin-bottom: 0;\n\n .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\n }\n }\n }\n > .panel-heading + .panel-collapse > .list-group {\n .list-group-item:first-child {\n .border-top-radius(0);\n }\n }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n .list-group-item:first-child {\n border-top-width: 0;\n }\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n > .table,\n > .table-responsive > .table,\n > .panel-collapse > .table {\n margin-bottom: 0;\n\n caption {\n padding-left: @panel-body-padding;\n padding-right: @panel-body-padding;\n }\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n border-top-right-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n border-bottom-right-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive,\n > .table + .panel-body,\n > .table-responsive + .panel-body {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n border: 0;\n margin-bottom: 0;\n }\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n margin-bottom: @line-height-computed;\n\n // Tighten up margin so it's only between panels\n .panel {\n margin-bottom: 0;\n border-radius: @panel-border-radius;\n\n + .panel {\n margin-top: 5px;\n }\n }\n\n .panel-heading {\n border-bottom: 0;\n\n + .panel-collapse > .panel-body,\n + .panel-collapse > .list-group {\n border-top: 1px solid @panel-inner-border;\n }\n }\n\n .panel-footer {\n border-top: 0;\n + .panel-collapse .panel-body {\n border-bottom: 1px solid @panel-inner-border;\n }\n }\n}\n\n\n// Contextual variations\n.panel-default {\n .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","// Panels\n\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n border-color: @border;\n\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\n + .panel-collapse > .panel-body {\n border-top-color: @border;\n }\n .badge {\n color: @heading-bg-color;\n background-color: @heading-text-color;\n }\n }\n & > .panel-footer {\n + .panel-collapse > .panel-body {\n border-bottom-color: @border;\n }\n }\n}\n","// Embeds responsive\n//\n// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n\n .embed-responsive-item,\n iframe,\n embed,\n object,\n video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n }\n}\n\n// Modifier class for 16:9 aspect ratio\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n\n// Modifier class for 4:3 aspect ratio\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: @well-bg;\n border: 1px solid @well-border;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n blockquote {\n border-color: #ddd;\n border-color: rgba(0,0,0,.15);\n }\n}\n\n// Sizes\n.well-lg {\n padding: 24px;\n border-radius: @border-radius-large;\n}\n.well-sm {\n padding: 9px;\n border-radius: @border-radius-small;\n}\n","//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n float: right;\n font-size: (@font-size-base * 1.5);\n font-weight: @close-font-weight;\n line-height: 1;\n color: @close-color;\n text-shadow: @close-text-shadow;\n .opacity(.2);\n\n &:hover,\n &:focus {\n color: @close-color;\n text-decoration: none;\n cursor: pointer;\n .opacity(.5);\n }\n\n // Additional properties for button version\n // iOS requires the button element instead of an anchor tag.\n // If you want the anchor version, it requires `href=\"#\"`.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n button& {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialog - positioning shell for the actual modal\n// .modal-content - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\n\n // When fading in the modal, animate it to slide down\n &.fade .modal-dialog {\n .translate(0, -25%);\n .transition-transform(~\"0.3s ease-out\");\n }\n &.in .modal-dialog { .translate(0, 0) }\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n position: relative;\n background-color: @modal-content-bg;\n border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n border: 1px solid @modal-content-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 3px 9px rgba(0,0,0,.5));\n background-clip: padding-box;\n // Remove focus outline from opened modal\n outline: 0;\n}\n\n// Modal background\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal-background;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n padding: @modal-title-padding;\n border-bottom: 1px solid @modal-header-border-color;\n min-height: (@modal-title-padding + @modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n margin: 0;\n line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n position: relative;\n padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n padding: @modal-inner-padding;\n text-align: right; // right align buttons\n border-top: 1px solid @modal-footer-border-color;\n &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n // Properly space out buttons\n .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n }\n // but override that for button groups\n .btn-group .btn + .btn {\n margin-left: -1px;\n }\n // and override it for block buttons as well\n .btn-block + .btn-block {\n margin-left: 0;\n }\n}\n\n// Measure scrollbar width for padding body during modal show/hide\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0,0,0,.5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n position: absolute;\n z-index: @zindex-tooltip;\n display: block;\n // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n .reset-text();\n font-size: @font-size-small;\n\n .opacity(0);\n\n &.in { .opacity(@tooltip-opacity); }\n &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }\n &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }\n &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }\n &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n max-width: @tooltip-max-width;\n padding: 3px 8px;\n color: @tooltip-color;\n text-align: center;\n background-color: @tooltip-bg;\n border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n// Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1\n.tooltip {\n &.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-left .tooltip-arrow {\n bottom: 0;\n right: @tooltip-arrow-width;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-right .tooltip-arrow {\n bottom: 0;\n left: @tooltip-arrow-width;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n border-right-color: @tooltip-arrow-color;\n }\n &.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-left-color: @tooltip-arrow-color;\n }\n &.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-left .tooltip-arrow {\n top: 0;\n right: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-right .tooltip-arrow {\n top: 0;\n left: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n",".reset-text() {\n font-family: @font-family-base;\n // We deliberately do NOT reset font-size.\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: @line-height-base;\n text-align: left; // Fallback for where `start` is not supported\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: @zindex-popover;\n display: none;\n max-width: @popover-max-width;\n padding: 1px;\n // Our parent element can be arbitrary since popovers are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n .reset-text();\n font-size: @font-size-base;\n\n background-color: @popover-bg;\n background-clip: padding-box;\n border: 1px solid @popover-fallback-border-color;\n border: 1px solid @popover-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n // Offset the popover to account for the popover arrow\n &.top { margin-top: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\n}\n\n.popover-title {\n margin: 0; // reset heading margin\n padding: 8px 14px;\n font-size: @font-size-base;\n background-color: @popover-title-bg;\n border-bottom: 1px solid darken(@popover-title-bg, 5%);\n border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0;\n}\n\n.popover-content {\n padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n &,\n &:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n }\n}\n.popover > .arrow {\n border-width: @popover-arrow-outer-width;\n}\n.popover > .arrow:after {\n border-width: @popover-arrow-width;\n content: \"\";\n}\n\n.popover {\n &.top > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-top-color: @popover-arrow-outer-color;\n bottom: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n bottom: 1px;\n margin-left: -@popover-arrow-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-color;\n }\n }\n &.right > .arrow {\n top: 50%;\n left: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-right-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n left: 1px;\n bottom: -@popover-arrow-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-color;\n }\n }\n &.bottom > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-bottom-color: @popover-arrow-outer-color;\n top: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n top: 1px;\n margin-left: -@popover-arrow-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-color;\n }\n }\n\n &.left > .arrow {\n top: 50%;\n right: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-right-width: 0;\n border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-left-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: @popover-arrow-color;\n bottom: -@popover-arrow-width;\n }\n }\n}\n","//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n\n > .item {\n display: none;\n position: relative;\n .transition(.6s ease-in-out left);\n\n // Account for jankitude on images\n > img,\n > a > img {\n &:extend(.img-responsive);\n line-height: 1;\n }\n\n // WebKit CSS3 transforms for supported devices\n @media all and (transform-3d), (-webkit-transform-3d) {\n .transition-transform(~'0.6s ease-in-out');\n .backface-visibility(~'hidden');\n .perspective(1000px);\n\n &.next,\n &.active.right {\n .translate3d(100%, 0, 0);\n left: 0;\n }\n &.prev,\n &.active.left {\n .translate3d(-100%, 0, 0);\n left: 0;\n }\n &.next.left,\n &.prev.right,\n &.active {\n .translate3d(0, 0, 0);\n left: 0;\n }\n }\n }\n\n > .active,\n > .next,\n > .prev {\n display: block;\n }\n\n > .active {\n left: 0;\n }\n\n > .next,\n > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n }\n\n > .next {\n left: 100%;\n }\n > .prev {\n left: -100%;\n }\n > .next.left,\n > .prev.right {\n left: 0;\n }\n\n > .active.left {\n left: -100%;\n }\n > .active.right {\n left: 100%;\n }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: @carousel-control-width;\n .opacity(@carousel-control-opacity);\n font-size: @carousel-control-font-size;\n color: @carousel-control-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n // We can't have this transition here because WebKit cancels the carousel\n // animation if you trip this while in the middle of another animation.\n\n // Set gradients for backgrounds\n &.left {\n #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n }\n &.right {\n left: auto;\n right: 0;\n #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n }\n\n // Hover/focus state\n &:hover,\n &:focus {\n outline: 0;\n color: @carousel-control-color;\n text-decoration: none;\n .opacity(.9);\n }\n\n // Toggles\n .icon-prev,\n .icon-next,\n .glyphicon-chevron-left,\n .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n }\n .icon-prev,\n .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n }\n\n\n .icon-prev {\n &:before {\n content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n }\n }\n .icon-next {\n &:before {\n content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n }\n }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n\n li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid @carousel-indicator-border-color;\n border-radius: 10px;\n cursor: pointer;\n\n // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0,0,0,0); // IE9\n }\n .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: @carousel-indicator-active-bg;\n }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: @carousel-caption-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n & .btn {\n text-shadow: none; // No shadow for button elements in carousel-caption\n }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n font-size: 30px;\n }\n .glyphicon-chevron-left,\n .icon-prev {\n margin-left: -15px;\n }\n .glyphicon-chevron-right,\n .icon-next {\n margin-right: -15px;\n }\n }\n\n // Show and left align the captions\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n\n // Move up the indicators\n .carousel-indicators {\n bottom: 20px;\n }\n}\n","// Clearfix\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n// contenteditable attribute is included anywhere else in the document.\n// Otherwise it causes space to appear at the top and bottom of elements\n// that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n// `:before` to contain the top-margins of child elements.\n//\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n\n.clearfix() {\n &:before,\n &:after {\n content: \" \"; // 1\n display: table; // 2\n }\n &:after {\n clear: both;\n }\n}\n","// Center-align a block level element\n\n.center-block() {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n","// CSS image replacement\n//\n// Heads up! v3 launched with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\n}\n","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#support-ie10-width\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n// Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\n\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-xs-block {\n @media (max-width: @screen-xs-max) {\n display: block !important;\n }\n}\n.visible-xs-inline {\n @media (max-width: @screen-xs-max) {\n display: inline !important;\n }\n}\n.visible-xs-inline-block {\n @media (max-width: @screen-xs-max) {\n display: inline-block !important;\n }\n}\n\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-sm-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: block !important;\n }\n}\n.visible-sm-inline {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline !important;\n }\n}\n.visible-sm-inline-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline-block !important;\n }\n}\n\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-md-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: block !important;\n }\n}\n.visible-md-inline {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline !important;\n }\n}\n.visible-md-inline-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline-block !important;\n }\n}\n\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n.visible-lg-block {\n @media (min-width: @screen-lg-min) {\n display: block !important;\n }\n}\n.visible-lg-inline {\n @media (min-width: @screen-lg-min) {\n display: inline !important;\n }\n}\n.visible-lg-inline-block {\n @media (min-width: @screen-lg-min) {\n display: inline-block !important;\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n// Note: Deprecated .visible-print as of v3.2.0\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n.visible-print-block {\n display: none !important;\n\n @media print {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n\n @media print {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n\n @media print {\n display: inline-block !important;\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n","// Responsive utilities\n\n//\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n display: block !important;\n table& { display: table !important; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\n"]}
\ No newline at end of file
--- /dev/null
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
\ No newline at end of file
--- /dev/null
+ .sm2-bar-ui {
+ font-size: 16px;
+ }
+ .sm2-bar-ui .sm2-main-controls,
+ .sm2-bar-ui .sm2-playlist-drawer {
+ background-color: #000000;
+ }
+ .sm2-bar-ui .sm2-inline-texture {
+ background: transparent;
+ }
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
+<font-face units-per-em="1200" ascent="960" descent="-240" />
+<missing-glyph horiz-adv-x="500" />
+<glyph horiz-adv-x="0" />
+<glyph horiz-adv-x="400" />
+<glyph unicode=" " />
+<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" />
+<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode=" " />
+<glyph unicode="¥" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" />
+<glyph unicode=" " horiz-adv-x="650" />
+<glyph unicode=" " horiz-adv-x="1300" />
+<glyph unicode=" " horiz-adv-x="650" />
+<glyph unicode=" " horiz-adv-x="1300" />
+<glyph unicode=" " horiz-adv-x="433" />
+<glyph unicode=" " horiz-adv-x="325" />
+<glyph unicode=" " horiz-adv-x="216" />
+<glyph unicode=" " horiz-adv-x="216" />
+<glyph unicode=" " horiz-adv-x="162" />
+<glyph unicode=" " horiz-adv-x="260" />
+<glyph unicode=" " horiz-adv-x="72" />
+<glyph unicode=" " horiz-adv-x="260" />
+<glyph unicode=" " horiz-adv-x="325" />
+<glyph unicode="€" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" />
+<glyph unicode="₽" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" />
+<glyph unicode="−" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="⌛" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" />
+<glyph unicode="◼" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="☁" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" />
+<glyph unicode="⛺" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " />
+<glyph unicode="✉" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" />
+<glyph unicode="✏" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" />
+<glyph unicode="" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" />
+<glyph unicode="" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" />
+<glyph unicode="" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" />
+<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" />
+<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" />
+<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" />
+<glyph unicode="" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" />
+<glyph unicode="" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" />
+<glyph unicode="" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" />
+<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" />
+<glyph unicode="" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" />
+<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" />
+<glyph unicode="" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" />
+<glyph unicode="" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" />
+<glyph unicode="" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" />
+<glyph unicode="" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" />
+<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" />
+<glyph unicode="" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
+<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" />
+<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" />
+<glyph unicode="" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" />
+<glyph unicode="" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" />
+<glyph unicode="" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" />
+<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" />
+<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" />
+<glyph unicode="" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" />
+<glyph unicode="" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" />
+<glyph unicode="" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" />
+<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
+<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" />
+<glyph unicode="" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" />
+<glyph unicode="" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" />
+<glyph unicode="" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" />
+<glyph unicode="" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" />
+<glyph unicode="" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" />
+<glyph unicode="" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" />
+<glyph unicode="" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" />
+<glyph unicode="" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" />
+<glyph unicode="" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" />
+<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" />
+<glyph unicode="" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" />
+<glyph unicode="" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" />
+<glyph unicode="" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" />
+<glyph unicode="" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" />
+<glyph unicode="" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" />
+<glyph unicode="" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" />
+<glyph unicode="" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" />
+<glyph unicode="" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" />
+<glyph unicode="" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" />
+<glyph unicode="" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" />
+<glyph unicode="" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" />
+<glyph unicode="" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" />
+<glyph unicode="" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" />
+<glyph unicode="" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" />
+<glyph unicode="" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" />
+<glyph unicode="" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" />
+<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" />
+<glyph unicode="" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" />
+<glyph unicode="" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" />
+<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" />
+<glyph unicode="" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" />
+<glyph unicode="" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" />
+<glyph unicode="" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
+<glyph unicode="" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" />
+<glyph unicode="" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" />
+<glyph unicode="" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" />
+<glyph unicode="" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" />
+<glyph unicode="" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" />
+<glyph unicode="" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" />
+<glyph unicode="" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" />
+<glyph unicode="" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" />
+<glyph unicode="" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" />
+<glyph unicode="" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" />
+<glyph unicode="" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" />
+<glyph unicode="" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" />
+<glyph unicode="" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" />
+<glyph unicode="" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" />
+<glyph unicode="" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" />
+<glyph unicode="" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" />
+<glyph unicode="" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" />
+<glyph unicode="" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" />
+<glyph unicode="" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" />
+<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" />
+<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" />
+<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" />
+<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" />
+<glyph unicode="" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" />
+<glyph unicode="" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " />
+<glyph unicode="" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" />
+<glyph unicode="" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" />
+<glyph unicode="" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" />
+<glyph unicode="" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" />
+<glyph unicode="" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" />
+<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" />
+<glyph unicode="" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" />
+<glyph unicode="" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" />
+<glyph unicode="" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" />
+<glyph unicode="" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" />
+<glyph unicode="" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" />
+<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" />
+<glyph unicode="" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " />
+<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " />
+<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" />
+<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" />
+<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" />
+<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" />
+<glyph unicode="" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" />
+<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" />
+<glyph unicode="" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" />
+<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" />
+<glyph unicode="" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
+<glyph unicode="" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" />
+<glyph unicode="" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" />
+<glyph unicode="" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" />
+<glyph unicode="" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" />
+<glyph unicode="" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
+<glyph unicode="" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" />
+<glyph unicode="" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" />
+<glyph unicode="" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
+<glyph unicode="" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" />
+<glyph unicode="" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" />
+<glyph unicode="" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" />
+<glyph unicode="" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" />
+<glyph unicode="" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" />
+<glyph unicode="" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" />
+<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" />
+<glyph unicode="" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" />
+<glyph unicode="" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" />
+<glyph unicode="" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" />
+<glyph unicode="" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" />
+<glyph unicode="" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" />
+<glyph unicode="" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" />
+<glyph unicode="" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " />
+<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
+<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" />
+<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" />
+<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" />
+<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" />
+<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" />
+<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" />
+<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" />
+<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" />
+<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" />
+<glyph unicode="" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" />
+<glyph unicode="" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" />
+<glyph unicode="" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" />
+<glyph unicode="" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" />
+<glyph unicode="" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" />
+<glyph unicode="" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" />
+<glyph unicode="" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" />
+<glyph unicode="" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" />
+<glyph unicode="" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" />
+<glyph unicode="" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" />
+<glyph unicode="" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" />
+<glyph unicode="" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" />
+<glyph unicode="" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" />
+<glyph unicode="" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" />
+<glyph unicode="" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " />
+<glyph unicode="" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" />
+<glyph unicode="" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" />
+<glyph unicode="" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" />
+<glyph unicode="" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" />
+<glyph unicode="" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
+<glyph unicode="" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" />
+<glyph unicode="" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" />
+<glyph unicode="" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
+<glyph unicode="" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" />
+<glyph unicode="" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" />
+<glyph unicode="" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" />
+<glyph unicode="" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" />
+<glyph unicode="" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" />
+<glyph unicode="" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" />
+<glyph unicode="" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" />
+<glyph unicode="" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" />
+<glyph unicode="" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" />
+<glyph unicode="" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" />
+<glyph unicode="" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" />
+<glyph unicode="" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" />
+<glyph unicode="" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" />
+<glyph unicode="" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" />
+<glyph unicode="" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" />
+<glyph unicode="" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" />
+<glyph unicode="" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" />
+<glyph unicode="" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" />
+<glyph unicode="" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" />
+<glyph unicode="" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" />
+<glyph unicode="" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" />
+<glyph unicode="" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" />
+<glyph unicode="" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" />
+<glyph unicode="" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" />
+<glyph unicode="" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" />
+<glyph unicode="🔑" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" />
+<glyph unicode="🚪" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" />
+</font>
+</defs></svg>
\ No newline at end of file
--- /dev/null
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+
+if (typeof jQuery === 'undefined') {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+ 'use strict';
+ var version = $.fn.jquery.split(' ')[0].split('.')
+ if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
+ }
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: transition.js v3.3.5
+ * http://getbootstrap.com/javascript/#transitions
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
+ // ============================================================
+
+ function transitionEnd() {
+ var el = document.createElement('bootstrap')
+
+ var transEndEventNames = {
+ WebkitTransition : 'webkitTransitionEnd',
+ MozTransition : 'transitionend',
+ OTransition : 'oTransitionEnd otransitionend',
+ transition : 'transitionend'
+ }
+
+ for (var name in transEndEventNames) {
+ if (el.style[name] !== undefined) {
+ return { end: transEndEventNames[name] }
+ }
+ }
+
+ return false // explicit for ie8 ( ._.)
+ }
+
+ // http://blog.alexmaccaw.com/css-transitions
+ $.fn.emulateTransitionEnd = function (duration) {
+ var called = false
+ var $el = this
+ $(this).one('bsTransitionEnd', function () { called = true })
+ var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
+ setTimeout(callback, duration)
+ return this
+ }
+
+ $(function () {
+ $.support.transition = transitionEnd()
+
+ if (!$.support.transition) return
+
+ $.event.special.bsTransitionEnd = {
+ bindType: $.support.transition.end,
+ delegateType: $.support.transition.end,
+ handle: function (e) {
+ if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
+ }
+ }
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: alert.js v3.3.5
+ * http://getbootstrap.com/javascript/#alerts
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // ALERT CLASS DEFINITION
+ // ======================
+
+ var dismiss = '[data-dismiss="alert"]'
+ var Alert = function (el) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.VERSION = '3.3.5'
+
+ Alert.TRANSITION_DURATION = 150
+
+ Alert.prototype.close = function (e) {
+ var $this = $(this)
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = $(selector)
+
+ if (e) e.preventDefault()
+
+ if (!$parent.length) {
+ $parent = $this.closest('.alert')
+ }
+
+ $parent.trigger(e = $.Event('close.bs.alert'))
+
+ if (e.isDefaultPrevented()) return
+
+ $parent.removeClass('in')
+
+ function removeElement() {
+ // detach from parent, fire event then clean up data
+ $parent.detach().trigger('closed.bs.alert').remove()
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent
+ .one('bsTransitionEnd', removeElement)
+ .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
+ removeElement()
+ }
+
+
+ // ALERT PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.alert')
+
+ if (!data) $this.data('bs.alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.alert
+
+ $.fn.alert = Plugin
+ $.fn.alert.Constructor = Alert
+
+
+ // ALERT NO CONFLICT
+ // =================
+
+ $.fn.alert.noConflict = function () {
+ $.fn.alert = old
+ return this
+ }
+
+
+ // ALERT DATA-API
+ // ==============
+
+ $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: button.js v3.3.5
+ * http://getbootstrap.com/javascript/#buttons
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // BUTTON PUBLIC CLASS DEFINITION
+ // ==============================
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Button.DEFAULTS, options)
+ this.isLoading = false
+ }
+
+ Button.VERSION = '3.3.5'
+
+ Button.DEFAULTS = {
+ loadingText: 'loading...'
+ }
+
+ Button.prototype.setState = function (state) {
+ var d = 'disabled'
+ var $el = this.$element
+ var val = $el.is('input') ? 'val' : 'html'
+ var data = $el.data()
+
+ state += 'Text'
+
+ if (data.resetText == null) $el.data('resetText', $el[val]())
+
+ // push to event loop to allow forms to submit
+ setTimeout($.proxy(function () {
+ $el[val](data[state] == null ? this.options[state] : data[state])
+
+ if (state == 'loadingText') {
+ this.isLoading = true
+ $el.addClass(d).attr(d, d)
+ } else if (this.isLoading) {
+ this.isLoading = false
+ $el.removeClass(d).removeAttr(d)
+ }
+ }, this), 0)
+ }
+
+ Button.prototype.toggle = function () {
+ var changed = true
+ var $parent = this.$element.closest('[data-toggle="buttons"]')
+
+ if ($parent.length) {
+ var $input = this.$element.find('input')
+ if ($input.prop('type') == 'radio') {
+ if ($input.prop('checked')) changed = false
+ $parent.find('.active').removeClass('active')
+ this.$element.addClass('active')
+ } else if ($input.prop('type') == 'checkbox') {
+ if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
+ this.$element.toggleClass('active')
+ }
+ $input.prop('checked', this.$element.hasClass('active'))
+ if (changed) $input.trigger('change')
+ } else {
+ this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
+ this.$element.toggleClass('active')
+ }
+ }
+
+
+ // BUTTON PLUGIN DEFINITION
+ // ========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.button')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.button', (data = new Button(this, options)))
+
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ var old = $.fn.button
+
+ $.fn.button = Plugin
+ $.fn.button.Constructor = Button
+
+
+ // BUTTON NO CONFLICT
+ // ==================
+
+ $.fn.button.noConflict = function () {
+ $.fn.button = old
+ return this
+ }
+
+
+ // BUTTON DATA-API
+ // ===============
+
+ $(document)
+ .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ Plugin.call($btn, 'toggle')
+ if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
+ })
+ .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: carousel.js v3.3.5
+ * http://getbootstrap.com/javascript/#carousel
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CAROUSEL CLASS DEFINITION
+ // =========================
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.$indicators = this.$element.find('.carousel-indicators')
+ this.options = options
+ this.paused = null
+ this.sliding = null
+ this.interval = null
+ this.$active = null
+ this.$items = null
+
+ this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
+
+ this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
+ .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
+ .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
+ }
+
+ Carousel.VERSION = '3.3.5'
+
+ Carousel.TRANSITION_DURATION = 600
+
+ Carousel.DEFAULTS = {
+ interval: 5000,
+ pause: 'hover',
+ wrap: true,
+ keyboard: true
+ }
+
+ Carousel.prototype.keydown = function (e) {
+ if (/input|textarea/i.test(e.target.tagName)) return
+ switch (e.which) {
+ case 37: this.prev(); break
+ case 39: this.next(); break
+ default: return
+ }
+
+ e.preventDefault()
+ }
+
+ Carousel.prototype.cycle = function (e) {
+ e || (this.paused = false)
+
+ this.interval && clearInterval(this.interval)
+
+ this.options.interval
+ && !this.paused
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+
+ return this
+ }
+
+ Carousel.prototype.getItemIndex = function (item) {
+ this.$items = item.parent().children('.item')
+ return this.$items.index(item || this.$active)
+ }
+
+ Carousel.prototype.getItemForDirection = function (direction, active) {
+ var activeIndex = this.getItemIndex(active)
+ var willWrap = (direction == 'prev' && activeIndex === 0)
+ || (direction == 'next' && activeIndex == (this.$items.length - 1))
+ if (willWrap && !this.options.wrap) return active
+ var delta = direction == 'prev' ? -1 : 1
+ var itemIndex = (activeIndex + delta) % this.$items.length
+ return this.$items.eq(itemIndex)
+ }
+
+ Carousel.prototype.to = function (pos) {
+ var that = this
+ var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
+
+ if (pos > (this.$items.length - 1) || pos < 0) return
+
+ if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
+ if (activeIndex == pos) return this.pause().cycle()
+
+ return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
+ }
+
+ Carousel.prototype.pause = function (e) {
+ e || (this.paused = true)
+
+ if (this.$element.find('.next, .prev').length && $.support.transition) {
+ this.$element.trigger($.support.transition.end)
+ this.cycle(true)
+ }
+
+ this.interval = clearInterval(this.interval)
+
+ return this
+ }
+
+ Carousel.prototype.next = function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ Carousel.prototype.prev = function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ Carousel.prototype.slide = function (type, next) {
+ var $active = this.$element.find('.item.active')
+ var $next = next || this.getItemForDirection(type, $active)
+ var isCycling = this.interval
+ var direction = type == 'next' ? 'left' : 'right'
+ var that = this
+
+ if ($next.hasClass('active')) return (this.sliding = false)
+
+ var relatedTarget = $next[0]
+ var slideEvent = $.Event('slide.bs.carousel', {
+ relatedTarget: relatedTarget,
+ direction: direction
+ })
+ this.$element.trigger(slideEvent)
+ if (slideEvent.isDefaultPrevented()) return
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ if (this.$indicators.length) {
+ this.$indicators.find('.active').removeClass('active')
+ var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
+ $nextIndicator && $nextIndicator.addClass('active')
+ }
+
+ var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
+ if ($.support.transition && this.$element.hasClass('slide')) {
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ $active
+ .one('bsTransitionEnd', function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () {
+ that.$element.trigger(slidEvent)
+ }, 0)
+ })
+ .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
+ } else {
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger(slidEvent)
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+
+ // CAROUSEL PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.carousel')
+ var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
+ var action = typeof option == 'string' ? option : options.slide
+
+ if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (action) data[action]()
+ else if (options.interval) data.pause().cycle()
+ })
+ }
+
+ var old = $.fn.carousel
+
+ $.fn.carousel = Plugin
+ $.fn.carousel.Constructor = Carousel
+
+
+ // CAROUSEL NO CONFLICT
+ // ====================
+
+ $.fn.carousel.noConflict = function () {
+ $.fn.carousel = old
+ return this
+ }
+
+
+ // CAROUSEL DATA-API
+ // =================
+
+ var clickHandler = function (e) {
+ var href
+ var $this = $(this)
+ var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
+ if (!$target.hasClass('carousel')) return
+ var options = $.extend({}, $target.data(), $this.data())
+ var slideIndex = $this.attr('data-slide-to')
+ if (slideIndex) options.interval = false
+
+ Plugin.call($target, options)
+
+ if (slideIndex) {
+ $target.data('bs.carousel').to(slideIndex)
+ }
+
+ e.preventDefault()
+ }
+
+ $(document)
+ .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
+ .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
+
+ $(window).on('load', function () {
+ $('[data-ride="carousel"]').each(function () {
+ var $carousel = $(this)
+ Plugin.call($carousel, $carousel.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: collapse.js v3.3.5
+ * http://getbootstrap.com/javascript/#collapse
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // COLLAPSE PUBLIC CLASS DEFINITION
+ // ================================
+
+ var Collapse = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Collapse.DEFAULTS, options)
+ this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
+ '[data-toggle="collapse"][data-target="#' + element.id + '"]')
+ this.transitioning = null
+
+ if (this.options.parent) {
+ this.$parent = this.getParent()
+ } else {
+ this.addAriaAndCollapsedClass(this.$element, this.$trigger)
+ }
+
+ if (this.options.toggle) this.toggle()
+ }
+
+ Collapse.VERSION = '3.3.5'
+
+ Collapse.TRANSITION_DURATION = 350
+
+ Collapse.DEFAULTS = {
+ toggle: true
+ }
+
+ Collapse.prototype.dimension = function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ Collapse.prototype.show = function () {
+ if (this.transitioning || this.$element.hasClass('in')) return
+
+ var activesData
+ var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
+
+ if (actives && actives.length) {
+ activesData = actives.data('bs.collapse')
+ if (activesData && activesData.transitioning) return
+ }
+
+ var startEvent = $.Event('show.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ if (actives && actives.length) {
+ Plugin.call(actives, 'hide')
+ activesData || actives.data('bs.collapse', null)
+ }
+
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ .addClass('collapsing')[dimension](0)
+ .attr('aria-expanded', true)
+
+ this.$trigger
+ .removeClass('collapsed')
+ .attr('aria-expanded', true)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse in')[dimension]('')
+ this.transitioning = 0
+ this.$element
+ .trigger('shown.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ var scrollSize = $.camelCase(['scroll', dimension].join('-'))
+
+ this.$element
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
+ }
+
+ Collapse.prototype.hide = function () {
+ if (this.transitioning || !this.$element.hasClass('in')) return
+
+ var startEvent = $.Event('hide.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ var dimension = this.dimension()
+
+ this.$element[dimension](this.$element[dimension]())[0].offsetHeight
+
+ this.$element
+ .addClass('collapsing')
+ .removeClass('collapse in')
+ .attr('aria-expanded', false)
+
+ this.$trigger
+ .addClass('collapsed')
+ .attr('aria-expanded', false)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.transitioning = 0
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse')
+ .trigger('hidden.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ this.$element
+ [dimension](0)
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
+ }
+
+ Collapse.prototype.toggle = function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ Collapse.prototype.getParent = function () {
+ return $(this.options.parent)
+ .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
+ .each($.proxy(function (i, element) {
+ var $element = $(element)
+ this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
+ }, this))
+ .end()
+ }
+
+ Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
+ var isOpen = $element.hasClass('in')
+
+ $element.attr('aria-expanded', isOpen)
+ $trigger
+ .toggleClass('collapsed', !isOpen)
+ .attr('aria-expanded', isOpen)
+ }
+
+ function getTargetFromTrigger($trigger) {
+ var href
+ var target = $trigger.attr('data-target')
+ || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+
+ return $(target)
+ }
+
+
+ // COLLAPSE PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.collapse')
+ var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
+ if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.collapse
+
+ $.fn.collapse = Plugin
+ $.fn.collapse.Constructor = Collapse
+
+
+ // COLLAPSE NO CONFLICT
+ // ====================
+
+ $.fn.collapse.noConflict = function () {
+ $.fn.collapse = old
+ return this
+ }
+
+
+ // COLLAPSE DATA-API
+ // =================
+
+ $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
+ var $this = $(this)
+
+ if (!$this.attr('data-target')) e.preventDefault()
+
+ var $target = getTargetFromTrigger($this)
+ var data = $target.data('bs.collapse')
+ var option = data ? 'toggle' : $this.data()
+
+ Plugin.call($target, option)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: dropdown.js v3.3.5
+ * http://getbootstrap.com/javascript/#dropdowns
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // DROPDOWN CLASS DEFINITION
+ // =========================
+
+ var backdrop = '.dropdown-backdrop'
+ var toggle = '[data-toggle="dropdown"]'
+ var Dropdown = function (element) {
+ $(element).on('click.bs.dropdown', this.toggle)
+ }
+
+ Dropdown.VERSION = '3.3.5'
+
+ function getParent($this) {
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = selector && $(selector)
+
+ return $parent && $parent.length ? $parent : $this.parent()
+ }
+
+ function clearMenus(e) {
+ if (e && e.which === 3) return
+ $(backdrop).remove()
+ $(toggle).each(function () {
+ var $this = $(this)
+ var $parent = getParent($this)
+ var relatedTarget = { relatedTarget: this }
+
+ if (!$parent.hasClass('open')) return
+
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
+
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this.attr('aria-expanded', 'false')
+ $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
+ })
+ }
+
+ Dropdown.prototype.toggle = function (e) {
+ var $this = $(this)
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ clearMenus()
+
+ if (!isActive) {
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
+ // if mobile we use a backdrop because click events don't delegate
+ $(document.createElement('div'))
+ .addClass('dropdown-backdrop')
+ .insertAfter($(this))
+ .on('click', clearMenus)
+ }
+
+ var relatedTarget = { relatedTarget: this }
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this
+ .trigger('focus')
+ .attr('aria-expanded', 'true')
+
+ $parent
+ .toggleClass('open')
+ .trigger('shown.bs.dropdown', relatedTarget)
+ }
+
+ return false
+ }
+
+ Dropdown.prototype.keydown = function (e) {
+ if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
+
+ var $this = $(this)
+
+ e.preventDefault()
+ e.stopPropagation()
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
+ if (e.which == 27) $parent.find(toggle).trigger('focus')
+ return $this.trigger('click')
+ }
+
+ var desc = ' li:not(.disabled):visible a'
+ var $items = $parent.find('.dropdown-menu' + desc)
+
+ if (!$items.length) return
+
+ var index = $items.index(e.target)
+
+ if (e.which == 38 && index > 0) index-- // up
+ if (e.which == 40 && index < $items.length - 1) index++ // down
+ if (!~index) index = 0
+
+ $items.eq(index).trigger('focus')
+ }
+
+
+ // DROPDOWN PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.dropdown')
+
+ if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.dropdown
+
+ $.fn.dropdown = Plugin
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ // DROPDOWN NO CONFLICT
+ // ====================
+
+ $.fn.dropdown.noConflict = function () {
+ $.fn.dropdown = old
+ return this
+ }
+
+
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
+ // ===================================
+
+ $(document)
+ .on('click.bs.dropdown.data-api', clearMenus)
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+ .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+ .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: modal.js v3.3.5
+ * http://getbootstrap.com/javascript/#modals
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // MODAL CLASS DEFINITION
+ // ======================
+
+ var Modal = function (element, options) {
+ this.options = options
+ this.$body = $(document.body)
+ this.$element = $(element)
+ this.$dialog = this.$element.find('.modal-dialog')
+ this.$backdrop = null
+ this.isShown = null
+ this.originalBodyPad = null
+ this.scrollbarWidth = 0
+ this.ignoreBackdropClick = false
+
+ if (this.options.remote) {
+ this.$element
+ .find('.modal-content')
+ .load(this.options.remote, $.proxy(function () {
+ this.$element.trigger('loaded.bs.modal')
+ }, this))
+ }
+ }
+
+ Modal.VERSION = '3.3.5'
+
+ Modal.TRANSITION_DURATION = 300
+ Modal.BACKDROP_TRANSITION_DURATION = 150
+
+ Modal.DEFAULTS = {
+ backdrop: true,
+ keyboard: true,
+ show: true
+ }
+
+ Modal.prototype.toggle = function (_relatedTarget) {
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
+ }
+
+ Modal.prototype.show = function (_relatedTarget) {
+ var that = this
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
+
+ this.$element.trigger(e)
+
+ if (this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = true
+
+ this.checkScrollbar()
+ this.setScrollbar()
+ this.$body.addClass('modal-open')
+
+ this.escape()
+ this.resize()
+
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
+
+ this.$dialog.on('mousedown.dismiss.bs.modal', function () {
+ that.$element.one('mouseup.dismiss.bs.modal', function (e) {
+ if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
+ })
+ })
+
+ this.backdrop(function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ if (!that.$element.parent().length) {
+ that.$element.appendTo(that.$body) // don't move modals dom position
+ }
+
+ that.$element
+ .show()
+ .scrollTop(0)
+
+ that.adjustDialog()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element.addClass('in')
+
+ that.enforceFocus()
+
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
+
+ transition ?
+ that.$dialog // wait for modal to slide in
+ .one('bsTransitionEnd', function () {
+ that.$element.trigger('focus').trigger(e)
+ })
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ that.$element.trigger('focus').trigger(e)
+ })
+ }
+
+ Modal.prototype.hide = function (e) {
+ if (e) e.preventDefault()
+
+ e = $.Event('hide.bs.modal')
+
+ this.$element.trigger(e)
+
+ if (!this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = false
+
+ this.escape()
+ this.resize()
+
+ $(document).off('focusin.bs.modal')
+
+ this.$element
+ .removeClass('in')
+ .off('click.dismiss.bs.modal')
+ .off('mouseup.dismiss.bs.modal')
+
+ this.$dialog.off('mousedown.dismiss.bs.modal')
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$element
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ this.hideModal()
+ }
+
+ Modal.prototype.enforceFocus = function () {
+ $(document)
+ .off('focusin.bs.modal') // guard against infinite focus loop
+ .on('focusin.bs.modal', $.proxy(function (e) {
+ if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
+ this.$element.trigger('focus')
+ }
+ }, this))
+ }
+
+ Modal.prototype.escape = function () {
+ if (this.isShown && this.options.keyboard) {
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
+ e.which == 27 && this.hide()
+ }, this))
+ } else if (!this.isShown) {
+ this.$element.off('keydown.dismiss.bs.modal')
+ }
+ }
+
+ Modal.prototype.resize = function () {
+ if (this.isShown) {
+ $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
+ } else {
+ $(window).off('resize.bs.modal')
+ }
+ }
+
+ Modal.prototype.hideModal = function () {
+ var that = this
+ this.$element.hide()
+ this.backdrop(function () {
+ that.$body.removeClass('modal-open')
+ that.resetAdjustments()
+ that.resetScrollbar()
+ that.$element.trigger('hidden.bs.modal')
+ })
+ }
+
+ Modal.prototype.removeBackdrop = function () {
+ this.$backdrop && this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ Modal.prototype.backdrop = function (callback) {
+ var that = this
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $(document.createElement('div'))
+ .addClass('modal-backdrop ' + animate)
+ .appendTo(this.$body)
+
+ this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
+ if (this.ignoreBackdropClick) {
+ this.ignoreBackdropClick = false
+ return
+ }
+ if (e.target !== e.currentTarget) return
+ this.options.backdrop == 'static'
+ ? this.$element[0].focus()
+ : this.hide()
+ }, this))
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ if (!callback) return
+
+ doAnimate ?
+ this.$backdrop
+ .one('bsTransitionEnd', callback)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ var callbackRemove = function () {
+ that.removeBackdrop()
+ callback && callback()
+ }
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$backdrop
+ .one('bsTransitionEnd', callbackRemove)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callbackRemove()
+
+ } else if (callback) {
+ callback()
+ }
+ }
+
+ // these following methods are used to handle overflowing modals
+
+ Modal.prototype.handleUpdate = function () {
+ this.adjustDialog()
+ }
+
+ Modal.prototype.adjustDialog = function () {
+ var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
+
+ this.$element.css({
+ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
+ paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
+ })
+ }
+
+ Modal.prototype.resetAdjustments = function () {
+ this.$element.css({
+ paddingLeft: '',
+ paddingRight: ''
+ })
+ }
+
+ Modal.prototype.checkScrollbar = function () {
+ var fullWindowWidth = window.innerWidth
+ if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
+ var documentElementRect = document.documentElement.getBoundingClientRect()
+ fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
+ }
+ this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
+ this.scrollbarWidth = this.measureScrollbar()
+ }
+
+ Modal.prototype.setScrollbar = function () {
+ var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
+ this.originalBodyPad = document.body.style.paddingRight || ''
+ if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
+ }
+
+ Modal.prototype.resetScrollbar = function () {
+ this.$body.css('padding-right', this.originalBodyPad)
+ }
+
+ Modal.prototype.measureScrollbar = function () { // thx walsh
+ var scrollDiv = document.createElement('div')
+ scrollDiv.className = 'modal-scrollbar-measure'
+ this.$body.append(scrollDiv)
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
+ this.$body[0].removeChild(scrollDiv)
+ return scrollbarWidth
+ }
+
+
+ // MODAL PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option, _relatedTarget) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.modal')
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option](_relatedTarget)
+ else if (options.show) data.show(_relatedTarget)
+ })
+ }
+
+ var old = $.fn.modal
+
+ $.fn.modal = Plugin
+ $.fn.modal.Constructor = Modal
+
+
+ // MODAL NO CONFLICT
+ // =================
+
+ $.fn.modal.noConflict = function () {
+ $.fn.modal = old
+ return this
+ }
+
+
+ // MODAL DATA-API
+ // ==============
+
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
+ var $this = $(this)
+ var href = $this.attr('href')
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
+
+ if ($this.is('a')) e.preventDefault()
+
+ $target.one('show.bs.modal', function (showEvent) {
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
+ $target.one('hidden.bs.modal', function () {
+ $this.is(':visible') && $this.trigger('focus')
+ })
+ })
+ Plugin.call($target, option, this)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tooltip.js v3.3.5
+ * http://getbootstrap.com/javascript/#tooltip
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TOOLTIP PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Tooltip = function (element, options) {
+ this.type = null
+ this.options = null
+ this.enabled = null
+ this.timeout = null
+ this.hoverState = null
+ this.$element = null
+ this.inState = null
+
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.VERSION = '3.3.5'
+
+ Tooltip.TRANSITION_DURATION = 150
+
+ Tooltip.DEFAULTS = {
+ animation: true,
+ placement: 'top',
+ selector: false,
+ template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
+ trigger: 'hover focus',
+ title: '',
+ delay: 0,
+ html: false,
+ container: false,
+ viewport: {
+ selector: 'body',
+ padding: 0
+ }
+ }
+
+ Tooltip.prototype.init = function (type, element, options) {
+ this.enabled = true
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
+ this.inState = { click: false, hover: false, focus: false }
+
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
+ }
+
+ var triggers = this.options.trigger.split(' ')
+
+ for (var i = triggers.length; i--;) {
+ var trigger = triggers[i]
+
+ if (trigger == 'click') {
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+ } else if (trigger != 'manual') {
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
+
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+ }
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ Tooltip.prototype.getDefaults = function () {
+ return Tooltip.DEFAULTS
+ }
+
+ Tooltip.prototype.getOptions = function (options) {
+ options = $.extend({}, this.getDefaults(), this.$element.data(), options)
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay,
+ hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ Tooltip.prototype.getDelegateOptions = function () {
+ var options = {}
+ var defaults = this.getDefaults()
+
+ this._options && $.each(this._options, function (key, value) {
+ if (defaults[key] != value) options[key] = value
+ })
+
+ return options
+ }
+
+ Tooltip.prototype.enter = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
+ }
+
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
+ self.hoverState = 'in'
+ return
+ }
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'in'
+
+ if (!self.options.delay || !self.options.delay.show) return self.show()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'in') self.show()
+ }, self.options.delay.show)
+ }
+
+ Tooltip.prototype.isInStateTrue = function () {
+ for (var key in this.inState) {
+ if (this.inState[key]) return true
+ }
+
+ return false
+ }
+
+ Tooltip.prototype.leave = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
+ }
+
+ if (self.isInStateTrue()) return
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'out'
+
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'out') self.hide()
+ }, self.options.delay.hide)
+ }
+
+ Tooltip.prototype.show = function () {
+ var e = $.Event('show.bs.' + this.type)
+
+ if (this.hasContent() && this.enabled) {
+ this.$element.trigger(e)
+
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
+ if (e.isDefaultPrevented() || !inDom) return
+ var that = this
+
+ var $tip = this.tip()
+
+ var tipId = this.getUID(this.type)
+
+ this.setContent()
+ $tip.attr('id', tipId)
+ this.$element.attr('aria-describedby', tipId)
+
+ if (this.options.animation) $tip.addClass('fade')
+
+ var placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ var autoToken = /\s?auto?\s?/i
+ var autoPlace = autoToken.test(placement)
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
+
+ $tip
+ .detach()
+ .css({ top: 0, left: 0, display: 'block' })
+ .addClass(placement)
+ .data('bs.' + this.type, this)
+
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+ this.$element.trigger('inserted.bs.' + this.type)
+
+ var pos = this.getPosition()
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (autoPlace) {
+ var orgPlacement = placement
+ var viewportDim = this.getPosition(this.$viewport)
+
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
+ placement
+
+ $tip
+ .removeClass(orgPlacement)
+ .addClass(placement)
+ }
+
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
+
+ this.applyPlacement(calculatedOffset, placement)
+
+ var complete = function () {
+ var prevHoverState = that.hoverState
+ that.$element.trigger('shown.bs.' + that.type)
+ that.hoverState = null
+
+ if (prevHoverState == 'out') that.leave(that)
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+ }
+ }
+
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
+ var $tip = this.tip()
+ var width = $tip[0].offsetWidth
+ var height = $tip[0].offsetHeight
+
+ // manually read margins because getBoundingClientRect includes difference
+ var marginTop = parseInt($tip.css('margin-top'), 10)
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
+
+ // we must check for NaN for ie 8/9
+ if (isNaN(marginTop)) marginTop = 0
+ if (isNaN(marginLeft)) marginLeft = 0
+
+ offset.top += marginTop
+ offset.left += marginLeft
+
+ // $.fn.offset doesn't round pixel values
+ // so we use setOffset directly with our own function B-0
+ $.offset.setOffset($tip[0], $.extend({
+ using: function (props) {
+ $tip.css({
+ top: Math.round(props.top),
+ left: Math.round(props.left)
+ })
+ }
+ }, offset), 0)
+
+ $tip.addClass('in')
+
+ // check to see if placing tip in new offset caused the tip to resize itself
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (placement == 'top' && actualHeight != height) {
+ offset.top = offset.top + height - actualHeight
+ }
+
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
+
+ if (delta.left) offset.left += delta.left
+ else offset.top += delta.top
+
+ var isVertical = /top|bottom/.test(placement)
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
+
+ $tip.offset(offset)
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
+ }
+
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
+ this.arrow()
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
+ .css(isVertical ? 'top' : 'left', '')
+ }
+
+ Tooltip.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ Tooltip.prototype.hide = function (callback) {
+ var that = this
+ var $tip = $(this.$tip)
+ var e = $.Event('hide.bs.' + this.type)
+
+ function complete() {
+ if (that.hoverState != 'in') $tip.detach()
+ that.$element
+ .removeAttr('aria-describedby')
+ .trigger('hidden.bs.' + that.type)
+ callback && callback()
+ }
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ $tip.removeClass('in')
+
+ $.support.transition && $tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+
+ this.hoverState = null
+
+ return this
+ }
+
+ Tooltip.prototype.fixTitle = function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+ }
+ }
+
+ Tooltip.prototype.hasContent = function () {
+ return this.getTitle()
+ }
+
+ Tooltip.prototype.getPosition = function ($element) {
+ $element = $element || this.$element
+
+ var el = $element[0]
+ var isBody = el.tagName == 'BODY'
+
+ var elRect = el.getBoundingClientRect()
+ if (elRect.width == null) {
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
+ }
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
+
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
+ }
+
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
+
+ }
+
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
+ var delta = { top: 0, left: 0 }
+ if (!this.$viewport) return delta
+
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
+ var viewportDimensions = this.getPosition(this.$viewport)
+
+ if (/right|left/.test(placement)) {
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
+ delta.top = viewportDimensions.top - topEdgeOffset
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
+ }
+ } else {
+ var leftEdgeOffset = pos.left - viewportPadding
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
+ delta.left = viewportDimensions.left - leftEdgeOffset
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
+ }
+ }
+
+ return delta
+ }
+
+ Tooltip.prototype.getTitle = function () {
+ var title
+ var $e = this.$element
+ var o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ return title
+ }
+
+ Tooltip.prototype.getUID = function (prefix) {
+ do prefix += ~~(Math.random() * 1000000)
+ while (document.getElementById(prefix))
+ return prefix
+ }
+
+ Tooltip.prototype.tip = function () {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ if (this.$tip.length != 1) {
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
+ }
+ }
+ return this.$tip
+ }
+
+ Tooltip.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
+ }
+
+ Tooltip.prototype.enable = function () {
+ this.enabled = true
+ }
+
+ Tooltip.prototype.disable = function () {
+ this.enabled = false
+ }
+
+ Tooltip.prototype.toggleEnabled = function () {
+ this.enabled = !this.enabled
+ }
+
+ Tooltip.prototype.toggle = function (e) {
+ var self = this
+ if (e) {
+ self = $(e.currentTarget).data('bs.' + this.type)
+ if (!self) {
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
+ $(e.currentTarget).data('bs.' + this.type, self)
+ }
+ }
+
+ if (e) {
+ self.inState.click = !self.inState.click
+ if (self.isInStateTrue()) self.enter(self)
+ else self.leave(self)
+ } else {
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+ }
+ }
+
+ Tooltip.prototype.destroy = function () {
+ var that = this
+ clearTimeout(this.timeout)
+ this.hide(function () {
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
+ if (that.$tip) {
+ that.$tip.detach()
+ }
+ that.$tip = null
+ that.$arrow = null
+ that.$viewport = null
+ })
+ }
+
+
+ // TOOLTIP PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tooltip')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tooltip
+
+ $.fn.tooltip = Plugin
+ $.fn.tooltip.Constructor = Tooltip
+
+
+ // TOOLTIP NO CONFLICT
+ // ===================
+
+ $.fn.tooltip.noConflict = function () {
+ $.fn.tooltip = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.3.5
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // POPOVER PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Popover = function (element, options) {
+ this.init('popover', element, options)
+ }
+
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+ Popover.VERSION = '3.3.5'
+
+ Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
+ placement: 'right',
+ trigger: 'click',
+ content: '',
+ template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+ })
+
+
+ // NOTE: POPOVER EXTENDS tooltip.js
+ // ================================
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+ Popover.prototype.constructor = Popover
+
+ Popover.prototype.getDefaults = function () {
+ return Popover.DEFAULTS
+ }
+
+ Popover.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+ var content = this.getContent()
+
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
+ this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
+ ](content)
+
+ $tip.removeClass('fade top bottom left right in')
+
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+ // this manually by checking the contents.
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+ }
+
+ Popover.prototype.hasContent = function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ Popover.prototype.getContent = function () {
+ var $e = this.$element
+ var o = this.options
+
+ return $e.attr('data-content')
+ || (typeof o.content == 'function' ?
+ o.content.call($e[0]) :
+ o.content)
+ }
+
+ Popover.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+ }
+
+
+ // POPOVER PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.popover')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.popover
+
+ $.fn.popover = Plugin
+ $.fn.popover.Constructor = Popover
+
+
+ // POPOVER NO CONFLICT
+ // ===================
+
+ $.fn.popover.noConflict = function () {
+ $.fn.popover = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: scrollspy.js v3.3.5
+ * http://getbootstrap.com/javascript/#scrollspy
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // SCROLLSPY CLASS DEFINITION
+ // ==========================
+
+ function ScrollSpy(element, options) {
+ this.$body = $(document.body)
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
+ this.selector = (this.options.target || '') + ' .nav li > a'
+ this.offsets = []
+ this.targets = []
+ this.activeTarget = null
+ this.scrollHeight = 0
+
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.VERSION = '3.3.5'
+
+ ScrollSpy.DEFAULTS = {
+ offset: 10
+ }
+
+ ScrollSpy.prototype.getScrollHeight = function () {
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
+ }
+
+ ScrollSpy.prototype.refresh = function () {
+ var that = this
+ var offsetMethod = 'offset'
+ var offsetBase = 0
+
+ this.offsets = []
+ this.targets = []
+ this.scrollHeight = this.getScrollHeight()
+
+ if (!$.isWindow(this.$scrollElement[0])) {
+ offsetMethod = 'position'
+ offsetBase = this.$scrollElement.scrollTop()
+ }
+
+ this.$body
+ .find(this.selector)
+ .map(function () {
+ var $el = $(this)
+ var href = $el.data('target') || $el.attr('href')
+ var $href = /^#./.test(href) && $(href)
+
+ return ($href
+ && $href.length
+ && $href.is(':visible')
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ that.offsets.push(this[0])
+ that.targets.push(this[1])
+ })
+ }
+
+ ScrollSpy.prototype.process = function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ var scrollHeight = this.getScrollHeight()
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
+ var offsets = this.offsets
+ var targets = this.targets
+ var activeTarget = this.activeTarget
+ var i
+
+ if (this.scrollHeight != scrollHeight) {
+ this.refresh()
+ }
+
+ if (scrollTop >= maxScroll) {
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
+ }
+
+ if (activeTarget && scrollTop < offsets[0]) {
+ this.activeTarget = null
+ return this.clear()
+ }
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
+ && this.activate(targets[i])
+ }
+ }
+
+ ScrollSpy.prototype.activate = function (target) {
+ this.activeTarget = target
+
+ this.clear()
+
+ var selector = this.selector +
+ '[data-target="' + target + '"],' +
+ this.selector + '[href="' + target + '"]'
+
+ var active = $(selector)
+ .parents('li')
+ .addClass('active')
+
+ if (active.parent('.dropdown-menu').length) {
+ active = active
+ .closest('li.dropdown')
+ .addClass('active')
+ }
+
+ active.trigger('activate.bs.scrollspy')
+ }
+
+ ScrollSpy.prototype.clear = function () {
+ $(this.selector)
+ .parentsUntil(this.options.target, '.active')
+ .removeClass('active')
+ }
+
+
+ // SCROLLSPY PLUGIN DEFINITION
+ // ===========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.scrollspy')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.scrollspy
+
+ $.fn.scrollspy = Plugin
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+
+ // SCROLLSPY NO CONFLICT
+ // =====================
+
+ $.fn.scrollspy.noConflict = function () {
+ $.fn.scrollspy = old
+ return this
+ }
+
+
+ // SCROLLSPY DATA-API
+ // ==================
+
+ $(window).on('load.bs.scrollspy.data-api', function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ Plugin.call($spy, $spy.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tab.js v3.3.5
+ * http://getbootstrap.com/javascript/#tabs
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TAB CLASS DEFINITION
+ // ====================
+
+ var Tab = function (element) {
+ // jscs:disable requireDollarBeforejQueryAssignment
+ this.element = $(element)
+ // jscs:enable requireDollarBeforejQueryAssignment
+ }
+
+ Tab.VERSION = '3.3.5'
+
+ Tab.TRANSITION_DURATION = 150
+
+ Tab.prototype.show = function () {
+ var $this = this.element
+ var $ul = $this.closest('ul:not(.dropdown-menu)')
+ var selector = $this.data('target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ if ($this.parent('li').hasClass('active')) return
+
+ var $previous = $ul.find('.active:last a')
+ var hideEvent = $.Event('hide.bs.tab', {
+ relatedTarget: $this[0]
+ })
+ var showEvent = $.Event('show.bs.tab', {
+ relatedTarget: $previous[0]
+ })
+
+ $previous.trigger(hideEvent)
+ $this.trigger(showEvent)
+
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
+
+ var $target = $(selector)
+
+ this.activate($this.closest('li'), $ul)
+ this.activate($target, $target.parent(), function () {
+ $previous.trigger({
+ type: 'hidden.bs.tab',
+ relatedTarget: $this[0]
+ })
+ $this.trigger({
+ type: 'shown.bs.tab',
+ relatedTarget: $previous[0]
+ })
+ })
+ }
+
+ Tab.prototype.activate = function (element, container, callback) {
+ var $active = container.find('> .active')
+ var transition = callback
+ && $.support.transition
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
+
+ function next() {
+ $active
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', false)
+
+ element
+ .addClass('active')
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+
+ if (transition) {
+ element[0].offsetWidth // reflow for transition
+ element.addClass('in')
+ } else {
+ element.removeClass('fade')
+ }
+
+ if (element.parent('.dropdown-menu').length) {
+ element
+ .closest('li.dropdown')
+ .addClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+ }
+
+ callback && callback()
+ }
+
+ $active.length && transition ?
+ $active
+ .one('bsTransitionEnd', next)
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
+ next()
+
+ $active.removeClass('in')
+ }
+
+
+ // TAB PLUGIN DEFINITION
+ // =====================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tab')
+
+ if (!data) $this.data('bs.tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tab
+
+ $.fn.tab = Plugin
+ $.fn.tab.Constructor = Tab
+
+
+ // TAB NO CONFLICT
+ // ===============
+
+ $.fn.tab.noConflict = function () {
+ $.fn.tab = old
+ return this
+ }
+
+
+ // TAB DATA-API
+ // ============
+
+ var clickHandler = function (e) {
+ e.preventDefault()
+ Plugin.call($(this), 'show')
+ }
+
+ $(document)
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: affix.js v3.3.5
+ * http://getbootstrap.com/javascript/#affix
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // AFFIX CLASS DEFINITION
+ // ======================
+
+ var Affix = function (element, options) {
+ this.options = $.extend({}, Affix.DEFAULTS, options)
+
+ this.$target = $(this.options.target)
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
+
+ this.$element = $(element)
+ this.affixed = null
+ this.unpin = null
+ this.pinnedOffset = null
+
+ this.checkPosition()
+ }
+
+ Affix.VERSION = '3.3.5'
+
+ Affix.RESET = 'affix affix-top affix-bottom'
+
+ Affix.DEFAULTS = {
+ offset: 0,
+ target: window
+ }
+
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ var targetHeight = this.$target.height()
+
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
+
+ if (this.affixed == 'bottom') {
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
+ }
+
+ var initializing = this.affixed == null
+ var colliderTop = initializing ? scrollTop : position.top
+ var colliderHeight = initializing ? targetHeight : height
+
+ if (offsetTop != null && scrollTop <= offsetTop) return 'top'
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
+
+ return false
+ }
+
+ Affix.prototype.getPinnedOffset = function () {
+ if (this.pinnedOffset) return this.pinnedOffset
+ this.$element.removeClass(Affix.RESET).addClass('affix')
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ return (this.pinnedOffset = position.top - scrollTop)
+ }
+
+ Affix.prototype.checkPositionWithEventLoop = function () {
+ setTimeout($.proxy(this.checkPosition, this), 1)
+ }
+
+ Affix.prototype.checkPosition = function () {
+ if (!this.$element.is(':visible')) return
+
+ var height = this.$element.height()
+ var offset = this.options.offset
+ var offsetTop = offset.top
+ var offsetBottom = offset.bottom
+ var scrollHeight = Math.max($(document).height(), $(document.body).height())
+
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
+
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
+
+ if (this.affixed != affix) {
+ if (this.unpin != null) this.$element.css('top', '')
+
+ var affixType = 'affix' + (affix ? '-' + affix : '')
+ var e = $.Event(affixType + '.bs.affix')
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+
+ this.$element
+ .removeClass(Affix.RESET)
+ .addClass(affixType)
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
+ }
+
+ if (affix == 'bottom') {
+ this.$element.offset({
+ top: scrollHeight - height - offsetBottom
+ })
+ }
+ }
+
+
+ // AFFIX PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.affix')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.affix
+
+ $.fn.affix = Plugin
+ $.fn.affix.Constructor = Affix
+
+
+ // AFFIX NO CONFLICT
+ // =================
+
+ $.fn.affix.noConflict = function () {
+ $.fn.affix = old
+ return this
+ }
+
+
+ // AFFIX DATA-API
+ // ==============
+
+ $(window).on('load', function () {
+ $('[data-spy="affix"]').each(function () {
+ var $spy = $(this)
+ var data = $spy.data()
+
+ data.offset = data.offset || {}
+
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
+
+ Plugin.call($spy, data)
+ })
+ })
+
+}(jQuery);
--- /dev/null
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.5",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.5",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.5",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.5",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.5",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.5",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.5",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);return this.$element.trigger(g),g.isDefaultPrevented()?void 0:(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this)},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=d?{top:0,left:0}:b.offset(),g={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},h=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,g,h,f)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.5",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.5",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),
+d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.5",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.5",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
\ No newline at end of file
--- /dev/null
+/*! jQuery v1.11.3 | (c) 2005, 2015 jQuery Foundation, Inc. | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.3",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b="length"in a&&a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,aa=/[+~]/,ba=/'|\\/g,ca=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),da=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ea=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fa){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(ba,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+ra(o[l]);w=aa.test(a)&&pa(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",ea,!1):e.attachEvent&&e.attachEvent("onunload",ea)),p=!f(g),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ca,da);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\f]' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?la(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ca,da),a[3]=(a[3]||a[4]||a[5]||"").replace(ca,da),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ca,da).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(ca,da),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return W.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(ca,da).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:oa(function(){return[0]}),last:oa(function(a,b){return[b-1]}),eq:oa(function(a,b,c){return[0>c?c+b:c]}),even:oa(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:oa(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:oa(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:oa(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=ma(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=na(b);function qa(){}qa.prototype=d.filters=d.pseudos,d.setFilters=new qa,g=ga.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?ga.error(a):z(a,i).slice(0)};function ra(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function sa(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function ta(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ua(a,b,c){for(var d=0,e=b.length;e>d;d++)ga(a,b[d],c);return c}function va(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wa(a,b,c,d,e,f){return d&&!d[u]&&(d=wa(d)),e&&!e[u]&&(e=wa(e,f)),ia(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ua(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:va(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=va(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=va(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sa(function(a){return a===b},h,!0),l=sa(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sa(ta(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wa(i>1&&ta(m),i>1&&ra(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xa(a.slice(i,e)),f>e&&xa(a=a.slice(e)),f>e&&ra(a))}m.push(c)}return ta(m)}function ya(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=va(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&ga.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,ya(e,d)),f.selector=a}return f},i=ga.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ca,da),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ca,da),aa.test(j[0].type)&&pa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&ra(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,aa.test(a)&&pa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ja(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;
+
+return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function aa(){return!0}function ba(){return!1}function ca(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ca()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ca()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?aa:ba):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=aa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=aa,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=aa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=ba;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=ba),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function da(a){var b=ea.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var ea="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fa=/ jQuery\d+="(?:null|\d+)"/g,ga=new RegExp("<(?:"+ea+")[\\s/>]","i"),ha=/^\s+/,ia=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,ja=/<([\w:]+)/,ka=/<tbody/i,la=/<|&#?\w+;/,ma=/<(?:script|style|link)/i,na=/checked\s*(?:[^=]|=\s*.checked.)/i,oa=/^$|\/(?:java|ecma)script/i,pa=/^true\/(.*)/,qa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ra={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sa=da(y),ta=sa.appendChild(y.createElement("div"));ra.optgroup=ra.option,ra.tbody=ra.tfoot=ra.colgroup=ra.caption=ra.thead,ra.th=ra.td;function ua(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ua(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function va(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wa(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xa(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function ya(a){var b=pa.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function za(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Aa(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Ba(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xa(b).text=a.text,ya(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!ga.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ta.innerHTML=a.outerHTML,ta.removeChild(f=ta.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ua(f),h=ua(a),g=0;null!=(e=h[g]);++g)d[g]&&Ba(e,d[g]);if(b)if(c)for(h=h||ua(a),d=d||ua(f),g=0;null!=(e=h[g]);g++)Aa(e,d[g]);else Aa(a,f);return d=ua(f,"script"),d.length>0&&za(d,!i&&ua(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=da(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(la.test(f)){h=h||o.appendChild(b.createElement("div")),i=(ja.exec(f)||["",""])[1].toLowerCase(),l=ra[i]||ra._default,h.innerHTML=l[1]+f.replace(ia,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&ha.test(f)&&p.push(b.createTextNode(ha.exec(f)[0])),!k.tbody){f="table"!==i||ka.test(f)?"<table>"!==l[1]||ka.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ua(p,"input"),va),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ua(o.appendChild(f),"script"),g&&za(h),c)){e=0;while(f=h[e++])oa.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ua(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&za(ua(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ua(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fa,""):void 0;if(!("string"!=typeof a||ma.test(a)||!k.htmlSerialize&&ga.test(a)||!k.leadingWhitespace&&ha.test(a)||ra[(ja.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ia,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ua(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ua(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&na.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ua(i,"script"),xa),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ua(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,ya),j=0;f>j;j++)d=g[j],oa.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qa,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Ca,Da={};function Ea(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fa(a){var b=y,c=Da[a];return c||(c=Ea(a,b),"none"!==c&&c||(Ca=(Ca||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ca[0].contentWindow||Ca[0].contentDocument).document,b.write(),b.close(),c=Ea(a,b),Ca.detach()),Da[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Ga=/^margin/,Ha=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ia,Ja,Ka=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ia=function(b){return b.ownerDocument.defaultView.opener?b.ownerDocument.defaultView.getComputedStyle(b,null):a.getComputedStyle(b,null)},Ja=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ia(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Ha.test(g)&&Ga.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ia=function(a){return a.currentStyle},Ja=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ia(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Ha.test(g)&&!Ka.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function La(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight),b.removeChild(i)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Ma=/alpha\([^)]*\)/i,Na=/opacity\s*=\s*([^)]*)/,Oa=/^(none|table(?!-c[ea]).+)/,Pa=new RegExp("^("+S+")(.*)$","i"),Qa=new RegExp("^([+-])=("+S+")","i"),Ra={position:"absolute",visibility:"hidden",display:"block"},Sa={letterSpacing:"0",fontWeight:"400"},Ta=["Webkit","O","Moz","ms"];function Ua(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Ta.length;while(e--)if(b=Ta[e]+c,b in a)return b;return d}function Va(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fa(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wa(a,b,c){var d=Pa.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xa(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Ya(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ia(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Ja(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ha.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xa(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Ja(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ua(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qa.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ua(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Ja(a,b,d)),"normal"===f&&b in Sa&&(f=Sa[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Oa.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Ra,function(){return Ya(a,b,d)}):Ya(a,b,d):void 0},set:function(a,c,d){var e=d&&Ia(a);return Wa(a,c,d?Xa(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Na.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Ma,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Ma.test(f)?f.replace(Ma,e):f+" "+e)}}),m.cssHooks.marginRight=La(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Ja,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Ga.test(a)||(m.cssHooks[a+b].set=Wa)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ia(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Va(this,!0)},hide:function(){return Va(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Za(a,b,c,d,e){
+return new Za.prototype.init(a,b,c,d,e)}m.Tween=Za,Za.prototype={constructor:Za,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px")},cur:function(){var a=Za.propHooks[this.prop];return a&&a.get?a.get(this):Za.propHooks._default.get(this)},run:function(a){var b,c=Za.propHooks[this.prop];return this.options.duration?this.pos=b=m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Za.propHooks._default.set(this),this}},Za.prototype.init.prototype=Za.prototype,Za.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Za.propHooks.scrollTop=Za.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Za.prototype.init,m.fx.step={};var $a,_a,ab=/^(?:toggle|show|hide)$/,bb=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cb=/queueHooks$/,db=[ib],eb={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bb.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bb.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fb(){return setTimeout(function(){$a=void 0}),$a=m.now()}function gb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hb(a,b,c){for(var d,e=(eb[b]||[]).concat(eb["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ib(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fa(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fa(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ab.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fa(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hb(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jb(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kb(a,b,c){var d,e,f=0,g=db.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$a||fb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$a||fb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jb(k,j.opts.specialEasing);g>f;f++)if(d=db[f].call(j,a,k,j.opts))return d;return m.map(k,hb,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kb,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],eb[c]=eb[c]||[],eb[c].unshift(b)},prefilter:function(a,b){b?db.unshift(a):db.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kb(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gb(b,!0),a,d,e)}}),m.each({slideDown:gb("show"),slideUp:gb("hide"),slideToggle:gb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($a=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$a=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_a||(_a=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_a),_a=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lb=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lb,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mb,nb,ob=m.expr.attrHandle,pb=/^(?:checked|selected)$/i,qb=k.getSetAttribute,rb=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nb:mb)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rb&&qb||!pb.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qb?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nb={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rb&&qb||!pb.test(c)?a.setAttribute(!qb&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=ob[b]||m.find.attr;ob[b]=rb&&qb||!pb.test(b)?function(a,b,d){var e,f;return d||(f=ob[b],ob[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,ob[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rb&&qb||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mb&&mb.set(a,b,c)}}),qb||(mb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},ob.id=ob.name=ob.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mb.set},m.attrHooks.contenteditable={set:function(a,b,c){mb.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sb=/^(?:input|select|textarea|button|object)$/i,tb=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sb.test(a.nodeName)||tb.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var ub=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ub," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(ub," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(ub," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vb=m.now(),wb=/\?/,xb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yb,zb,Ab=/#.*$/,Bb=/([?&])_=[^&]*/,Cb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Db=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Eb=/^(?:GET|HEAD)$/,Fb=/^\/\//,Gb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hb={},Ib={},Jb="*/".concat("*");try{zb=location.href}catch(Kb){zb=y.createElement("a"),zb.href="",zb=zb.href}yb=Gb.exec(zb.toLowerCase())||[];function Lb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mb(a,b,c,d){var e={},f=a===Ib;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nb(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Ob(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zb,type:"GET",isLocal:Db.test(yb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nb(Nb(a,m.ajaxSettings),b):Nb(m.ajaxSettings,a)},ajaxPrefilter:Lb(Hb),ajaxTransport:Lb(Ib),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cb.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zb)+"").replace(Ab,"").replace(Fb,yb[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gb.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yb[1]&&c[2]===yb[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yb[3]||("http:"===yb[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mb(Hb,k,b,v),2===t)return v;h=m.event&&k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Eb.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wb.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bb.test(e)?e.replace(Bb,"$1_="+vb++):e+(wb.test(e)?"&":"?")+"_="+vb++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jb+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mb(Ib,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Ob(k,v,c)),u=Pb(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qb=/%20/g,Rb=/\[\]$/,Sb=/\r?\n/g,Tb=/^(?:submit|button|image|reset|file)$/i,Ub=/^(?:input|select|textarea|keygen)/i;function Vb(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rb.test(a)?d(a,e):Vb(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vb(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vb(c,a[c],b,e);return d.join("&").replace(Qb,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Ub.test(this.nodeName)&&!Tb.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sb,"\r\n")}}):{name:b.name,value:c.replace(Sb,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zb()||$b()}:Zb;var Wb=0,Xb={},Yb=m.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in Xb)Xb[a](void 0,!0)}),k.cors=!!Yb&&"withCredentials"in Yb,Yb=k.ajax=!!Yb,Yb&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wb;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xb[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xb[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zb(){try{return new a.XMLHttpRequest}catch(b){}}function $b(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _b=[],ac=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_b.pop()||m.expando+"_"+vb++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ac.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ac.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ac,"$1"+e):b.jsonp!==!1&&(b.url+=(wb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_b.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bc=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bc)return bc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cc=a.document.documentElement;function dc(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cc;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cc})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=La(k.pixelPosition,function(a,c){return c?(c=Ja(a,b),Ha.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ec=a.jQuery,fc=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fc),b&&a.jQuery===m&&(a.jQuery=ec),m},typeof b===K&&(a.jQuery=a.$=m),m});
+//# sourceMappingURL=jquery.min.map
\ No newline at end of file
--- /dev/null
+// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
+require('../../js/transition.js')
+require('../../js/alert.js')
+require('../../js/button.js')
+require('../../js/carousel.js')
+require('../../js/collapse.js')
+require('../../js/dropdown.js')
+require('../../js/modal.js')
+require('../../js/tooltip.js')
+require('../../js/popover.js')
+require('../../js/scrollspy.js')
+require('../../js/tab.js')
+require('../../js/affix.js')
\ No newline at end of file
--- /dev/null
+== SoundManager 2: JavaScript Sound for the Web\r
+\r
+By wrapping and extending HTML5 and Flash Audio APIs, SoundManager 2 brings reliable cross-platform audio to JavaScript. \r
+\r
+== HTML5 Audio() Support\r
+\r
+ * 100% Flash-free MP3 + MP4/AAC where supported\r
+ * Compatible with Apple iPad 3.2, iPhone/iOS 4 and newer\r
+ * Fallback to Flash for MP3/MP4 support, as needed\r
+ * SM2 API is transparent; HTML5/flash switching handled internally\r
+ * HTML5 API support approximates Flash 8 API features\r
+ * Some other formats (WAV/OGG) supported via HTML5, depending on browser\r
+ * See "useHTML5Audio" property for implementation details\r
+\r
+== Basic API Features (Flash 8)\r
+\r
+ * Load, stop, play, pause, mute, seek, pan and volume control of sounds from Javascript\r
+ * Events: onload, whileloading, whileplaying, onfinish and more\r
+ * ID3V1 and ID3V2 tag support for MP3s (title, artist, genre etc.)\r
+\r
+== Shiny Flash 9 Features\r
+\r
+ * RTMP / Flash Media Server streaming support\r
+ * MPEG-4 (AAC, HE-AAC, H.264) audio support\r
+ * "MultiShot" play (layered/chorusing effects)\r
+ * Waveform/frequency spectrum data\r
+ * Peak (L/R channel volume) data\r
+ * Audio buffering state/event handling\r
+\r
+== General Tech Stuff\r
+\r
+ * Full API Documentation with examples and notes\r
+ * console.log()-style debug output and troubleshooting tools\r
+ * Community-based discussion/support\r
+\r
+== As Heard On The Internets\r
+\r
+A few nifty sites that have implemented SM2 for driving audio:\r
+\r
+ * Tidal\r
+ * Beats\r
+ * Songza\r
+ * Earbits\r
+ * freesound.org\r
+ * last.fm\r
+ * 8tracks\r
+ * Discogs\r
+ * The Hype Machine\r
+ * nyan.cat\r
+\r
+== Project home, documentation, live demos etc.:\r
+\r
+http://www.schillmania.com/projects/soundmanager2/\r
+\r
+== Compiling JS builds (-nodebug, -jsmin) and Flash components, AS2/AS3 to SWF\r
+\r
+An Ant build file defines the tasks for compiling JS and SWF components, useful if you make changes to the SM2 source and want to recompile.\r
+Google's Closure Compiler is used for the JS. AS2 compilation is done by MTASC, and AS3 is handled by Adobe's Open Source Flex SDK (mxmlc) compiler.\r
+Refer to the build.xml file for compiler downloads and path definitions.\r
+\r
+== Versioning / Development Notes\r
+\r
+Releases are versioned by date, e.g., V2.97a.20110424 and are tagged as such.*\r
+The latest official release is always on trunk/master.\r
+Post-release development builds may be available on the appropriate +DEV branch, eg., V2.97a.20110801+DEV\r
+\r
+== Forks and Pull Requests\r
+\r
+Firstly, thank you for wanting to contribute! Bug fixes and tweaks are welcomed, particularly if they follow the general coding style of the project.\r
+If making a pull request, use the project's current +DEV development branch as the merge target instead of "master", if possible (please and thank-you.)\r
+\r
+* SoundManager 2 has been at "version" 2.97 for a long time, because 2.97 was arguably the best llama-ass-whipping version of WinAmp. (WinAmp 3 was not as good, and WinAmp 5 was "the best of 2 and 3 combined.") This MP3 player was my favourite Windows app during the 90's, and is missed as there's nothing quite like it on OS X where I spend most of my time these days.\r
--- /dev/null
+{
+ "name": "SoundManager2",
+ "version": "2.97.20150601",
+ "homepage": "https://github.com/scottschiller/SoundManager2",
+ "main": "script/soundmanager2.js",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "demo",
+ "doc",
+ "test",
+ "tests",
+ "tasks",
+ "component.json",
+ "composer.json",
+ "CONTRIBUTING.md",
+ "package.js",
+ "package.json"
+ ]
+}
--- /dev/null
+{\r
+ "name": "soundmanager2",\r
+ "repo": "scottschiller/soundmanager2",\r
+ "description": "A JavaScript Sound API supporting MP3, MPEG4 and HTML5 audio + RTMP, providing reliable cross-browser/platform audio control in as little as 12 KB.",\r
+ "version": "V2.97a.20150601-nodebug-jsmin",\r
+ "keywords": [\r
+ "audio",\r
+ "soundmanager2",\r
+ "soundmanager"\r
+ ],\r
+ "license": "BSD",\r
+ "scripts": [\r
+ "script/soundmanager2-nodebug-jsmin.js"\r
+ ],\r
+ "main": "script/soundmanager2-nodebug-jsmin.js",\r
+ "files":[\r
+ "swf/soundmanager2.swf",\r
+ "swf/soundmanager2_flash9.swf"\r
+ ]\r
+}
\ No newline at end of file
--- /dev/null
+/* larger canvas, spectrum + EQ visualization and other items */\r
+\r
+.ui360-vis,\r
+.ui360-vis .sm2-360ui,\r
+.sm2-inline-list .ui360-vis {\r
+ /* size of the container for the circle, etc. */\r
+ width:256px;\r
+ height:256px;\r
+}\r
+\r
+.ui360-vis {\r
+ position:relative;\r
+ /* a little extra spacing */\r
+ padding-top:1px;\r
+ padding-bottom:1px;\r
+ padding-left:248px;\r
+ margin-left:0px;\r
+ background-position:22.6% 50%; /* (~109px) initial play button position */\r
+}\r
+\r
+.sm2-inline-list .ui360-vis {\r
+ cursor:pointer\r
+}\r
+\r
+.ui360-vis a {\r
+ font:14px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;\r
+ white-space:nowrap;\r
+ text-indent:0px; /* undo inline style */\r
+ top:46%; /* ehh. */\r
+}\r
+\r
+.sm2-inline-list .ui360-vis a {\r
+ line-height:256px;\r
+ top:auto;\r
+}\r
+\r
+.ui360-vis .sm2-360ui {\r
+ margin-left:-256px;\r
+}\r
+\r
+.ui360-vis .sm2-timing {\r
+ font:bold 24px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;\r
+ color:#333;\r
+ text-align:center;\r
+ line-height:256px;\r
+ text-indent:0px;\r
+}\r
+\r
+.sm2-inline-list .ui360-vis,\r
+.sm2-inline-list .ui360-vis .sm2-360ui {\r
+ margin-left:0px;\r
+}\r
+\r
+.sm2-inline-list .ui360-vis {\r
+ margin:8px 13px 7px 0px;\r
+ padding-left:0px;\r
+ background-position:50% 50%; /* initial play button position */\r
+}\r
+\r
+.sm2-inline-list .ui360-vis .sm2-360ui {\r
+ border:1px solid #eee;\r
+ /* offset the border */\r
+ margin-left:-1px;\r
+ margin-top:-1px;\r
+}\r
+\r
+.sm2-inline-list .ui360-vis a {\r
+ position:absolute;\r
+ display:inline;\r
+ left:0px;\r
+ bottom:0px;\r
+ top:1px;\r
+ width:100%; /* 2px padding in box */\r
+ height:99%; /* dumb vertical hack */\r
+ *height:256px; /* IE is dumb. */\r
+ overflow:hidden;\r
+ font-size:small;\r
+ font-weight:300;\r
+ color:#333;\r
+ margin:0px;\r
+ padding:0px;\r
+ line-height:488px; /* bottom vertical alignment for text */\r
+ *line-height:480px; /* IE again */\r
+ text-align:center;\r
+ border-radius:0px;\r
+}\r
+\r
+.sm2-inline-list .ui360 a:hover {\r
+ background-color:transparent; /* reset */\r
+}\r
+\r
+.sm2-inline-list .ui360-vis:hover .sm2-360ui,\r
+.sm2-inline-list .ui360-vis a.sm2_link:hover,\r
+.sm2-inline-list .ui360-vis a.sm2_link:active,\r
+.sm2-inline-list .ui360-vis a.sm2_link:focus {\r
+ background-color:transparent;\r
+}\r
+\r
+/* Use a bigger loading image for this layout */\r
+\r
+.ui360-vis .sm2-360btn,\r
+.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn,\r
+.ui360-vis .sm2-360ui.sm2_playing .sm2-360btn {\r
+ width:48px;\r
+ height:48px;\r
+ margin-left:-24px;\r
+ margin-top:-24px;\r
+ border-radius: none;\r
+}\r
+\r
+.ui360-vis,\r
+.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn,\r
+.ui360-vis .sm2-360btn-default {\r
+ background:transparent url(360-button-vis-play.png) no-repeat 50% 50%;\r
+ background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAABuVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7++lpaXr6+uAgIDk5OQzMzPt7e1tbW3n5+dgYGDW1tZNTU10dHQ5OTnw8PCvr6/e3t6JiYlAQEDb29vo6OgrKyuqqqrq6uq4uLjf399AQEDGxsbq6uqAgIDY2Nje3t61tbXp6enU1NTu7u7r6+vl5eXt7e2fn5/n5+fDw8Ph4eHv7+/t7e3CwsLW1tbu7u7b29vw8PDm5uYgICDp6enY2Nji4uLo6Ojm5uakpKTS0tLPz8/h4eHw8PDs7Ozj4+Pa2trg4ODx8fHT09Pk5OTPz8/S0tLBwcGmpqawsLCOjo7h4eHn5+fo6OgAAADY2NjNzc3n5+cAAADd3d3Gxsbu7u7t7e0AAADX19fl5eXi4uLf39/Hx8fn5+fs7Ozg4ODR0dHX19e4uLjv7+/z8/P09PTy8vL19fXv7+/n5+fx8fH29vbs7Ozq6urm5ubo6Ojw8PDu7u7p6enr6+sAAAB/f3/Z2dn39/fh4eGOjo4ODg7t7e3l5eWWlpba2tqjo6NVVVXk5OTe3t65ubnMzMzExMTf39/GxsampqZiYmJNcTiZAAAAbXRSTlMAAQIEAwcFCAb5EdAImAXpB6oIUAoLCfsgZQ0EVrsGEr4ZYQgbsgpUYxikNd/aatQQli+R7rlUUdas6+8I+VaFruoOOV/S8Nq5sWL8UqmKUFsuHyTcrtsJm0z7C49V3NMKkdKXuk7S7oVeVSv7tAAEVwAAAu5JREFUeF6llmVz3DwURmNLsr1pmJmZmZmxzMwsybS8gXJfhl9cKXbHEK+TmZ4P/nDnOXN1NbalHD8CQ7QRGDmhnIQhBDYQnkhheRECSVIQQrLMHookAciUkHhBw1zVwuLShcJIpPDC0uJC1VxDQTaFx1srSvM3DUxU1TRVlWBjM7+0opUrQaupLSnrLK7ELIepwaCYmbiyuLOspJY38eeLykdGxzDhYQfKCmOjI+VFPkMQYF7NZD0l2DgFJrR+siYPegxBzBvqeoQxpgGw8qOuoTz3HGw9udUPCaFZIORhdS5blZOHjXWDBIdABusanb0S4MpqEw4XcNPqCrQFQQTN+XwPQ8CY5jcDUbB3KLdlg6hnQDZacqEgWA3a2rF6Jri9zWohwI6dXXK2QHZ3OqBw0qC7B6vnAPd0sxZMkHr7VNPD34YZgNrXK3EBSgPU9HJ4eIQDDDogQS4ow4QJxy4+MmKs4oYJZFhhggjQuMoKHoHzn3bsQx1HQOTClOkXLP6lviZTtjCjmn7B5g/izqszliBHTB+HDhl3PSJbwnxSS3n45HDkVLXkvCWg5Uws7eHgJ98/uKqxzLI9w3o6oXuwhd+OPNVEet0WtnU9/sWNJfz1u6cY1/VtLghQuRgk/PmBmT7hogJPXo3L8YQed3Nw8PWfuB89Eb8scUGUrl33DfH/N93BGeH6NUnkArh1O5FOuNETp2GR27cAE/iaJu6mz8HdCQnan+i96XQmdgaZ9PQ9+xMVoPJgNhrNhBKNzj5Q+E/AavH4SSz6OZRo7Mlj3oDDp7jyPJoKJfr8CpvAOUrQi6eppJaVZOrpCwTdP1cgr93UjKxoN9dka2KX8ealZtBADO3lG2+e7xRAd7Y0igOg2tYdBKD/CBIBenf/lYGJD2y8uv8OgaBDDkry3v57SlQXhL7f35OlwJOXGUBBl571JykmzCIE02T/s0tIASyf/R6Arr59fcM62G+8fnsVhdwFwq4Ov345Of/15wd0RYY81HHUTQAAAABJRU5ErkJggg==);\r
+ *background-image:url(360-button-vis-play.png);\r
+ _background:transparent url(360-button-vis-play.gif) no-repeat 50% 50%;\r
+ cursor:pointer;\r
+}\r
+\r
+.ui360-vis:hover .sm2-360btn,\r
+.ui360-vis .sm2-360btn-default:hover,\r
+.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn:hover {\r
+ background:transparent url(360-button-vis-play-light.png) no-repeat 50% 50%;\r
+ _background:transparent url(360-button-vis-play.gif) no-repeat 50% 50%;\r
+ cursor:pointer;\r
+}\r
+\r
+\r
+.ui360-vis .sm2-360ui.sm2_playing .sm2-360btn:hover,\r
+.ui360-vis .sm2-360btn-playing:hover {\r
+ background:transparent url(360-button-vis-pause-light.png) no-repeat 50% 50%;\r
+ _background:transparent url(360-button-vis-pause-light.gif) no-repeat 50% 50%;\r
+ cursor:pointer;\r
+}\r
+\r
+.ui360-vis {\r
+ /* non-JS / before-loaded state */\r
+ background-position: 21% 50%;\r
+ _background:transparent url(360-button-vis-play.gif) no-repeat 21% 50%; /* IE 6-only: special crap GIF */\r
+}\r
+\r
+.ui360-vis .sm2-360btn-default {\r
+ /* real button, post-loaded state */\r
+ _background:transparent url(360-button-vis-play.gif) no-repeat 50% 50%; /* IE 6-only: special crap GIF */\r
+}\r
+\r
+.ui360-vis .sm2-360ui.sm2_dragging .sm2-360btn {\r
+ visibility: hidden;\r
+}
\ No newline at end of file
--- /dev/null
+/* General warning: Beta-ish. Code could be a bit cleaner. */\r
+\r
+.ui360, /* entire UI */\r
+.sm2-360ui { /* canvas container */\r
+ position:relative;\r
+}\r
+\r
+.ui360 {\r
+ margin-bottom: 5px;\r
+ margin-right: 5px;\r
+}\r
+\r
+.ui360,\r
+.sm2-360ui {\r
+ min-width:50px; /* should always be at least this. */\r
+ min-height:50px;\r
+}\r
+\r
+.sm2-360ui {\r
+ width:50px;\r
+ height:50px;\r
+}\r
+\r
+.sm2-360ui {\r
+ /* slight inner shadow + BG color + border */\r
+ background-color: #f9f9f9;\r
+ background-color: rgba(0,0,0,0.025);\r
+ box-shadow: inset 0px 0px 8px rgba(0,0,0,0.15);\r
+ /* a little radii, modern browsers only */\r
+ border-radius: 100%;\r
+ -webkit-transition: all 0.1s ease-in-out;\r
+ -moz-transition: all 0.1s ease-in-out;\r
+ transition: all 0.1s ease-in-out;\r
+ /* specifics */\r
+ -moz-transition-property: background, border, box-shadow;\r
+ -webkit-transition-property: background, border, box-shadow;\r
+ transition-property: background, border, box-shadow;\r
+}\r
+\r
+.sm2-360ui:hover {\r
+ background-color: rgba(0,0,0,0.1);\r
+ border-color: rgba(0,0,0,0.15);\r
+ box-shadow: inset 0px 0px 5px rgba(0,0,0,0.15);\r
+}\r
+\r
+.ui360,\r
+.ui360 * {\r
+ vertical-align:middle;\r
+}\r
+\r
+.sm2-360ui {\r
+ position:relative;\r
+ display:inline-block; /* firefox 3 et al */\r
+ float:left; /* IE 6+7, firefox 2 needs this, inline-block would work with fx3 and others */\r
+ *display:inline;\r
+ clear:left;\r
+}\r
+\r
+.sm2-360ui.sm2_playing,\r
+.sm2-360ui.sm2_paused {\r
+ /* bump on top when active */\r
+ z-index:10;\r
+}\r
+\r
+.ui360 a { /* .sm2_link class added to playable links by SM2 */\r
+ float:left;\r
+ display:inline;\r
+ position:relative;\r
+ color:#000;\r
+ text-decoration:none;\r
+ left:3px; /* slight spacing on left UI */\r
+ top:18px; /* vertical align */\r
+ text-indent:50px; /* make room for UI at left */\r
+}\r
+\r
+.ui360 a.sm2_link { /* SM2 has now started */\r
+ text-indent:0px; /* UI now in place. */\r
+}\r
+\r
+.ui360 a,\r
+.ui360 a:hover,\r
+.ui360 a:focus {\r
+ padding:2px;\r
+ margin-left:-2px;\r
+ margin-top:-2px;\r
+}\r
+\r
+.ui360 a:hover,\r
+.ui360 a:focus {\r
+ background:#eee;\r
+ border-radius:3px;\r
+ outline:none;\r
+}\r
+\r
+.ui360 .sm2-canvas {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+}\r
+\r
+.ui360 .sm2-canvas.hi-dpi {\r
+ /* hi-dpi / "retina" screens */\r
+ top: -50%;\r
+ left: -50%;\r
+ -moz-transform: scale(0.5);\r
+ -ms-transform: scale(0.5);\r
+ -webkit-transform: scale(0.5);\r
+ transform: scale(0.5);\r
+}\r
+\r
+.ui360 .sm2-timing {\r
+ position:absolute;\r
+ display:block;\r
+ left:0px;\r
+ top:0px;\r
+ width:100%;\r
+ height:100%;\r
+ margin:0px;\r
+ font:11px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;\r
+ color:#666;\r
+ text-align:center;\r
+ line-height:50px;\r
+}\r
+\r
+.ui360 .sm2-timing.alignTweak {\r
+ /* devious center-alignment tweak for Safari (might break things for others.) */\r
+ /* no longer applies. */\r
+ /*\r
+ text-indent:1px;\r
+ */\r
+}\r
+\r
+.ui360 .sm2-cover {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:100%;\r
+ height:100%;\r
+ z-index:2;\r
+ display:none;\r
+ background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==); /* old-skool bug: IE 9 won't catch mouse events otherwise. /smash */\r
+}\r
+\r
+.ui360 .sm2-360btn {\r
+ position:absolute;\r
+ display:block;\r
+ top:50%;\r
+ left:50%;\r
+/*\r
+ width:22px;\r
+ height:22px;\r
+ margin-left:-11px;\r
+ margin-top:-11px;\r
+*/\r
+ /* by default, cover whole space. make smaller when playing. */\r
+ width:50px;\r
+ height:50px;\r
+ margin-left:-25px;\r
+ margin-top:-25px;\r
+ border-radius: 25px;\r
+ cursor:pointer;\r
+ z-index:3;\r
+}\r
+\r
+.ui360 .sm2-360data {\r
+ display:inline-block;\r
+ font-family:helvetica;\r
+}\r
+\r
+.sm2-inline-block .ui360 .sm2-360btn,\r
+.ui360 .sm2-360ui.sm2_playing .sm2-360btn,\r
+.ui360 .sm2-360ui.sm2_paused .sm2-360btn {\r
+ /* smaller clickable button, in center */\r
+ width:22px;\r
+ height:22px;\r
+ margin-left:-11px;\r
+ margin-top:-11px;\r
+}\r
+\r
+.ui360 .sm2-360ui.sm2_playing .sm2-cover,\r
+.ui360 .sm2-360ui.sm2_paused .sm2-cover {\r
+ display:block;\r
+}\r
+\r
+/* this could be optimized a fair bit. */\r
+\r
+.ui360,\r
+.ui360 .sm2-360btn-default,\r
+.ui360 .sm2-360ui.sm2_paused .sm2-360btn {\r
+ background:transparent url(360-button-play.png) no-repeat;\r
+ /* if you change the source image, update these data: URIs as well. */\r
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAABoUlEQVR42sWVu2oCQRhGU/s8gpVYJeQJNkZSbiH4QNuLlQZS21sJayGYaOEFVFDxNiremj9zig2uzk5YQpKFg8PMd75ZZle9E5Ff4e+Ll8tlQuNoPI2vUcCYOdbIxCmm9F5T0YgNMmS/LebSwWdNa7VayXq9ls1mI9vtVna7nQBj5lgjQxYHN7KY3QkiUbDf7+V4PMrpdArBHGtkyOJc3/n1mVaUUl+F5/PZSrABDi4dpmKH3QkixQEHlw5TsccZmsRCoSD1et1ajkuHqdg/HA5GKZPJCOTzeanVasYMLh2mYsXDIGAoDuG6rlSr1WCdBxrcsTIWazgrQiHS6bSRYJ3XDzeq2O/3+9Ltdm9IpVIhstmslEqlUAY36ii8ZrMpjUbjhmQyKeA4jhSLRWMGN+rhOZ1Oh8ANuVxOyuUy40hwo163RK/XeyPQbrdjgYNr/ILAYDB41Gf1wZnFAQfX+iM0HA5fxuPx+2g0Ej22QoYsDq61mGsymTxMp9NX/Sk2yJDFsRZfXpzXbDZ7WiwW3nw+9zUKGDPHGpkL5V//mn7OJyJZApyzeUS5AAAAAElFTkSuQmCC);\r
+ /* hi-dpi, we presume */\r
+ background-image: none, url(360-button-play-2x.png);\r
+ background-size: 22px 22px;\r
+ *background-image: url(360-button-play.png);\r
+ background-repeat: no-repeat;\r
+}\r
+\r
+.ui360 {\r
+ /*\r
+ "fake" button shown before SM2 has started, non-JS/non-SM2 case etc.\r
+ background image will be removed via JS, in threeSixyPlayer.init()\r
+ */\r
+ background-position: 14px 50%;\r
+ _background:transparent url(360-button-play.gif) no-repeat 14px 50%; /* IE 6-only: special crap GIF */\r
+}\r
+\r
+.ui360 .sm2-360btn-default,\r
+.ui360 .sm2-360ui.sm2_paused .sm2-360btn {\r
+ background-position:50% 50%;\r
+ _background:transparent url(360-button-play.gif) no-repeat 50% 50%; /* IE 6-only: special crap GIF */\r
+}\r
+\r
+.ui360 .sm2-360btn-default,\r
+.ui360 .sm2-360ui.sm2_paused .sm2-360btn {\r
+ cursor:pointer;\r
+}\r
+\r
+.ui360 .sm2-360btn-default:hover,\r
+.ui360 .sm2-360ui.sm2_paused .sm2-360btn:hover {\r
+ background:transparent url(360-button-play-light.png) no-repeat 50% 50%;\r
+ /* hi-dpi, we presume */\r
+ background-image: none, url(360-button-play-light-2x.png);\r
+ background-size: 22px 22px;\r
+ _background:transparent url(360-button-play.gif) no-repeat 50% 50%;\r
+ cursor:pointer;\r
+}\r
+\r
+.ui360 .sm2-360ui.sm2_playing .sm2-360btn:hover,\r
+.ui360 .sm2-360btn-playing:hover {\r
+ background:transparent url(360-button-pause-light.png) no-repeat 50% 50%;\r
+ background-image: none, url(360-button-pause-light-2x.png);\r
+ background-size: 22px 22px;\r
+ _background:transparent url(360-button-pause-light.gif) no-repeat 50% 50%;\r
+ cursor:pointer;\r
+}\r
+\r
+.ui360 .sm2-360ui.sm2_playing .sm2-timing {\r
+ visibility:visible;\r
+}\r
+\r
+.ui360 .sm2-360ui.sm2_buffering .sm2-timing {\r
+ visibility:hidden;\r
+}\r
+\r
+.ui360 .sm2-360ui .sm2-timing,\r
+.ui360 .sm2-360ui .sm2-360btn:hover + .sm2-timing,\r
+.ui360 .sm2-360ui.sm2_paused .sm2-timing {\r
+ visibility:hidden;\r
+}\r
+\r
+.ui360 .sm2-360ui.sm2_dragging .sm2-timing,\r
+.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover + .sm2-timing {\r
+ /* paused + dragging */\r
+ visibility:visible;\r
+}\r
+\r
+.ui360 .sm2-360ui.sm2_playing .sm2-360btn,\r
+.ui360 .sm2-360ui.sm2_dragging .sm2-360btn,\r
+.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover,\r
+.ui360 .sm2-360ui.sm2_dragging .sm2-360btn-playing:hover {\r
+ /* don't let pause button show on hover when dragging (or paused and dragging) */\r
+ background:transparent;\r
+ cursor:auto;\r
+}\r
+\r
+.ui360 .sm2-360ui.sm2_buffering .sm2-360btn,\r
+.ui360 .sm2-360ui.sm2_buffering .sm2-360btn:hover {\r
+ background:transparent url(icon_loading_spinner.gif) no-repeat 50% 50%;\r
+ opacity:0.5;\r
+ visibility:visible;\r
+}\r
+\r
+/* inline list style */\r
+\r
+.sm2-inline-list .ui360,\r
+.sm2-inline-block .ui360 {\r
+ position:relative;\r
+ display:inline-block;\r
+ float:left;\r
+ _display:inline;\r
+ /*\r
+ margin-bottom:-15px;\r
+ */\r
+}\r
+\r
+.sm2-inline-block .ui360 {\r
+ margin-right:8px;\r
+}\r
+\r
+.sm2-inline-list .ui360 a {\r
+ display:none;\r
+}\r
+\r
+/* annotations */\r
+\r
+ul.ui360playlist {\r
+ list-style-type:none;\r
+}\r
+\r
+ul.ui360playlist,\r
+ul.ui360playlist li {\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+div.ui360 div.metadata {\r
+ display:none;\r
+}\r
+\r
+div.ui360 a span.metadata,\r
+div.ui360 a span.metadata * {\r
+ /* name of track, note etc. */\r
+ vertical-align:baseline;\r
+}\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>360° MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization, basic example</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Basic example of 360-degree circular control for MP3 links, with EQ and spectrum visualization options" />\r
+<!-- demo: make the fonts nicer etc. -->\r
+<link rel="stylesheet" type="text/css" href="../index.css" />\r
+\r
+<!-- soundManager.useFlashBlock: related CSS -->\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+\r
+<!-- required -->\r
+<link rel="stylesheet" type="text/css" href="360player.css" />\r
+<link rel="stylesheet" type="text/css" href="360player-visualization.css" />\r
+\r
+<!-- special IE-only canvas fix -->\r
+<!--[if IE]><script type="text/javascript" src="script/excanvas.js"></script><![endif]-->\r
+\r
+<!-- Apache-licensed animation library -->\r
+<script type="text/javascript" src="script/berniecode-animator.js"></script>\r
+\r
+<!-- the core stuff -->\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/360player.js"></script>\r
+\r
+<script type="text/javascript">\r
+\r
+soundManager.setup({\r
+ // path to directory containing SM2 SWF\r
+ url: '../../swf/'\r
+});\r
+\r
+threeSixtyPlayer.config.scaleFont = (navigator.userAgent.match(/msie/i)?false:true);\r
+threeSixtyPlayer.config.showHMSTime = true;\r
+\r
+// enable some spectrum stuffs\r
+\r
+threeSixtyPlayer.config.useWaveformData = true;\r
+threeSixtyPlayer.config.useEQData = true;\r
+\r
+// enable this in SM2 as well, as needed\r
+\r
+if (threeSixtyPlayer.config.useWaveformData) {\r
+ soundManager.flash9Options.useWaveformData = true;\r
+}\r
+if (threeSixtyPlayer.config.useEQData) {\r
+ soundManager.flash9Options.useEQData = true;\r
+}\r
+if (threeSixtyPlayer.config.usePeakData) {\r
+ soundManager.flash9Options.usePeakData = true;\r
+}\r
+\r
+if (threeSixtyPlayer.config.useWaveformData || threeSixtyPlayer.flash9Options.useEQData || threeSixtyPlayer.flash9Options.usePeakData) {\r
+ // even if HTML5 supports MP3, prefer flash so the visualization features can be used.\r
+ soundManager.preferFlash = true;\r
+}\r
+\r
+// favicon is expensive CPU-wise, but can be enabled.\r
+threeSixtyPlayer.config.useFavIcon = false;\r
+\r
+</script>\r
+\r
+<link rel="stylesheet" type="text/css" href="demo.css" />\r
+<style type="text/css">\r
+\r
+#left h2 {\r
+ padding-top:0px;\r
+ margin-bottom:0.25em;\r
+ color:#666;\r
+}\r
+\r
+pre.block {\r
+ margin-top:0.5em;\r
+}\r
+\r
+/* special case */\r
+\r
+#left {\r
+ width:auto;\r
+ max-width:100%;\r
+}\r
+\r
+</style>\r
+\r
+</head>\r
+\r
+<body>\r
+\r
+<div id="left">\r
+\r
+ <h1><a href="http://schillmania.com/projects/soundmanager2/demo/360-player/">360° Player Demo</a> - Visualization Example, Basic Template</h1>\r
+\r
+ <p class="note" style="color:#666;margin-bottom:0.5em">Canvas-based UI with visualization options. <b>Note: No EQ/spectrum support for IE < 9 (too slow.) Data not implemented in HTML5.</b></p>\r
+\r
+ <div style="clear:left"></div>\r
+ \r
+ <div id="sm2-container">\r
+ <!-- sm2 flash goes here -->\r
+ </div>\r
+\r
+ <!-- here are the MP3 links, which are decorated with the 360 canvas element/UI etc. -->\r
+\r
+ <h2 style="margin-top:1em">Inline list</h2>\r
+\r
+ <div class="sm2-inline-list"> <!-- remove this class to have one item per line -->\r
+\r
+ <div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CRASH_1.mp3">Crash 1</a></div>\r
+ <div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CRASH_5.mp3">Crash 5</a></div>\r
+ <div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CRASH_6.mp3">Crash 6</a></div>\r
+ <div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CHINA_1.mp3">China 1</a></div>\r
+\r
+ </div>\r
+\r
+ <h2 style="clear:both;padding-top:1em">Block list</h2>\r
+\r
+ <div>\r
+ <div class="ui360 ui360-vis"><a href="../../demo/_mp3/sine,%20square,%20sawtooth,%20rando.mp3">Sine, Square, Sawtooth, Wave (Warning: LOUD)</a></div>\r
+ <div class="ui360 ui360-vis"><a href="../../demo/_mp3/1hz-10khz-sweep.mp3">1-10 Khz Sweep (Warning: LOUD)</a></div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <p style="margin-left:1em">\r
+ <a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)\r
+ </p>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>360° MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Javascript + Canvas + SoundManager 2: 360-degree circular control / jog wheel example for playing MP3 links, with EQ and spectrum visualization options" />\r
+<!-- demo, make the fonts nicer etc. -->\r
+<link rel="stylesheet" type="text/css" href="../index.css" />\r
+\r
+<!-- soundManager.useFlashBlock: related CSS -->\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+\r
+<!-- required -->\r
+<link rel="stylesheet" type="text/css" href="360player.css" />\r
+<link rel="stylesheet" type="text/css" href="360player-visualization.css" />\r
+\r
+<!-- special IE-only canvas fix -->\r
+<!--[if IE]><script type="text/javascript" src="script/excanvas.js"></script><![endif]-->\r
+\r
+<!-- Apache-licensed animation library -->\r
+<script type="text/javascript" src="script/berniecode-animator.js"></script>\r
+\r
+<!-- the core stuff -->\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/360player.js"></script>\r
+\r
+<script type="text/javascript">\r
+\r
+soundManager.setup({\r
+ // path to directory containing SM2 SWF\r
+ url: '../../swf/'\r
+});\r
+\r
+threeSixtyPlayer.config.scaleFont = (navigator.userAgent.match(/msie/i)?false:true);\r
+threeSixtyPlayer.config.showHMSTime = true;\r
+\r
+// enable some spectrum stuffs\r
+\r
+threeSixtyPlayer.config.useWaveformData = true;\r
+threeSixtyPlayer.config.useEQData = true;\r
+\r
+// enable this in SM2 as well, as needed\r
+\r
+if (threeSixtyPlayer.config.useWaveformData) {\r
+ soundManager.flash9Options.useWaveformData = true;\r
+}\r
+if (threeSixtyPlayer.config.useEQData) {\r
+ soundManager.flash9Options.useEQData = true;\r
+}\r
+if (threeSixtyPlayer.config.usePeakData) {\r
+ soundManager.flash9Options.usePeakData = true;\r
+}\r
+\r
+if (threeSixtyPlayer.config.useWaveformData || threeSixtyPlayer.flash9Options.useEQData || threeSixtyPlayer.flash9Options.usePeakData) {\r
+ // even if HTML5 supports MP3, prefer flash so the visualization features can be used.\r
+ soundManager.preferFlash = true;\r
+}\r
+\r
+// favicon is expensive CPU-wise, but can be used.\r
+if (window.location.href.match(/hifi/i)) {\r
+ threeSixtyPlayer.config.useFavIcon = true;\r
+}\r
+\r
+if (window.location.href.match(/html5/i)) {\r
+ // for testing IE 9, etc.\r
+ soundManager.useHTML5Audio = true;\r
+}\r
+\r
+</script>\r
+\r
+<!-- DEMO only, customization UI: Yahoo! YUI colorpicker stuff -->\r
+<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/slider/assets/skins/sam/slider.css" />\r
+<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/colorpicker/assets/skins/sam/colorpicker.css" />\r
+<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>\r
+<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/animation/animation-min.js"></script>\r
+<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/dragdrop/dragdrop-min.js"></script>\r
+<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/slider/slider-min.js"></script>\r
+<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/element/element-min.js"></script>\r
+<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/colorpicker/colorpicker-min.js"></script>\r
+\r
+<link rel="stylesheet" type="text/css" href="demo.css" />\r
+<style type="text/css">\r
+\r
+body {\r
+ background-image: none;\r
+}\r
+\r
+#left h2 {\r
+ padding-top:0px;\r
+ margin-bottom:0.25em;\r
+ color:#666;\r
+}\r
+\r
+pre.block {\r
+ margin-top:0.5em;\r
+}\r
+\r
+/* special case */\r
+\r
+#left {\r
+ width:auto;\r
+ max-width:100%;\r
+}\r
+\r
+.ui360 span {\r
+ vertical-align: top;\r
+}\r
+\r
+</style>\r
+\r
+<!-- demo configuration stuff, you don't need this -->\r
+<link rel="stylesheet" type="text/css" href="demo-slider-controls.css" />\r
+<script type="text/javascript" src="demo-slider-controls.js"></script>\r
+\r
+</head>\r
+\r
+<body>\r
+ \r
+<div id="left">\r
+\r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Javascript MP3 player project home">SoundManager 2</a> / <a href="http://schillmania.com/projects/soundmanager2/demo/360-player/">360° Player Demo</a>: JS + Canvas Visualization</h1>\r
+\r
+ <p class="note" style="color:#666;margin-top:0.5em;margin-bottom:0.5em">Canvas-based UI with visualization options. <b>Note: Spectrum/EQ visualizations disabled for IE < 9 (too slow.) Data is not implemented under HTML5.</b></p>\r
+ <p class="note" style="color:#666;margin-bottom:0.5em">You can also <a href="#debug=1" onclick="window.location.href = this.href;window.location.reload()" title="Enable debug mode, show frames per second">show FPS</a><span id="config-link"> or <a href="#customize" onclick="window.location.href=this.href;window.location.reload()">customize the UI</a></span><span id="hifi">, or see the <a href="#hifi=1" onclick="window.location.href=this.href;window.location.reload()">hi-fi version</a></span>. Check the <a href="canvas-visualization-basic.html">basic template</a> for a minimal code example; also see the <a href="../360-player/" title="360° player UI">default 360° UI</a>.</p>\r
+\r
+ <!-- customization crap -->\r
+\r
+ <div id="config-ui" style="clear:both;position:relative;max-width:1110px;margin-top:1em;display:none">\r
+\r
+ <div style="position:relative">\r
+\r
+ <form action="#" method="get">\r
+\r
+ <div id="controls">\r
+\r
+ <div class="checkbox">\r
+ <div>\r
+ <input id="use-waveform" type="checkbox" checked="checked" title="Enable waveform feature." onclick="controller.updateExample();controller.updateExampleCode()" value="Apply" /> Waveform\r
+ <input id="disabled-1" type="checkbox" title="Enable EQ (spectrum) feature." onclick="controller.updateExample();controller.updateExampleCode()" value="Apply" style="margin-left:1em" checked="checked" /> EQ\r
+ <input type="checkbox" name="use-amplifier" id="use-amplifier" checked="checked" onclick="controller.updateExample();controller.updateExampleCode()" style="margin-left:1em"> Amplifier\r
+ </div>\r
+ </div>\r
+\r
+ <div style="clear:left"></div>\r
+\r
+ <dl class="col">\r
+\r
+ <dt>Circle Diameter</dt>\r
+ <dd class="title">Size</dd>\r
+ <dd>1-256</dd>\r
+ <dd class="control">\r
+ <div class="bar" title="Click to move here"></div>\r
+ <div class="slider" title="Size of circle"></div>\r
+ </dd>\r
+\r
+ <dt>Waveform Thickness</dt>\r
+ <dd class="title">thickness</dd>\r
+ <dd>1-100</dd>\r
+ <dd class="control">\r
+ <div class="bar" title="Click to move here"></div>\r
+ <div class="slider" title="Thickness of line"></div>\r
+ </dd>\r
+\r
+ <dt>Wave Downsample</dt>\r
+ <dd class="title">(Scale)</dd>\r
+ <dd>1-16</dd>\r
+ <dd class="control">\r
+ <div class="bar" title="Click to move here"></div>\r
+ <div class="slider" title="Amount to downsample waveform data by"></div>\r
+ </dd>\r
+\r
+ <dt>EQ Thickness</dt>\r
+ <dd class="title">thickness</dd>\r
+ <dd>1-50</dd>\r
+ <dd class="control">\r
+ <div class="bar" title="Click to move here"></div>\r
+ <div class="slider" title="Thickness of line"></div>\r
+ </dd>\r
+\r
+ <dt>EQ Downsample</dt>\r
+ <dd class="title">(Scale)</dd>\r
+ <dd>1-16</dd>\r
+ <dd class="control">\r
+ <div class="bar" title="Click to move here"></div>\r
+ <div class="slider" title="Amount to downsample EQ data by"></div>\r
+ </dd>\r
+\r
+ <dt>Ring Thickness</dt>\r
+ <dd class="title">(Scale)</dd>\r
+ <dd>1-200</dd>\r
+ <dd class="control">\r
+ <div class="bar" title="Click to move here"></div>\r
+ <div class="slider" title="Scale factor for the ring width"></div>\r
+ </dd>\r
+\r
+ </dl>\r
+\r
+ <div id="options" class="col">\r
+\r
+ <div>\r
+ Waveform position:\r
+ <input type="radio" name="waveform-inside" id="waveform-inside" value="true" checked="checked" onclick="controller.updateExample();controller.updateExampleCode()"> Inside | <input type="radio" name="waveform-inside" id="waveform-inside" value="false" onclick="controller.updateExample();controller.updateExampleCode()"> Outside\r
+ </div>\r
+\r
+ <div>\r
+ EQ position:\r
+ <input type="radio" name="eq-inside" id="eq-inside" value="true" onclick="controller.updateExample();controller.updateExampleCode()"> Inside | <input type="radio" name="eq-inside" id="eq-inside" value="false" checked="checked" onclick="controller.updateExample();controller.updateExampleCode()"> Outside\r
+ </div>\r
+\r
+ <div>\r
+ Waveform color:\r
+ <input type="text" name="waveform-color" id="waveform-color" value="#000000" onclick="createCP(this,setWaveformColor)" />\r
+ </div>\r
+\r
+ <div>\r
+ EQ color:\r
+ <input type="text" name="eq-color" id="eq-color" value="#000000" onclick="createCP(this,setEQColor)" />\r
+ </div>\r
+\r
+ <div>\r
+ Loaded ring color:\r
+ <input type="text" name="loaded-ring-color" id="loaded-ring-color" value="#000000" onclick="createCP(this,setLoadedRingColor)" />\r
+ </div>\r
+\r
+ <div>\r
+ Progress ring color:\r
+ <input type="text" name="progress-ring-color" id="progress-ring-color" value="#000000" onclick="createCP(this,setProgressRingColor)" />\r
+ </div>\r
+\r
+ <div>\r
+ Background ring color:\r
+ <input type="text" name="bg-ring-color" id="bg-ring-color" value="#000000" onclick="createCP(this,setBackgroundRingColor)" />\r
+ </div>\r
+ \r
+ <p class="compact">\r
+ <input type="button" onclick="controller.randomize()" value="Randomize controls" title="Assign random control values" style="font-size:x-small" />\r
+ </p>\r
+\r
+ </form>\r
+ \r
+ </div>\r
+\r
+ <div id="cp-container">\r
+ <!-- color picker stuff goes here -->\r
+ </div>\r
+ \r
+ <div id="config-code-block" style="float:right;display:inline;margin-left:1em;margin-top:-0.7em">\r
+ <!--\r
+ <pre id="config-link" class="block"><code style="cursor:pointer" onclick="document.getElementById('config-link').style.display='none';document.getElementById('config-pre-block').style.display='block';return false"> [click to show code] </code></pre>\r
+ -->\r
+ <pre id="config-pre-block" class="block"><code id="config-code">Code goes here</code></pre>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ <p style="clear:left">Get a sound playing, then adjust the values to see real-time updates.</p>\r
+\r
+ </div>\r
+\r
+ <!-- here are the MP3 links, which are decorated with the 360 canvas element/UI etc. -->\r
+ \r
+ <div id="sm2-container">\r
+ <!-- sm2 flash goes here -->\r
+ </div>\r
+\r
+ <h2 style="margin-top:1em">Inline list</h2>\r
+\r
+ <div class="sm2-inline-list"> <!-- remove this class to have one item per line -->\r
+\r
+ <div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/The%20Fugitives%20-%20Graffiti%20Sex.mp3">The Fugitives - Graffiti Sex</a></div>\r
+ <div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Blue%20Belle%20Lament.mp3">Adrian Glynn - Blue Belle Lament</a></div>\r
+ <div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20I%20Tried.mp3">SonReal - I Tried</a></div>\r
+ <div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20People%20Asking.mp3">SonReal - People Asking</a></div>\r
+ <div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3">20060826 - Armstrong Groove</a></div>\r
+\r
+ </div>\r
+ \r
+ <p class="note medium-note" style="clear:both"><b>Artist thank-yous</b>: "Graffiti Sex" courtesy of <a href="http://www.fugitives.ca/" title="A group of musicians, poets, and multi-instrumentalists from Vancouver, Canada">The Fugitives</a>. "Blue Belle Lament" courtesy of <a href="http://www.adrianglynn.com/" title="Adrian Glynn, Vancouver-based Singer/Songwriter">Adrian Glynn</a>. "I Tried" and "People Asking" courtesy of <a href="http://sonreal.bandcamp.com/album/the-lightyear-mixtape" title="The Lightyear Mixtape from SonReal, Vancouver-based hip-hop artist">SonReal</a>.</p>\r
+\r
+ <h2 style="clear:left;padding-top:1em">Block list</h2>\r
+\r
+ <div>\r
+ <div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/gong-192kbps.mp3">32" Chau Gong Sounds</a></div>\r
+ <div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/mpc/20090207%20-%20Loverman.mp3">20090207 - Loverman</a></div>\r
+ <div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/dialup.mp3">56K Modem dial-up sound (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>\r
+ <div class="ui360 ui360-vis"><a href="../../demo/_mp3/1hz-10khz-sweep.mp3">1-10 Khz Sweep (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>\r
+ <div class="ui360 ui360-vis"><a href="../../demo/_mp3/sine,%20square,%20sawtooth,%20rando.mp3">Sine, Square, Sawtooth, Wave (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>\r
+ </div>\r
+\r
+ <p class="note medium-note" style="clear:left">56K Modem sound (Creative Commons license) via <a href="http://www.freesound.org/samplesViewSingle.php?id=16475">dialup.mp3</a>, from freesound.org user <a href="http://www.freesound.org/usersViewSingle.php?id=54447">Jlew</a>.</p>\r
+\r
+ \r
+ <h2 style="clear:left;padding-top:1em">Variant: Annotations/meta-data</h2>\r
+\r
+\r
+ <ul class="ui360playlist">\r
+\r
+ <li>\r
+\r
+ <div class="ui360 ui360-vis">\r
+ <a href="http://freshly-ground.com/data/audio/binaural/A%20Virtual%20Haircut%20in%20San%20Francisco%20%283%20Scenes%29.mp3">A Virtual Haircut (3 scenes)</a>\r
+ <div class="metadata">\r
+ <div class="duration">4:43</div> <!-- total track time (for positioning while loading, until determined -->\r
+ <ul>\r
+ <li><p>Electric razor</p><span>0:00</span></li> <!-- first scene -->\r
+ <li><p>Water, scissors</p><span>2:41</span></li> <!-- start time of second scene -->\r
+ <li><p>More razor work</p><span>4:00</span></li>\r
+ </ul>\r
+ </div>\r
+ </div>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <div class="ui360 ui360-vis">\r
+ <a href="http://freshly-ground.com/data/audio/binaural/Rubber%20Chicken%20Launch%20%28office%29.mp3">Rubber Chicken Launch (Office)</a>\r
+\r
+ <div class="metadata">\r
+ <div class="duration">0:47</div>\r
+ <ul>\r
+ <li><p>First attempt</p><span>0:00</span></li>\r
+ <li><p>Fire!</p><span>0:02</span></li>\r
+ <li><p>"Too much angle"</p><span>0:05</span></li>\r
+ <li><p>Random chicken noise</p><span>0:18</span></li>\r
+ <li><p>"Wait a second"</p><span>0:31</span></li>\r
+ <li><p>Derrr..</p><span>0:34</span></li>\r
+ <li><p>Launch attempt #2</p><span>0:36</span></li>\r
+ <li><p>"Wrong angle"</p><span>0:39</span></li>\r
+ <li><p>"Fail"</p><span>0:42</span></li>\r
+ </ul>\r
+ </div>\r
+\r
+\r
+ </div>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ <div style="clear:both"></div>\r
+ \r
+ <p style="margin-left:1em">\r
+ <a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)\r
+ </p>\r
+ \r
+ <script type="text/javascript">\r
+ if (window.location.toString().match(/#customize/i)) {\r
+ document.getElementById('config-link').style.display = 'none';\r
+ document.getElementById('config-ui').style.display = 'block'; \r
+ }\r
+ </script>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+#cp-container { position:relative;float:left;display:inline; margin-left:1em;padding: 6px; background-color: #f6f6f6; border:1px solid #eee; width: 320px; height:180px;z-index:2; }\r
+\r
+.yui-picker-controls li,\r
+.yui-picker-controls input {\r
+ font-size:1em;\r
+ font-family:"helvetica neue",helvetica,arial,verdana;\r
+}\r
+\r
+#controls {\r
+ position:relative;\r
+ margin-top:1.5em;\r
+ font-size:0.85em;\r
+}\r
+\r
+#options {\r
+ float:left;\r
+ display:inline;\r
+ margin-bottom:0.5em;\r
+ margin-top:-1.2em;\r
+}\r
+\r
+#controls .checkbox {\r
+ float:left;\r
+ display:inline;\r
+ width:21.2em;\r
+ margin-right:2.5em;\r
+}\r
+\r
+#controls .checkbox div {\r
+ /* tab */\r
+ width:auto;\r
+ padding:0.4em;\r
+ border:1px solid #ddd;\r
+ border-bottom:none;\r
+ background:#eee;\r
+}\r
+\r
+#controls .checkbox div,\r
+#controls .checkbox input {\r
+ font-family:arial,tahoma,verdana,"sans serif";\r
+ font-size:1em;\r
+ vertical-align:middle;\r
+}\r
+\r
+#controls dl {\r
+ width:21em;\r
+}\r
+\r
+#controls dl.col {\r
+ position:relative;\r
+ float:left;\r
+ display:inline;\r
+ margin:0px;\r
+ margin-right:1em;\r
+ padding:0.75em;\r
+/*\r
+ height:12.4em;\r
+*/\r
+ height:auto;\r
+ border:1px solid #ddd;\r
+ background:#f6f6f6;\r
+}\r
+\r
+#controls .disabled {\r
+ color:#ccc;\r
+}\r
+\r
+#controls .disabled dt,\r
+#controls .disabled dd {\r
+ color:#999;\r
+ opacity:0.5;\r
+}\r
+\r
+#controls dl dd p {\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+#controls dt,\r
+#controls dd {\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+#controls dt {\r
+ border-bottom:none;\r
+}\r
+\r
+#controls dt {\r
+ float:left;\r
+ display:inline;\r
+ background:transparent;\r
+ padding-right:0.7em;\r
+ margin-right:0.7em;\r
+ border-right:1px solid #ccc;\r
+ font-size:1.1em;\r
+ color:#333;\r
+ font-family:"helvetica neue",helvetica,verdana,arial,"sans serif";\r
+}\r
+\r
+#controls dd {\r
+ margin:0px;\r
+ padding:0px;\r
+ font-size:0.9em;\r
+ vertical-align:middle;\r
+ color:#666;\r
+}\r
+\r
+#controls .title {\r
+ float:left;\r
+ display:inline;\r
+ margin-right:0.6em;\r
+ color:#333;\r
+}\r
+\r
+/* those slider bits you might be wondering about */\r
+\r
+#controls .control {\r
+ position:relative;\r
+ border-left:0px;\r
+ width:214px;\r
+ height:20px;\r
+}\r
+\r
+#controls .control .bar {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:214px;\r
+ height:20px;\r
+ background:transparent url(../_image/slider-bar.gif) no-repeat 0px 9px;\r
+ cursor:pointer;\r
+ cursor:hand;\r
+}\r
+\r
+#controls .control .slider {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:20px;\r
+ height:20px;\r
+ background:transparent url(../_image/slider.png) no-repeat 0px 0px;\r
+ *background:none;\r
+ filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider.png');\r
+ cursor:pointer;\r
+ cursor:hand;\r
+}\r
+\r
+#controls .control .slider:hover {\r
+ background:transparent url(../_image/slider-1.png) no-repeat 0px 0px;\r
+ *background:none;\r
+}\r
+\r
+#controls .control .slider.hover {\r
+ filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-1.png');\r
+}\r
+\r
+#controls .disabled .control .slider {\r
+ background:transparent url(../_image/slider-disabled.png) no-repeat 0px 0px;\r
+ *background:none;\r
+ filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-disabled.png');\r
+}\r
+\r
+#controls .disabled .control .slider:hover {\r
+ background:transparent url(../_image/slider-disabled-1.png) no-repeat 0px 0px;\r
+ *background:none;\r
+}\r
+\r
+#controls .disabled .control .slider.hover {\r
+ filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-disabled-1.png');\r
+}\r
+\r
+#controls input[type=text] {\r
+ width:5em;\r
+}\r
+\r
+#options div {\r
+ margin-bottom:0.25em;\r
+}
\ No newline at end of file
--- /dev/null
+/*\r
+ Ancient fireworks slider control code (2005)\r
+ Kinda/sorta refactored for SM2 360 demo\r
+ http://schillmania.com/projects/fireworks/\r
+ --------------------------------------------\r
+ Not required for your use!\r
+*/\r
+\r
+function Animator2() {\r
+ var self = this;\r
+ this.tweens = [];\r
+ this.tweens['default'] = [1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1];\r
+ this.tweens['blast'] = [12,12,11,10,10,9,8,7,6,5,4,3,2,1];\r
+ this.tweens['fade'] = [10,10,10,10,10,10,10,10,10,10];\r
+ this.queue = [];\r
+ this.queue.IDs = [];\r
+ this.active = false;\r
+ this.timer = null;\r
+\r
+ this.createTween = function(start,end,type) {\r
+ // return array of tween coordinate data (start->end)\r
+ type = type||'default';\r
+ var tween = [start];\r
+ var tmp = start;\r
+ var diff = end-start;\r
+ var x = self.tweens[type].length;\r
+ for (var i=0; i<x; i++) {\r
+ tmp += diff*self.tweens[type][i]*0.01;\r
+ tween[i] = new Object();\r
+ tween[i].data = tmp;\r
+ tween[i].event = null;\r
+ }\r
+ return tween;\r
+ }\r
+\r
+ this.enqueue = function(o,fMethod,fOnComplete) {\r
+ // add object and associated methods to animation queue\r
+ // writeDebug('animator.enqueue()');\r
+ if (!fMethod) {\r
+ // writeDebug('animator.enqueue(): missing fMethod');\r
+ }\r
+ if (typeof(self.queue.IDs[o.oID])=='undefined') {\r
+ // writeDebug('animator.enqueue(): added '+o.oID);\r
+ var i = self.queue.length;\r
+ self.queue.IDs[o.oID] = i;\r
+ self.queue[i] = o;\r
+ } else {\r
+ // writeDebug('animator.enqueue(): '+o.oID+' already queued');\r
+ var i = self.queue.IDs[o.oID]; // retrieve queue index\r
+ self.queue[i].active = true;\r
+ self.queue[i].frame = 0;\r
+ }\r
+ o.active = true; // flag for animation\r
+ self.queue[i]._method = fMethod;\r
+ self.queue[i]._oncomplete = fOnComplete?fOnComplete:null;\r
+ }\r
+\r
+ this.animate = function() {\r
+ var active = 0;\r
+ for (var i=self.queue.length; i--;) {\r
+ if (self.queue[i].active) {\r
+ self.queue[i]._method();\r
+ active++;\r
+ }\r
+ }\r
+ if (active==0 && self.timer) {\r
+ // all animations finished\r
+ self.stop();\r
+ } else {\r
+ // writeDebug(active+' active');\r
+ }\r
+ }\r
+\r
+ this.start = function() {\r
+ if (self.timer || self.active) {\r
+ // writeDebug('animator.start(): already active');\r
+ return false;\r
+ }\r
+ // writeDebug('animator.start()'); // report only if started\r
+ self.active = true;\r
+ self.timer = setInterval(self.animate,mc.intervalRate);\r
+ }\r
+\r
+ this.stop = function() {\r
+ // writeDebug('animator.stop()',true);\r
+ clearInterval(self.timer);\r
+ self.timer = null;\r
+ self.active = false;\r
+ self.queue = [];\r
+ self.queue.IDs = [];\r
+ }\r
+\r
+}\r
+\r
+function MainController() {\r
+ var self = this;\r
+ this.intervalRate = 20; // rate (ms) to run animation at, general best default = 20\r
+ this.DEBUG = true; // debug mode disabled by default\r
+ this.oFW = null;\r
+ this.isIE = (navigator.appVersion.indexOf('MSIE')+1);\r
+ this.isOpera = (navigator.userAgent.toLowerCase().indexOf('opera')+1);\r
+ if (this.isOpera) this.isIE = false; // no impersonation allowed here!\r
+ this.animator = null;\r
+ this.gOID = 0; // global object ID counter (for animation queue)\r
+ this.particleTypes = 6;\r
+ this.particleXY = 10;\r
+ this.tweenFade = [100,90,80,70,60,50,40,30,20,10,0];\r
+ this.isSafari = (navigator.appVersion.toLowerCase().indexOf('safari')+1?1:0);\r
+ this.canvasX = null;\r
+ this.canvasY = null;\r
+ this.screenY = null; // screen area (not entire page)\r
+ self.scrollY = null;\r
+\r
+ self.getWindowCoords = function() {\r
+ self.canvasX = (document.documentElement.clientWidth||document.body.clientWidth||document.body.scrollWidth);\r
+ self.canvasY = (document.documentElement.clientHeight||document.body.clientHeight||document.body.scrollHeight);\r
+ self.screenY = self.canvasY;\r
+ self.scrollY = parseInt(window.scrollY||document.documentElement.scrollTop||document.body.scrollTop);\r
+ self.canvasY += self.scrollY;\r
+ }\r
+\r
+ this.getWindowCoordsAlt = function() {\r
+ self.canvasX = window.innerWidth;\r
+ self.canvasY = window.innerHeight;\r
+ self.screenY = self.canvasY;\r
+ self.scrollY = parseInt(window.scrollY||document.documentElement.scrollTop||document.body.scrollTop);\r
+ self.canvasY += self.scrollY;\r
+ }\r
+\r
+ this.getPanX = function(x) {\r
+ x = parseInt(x);\r
+ var pos = x/self.canvasX;\r
+ if (pos<0.4) {\r
+ pos *= -1;\r
+ } else if (pos >= 0.4 && pos <= 0.6) {\r
+ pos = 0.5;\r
+ }\r
+ pos = parseInt(pos*100);\r
+ // writeDebug('getPanX('+x+'): '+pos+'%');\r
+ return pos;\r
+ }\r
+\r
+ this.isEmpty = function(o) {\r
+ // needs further hacking\r
+ return (typeof(o)=='undefined'||(o==null&&o!=0)||(o==''&&o!=0)||o=='null');\r
+ }\r
+\r
+ this.init = function() {\r
+// self.oFW = document.getElementById('fw');\r
+// self.oFP = document.getElementById('fp');\r
+// if (typeof(enableDebugMode)!='undefined' && (self.DEBUG||window.location.toString().toLowerCase().indexOf('debug')>=0)) enableDebugMode();\r
+ self.getWindowCoords();\r
+ self.animator = new Animator2();\r
+ }\r
+\r
+ this.destructor = function() {\r
+/*\r
+ for (var i=self.fireworks.length; i--;) {\r
+ self.fireworks[i] = null;\r
+ }\r
+ self.fireworks = null;\r
+ if (soundManager) {\r
+ soundManager.destructor();\r
+ soundManager = null;\r
+ }\r
+*/\r
+ }\r
+\r
+ if (this.isSafari || this.isOpera) this.getWindowCoords = this.getWindowCoordsAlt;\r
+\r
+}\r
+\r
+\r
+function Controller(o) {\r
+ var self = this;\r
+ this.o = o;\r
+ this.controls = [];\r
+ this.cb = [];\r
+ this.options = [];\r
+ this.functionExample = document.getElementById('function-example');\r
+ this.fbIE = null;\r
+\r
+ this.randomize = function() {\r
+ for (var i=1; i<self.controls.length; i++) {\r
+ setTimeout(self.controls[i].randomize,20+(20*i+1));\r
+ }\r
+ }\r
+\r
+ this.cbClick = function(nIndex) {\r
+ document.getElementById('controls').getElementsByTagName('dl')[nIndex].className = 'col'+(this.checked==false||this.checked==''?' disabled':'');\r
+ self.updateExample();\r
+ self.updateExampleCode();\r
+ }\r
+\r
+ this.updateExample = function() {\r
+ if (threeSixtyPlayer) {\r
+ var val = self.controls[0].value;\r
+ threeSixtyPlayer.config.circleDiameter = self.controls[0].value;\r
+\r
+ threeSixtyPlayer.config.circleRadius = self.controls[0].value/2;\r
+ // update some stuff\r
+\r
+ // set the cover width/height to match the canvas\r
+ if (threeSixtyPlayer.lastSound) {\r
+ // always set cover to max area?\r
+ // threeSixtyPlayer.lastSound._data.oCover.style.width = 250+'px';\r
+ // threeSixtyPlayer.lastSound._data.oCover.style.height = 250+'px';\r
+ // threeSixtyPlayer.lastSound._data.oCover.style.width = threeSixtyPlayer.config.circleDiameter+'px';\r
+ // threeSixtyPlayer.lastSound._data.oCover.style.height = threeSixtyPlayer.config.circleDiameter+'px';\r
+ threeSixtyPlayer.refreshCoords(threeSixtyPlayer.lastSound);\r
+ }\r
+ \r
+ threeSixtyPlayer.config.waveformDataLineRatio = (self.controls[1].value/100)*2;\r
+\r
+ threeSixtyPlayer.config.waveformDataDownsample = (self.controls[2].value);\r
+\r
+ threeSixtyPlayer.config.eqDataLineRatio = parseInt((self.controls[3].value/100)*3*1000)/1000;\r
+ \r
+ threeSixtyPlayer.config.eqDataDownsample = (self.controls[4].value);\r
+\r
+ threeSixtyPlayer.config.scaleArcWidth = (self.controls[5].value/100);\r
+ \r
+ threeSixtyPlayer.config.useEQData = (document.getElementById('disabled-1').checked?true:false);\r
+ \r
+ // radio buttons\r
+\r
+ threeSixtyPlayer.config.useWaveformData=(document.getElementById('use-waveform').checked?true:false);\r
+ \r
+ threeSixtyPlayer.config.waveformDataOutside = document.getElementById('waveform-inside').checked?false:true;\r
+ \r
+ threeSixtyPlayer.config.eqDataOutside = document.getElementById('eq-inside').checked?false:true;\r
+\r
+ threeSixtyPlayer.config.useAmplifier = (document.getElementById('use-amplifier').checked?true:false);\r
+ \r
+ // threeSixtyPlayer.refreshCoords();\r
+ }\r
+\r
+ if (threeSixtyPlayer.lastSound) {\r
+\r
+ threeSixtyPlayer.lastSound._360data.circleDiameter = self.controls[0].value;\r
+\r
+ threeSixtyPlayer.lastSound._360data.circleRadius = self.controls[0].value/2;\r
+\r
+ threeSixtyPlayer.lastSound._360data.waveformDataLineRatio = (self.controls[1].value/100)*2;\r
+\r
+ threeSixtyPlayer.lastSound._360data.waveformDataDownsample = (self.controls[2].value);\r
+\r
+ threeSixtyPlayer.lastSound._360data.eqDataLineRatio = parseInt((self.controls[3].value/100)*3*1000)/1000;\r
+ \r
+ threeSixtyPlayer.lastSound._360data.eqDataDownsample = (self.controls[4].value);\r
+ \r
+ threeSixtyPlayer.lastSound._360data.useEQData = (document.getElementById('disabled-1').checked?true:false);\r
+ \r
+ // radio buttons\r
+\r
+ threeSixtyPlayer.lastSound._360data.useWaveformData=(document.getElementById('use-waveform').checked?true:false);\r
+ \r
+ threeSixtyPlayer.lastSound._360data.waveformDataOutside = document.getElementById('waveform-inside').checked?false:true;\r
+ \r
+ threeSixtyPlayer.lastSound._360data.eqDataOutside = document.getElementById('eq-inside').checked?false:true;\r
+\r
+ threeSixtyPlayer.lastSound._360data.useAmplifier = (document.getElementById('use-amplifier').checked?true:false);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ this.updateExampleCode = function() {\r
+ // set innerHTML\r
+document.getElementById('config-code').innerHTML = "\\r
+// 360player.js, config section\n\\r
+\n\\r
+this.config = {\n\\r
+\n\\r
+ playNext: <span>"+threeSixtyPlayer.config.playNext+"</span>,\n\\r
+ autoPlay: <span>"+threeSixtyPlayer.config.autoPlay+"</span>,\n\\r
+ allowMultiple: <span>"+threeSixtyPlayer.config.allowMultiple+"</span>,\n\\r
+ loadRingColor: <span>'"+threeSixtyPlayer.config.loadRingColor+"'</span>,\n\\r
+ playRingColor: <span>'"+threeSixtyPlayer.config.playRingColor+"'</span>,\n\\r
+ backgroundRingColor: <span>'"+threeSixtyPlayer.config.backgroundRingColor+"'</span>,\n\\r
+ circleDiameter: <span>"+threeSixtyPlayer.config.circleDiameter+"</span>,\n\\r
+ circleRadius: <span>"+threeSixtyPlayer.config.circleRadius+"</span>,\n\\r
+ animDuration: <span>"+threeSixtyPlayer.config.animDuration+"</span>,\n\\r
+ animTransition: <span>Animator.tx.bouncy</span>,\n\\r
+ showHMSTime: <span>"+threeSixtyPlayer.config.showHMSTime+"</span>,\n\\r
+\n\\r
+ useWaveformData: <span>"+threeSixtyPlayer.config.useWaveformData+"</span>,\n\\r
+ waveformDataColor: <span>'"+threeSixtyPlayer.config.waveformDataColor+"'</span>,\n\\r
+ waveformDataDownsample: <span>"+threeSixtyPlayer.config.waveformDataDownsample+"</span>,\n\\r
+ waveformDataOutside: <span>"+threeSixtyPlayer.config.waveformDataOutside+"</span>,\n\\r
+ waveformDataConstrain: <span>false</span>,\n\\r
+ waveformDataLineRatio: <span>"+threeSixtyPlayer.config.waveformDataLineRatio+"</span>,\n\\r
+\n\\r
+ useEQData: <span>"+threeSixtyPlayer.config.useEQData+"</span>,\n\\r
+ eqDataColor: <span>'"+threeSixtyPlayer.config.eqDataColor+"'</span>,\n\\r
+ eqDataDownsample: <span>"+threeSixtyPlayer.config.eqDataDownsample+"</span>,\n\\r
+ eqDataOutside: <span>"+threeSixtyPlayer.config.eqDataOutside+"</span>,\n\\r
+ eqDataLineRatio: <span>"+threeSixtyPlayer.config.eqDataLineRatio+"</span>,\n\\r
+\n\\r
+ usePeakData: <span>"+threeSixtyPlayer.config.usePeakData+"</span>,\n\\r
+ peakDataColor: <span>'"+threeSixtyPlayer.config.peakDataColor+"'</span>,\n\\r
+ peakDataOutside: <span>"+threeSixtyPlayer.config.peakDataOutside+"</span>,\n\\r
+ peakDataLineRatio: <span>"+threeSixtyPlayer.config.peakDataLineRatio+"</span>,\n\\r
+\n\\r
+ useAmplifier: <span>"+threeSixtyPlayer.config.useAmplifier+"</span>\n\\r
+\n\\r
+}";\r
+document.getElementById('config-code').style.display = 'block'; // weird Fx fix\r
+ }\r
+\r
+ this.createCustomFirework = function() {\r
+ }\r
+\r
+ this.destructor = function() {\r
+ for (var i=self.controls.length; i--;) {\r
+ self.controls[i].destructor();\r
+ }\r
+ for (i=self.cb.length; i--;) {\r
+ self.cb.onclick = null;\r
+ self.cb[i] = null;\r
+ }\r
+ for (i=self.options.length; i--;) {\r
+ self.options[i] = null;\r
+ }\r
+ if (navigator.userAgent.match(/msie/i)) {\r
+ self.fbIE.onmouseover = null;\r
+ self.fbIE.onmouseout = null;\r
+ self.fbIE = null;\r
+ }\r
+ self.cb = null;\r
+ self.options = null;\r
+ self.controls = null;\r
+ self.functionExample = null;\r
+ self.o = null;\r
+ }\r
+\r
+ var items = parseInt(this.o.length/3);\r
+ for (var i=0; i<items; i++) {\r
+ this.controls[this.controls.length] = new Slider(this.o[(3*i)+2].getElementsByTagName('div')[1],this.o[(3*i)+1],this.o[(3*i)+2].getElementsByTagName('div')[0]);\r
+ }\r
+ this.cb = [document.getElementById('disabled-0'),document.getElementById('disabled-1')];\r
+/*\r
+ for (i=this.cb.length; i--;) {\r
+ this.cb[i]._index = i;\r
+ this.cb[i].onclick = this.cbClick;\r
+ }\r
+*/\r
+ this.options = [];\r
+/*\r
+ this.cb[1].checked = false;\r
+ this.options = [document.getElementById('opt-random0'),document.getElementById('opt-random1')];\r
+ this.options[0].checked = false;\r
+ this.options[1].checked = true;\r
+ if (navigator.userAgent.match(/msie/i)) {\r
+ this.fbIE = document.getElementById('fireButton');\r
+ this.fbIE.onmouseover = function() {this.className='hover';}\r
+ this.fbIE.onmouseout = function() {this.className='';}\r
+ }\r
+*/\r
+\r
+ setTimeout(function(){\r
+ // default values for controls\r
+ var values = [\r
+ 256,\r
+ 65,\r
+ 40,\r
+ 72,\r
+ 48,\r
+ 100\r
+ ];\r
+ for (var i=0; i<values.length; i++) {\r
+ self.controls[i].setValue(values[i]); // defaults\r
+ }\r
+ },1);\r
+}\r
+\r
+function Slider(o,oV,oB) {\r
+ var self = this;\r
+ this.o = o;\r
+ this.oV = oV;\r
+ this.oB = oB;\r
+ this.scale = parseInt(oV.innerHTML.toString().substr(2));\r
+ this.oID = 'sc'+(gOID++);\r
+ this.offX = 0;\r
+ this.x = 0;\r
+ this.xMin = 0-10;\r
+ this.xMax = self.o.parentNode.offsetWidth-10;\r
+ this.value = 0;\r
+ this.timer = null;\r
+ this._className = this.o.className;\r
+ this.tween = [];\r
+ this.frame = 0;\r
+\r
+ this.over = function() {\r
+ this.className = self._className+' hover';\r
+ event.cancelBubble=true;\r
+ return false;\r
+ }\r
+\r
+ this.out = function() {\r
+ this.className = self._className;\r
+ event.cancelBubble=true;\r
+ return false;\r
+ }\r
+\r
+ this.down = function(e) {\r
+ var e = e?e:event;\r
+ self.offX = e.clientX-self.o.offsetLeft;\r
+ addEvent(document,'mousemove',self.move);\r
+ addEvent(document,'mouseup',self.up);\r
+ return false;\r
+ }\r
+\r
+ this.barClick = function(e) {\r
+ var e=e?e:event;\r
+ self.slide(self.x,e.clientX-self.o.parentNode.parentNode.offsetLeft-self.o.offsetWidth);\r
+ }\r
+\r
+ this.move = function(e) {\r
+ var e=e?e:event;\r
+ var x = e.clientX-self.offX;\r
+ if (x>self.xMax) {\r
+ x = self.xMax;\r
+ } else if (x<self.xMin) {\r
+ x = self.xMin;\r
+ }\r
+ if (x != self.x) {\r
+ self.moveTo(x);\r
+ self.doUpdate();\r
+ controller.updateExample();\r
+ controller.updateExampleCode();\r
+ }\r
+ e.stopPropgation?e.stopPropagation():e.cancelBubble=true;\r
+ return false;\r
+ }\r
+\r
+ this.up = function(e) {\r
+ removeEvent(document,'mousemove',self.move);\r
+ removeEvent(document,'mouseup',self.up);\r
+ // controller.updateExample();\r
+ controller.updateExampleCode();\r
+ }\r
+\r
+ this.slide = function(x0,x1) {\r
+ self.tween = mc.animator.createTween(x0,x1);\r
+ mc.animator.enqueue(self,self.animate,function(){\r
+ controller.updateExample()\r
+ controller.updateExampleCode();\r
+ });\r
+ mc.animator.start();\r
+ }\r
+\r
+ this.moveTo = function(x) {\r
+ self.x = x;\r
+ self.o.style.marginLeft = x+'px';\r
+ }\r
+\r
+ this.animate = function() {\r
+ self.moveTo(self.tween[self.frame].data);\r
+ self.doUpdate(50);\r
+ controller.updateExample();\r
+ if (self.frame++>=self.tween.length-1) {\r
+ self.active = false;\r
+ self.frame = 0;\r
+ if (self._oncomplete) self._oncomplete();\r
+// self.doUpdate();\r
+ return false;\r
+ }\r
+ self.doUpdate();\r
+ return true;\r
+ }\r
+\r
+ this.doUpdate = function(t) {\r
+ // if (!self.timer) self.timer = setTimeout(self.update,t||20);\r
+ self.update();\r
+ }\r
+\r
+ this.update = function() {\r
+ self.timer = null;\r
+ self.value = 1+parseInt(self.x/self.xMax*(self.scale-1));\r
+ if (self.value<1) self.value = 1;\r
+ // if (self.oV.innerHTML != self.value) self.oV.innerHTML = self.value;\r
+ // self.oV.innerHTML = self.value;\r
+ }\r
+\r
+ this.setValue = function(x) {\r
+ self.slide(self.x,Math.min(self.xMax,x));\r
+ }\r
+\r
+ this.randomize = function() {\r
+ self.slide(self.x,parseInt(Math.random()*self.xMax));\r
+ }\r
+\r
+ this.destructor = function() {\r
+ self.o.onmouseover = null;\r
+ self.o.onmouseout = null;\r
+ self.o.onmousedown = null;\r
+ self.o = null;\r
+ self.oV = null;\r
+ self.oB.onclick = null;\r
+ self.oB = null;\r
+ }\r
+\r
+ if (soundManager.isIE) {\r
+ // IE is lame, no :hover\r
+ this.o.onmouseover = this.over;\r
+ this.o.onmouseout = this.out;\r
+ }\r
+\r
+ this.o.onmousedown = this.down;\r
+ this.oB.onclick = this.barClick;\r
+ self.update();\r
+\r
+}\r
+\r
+var gOID = 0;\r
+\r
+function demoInit() {\r
+ controller = new Controller(document.getElementById('controls').getElementsByTagName('dd'));\r
+}\r
+\r
+function demoDestuctor() {\r
+ controller.destructor();\r
+ controller = null;\r
+}\r
+\r
+var controller = null;\r
+\r
+var mc = new MainController();\r
+// create null objects if APIs not present\r
+\r
+function createCP(oInput,oHandler) {\r
+ var Event = YAHOO.util.Event;\r
+\r
+ cpHandler = oHandler;\r
+ if (picker != null) {\r
+ // picker.showcontrols(true);\r
+ var c = oInput.value.substr(1);\r
+ picker.setValue(hex2decArray([c.substr(0,2),c.substr(2,2),c.substr(4,2)]),true); // be silent \r
+ return false;\r
+ }\r
+\r
+ Event.onDOMReady(function() {\r
+ picker = new YAHOO.widget.ColorPicker("cp-container", {\r
+ showhsvcontrols: true,\r
+ showhexcontrols: true,\r
+ images: {\r
+ PICKER_THUMB: "../_image/picker_thumb.png",\r
+ HUE_THUMB: "../_image/hue_thumb.png"\r
+ }\r
+ });\r
+\r
+// picker.showcontrols(false);\r
+ //a listener for logging RGB color changes;\r
+ //this will only be visible if logger is enabled:\r
+ var onRgbChange = function(o) {\r
+ /*o is an object\r
+ { newValue: (array of R, G, B values),\r
+ prevValue: (array of R, G, B values),\r
+ type: "rgbChange"\r
+ }\r
+ */\r
+ cpHandler(o.newValue);\r
+ controller.updateExampleCode();\r
+ }\r
+\r
+ //subscribe to the rgbChange event;\r
+ picker.on("rgbChange", onRgbChange);\r
+\r
+ //use setValue to reset the value to white:\r
+ Event.on("reset", "click", function(e) {\r
+ picker.setValue([255, 255, 255], false); //false here means that rgbChange\r
+ //wil fire; true would silence it\r
+ });\r
+\r
+ //use the "get" method to get the current value\r
+ //of one of the Color Picker's properties; in \r
+ //this case, we'll get the hex value and write it\r
+ //to the log:\r
+ Event.on("gethex", "click", function(e) {\r
+ console.log("Current hex value: " + picker.get("hex"));\r
+ });\r
+\r
+ });\r
+}\r
+\r
+var picker = null;\r
+\r
+cpHandler = function() {\r
+}\r
+\r
+\r
+ // hex -> dec / dec -> hex\r
+ // http://www.southwest.com.au/~jfuller/binary/converter.htm\r
+\r
+ function dec2hex(cval) {\r
+ if (cval > 255) cval = 255;\r
+ var hexascii = "0123456789ABCDEF";\r
+ var cval0 = Math.floor(cval/16);\r
+ var cval1 = cval-(cval0*16);\r
+ var c1 = hexascii.charAt(cval0);\r
+ var c2 = hexascii.charAt(cval1);\r
+ return (c1+c2);\r
+ }\r
+\r
+ function hex2dec(cval) {\r
+ cval = cval.toUpperCase();\r
+ var tval = 0;\r
+ var hexascii = "0123456789ABCDEF";\r
+ var mychar, ch;\r
+ for (var c=0; c<cval.length; c++) {\r
+ mychar = cval.charAt(c);\r
+ for (ch=0; ch<16; ch++) {\r
+ if (mychar == hexascii.charAt(ch)) {\r
+ tval += ch;\r
+ if (c<cval.length-1) tval *= 16;\r
+ }\r
+ }\r
+ }\r
+ return tval;\r
+ }\r
+\r
+ function hex2decArray(hArray) {\r
+ var result = [];\r
+ for (var i=0,j=hArray.length; i<j; i++) {\r
+ result[i] = hex2dec(hArray[i]);\r
+ }\r
+ return result;\r
+ }\r
+\r
+ function dec2hexArray(dArray) {\r
+ var result = [];\r
+ for (var i=0,j=dArray.length; i<j; i++) {\r
+ result[i] = dec2hex(dArray[i]);\r
+ }\r
+ return result;\r
+ }\r
+\r
+\r
+/*\r
+\r
+\r
+threeSixtyPlayer.config.waveformDataColor = '#'+dec2hexArray([self.controls[5].value,self.controls[6].value,self.controls[7].value]).join('');\r
+\r
+threeSixtyPlayer.config.eqDataColor = '#'+dec2hexArray([self.controls[8].value,self.controls[9].value,self.controls[10].value]).join('');\r
+\r
+threeSixtyPlayer.config.loadRingColor = '#'+dec2hexArray([self.controls[11].value,self.controls[12].value,self.controls[13].value]).join('');\r
+\r
+threeSixtyPlayer.config.playRingColor = '#'+dec2hexArray([self.controls[14].value,self.controls[15].value,self.controls[16].value]).join('');\r
+\r
+threeSixtyPlayer.config.waveformDataLineRatio = (self.controls[1].value/100)*2;\r
+\r
+threeSixtyPlayer.config.waveformDataDownsample = (self.controls[2].value);\r
+\r
+threeSixtyPlayer.config.eqDataLineRatio = (self.controls[3].value/100)*3;\r
+\r
+threeSixtyPlayer.config.eqDataDownsample = (self.controls[4].value);\r
+\r
+*/\r
+\r
+function _id(sID) {\r
+ return document.getElementById(sID);\r
+}\r
+\r
+function setWaveformColor(sColor) {\r
+ var value = '#'+(dec2hexArray(sColor).join(''));\r
+ threeSixtyPlayer.config.waveformDataColor = value;\r
+ _id('waveform-color').value = value;\r
+}\r
+\r
+function setEQColor(sColor) {\r
+ var value = '#'+dec2hexArray(sColor).join('');\r
+ _id('eq-color').value = value;\r
+ threeSixtyPlayer.config.eqDataColor = value;\r
+}\r
+\r
+function setLoadedRingColor(sColor) {\r
+ var value = '#'+dec2hexArray(sColor).join('');\r
+ _id('loaded-ring-color').value = value;\r
+ threeSixtyPlayer.config.loadRingColor = value; \r
+}\r
+\r
+function setProgressRingColor(sColor) {\r
+ var value = '#'+dec2hexArray(sColor).join('');\r
+ _id('progress-ring-color').value = value;\r
+ threeSixtyPlayer.config.playRingColor = value;\r
+}\r
+\r
+function setBackgroundRingColor(sColor) {\r
+ var value = '#'+dec2hexArray(sColor).join('');\r
+ _id('bg-ring-color').value = value;\r
+ threeSixtyPlayer.config.backgroundRingColor = value;\r
+}\r
+\r
+function addEvent(o,evtName,evtHandler) {\r
+ typeof window.addEventListener !== 'undefined' ? o.addEventListener(evtName,evtHandler,false) : o.attachEvent('on'+evtName,evtHandler);\r
+}\r
+\r
+function removeEvent(o,evtName,evtHandler) {\r
+ typeof window.removeEventListener !== 'undefined' ? o.removeEventListener(evtName,evtHandler,false) : o.detachEvent('on'+evtName,evtHandler);\r
+}\r
+\r
+if (window.location.toString().match(/#customize/i)) {\r
+ addEvent(window,'resize',mc.getWindowCoords);\r
+ addEvent(window,'scroll',mc.getWindowCoords);\r
+ addEvent(window,'load',mc.init);\r
+ addEvent(window,'load',demoInit);\r
+}\r
+\r
+if (window.location.toString().match(/hifi/i)) {\r
+ soundManager.onready(function(){\r
+ document.getElementById('hifi').style.display = 'none';\r
+\r
+ threeSixtyPlayer.config = {\r
+\r
+ playNext: false,\r
+ autoPlay: false,\r
+ loadRingColor: '#ccc',\r
+ playRingColor: '#000',\r
+ backgroundRingColor: '#eee',\r
+ circleDiameter: 256,\r
+ circleRadius: 128,\r
+ animDuration: 500,\r
+ animTransition: Animator.tx.bouncy,\r
+ showHMSTime: true,\r
+\r
+ useWaveformData: true,\r
+ waveformDataColor: '#0099ff',\r
+ waveformDataDownsample: 1,\r
+ waveformDataOutside: true,\r
+ waveformDataConstrain: false,\r
+ waveformDataLineRatio: 0.56,\r
+\r
+ useEQData: true,\r
+ eqDataColor: '#339933',\r
+ eqDataDownsample: 1,\r
+ eqDataOutside: true,\r
+ eqDataLineRatio: 0.72,\r
+\r
+ usePeakData: true,\r
+ peakDataColor: '#ff33ff',\r
+ peakDataOutside: true,\r
+ peakDataLineRatio: 0.5,\r
+ scaleArcWidth: 1, // thickness factor of playback progress ring\r
+ useAmplifier: true\r
+\r
+ }\r
+\r
+ });\r
+}
\ No newline at end of file
--- /dev/null
+/** \r
+ * In-page demo CSS - see external CSS for actual relevant stuff.\r
+*/\r
+\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, makes debug more useable) */\r
+ position:absolute;position:fixed;*position:absolute;bottom:10px;right:10px;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);\r
+}\r
+\r
+body {\r
+ font:75% normal verdana,arial,tahoma,"sans serif";\r
+}\r
+\r
+h1, h2, h3 {\r
+ font:3em arial,tahoma,verdana;\r
+ font-weight:normal;\r
+ margin-bottom:0px;\r
+}\r
+\r
+h1 {\r
+ margin-top:0.25em;\r
+}\r
+\r
+h1, h2 {\r
+ letter-spacing: -0.005em; /* zomg web x.0! ;) */ \r
+}\r
+\r
+h2 {\r
+ font-size:2em;\r
+ margin-top:0px;\r
+ margin-bottom:0.1em;\r
+}\r
+\r
+h3 {\r
+ font-size:1.5em;\r
+ margin-bottom:1em;\r
+}\r
+\r
+h1 a,\r
+h1 a:hover {\r
+ color:#000;\r
+ text-decoration:none;\r
+}\r
+\r
+h1 a:hover {\r
+ text-decoration:underline;\r
+}\r
+\r
+ul.notes {\r
+ margin-left:0px;\r
+ padding-left:1.5em;\r
+}\r
+\r
+.note {\r
+ margin-top:0px;\r
+ font-style:italic;\r
+ color:#999;\r
+ margin-bottom:0px;\r
+}\r
+\r
+#left {\r
+ max-width:56em;\r
+ margin-left:1em;\r
+}\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>360° MP3 player UI demo (SoundManager 2)</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Javascript-driven sound, canvas-based MP3 player UI demo: 360-degree circular control / jog wheel example for playing MP3 links using SoundManager 2, Javascript and Canvas.">\r
+\r
+<!-- required -->\r
+<link rel="stylesheet" type="text/css" href="360player.css" />\r
+\r
+<!-- special IE-only canvas fix -->\r
+<!--[if IE]><script type="text/javascript" src="script/excanvas.js"></script><![endif]-->\r
+\r
+<!-- Apache-licensed animation library -->\r
+<script type="text/javascript" src="script/berniecode-animator.js"></script>\r
+\r
+<!-- the core stuff -->\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/360player.js"></script>\r
+\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ // path to directory containing SM2 SWF\r
+ url: '../../swf/'\r
+});\r
+</script>\r
+\r
+<!-- stuff you don't need -->\r
+<!-- makes the fonts nicer etc. -->\r
+<link rel="stylesheet" type="text/css" href="../index.css" />\r
+<link rel="stylesheet" type="text/css" href="demo.css" />\r
+\r
+<!-- soundManager.useFlashBlock: related CSS -->\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+\r
+<style type="text/css">\r
+\r
+/* Demo page, general layout */\r
+\r
+body {\r
+ background-image: none;\r
+}\r
+\r
+#left {\r
+ position:relative;\r
+ width:950px;\r
+ max-width:100%;\r
+}\r
+\r
+#left h2 {\r
+ padding-top:0px;\r
+ margin-bottom:0.25em;\r
+ color:#666;\r
+}\r
+\r
+pre.block {\r
+ margin-top:0.5em;\r
+}\r
+\r
+</style>\r
+\r
+</head>\r
+\r
+<body>\r
+\r
+<div id="left">\r
+\r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Javascript MP3 player project home">SoundManager 2</a> / <a href="http://schillmania.com/projects/soundmanager2/demo/360-player/">360° Player</a>: JavaScript + Canvas UI</h1>\r
+\r
+ <p class="note" style="color:#666;margin-top:0.5em;margin-bottom:0.5em">Canvas-based UI. Load progress, seek, play/pause etc. Also see <a href="canvas-visualization.html" title="Javascript canvas visualization with waveform/eq data">360° UI visualization</a> demo.</p>\r
+\r
+<div id="sm2-container">\r
+ <!-- flash movie is added here -->\r
+</div>\r
+\r
+<div style="margin-top:1.25em">\r
+\r
+ <div style="float:left;display:inline;min-width:200px"> <!-- float is just for this demo layout, you don't need it. -->\r
+ \r
+ <div class="ui360" style="margin-top:-0.55em"><a href="../_mp3/rain.mp3">Rain</a></div>\r
+\r
+ <div class="ui360"><a href="http://freshly-ground.com/data/audio/mpc/20090119%20-%20Untitled%20Groove.mp3">20090119 - Untitled Groove</a></div>\r
+\r
+ </div>\r
+\r
+\r
+ <div style="float:left;display:inline;margin-left:40px;border-left:1px solid #ccc;padding-left:30px;width:150px">\r
+\r
+ <div class="sm2-inline-list" style="margin-bottom:10px"> <!-- note the CSS class, changes the layout -->\r
+\r
+ <div class="ui360"><a href="http://www.freshly-ground.com/data/audio/binaural/Mak.mp3">Angry cow sound?</a></div>\r
+ <div class="ui360"><a href="http://www.freshly-ground.com/data/audio/binaural/Things that open, close and roll.mp3">Things that open, close and roll</a></div>\r
+ <div class="ui360"><a href="http://www.freshly-ground.com/misc/music/20060826%20-%20Armstrong.mp3">20060826 - Armstrong</a></div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+<div style="clear:both"></div>\r
+\r
+ \r
+ <h3>How This Works</h3>\r
+\r
+ <p>The script looks for a container element matching <code>div.<span>ui360</span></code>, and then the first link inside of it.</p>\r
+\r
+ <div>\r
+ \r
+<pre class="block"><code><div class="<span>ui360</span>">\r
+ <a href="/path/to/an.mp3">play "an.mp3"</a>\r
+</div></code></pre>\r
+ \r
+ </div>\r
+\r
+ <p>When the 360 player script loads, it adds a <code>UI</code> template to the block, prepending it in front of the MP3 link:</p>\r
+\r
+<pre class="block"><code><div class="<span>ui360</span>">\r
+ <span><span><-- dynamically-inserted block --></span></span>\r
+ <div class="<span>ui</span>">\r
+ <canvas class="<span>sm2-canvas</span>"></canvas>\r
+ <span class="<span>sm2-360btn</span>"></span> \r
+ <div class="<span>sm2-timing</span>"></div>\r
+ <div class="<span>sm2-cover</span>"></div>\r
+ </div>\r
+ <span><span><-- /UI --></span></span>\r
+ <a href="<span>/path/to/an.mp3</span>">\r
+</div></code></pre>\r
+\r
+<h3>Customizing the UI</h3>\r
+\r
+<p>The player's default 50x50-pixel canvas is defined both within JavaScript and CSS. For an example with different values, see this <a href="canvas-visualization.html" title="360° UI: larger version">larger version</a>.</p>\r
+\r
+<pre class="block"><code>threeSixtyPlayer.config = {\r
+ playNext: <span>false</span>, <span><span>// stop after one sound, or play through list until end</span></span>\r
+ autoPlay: <span>false</span>, <span><span>// start playing the first sound right away</span></span>\r
+ allowMultiple: <span>true</span>, <span><span>// let many sounds play at once (false = one at a time)</span></span>\r
+ loadRingColor: <span>'#ccc',</span> <span><span>// amount of sound which has loaded</span></span>\r
+ playRingColor: <span>'#000'</span>, <span><span>// amount of sound which has played</span></span>\r
+ backgroundRingColor: <span>'#eee', </span><span><span>// "default" color shown underneath everything else</span></span>\r
+ animDuration: <span>500</span>,\r
+ animTransition: <span>Animator.tx.bouncy</span> <span><span>// http://www.berniecode.com/writing/animator.html</span></span>\r
+}</code></pre>\r
+\r
+<p>The CSS for the canvas UI block is a bit ugly, but JavaScript reads the width of the <code>.sm2-360ui</code> element in the DOM as set by CSS and uses that to later draw and update the canvas element while playing.</p>\r
+\r
+<pre class="block"><code>.ui360,\r
+.sm2-360ui {\r
+ <span><span>/* size of the container for the circle, etc. */</span></span>\r
+ width:<span>50px</span>;\r
+ height:<span>50px</span>;\r
+}\r
+</code></pre>\r
+\r
+<h3>Third-party Components</h3>\r
+\r
+<p>This demo includes use of <a href="http://www.berniecode.com/writing/animator.html">Bernie's Better Animation Class</a> (Apache licensed) for some animation effects.</p>\r
+<p>Also, some loader/spinner icons from <a href="http://ajaxload.info">ajaxload.info</a> are used for showing loading/buffering states.</p>\r
+\r
+<hr />\r
+\r
+ <p>\r
+ <a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)\r
+ </p>\r
+\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+/**\r
+ *\r
+ * SoundManager 2 Demo: 360-degree / "donut player"\r
+ * ------------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * An inline player with a circular UI.\r
+ * Based on the original SM2 inline player.\r
+ * Inspired by Apple's preview feature in the\r
+ * iTunes music store (iPhone), among others.\r
+ *\r
+ * Requires SoundManager 2 Javascript API.\r
+ * Also uses Bernie's Better Animation Class (BSD):\r
+ * http://www.berniecode.com/writing/animator.html\r
+ *\r
+*/\r
+\r
+/*jslint white: false, onevar: true, undef: true, nomen: false, eqeqeq: true, plusplus: false, bitwise: true, regexp: false, newcap: true, immed: true */\r
+/*global document, window, soundManager, navigator */\r
+\r
+var threeSixtyPlayer, // instance\r
+ ThreeSixtyPlayer; // constructor\r
+\r
+(function(window) {\r
+\r
+function ThreeSixtyPlayer() {\r
+\r
+ var self = this,\r
+ pl = this,\r
+ sm = soundManager, // soundManager instance\r
+ uA = navigator.userAgent,\r
+ isIE = (uA.match(/msie/i)),\r
+ isOpera = (uA.match(/opera/i)),\r
+ isSafari = (uA.match(/safari/i)),\r
+ isChrome = (uA.match(/chrome/i)),\r
+ isFirefox = (uA.match(/firefox/i)),\r
+ isTouchDevice = (uA.match(/ipad|iphone/i)),\r
+ hasRealCanvas = (typeof window.G_vmlCanvasManager === 'undefined' && typeof document.createElement('canvas').getContext('2d') !== 'undefined'),\r
+ // I dunno what Opera doesn't like about this. I'm probably doing it wrong.\r
+ fullCircle = (isOpera||isChrome?359.9:360),\r
+ // exclude old IE from hi-DPI / "retina"-scale display size\r
+ hiDPIScale = (navigator.userAgent.match(/msie [678]/i)? 1 : 2);\r
+\r
+ // CSS class for ignoring MP3 links\r
+ this.excludeClass = 'threesixty-exclude';\r
+ this.links = [];\r
+ this.sounds = [];\r
+ this.soundsByURL = [];\r
+ this.indexByURL = [];\r
+ this.lastSound = null;\r
+ this.lastTouchedSound = null;\r
+ this.soundCount = 0;\r
+ this.oUITemplate = null;\r
+ this.oUIImageMap = null;\r
+ this.vuMeter = null;\r
+ this.callbackCount = 0;\r
+ this.peakDataHistory = [];\r
+\r
+ // 360player configuration options\r
+ this.config = {\r
+\r
+ playNext: false, // stop after one sound, or play through list until end\r
+ autoPlay: false, // start playing the first sound right away\r
+ allowMultiple: false, // let many sounds play at once (false = only one sound playing at a time)\r
+ loadRingColor: '#ccc', // how much has loaded\r
+ playRingColor: '#000', // how much has played\r
+ backgroundRingColor: '#eee', // color shown underneath load + play ("not yet loaded" color)\r
+\r
+ // optional segment/annotation (metadata) stuff..\r
+ segmentRingColor: 'rgba(255,255,255,0.33)', // metadata/annotation (segment) colors\r
+ segmentRingColorAlt: 'rgba(0,0,0,0.1)',\r
+ loadRingColorMetadata: '#ddd', // "annotations" load color\r
+ playRingColorMetadata: 'rgba(128,192,256,0.9)', // how much has played when metadata is present\r
+\r
+ circleDiameter: null, // set dynamically according to values from CSS\r
+ circleRadius: null,\r
+ animDuration: 500,\r
+ animTransition: window.Animator.tx.bouncy, // http://www.berniecode.com/writing/animator.html\r
+ showHMSTime: false, // hours:minutes:seconds vs. seconds-only\r
+ scaleFont: true, // also set the font size (if possible) while animating the circle\r
+\r
+ // optional: spectrum or EQ graph in canvas (not supported in IE <9, too slow via ExCanvas)\r
+ useWaveformData: false,\r
+ waveformDataColor: '#0099ff',\r
+ waveformDataDownsample: 3, // use only one in X (of a set of 256 values) - 1 means all 256\r
+ waveformDataOutside: false,\r
+ waveformDataConstrain: false, // if true, +ve values only - keep within inside circle\r
+ waveformDataLineRatio: 0.64,\r
+\r
+ // "spectrum frequency" option\r
+ useEQData: false,\r
+ eqDataColor: '#339933',\r
+ eqDataDownsample: 4, // use only one in X (of 256 values)\r
+ eqDataOutside: true,\r
+ eqDataLineRatio: 0.54,\r
+\r
+ // enable "amplifier" (canvas pulses like a speaker) effect\r
+ usePeakData: true,\r
+ peakDataColor: '#ff33ff',\r
+ peakDataOutside: true,\r
+ peakDataLineRatio: 0.5,\r
+\r
+ useAmplifier: true, // "pulse" like a speaker\r
+\r
+ fontSizeMax: null, // set according to CSS\r
+\r
+ scaleArcWidth: 1, // thickness factor of playback progress ring\r
+\r
+ useFavIcon: false // Experimental (also requires usePeakData: true).. Try to draw a "VU Meter" in the favicon area, if browser supports it (Firefox + Opera as of 2009)\r
+\r
+ };\r
+\r
+ this.css = {\r
+\r
+ // CSS class names appended to link during various states\r
+ sDefault: 'sm2_link', // default state\r
+ sBuffering: 'sm2_buffering',\r
+ sPlaying: 'sm2_playing',\r
+ sPaused: 'sm2_paused'\r
+\r
+ };\r
+\r
+ this.addEventHandler = (typeof window.addEventListener !== 'undefined' ? function(o, evtName, evtHandler) {\r
+ return o.addEventListener(evtName,evtHandler,false);\r
+ } : function(o, evtName, evtHandler) {\r
+ o.attachEvent('on'+evtName,evtHandler);\r
+ });\r
+\r
+ this.removeEventHandler = (typeof window.removeEventListener !== 'undefined' ? function(o, evtName, evtHandler) {\r
+ return o.removeEventListener(evtName,evtHandler,false);\r
+ } : function(o, evtName, evtHandler) {\r
+ return o.detachEvent('on'+evtName,evtHandler);\r
+ });\r
+\r
+ this.hasClass = function(o,cStr) {\r
+ return typeof(o.className)!=='undefined'?o.className.match(new RegExp('(\\s|^)'+cStr+'(\\s|$)')):false;\r
+ };\r
+\r
+ this.addClass = function(o,cStr) {\r
+\r
+ if (!o || !cStr || self.hasClass(o,cStr)) {\r
+ return false;\r
+ }\r
+ o.className = (o.className?o.className+' ':'')+cStr;\r
+\r
+ };\r
+\r
+ this.removeClass = function(o,cStr) {\r
+\r
+ if (!o || !cStr || !self.hasClass(o,cStr)) {\r
+ return false;\r
+ }\r
+ o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');\r
+\r
+ };\r
+\r
+ this.getElementsByClassName = function(className,tagNames,oParent) {\r
+\r
+ var doc = (oParent||document),\r
+ matches = [], i,j, nodes = [];\r
+ if (typeof tagNames !== 'undefined' && typeof tagNames !== 'string') {\r
+ for (i=tagNames.length; i--;) {\r
+ if (!nodes || !nodes[tagNames[i]]) {\r
+ nodes[tagNames[i]] = doc.getElementsByTagName(tagNames[i]);\r
+ }\r
+ }\r
+ } else if (tagNames) {\r
+ nodes = doc.getElementsByTagName(tagNames);\r
+ } else {\r
+ nodes = doc.all||doc.getElementsByTagName('*');\r
+ }\r
+ if (typeof(tagNames)!=='string') {\r
+ for (i=tagNames.length; i--;) {\r
+ for (j=nodes[tagNames[i]].length; j--;) {\r
+ if (self.hasClass(nodes[tagNames[i]][j],className)) {\r
+ matches.push(nodes[tagNames[i]][j]);\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ for (i=0; i<nodes.length; i++) {\r
+ if (self.hasClass(nodes[i],className)) {\r
+ matches.push(nodes[i]);\r
+ }\r
+ }\r
+ }\r
+ return matches;\r
+\r
+ };\r
+\r
+ this.getParentByNodeName = function(oChild,sParentNodeName) {\r
+\r
+ if (!oChild || !sParentNodeName) {\r
+ return false;\r
+ }\r
+ sParentNodeName = sParentNodeName.toLowerCase();\r
+ while (oChild.parentNode && sParentNodeName !== oChild.parentNode.nodeName.toLowerCase()) {\r
+ oChild = oChild.parentNode;\r
+ }\r
+ return (oChild.parentNode && sParentNodeName === oChild.parentNode.nodeName.toLowerCase()?oChild.parentNode:null);\r
+\r
+ };\r
+\r
+ this.getParentByClassName = function(oChild,sParentClassName) {\r
+\r
+ if (!oChild || !sParentClassName) {\r
+ return false;\r
+ }\r
+ while (oChild.parentNode && !self.hasClass(oChild.parentNode,sParentClassName)) {\r
+ oChild = oChild.parentNode;\r
+ }\r
+ return (oChild.parentNode && self.hasClass(oChild.parentNode,sParentClassName)?oChild.parentNode:null);\r
+\r
+ };\r
+\r
+ this.getSoundByURL = function(sURL) {\r
+ return (typeof self.soundsByURL[sURL] !== 'undefined'?self.soundsByURL[sURL]:null);\r
+ };\r
+\r
+ this.isChildOfNode = function(o,sNodeName) {\r
+\r
+ if (!o || !o.parentNode) {\r
+ return false;\r
+ }\r
+ sNodeName = sNodeName.toLowerCase();\r
+ do {\r
+ o = o.parentNode;\r
+ } while (o && o.parentNode && o.nodeName.toLowerCase() !== sNodeName);\r
+ return (o && o.nodeName.toLowerCase() === sNodeName?o:null);\r
+\r
+ };\r
+\r
+ this.isChildOfClass = function(oChild,oClass) {\r
+\r
+ if (!oChild || !oClass) {\r
+ return false;\r
+ }\r
+ while (oChild.parentNode && !self.hasClass(oChild,oClass)) {\r
+ oChild = self.findParent(oChild);\r
+ }\r
+ return (self.hasClass(oChild,oClass));\r
+\r
+ };\r
+\r
+ this.findParent = function(o) {\r
+\r
+ if (!o || !o.parentNode) {\r
+ return false;\r
+ }\r
+ o = o.parentNode;\r
+ if (o.nodeType === 2) {\r
+ while (o && o.parentNode && o.parentNode.nodeType === 2) {\r
+ o = o.parentNode;\r
+ }\r
+ }\r
+ return o;\r
+\r
+ };\r
+\r
+ this.getStyle = function(o,sProp) {\r
+\r
+ // http://www.quirksmode.org/dom/getstyles.html\r
+ try {\r
+ if (o.currentStyle) {\r
+ return o.currentStyle[sProp];\r
+ } else if (window.getComputedStyle) {\r
+ return document.defaultView.getComputedStyle(o,null).getPropertyValue(sProp);\r
+ }\r
+ } catch(e) {\r
+ // oh well\r
+ }\r
+ return null;\r
+\r
+ };\r
+\r
+ this.findXY = function(obj) {\r
+\r
+ var curleft = 0, curtop = 0;\r
+ do {\r
+ curleft += obj.offsetLeft;\r
+ curtop += obj.offsetTop;\r
+ } while (!!(obj = obj.offsetParent));\r
+ return [curleft,curtop];\r
+\r
+ };\r
+\r
+ this.getMouseXY = function(e) {\r
+\r
+ // http://www.quirksmode.org/js/events_properties.html\r
+ e = e?e:window.event;\r
+ if (isTouchDevice && e.touches) {\r
+ e = e.touches[0];\r
+ }\r
+ if (e.pageX || e.pageY) {\r
+ return [e.pageX,e.pageY];\r
+ } else if (e.clientX || e.clientY) {\r
+ return [e.clientX+self.getScrollLeft(),e.clientY+self.getScrollTop()];\r
+ }\r
+\r
+ };\r
+\r
+ this.getScrollLeft = function() {\r
+ return (document.body.scrollLeft+document.documentElement.scrollLeft);\r
+ };\r
+\r
+ this.getScrollTop = function() {\r
+ return (document.body.scrollTop+document.documentElement.scrollTop);\r
+ };\r
+\r
+ this.events = {\r
+\r
+ // handlers for sound events as they're started/stopped/played\r
+\r
+ play: function() {\r
+ pl.removeClass(this._360data.oUIBox,this._360data.className);\r
+ this._360data.className = pl.css.sPlaying;\r
+ pl.addClass(this._360data.oUIBox,this._360data.className);\r
+ self.fanOut(this);\r
+ },\r
+\r
+ stop: function() {\r
+ pl.removeClass(this._360data.oUIBox,this._360data.className);\r
+ this._360data.className = '';\r
+ self.fanIn(this);\r
+ },\r
+\r
+ pause: function() {\r
+ pl.removeClass(this._360data.oUIBox,this._360data.className);\r
+ this._360data.className = pl.css.sPaused;\r
+ pl.addClass(this._360data.oUIBox,this._360data.className);\r
+ },\r
+\r
+ resume: function() {\r
+ pl.removeClass(this._360data.oUIBox,this._360data.className);\r
+ this._360data.className = pl.css.sPlaying;\r
+ pl.addClass(this._360data.oUIBox,this._360data.className); \r
+ },\r
+\r
+ finish: function() {\r
+ var nextLink;\r
+ pl.removeClass(this._360data.oUIBox,this._360data.className);\r
+ this._360data.className = '';\r
+ // self.clearCanvas(this._360data.oCanvas);\r
+ this._360data.didFinish = true; // so fan draws full circle\r
+ self.fanIn(this);\r
+ if (pl.config.playNext) {\r
+ nextLink = (pl.indexByURL[this._360data.oLink.href]+1);\r
+ if (nextLink<pl.links.length) {\r
+ pl.handleClick({'target':pl.links[nextLink]});\r
+ }\r
+ }\r
+ },\r
+\r
+ whileloading: function() {\r
+ if (this.paused) {\r
+ self.updatePlaying.apply(this);\r
+ }\r
+ },\r
+\r
+ whileplaying: function() {\r
+ self.updatePlaying.apply(this);\r
+ this._360data.fps++;\r
+ },\r
+\r
+ bufferchange: function() {\r
+ if (this.isBuffering) {\r
+ pl.addClass(this._360data.oUIBox,pl.css.sBuffering);\r
+ } else {\r
+ pl.removeClass(this._360data.oUIBox,pl.css.sBuffering);\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ this.stopEvent = function(e) {\r
+\r
+ if (typeof e !== 'undefined' && typeof e.preventDefault !== 'undefined') {\r
+ e.preventDefault();\r
+ } else if (typeof window.event !== 'undefined' && typeof window.event.returnValue !== 'undefined') {\r
+ window.event.returnValue = false;\r
+ }\r
+ return false;\r
+\r
+ };\r
+\r
+ this.getTheDamnLink = (isIE)?function(e) {\r
+ // I really didn't want to have to do this.\r
+ return (e && e.target?e.target:window.event.srcElement);\r
+ }:function(e) {\r
+ return e.target;\r
+ };\r
+\r
+ this.handleClick = function(e) {\r
+\r
+ // a sound link was clicked\r
+ if (e.button > 1) {\r
+ // only catch left-clicks\r
+ return true;\r
+ }\r
+\r
+ var o = self.getTheDamnLink(e),\r
+ canvasElements, sURL, soundURL, thisSound, oContainer, has_vis, diameter;\r
+\r
+ if (o.nodeName.toLowerCase() !== 'a') {\r
+ o = self.isChildOfNode(o,'a');\r
+ if (!o) {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ if (!self.isChildOfClass(o,'ui360')) {\r
+ // not a link we're interested in\r
+ return true;\r
+ }\r
+\r
+ sURL = o.getAttribute('href');\r
+\r
+ if (!o.href || !sm.canPlayLink(o) || self.hasClass(o,self.excludeClass)) {\r
+ return true; // pass-thru for non-MP3/non-links\r
+ }\r
+\r
+ sm._writeDebug('handleClick()');\r
+ soundURL = (o.href);\r
+ thisSound = self.getSoundByURL(soundURL);\r
+\r
+ if (thisSound) {\r
+\r
+ // already exists\r
+ if (thisSound === self.lastSound) {\r
+ // and was playing (or paused)\r
+ thisSound.togglePause();\r
+ } else {\r
+ // different sound\r
+ thisSound.togglePause(); // start playing current\r
+ sm._writeDebug('sound different than last sound: '+self.lastSound.id);\r
+ if (!self.config.allowMultiple && self.lastSound) {\r
+ self.stopSound(self.lastSound);\r
+ }\r
+ }\r
+\r
+ } else {\r
+\r
+ // append some dom shiz, make noise\r
+\r
+ oContainer = o.parentNode;\r
+ has_vis = (self.getElementsByClassName('ui360-vis','div',oContainer.parentNode).length);\r
+\r
+ // create sound\r
+ thisSound = sm.createSound({\r
+ id:'ui360Sound'+(self.soundCount++),\r
+ url:soundURL,\r
+ onplay:self.events.play,\r
+ onstop:self.events.stop,\r
+ onpause:self.events.pause,\r
+ onresume:self.events.resume,\r
+ onfinish:self.events.finish,\r
+ onbufferchange:self.events.bufferchange,\r
+ type:(o.type||null),\r
+ whileloading:self.events.whileloading,\r
+ whileplaying:self.events.whileplaying,\r
+ useWaveformData:(has_vis && self.config.useWaveformData),\r
+ useEQData:(has_vis && self.config.useEQData),\r
+ usePeakData:(has_vis && self.config.usePeakData)\r
+ });\r
+\r
+ // tack on some custom data\r
+\r
+ diameter = parseInt(self.getElementsByClassName('sm2-360ui','div',oContainer)[0].offsetWidth * hiDPIScale, 10);\r
+\r
+ // see note re: IE <9 and excanvas when Modernizr is included, making weird things happen with <canvas>.\r
+ canvasElements = self.getElementsByClassName('sm2-canvas','canvas',oContainer),\r
+\r
+ thisSound._360data = {\r
+ oUI360: self.getParentByClassName(o,'ui360'), // the (whole) entire container\r
+ oLink: o, // DOM node for reference within SM2 object event handlers\r
+ className: self.css.sPlaying,\r
+ oUIBox: self.getElementsByClassName('sm2-360ui','div',oContainer)[0],\r
+ oCanvas: canvasElements[canvasElements.length-1],\r
+ oButton: self.getElementsByClassName('sm2-360btn','span',oContainer)[0],\r
+ oTiming: self.getElementsByClassName('sm2-timing','div',oContainer)[0],\r
+ oCover: self.getElementsByClassName('sm2-cover','div',oContainer)[0],\r
+ circleDiameter: diameter,\r
+ circleRadius: diameter/2,\r
+ lastTime: null,\r
+ didFinish: null,\r
+ pauseCount:0,\r
+ radius:0,\r
+ fontSize: 1,\r
+ fontSizeMax: self.config.fontSizeMax,\r
+ scaleFont: (has_vis && self.config.scaleFont),\r
+ showHMSTime: has_vis,\r
+ amplifier: (has_vis && self.config.usePeakData?0.9:1), // TODO: x1 if not being used, else use dynamic "how much to amplify by" value\r
+ radiusMax: diameter*0.175, // circle radius\r
+ width:0,\r
+ widthMax: diameter*0.4, // width of the outer ring\r
+ lastValues: {\r
+ bytesLoaded: 0,\r
+ bytesTotal: 0,\r
+ position: 0,\r
+ durationEstimate: 0\r
+ }, // used to track "last good known" values before sound finish/reset for anim\r
+ animating: false,\r
+ oAnim: new window.Animator({\r
+ duration: self.config.animDuration,\r
+ transition:self.config.animTransition,\r
+ onComplete: function() {\r
+ // var thisSound = this;\r
+ // thisSound._360data.didFinish = false; // reset full circle\r
+ }\r
+ }),\r
+ oAnimProgress: function(nProgress) {\r
+ var thisSound = this;\r
+ thisSound._360data.radius = parseInt(thisSound._360data.radiusMax*thisSound._360data.amplifier*nProgress, 10);\r
+ thisSound._360data.width = parseInt(thisSound._360data.widthMax*thisSound._360data.amplifier*nProgress, 10);\r
+ if (thisSound._360data.scaleFont && thisSound._360data.fontSizeMax !== null) {\r
+ thisSound._360data.oTiming.style.fontSize = parseInt(Math.max(1,thisSound._360data.fontSizeMax*nProgress), 10)+'px';\r
+ thisSound._360data.oTiming.style.opacity = nProgress;\r
+ }\r
+ if (thisSound.paused || thisSound.playState === 0 || thisSound._360data.lastValues.bytesLoaded === 0 || thisSound._360data.lastValues.position === 0) {\r
+ self.updatePlaying.apply(thisSound);\r
+ }\r
+ },\r
+ fps: 0\r
+ };\r
+\r
+ // "Metadata" (annotations)\r
+ if (typeof self.Metadata !== 'undefined' && self.getElementsByClassName('metadata','div',thisSound._360data.oUI360).length) {\r
+ thisSound._360data.metadata = new self.Metadata(thisSound,self);\r
+ }\r
+\r
+ // minimize ze font\r
+ if (thisSound._360data.scaleFont && thisSound._360data.fontSizeMax !== null) {\r
+ thisSound._360data.oTiming.style.fontSize = '1px';\r
+ }\r
+\r
+ // set up ze animation\r
+ thisSound._360data.oAnim.addSubject(thisSound._360data.oAnimProgress,thisSound);\r
+\r
+ // animate the radius out nice\r
+ self.refreshCoords(thisSound);\r
+\r
+ self.updatePlaying.apply(thisSound);\r
+\r
+ self.soundsByURL[soundURL] = thisSound;\r
+ self.sounds.push(thisSound);\r
+ if (!self.config.allowMultiple && self.lastSound) {\r
+ self.stopSound(self.lastSound);\r
+ }\r
+ thisSound.play();\r
+\r
+ }\r
+\r
+ self.lastSound = thisSound; // reference for next call\r
+\r
+ if (typeof e !== 'undefined' && typeof e.preventDefault !== 'undefined') {\r
+ e.preventDefault();\r
+ } else if (typeof window.event !== 'undefined') {\r
+ window.event.returnValue = false;\r
+ }\r
+ return false;\r
+\r
+ };\r
+\r
+ this.fanOut = function(oSound) {\r
+\r
+ var thisSound = oSound;\r
+ if (thisSound._360data.animating === 1) {\r
+ return false;\r
+ }\r
+ thisSound._360data.animating = 0;\r
+ soundManager._writeDebug('fanOut: '+thisSound.id+': '+thisSound._360data.oLink.href);\r
+ thisSound._360data.oAnim.seekTo(1); // play to end\r
+ window.setTimeout(function() {\r
+ // oncomplete hack\r
+ thisSound._360data.animating = 0;\r
+ },self.config.animDuration+20);\r
+\r
+ };\r
+\r
+ this.fanIn = function(oSound) {\r
+\r
+ var thisSound = oSound;\r
+ if (thisSound._360data.animating === -1) {\r
+ return false;\r
+ }\r
+ thisSound._360data.animating = -1;\r
+ soundManager._writeDebug('fanIn: '+thisSound.id+': '+thisSound._360data.oLink.href);\r
+ // massive hack\r
+ thisSound._360data.oAnim.seekTo(0); // play to end\r
+ window.setTimeout(function() {\r
+ // reset full 360 fill after animation has completed (oncomplete hack)\r
+ thisSound._360data.didFinish = false;\r
+ thisSound._360data.animating = 0;\r
+ self.resetLastValues(thisSound);\r
+ }, self.config.animDuration+20);\r
+\r
+ };\r
+\r
+ this.resetLastValues = function(oSound) {\r
+ oSound._360data.lastValues.position = 0;\r
+ };\r
+\r
+ this.refreshCoords = function(thisSound) {\r
+\r
+ thisSound._360data.canvasXY = self.findXY(thisSound._360data.oCanvas);\r
+ thisSound._360data.canvasMid = [thisSound._360data.circleRadius,thisSound._360data.circleRadius];\r
+ thisSound._360data.canvasMidXY = [thisSound._360data.canvasXY[0]+thisSound._360data.canvasMid[0], thisSound._360data.canvasXY[1]+thisSound._360data.canvasMid[1]];\r
+\r
+ };\r
+\r
+ this.stopSound = function(oSound) {\r
+\r
+ soundManager._writeDebug('stopSound: '+oSound.id);\r
+ soundManager.stop(oSound.id);\r
+ if (!isTouchDevice) { // iOS 4.2+ security blocks onfinish() -> playNext() if we set a .src in-between(?)\r
+ soundManager.unload(oSound.id);\r
+ }\r
+\r
+ };\r
+\r
+ this.buttonClick = function(e) {\r
+\r
+ var o = e?(e.target?e.target:e.srcElement):window.event.srcElement;\r
+ self.handleClick({target:self.getParentByClassName(o,'sm2-360ui').nextSibling}); // link next to the nodes we inserted\r
+ return false;\r
+\r
+ };\r
+\r
+ this.buttonMouseDown = function(e) {\r
+\r
+ // user might decide to drag from here\r
+ // watch for mouse move\r
+ if (!isTouchDevice) {\r
+ document.onmousemove = function(e) {\r
+ // should be boundary-checked, really (eg. move 3px first?)\r
+ self.mouseDown(e);\r
+ };\r
+ } else {\r
+ self.addEventHandler(document,'touchmove',self.mouseDown);\r
+ }\r
+ self.stopEvent(e);\r
+ return false;\r
+\r
+ };\r
+\r
+ this.mouseDown = function(e) {\r
+\r
+ if (!isTouchDevice && e.button > 1) {\r
+ return true; // ignore non-left-click\r
+ }\r
+\r
+ if (!self.lastSound) {\r
+ self.stopEvent(e);\r
+ return false;\r
+ }\r
+\r
+ var evt = e?e:window.event,\r
+ target, thisSound, oData;\r
+\r
+ if (isTouchDevice && evt.touches) {\r
+ evt = evt.touches[0];\r
+ }\r
+ target = (evt.target||evt.srcElement);\r
+\r
+ thisSound = self.getSoundByURL(self.getElementsByClassName('sm2_link','a',self.getParentByClassName(target,'ui360'))[0].href); // self.lastSound; // TODO: In multiple sound case, figure out which sound is involved etc.\r
+ // just in case, update coordinates (maybe the element moved since last time.)\r
+ self.lastTouchedSound = thisSound;\r
+ self.refreshCoords(thisSound);\r
+ oData = thisSound._360data;\r
+ self.addClass(oData.oUIBox,'sm2_dragging');\r
+ oData.pauseCount = (self.lastTouchedSound.paused?1:0);\r
+ // self.lastSound.pause();\r
+ self.mmh(e?e:window.event);\r
+\r
+ if (isTouchDevice) {\r
+ self.removeEventHandler(document,'touchmove',self.mouseDown);\r
+ self.addEventHandler(document,'touchmove',self.mmh);\r
+ self.addEventHandler(document,'touchend',self.mouseUp);\r
+ } else {\r
+ // incredibly old-skool. TODO: Modernize.\r
+ document.onmousemove = self.mmh;\r
+ document.onmouseup = self.mouseUp;\r
+ }\r
+\r
+ self.stopEvent(e);\r
+ return false;\r
+\r
+ };\r
+\r
+ this.mouseUp = function(e) {\r
+\r
+ var oData = self.lastTouchedSound._360data;\r
+ self.removeClass(oData.oUIBox,'sm2_dragging');\r
+ if (oData.pauseCount === 0) {\r
+ self.lastTouchedSound.resume();\r
+ }\r
+ if (!isTouchDevice) {\r
+ document.onmousemove = null;\r
+ document.onmouseup = null;\r
+ } else {\r
+ self.removeEventHandler(document,'touchmove',self.mmh);\r
+ self.removeEventHandler(document,'touchend',self.mouseUP);\r
+ }\r
+\r
+ };\r
+\r
+ this.mmh = function(e) {\r
+\r
+ if (typeof e === 'undefined') {\r
+ e = window.event;\r
+ }\r
+ var oSound = self.lastTouchedSound,\r
+ coords = self.getMouseXY(e),\r
+ x = coords[0],\r
+ y = coords[1],\r
+ deltaX = x-oSound._360data.canvasMidXY[0],\r
+ deltaY = y-oSound._360data.canvasMidXY[1],\r
+ angle = Math.floor(fullCircle-(self.rad2deg(Math.atan2(deltaX,deltaY))+180));\r
+\r
+ oSound.setPosition(oSound.durationEstimate*(angle/fullCircle));\r
+ self.stopEvent(e);\r
+ return false;\r
+\r
+ };\r
+\r
+ // assignMouseDown();\r
+\r
+ this.drawSolidArc = function(oCanvas, color, radius, width, radians, startAngle, noClear) {\r
+\r
+ // thank you, http://www.snipersystems.co.nz/community/polarclock/tutorial.html\r
+\r
+ var x = radius,\r
+ y = radius,\r
+ canvas = oCanvas,\r
+ ctx, innerRadius, doesntLikeZero, endPoint;\r
+\r
+ if (canvas.getContext) {\r
+ // use getContext to use the canvas for drawing\r
+ ctx = canvas.getContext('2d');\r
+ }\r
+\r
+ // re-assign canvas as the actual context\r
+ oCanvas = ctx;\r
+\r
+ if (!noClear) {\r
+ self.clearCanvas(canvas);\r
+ }\r
+ // ctx.restore();\r
+\r
+ if (color) {\r
+ ctx.fillStyle = color;\r
+ }\r
+\r
+ oCanvas.beginPath();\r
+\r
+ if (isNaN(radians)) {\r
+ radians = 0;\r
+ }\r
+\r
+ innerRadius = radius-width;\r
+ doesntLikeZero = (isOpera || isSafari); // safari 4 doesn't actually seem to mind.\r
+\r
+ if (!doesntLikeZero || (doesntLikeZero && radius > 0)) {\r
+ oCanvas.arc(0, 0, radius, startAngle, radians, false);\r
+ endPoint = self.getArcEndpointCoords(innerRadius, radians);\r
+ oCanvas.lineTo(endPoint.x, endPoint.y);\r
+ oCanvas.arc(0, 0, innerRadius, radians, startAngle, true);\r
+ oCanvas.closePath();\r
+ oCanvas.fill();\r
+ }\r
+\r
+ };\r
+\r
+ this.getArcEndpointCoords = function(radius, radians) {\r
+\r
+ return {\r
+ x: radius * Math.cos(radians), \r
+ y: radius * Math.sin(radians)\r
+ };\r
+\r
+ };\r
+\r
+ this.deg2rad = function(nDeg) {\r
+ return (nDeg * Math.PI/180);\r
+ };\r
+\r
+ this.rad2deg = function(nRad) {\r
+ return (nRad * 180/Math.PI);\r
+ };\r
+\r
+ this.getTime = function(nMSec,bAsString) {\r
+\r
+ // convert milliseconds to mm:ss, return as object literal or string\r
+ var nSec = Math.floor(nMSec/1000),\r
+ min = Math.floor(nSec/60),\r
+ sec = nSec-(min*60);\r
+ // if (min === 0 && sec === 0) return null; // return 0:00 as null\r
+ return (bAsString?(min+':'+(sec<10?'0'+sec:sec)):{'min':min,'sec':sec});\r
+\r
+ };\r
+\r
+ this.clearCanvas = function(oCanvas) {\r
+\r
+ var canvas = oCanvas,\r
+ ctx = null,\r
+ width, height;\r
+\r
+ if (canvas.getContext) {\r
+ // use getContext to use the canvas for drawing\r
+ ctx = canvas.getContext('2d');\r
+ }\r
+\r
+ if (ctx) {\r
+ width = canvas.offsetWidth;\r
+ height = canvas.offsetHeight;\r
+ ctx.clearRect(-(width/2), -(height/2), width, height);\r
+ }\r
+\r
+ };\r
+\r
+ this.updatePlaying = function() {\r
+\r
+ var timeNow = (this._360data.showHMSTime?self.getTime(this.position,true):parseInt(this.position/1000, 10));\r
+ var ringScaleFactor = self.config.scaleArcWidth;\r
+\r
+ if (this.bytesLoaded) {\r
+ this._360data.lastValues.bytesLoaded = this.bytesLoaded;\r
+ this._360data.lastValues.bytesTotal = this.bytesTotal;\r
+ }\r
+\r
+ if (this.position) {\r
+ this._360data.lastValues.position = this.position;\r
+ }\r
+\r
+ if (this.durationEstimate) {\r
+ this._360data.lastValues.durationEstimate = this.durationEstimate;\r
+ }\r
+\r
+ // background ring\r
+ self.drawSolidArc(this._360data.oCanvas,self.config.backgroundRingColor,this._360data.width,this._360data.radius * ringScaleFactor,self.deg2rad(fullCircle),false);\r
+\r
+ // loaded ring\r
+ self.drawSolidArc(this._360data.oCanvas,(this._360data.metadata?self.config.loadRingColorMetadata:self.config.loadRingColor),this._360data.width,this._360data.radius * ringScaleFactor,self.deg2rad(fullCircle*(this._360data.lastValues.bytesLoaded/this._360data.lastValues.bytesTotal)),0,true);\r
+\r
+ // don't draw if 0 (full black circle in Opera)\r
+ if (this._360data.lastValues.position !== 0) {\r
+ self.drawSolidArc(this._360data.oCanvas,(this._360data.metadata?self.config.playRingColorMetadata:self.config.playRingColor),this._360data.width,this._360data.radius * ringScaleFactor,self.deg2rad((this._360data.didFinish===1?fullCircle:fullCircle*(this._360data.lastValues.position/this._360data.lastValues.durationEstimate))),0,true);\r
+ }\r
+\r
+ // metadata goes here\r
+ if (this._360data.metadata) {\r
+ this._360data.metadata.events.whileplaying();\r
+ }\r
+\r
+ if (timeNow !== this._360data.lastTime) {\r
+ this._360data.lastTime = timeNow;\r
+ this._360data.oTiming.innerHTML = timeNow;\r
+ }\r
+\r
+ // draw spectrum, if applicable\r
+ if ((this.instanceOptions.useWaveformData || this.instanceOptions.useEQData) && hasRealCanvas) { // IE <9 can render maybe 3 or 4 FPS when including the wave/EQ, so don't bother.\r
+ self.updateWaveform(this);\r
+ }\r
+\r
+ if (self.config.useFavIcon && self.vuMeter) {\r
+ self.vuMeter.updateVU(this);\r
+ }\r
+\r
+ };\r
+\r
+ this.updateWaveform = function(oSound) {\r
+\r
+ if ((!self.config.useWaveformData && !self.config.useEQData) || (!sm.features.waveformData && !sm.features.eqData)) {\r
+ // feature not enabled..\r
+ return false;\r
+ }\r
+\r
+ if (!oSound.waveformData.left.length && !oSound.eqData.length && !oSound.peakData.left) {\r
+ // no data (or errored out/paused/unavailable?)\r
+ return false;\r
+ }\r
+\r
+ /* use for testing the data */\r
+ /*\r
+ for (i=0; i<256; i++) {\r
+ oSound.eqData[i] = 1-(i/256);\r
+ }\r
+ */\r
+\r
+ var oCanvas = oSound._360data.oCanvas.getContext('2d'),\r
+ offX = 0,\r
+ offY = parseInt(oSound._360data.circleDiameter/2, 10),\r
+ scale = offY/2, // Y axis (+/- this distance from 0)\r
+ // lineWidth = Math.floor(oSound._360data.circleDiameter-(oSound._360data.circleDiameter*0.175)/(oSound._360data.circleDiameter/255)); // width for each line\r
+ lineWidth = 1,\r
+ lineHeight = 1,\r
+ thisY = 0,\r
+ offset = offY,\r
+ i, j, direction, downSample, dataLength, sampleCount, startAngle, endAngle, waveData, innerRadius, perItemAngle, yDiff, eqSamples, playedAngle, iAvg, nPeak;\r
+\r
+ if (self.config.useWaveformData) {\r
+ // raw waveform\r
+ downSample = self.config.waveformDataDownsample; // only sample X in 256 (greater number = less sample points)\r
+ downSample = Math.max(1,downSample); // make sure it's at least 1\r
+ dataLength = 256;\r
+ sampleCount = (dataLength/downSample);\r
+ startAngle = 0;\r
+ endAngle = 0;\r
+ waveData = null;\r
+ innerRadius = (self.config.waveformDataOutside?1:(self.config.waveformDataConstrain?0.5:0.565));\r
+ scale = (self.config.waveformDataOutside?0.7:0.75);\r
+ perItemAngle = self.deg2rad((360/sampleCount)*self.config.waveformDataLineRatio); // 0.85 = clean pixel lines at 150? // self.deg2rad(360*(Math.max(1,downSample-1))/sampleCount);\r
+ for (i=0; i<dataLength; i+=downSample) {\r
+ startAngle = self.deg2rad(360*(i/(sampleCount)*1/downSample)); // +0.67 - counter for spacing\r
+ endAngle = startAngle+perItemAngle;\r
+ waveData = oSound.waveformData.left[i];\r
+ if (waveData<0 && self.config.waveformDataConstrain) {\r
+ waveData = Math.abs(waveData);\r
+ }\r
+ self.drawSolidArc(oSound._360data.oCanvas,self.config.waveformDataColor,oSound._360data.width*innerRadius*(2-self.config.scaleArcWidth),oSound._360data.radius*scale*1.25*waveData,endAngle,startAngle,true);\r
+ }\r
+ }\r
+\r
+ if (self.config.useEQData) {\r
+ // EQ spectrum\r
+ downSample = self.config.eqDataDownsample; // only sample N in 256\r
+ yDiff = 0;\r
+ downSample = Math.max(1,downSample); // make sure it's at least 1\r
+ eqSamples = 192; // drop the last 25% of the spectrum (>16500 Hz), most stuff won't actually use it.\r
+ sampleCount = (eqSamples/downSample);\r
+ innerRadius = (self.config.eqDataOutside?1:0.565);\r
+ direction = (self.config.eqDataOutside?-1:1);\r
+ scale = (self.config.eqDataOutside?0.5:0.75);\r
+ startAngle = 0;\r
+ endAngle = 0;\r
+ perItemAngle = self.deg2rad((360/sampleCount)*self.config.eqDataLineRatio); // self.deg2rad(360/(sampleCount+1));\r
+ playedAngle = self.deg2rad((oSound._360data.didFinish===1?360:360*(oSound._360data.lastValues.position/oSound._360data.lastValues.durationEstimate)));\r
+ j=0;\r
+ iAvg = 0;\r
+ for (i=0; i<eqSamples; i+=downSample) {\r
+ startAngle = self.deg2rad(360*(i/eqSamples));\r
+ endAngle = startAngle+perItemAngle;\r
+ self.drawSolidArc(oSound._360data.oCanvas,(endAngle>playedAngle?self.config.eqDataColor:self.config.playRingColor),oSound._360data.width*innerRadius,oSound._360data.radius*scale*(oSound.eqData.left[i]*direction),endAngle,startAngle,true);\r
+ }\r
+ }\r
+\r
+ if (self.config.usePeakData) {\r
+ if (!oSound._360data.animating) {\r
+ nPeak = (oSound.peakData.left||oSound.peakData.right);\r
+ // GIANT HACK: use EQ spectrum data for bass frequencies\r
+ eqSamples = 3;\r
+ for (i=0; i<eqSamples; i++) {\r
+ nPeak = (nPeak||oSound.eqData[i]);\r
+ }\r
+ oSound._360data.amplifier = (self.config.useAmplifier?(0.9+(nPeak*0.1)):1);\r
+ oSound._360data.radiusMax = oSound._360data.circleDiameter*0.175*oSound._360data.amplifier;\r
+ oSound._360data.widthMax = oSound._360data.circleDiameter*0.4*oSound._360data.amplifier;\r
+ oSound._360data.radius = parseInt(oSound._360data.radiusMax*oSound._360data.amplifier, 10);\r
+ oSound._360data.width = parseInt(oSound._360data.widthMax*oSound._360data.amplifier, 10);\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ this.getUIHTML = function(diameter) {\r
+\r
+ return [\r
+ '<canvas class="sm2-canvas" width="'+diameter+'" height="'+diameter+'"></canvas>',\r
+ ' <span class="sm2-360btn sm2-360btn-default"></span>', // note use of imageMap, edit or remove if you use a different-size image.\r
+ ' <div class="sm2-timing'+(navigator.userAgent.match(/safari/i)?' alignTweak':'')+'"></div>', // + Ever-so-slight Safari horizontal alignment tweak\r
+ ' <div class="sm2-cover"></div>'\r
+ ];\r
+\r
+ };\r
+\r
+ this.uiTest = function(sClass) {\r
+\r
+ // fake a 360 UI so we can get some numbers from CSS, etc.\r
+\r
+ var oTemplate = document.createElement('div'),\r
+ oFakeUI, oFakeUIBox, oTemp, fakeDiameter, uiHTML, circleDiameter, circleRadius, fontSizeMax, oTiming;\r
+\r
+ oTemplate.className = 'sm2-360ui';\r
+\r
+ oFakeUI = document.createElement('div');\r
+ oFakeUI.className = 'ui360'+(sClass?' '+sClass:''); // ui360 ui360-vis\r
+\r
+ oFakeUIBox = oFakeUI.appendChild(oTemplate.cloneNode(true));\r
+\r
+ oFakeUI.style.position = 'absolute';\r
+ oFakeUI.style.left = '-9999px';\r
+\r
+ oTemp = document.body.appendChild(oFakeUI);\r
+\r
+ fakeDiameter = oFakeUIBox.offsetWidth * hiDPIScale;\r
+\r
+ uiHTML = self.getUIHTML(fakeDiameter);\r
+\r
+ oFakeUIBox.innerHTML = uiHTML[1]+uiHTML[2]+uiHTML[3];\r
+\r
+ circleDiameter = parseInt(fakeDiameter, 10);\r
+ circleRadius = parseInt(circleDiameter/2, 10);\r
+\r
+ oTiming = self.getElementsByClassName('sm2-timing','div',oTemp)[0];\r
+ fontSizeMax = parseInt(self.getStyle(oTiming,'font-size'), 10);\r
+ if (isNaN(fontSizeMax)) {\r
+ // getStyle() etc. didn't work.\r
+ fontSizeMax = null;\r
+ }\r
+\r
+ // soundManager._writeDebug('diameter, font size: '+circleDiameter+','+fontSizeMax);\r
+\r
+ oFakeUI.parentNode.removeChild(oFakeUI);\r
+\r
+ uiHTML = oFakeUI = oFakeUIBox = oTemp = null;\r
+\r
+ return {\r
+ circleDiameter: circleDiameter,\r
+ circleRadius: circleRadius,\r
+ fontSizeMax: fontSizeMax\r
+ };\r
+\r
+ };\r
+\r
+ this.init = function() {\r
+\r
+ sm._writeDebug('threeSixtyPlayer.init()');\r
+\r
+ var oItems = self.getElementsByClassName('ui360','div'),\r
+ i, j, oLinks = [], is_vis = false, foundItems = 0, canvasElements, oCanvas, oCanvasCTX, oCover, diameter, radius, uiData, uiDataVis, oUI, oBtn, o, o2, oID;\r
+\r
+ for (i=0,j=oItems.length; i<j; i++) {\r
+ oLinks.push(oItems[i].getElementsByTagName('a')[0]);\r
+ // remove "fake" play button (unsupported case)\r
+ oItems[i].style.backgroundImage = 'none';\r
+ }\r
+ // grab all links, look for .mp3\r
+\r
+ self.oUITemplate = document.createElement('div');\r
+ self.oUITemplate.className = 'sm2-360ui';\r
+\r
+ self.oUITemplateVis = document.createElement('div');\r
+ self.oUITemplateVis.className = 'sm2-360ui';\r
+\r
+ uiData = self.uiTest();\r
+\r
+ self.config.circleDiameter = uiData.circleDiameter;\r
+ self.config.circleRadius = uiData.circleRadius;\r
+ // self.config.fontSizeMax = uiData.fontSizeMax;\r
+\r
+ uiDataVis = self.uiTest('ui360-vis');\r
+\r
+ self.config.fontSizeMax = uiDataVis.fontSizeMax;\r
+\r
+ // canvas needs inline width and height, doesn't quite work otherwise\r
+ self.oUITemplate.innerHTML = self.getUIHTML(self.config.circleDiameter).join('');\r
+\r
+ self.oUITemplateVis.innerHTML = self.getUIHTML(uiDataVis.circleDiameter).join('');\r
+\r
+ for (i=0,j=oLinks.length; i<j; i++) {\r
+ if (sm.canPlayLink(oLinks[i]) && !self.hasClass(oLinks[i],self.excludeClass) && !self.hasClass(oLinks[i],self.css.sDefault)) {\r
+ self.addClass(oLinks[i],self.css.sDefault); // add default CSS decoration\r
+ self.links[foundItems] = (oLinks[i]);\r
+ self.indexByURL[oLinks[i].href] = foundItems; // hack for indexing\r
+ foundItems++;\r
+\r
+ is_vis = self.hasClass(oLinks[i].parentNode, 'ui360-vis');\r
+\r
+ diameter = (is_vis ? uiDataVis : uiData).circleDiameter;\r
+ radius = (is_vis ? uiDataVis : uiData).circleRadius;\r
+\r
+ // add canvas shiz\r
+ oUI = oLinks[i].parentNode.insertBefore((is_vis?self.oUITemplateVis:self.oUITemplate).cloneNode(true),oLinks[i]);\r
+\r
+ if (isIE && typeof window.G_vmlCanvasManager !== 'undefined') { // IE only\r
+ o = oLinks[i].parentNode;\r
+ o2 = document.createElement('canvas');\r
+ o2.className = 'sm2-canvas';\r
+ oID = 'sm2_canvas_'+i+(new Date().getTime());\r
+ o2.id = oID;\r
+ o2.width = diameter;\r
+ o2.height = diameter;\r
+ oUI.appendChild(o2);\r
+ window.G_vmlCanvasManager.initElement(o2); // Apply ExCanvas compatibility magic\r
+ oCanvas = document.getElementById(oID);\r
+ /**\r
+ * 05/2013: If present, Modernizr results in two canvas elements or something being made, one being <:canvas>.\r
+ * When this is the case, the first doesn't have getContext('2d') and such - so, use the second.\r
+ */\r
+ canvasElements = oCanvas.parentNode.getElementsByTagName('canvas');\r
+ if (canvasElements.length > 1) {\r
+ oCanvas = canvasElements[canvasElements.length-1];\r
+ }\r
+ } else { \r
+ // add a handler for the button\r
+ oCanvas = oLinks[i].parentNode.getElementsByTagName('canvas')[0];\r
+ }\r
+ // enable hi-DPI / retina features?\r
+ if (hiDPIScale > 1) {\r
+ self.addClass(oCanvas, 'hi-dpi');\r
+ }\r
+ oCover = self.getElementsByClassName('sm2-cover','div',oLinks[i].parentNode)[0];\r
+ oBtn = oLinks[i].parentNode.getElementsByTagName('span')[0];\r
+ self.addEventHandler(oBtn,'click',self.buttonClick);\r
+ if (!isTouchDevice) {\r
+ self.addEventHandler(oCover,'mousedown',self.mouseDown);\r
+ } else {\r
+ self.addEventHandler(oCover,'touchstart',self.mouseDown);\r
+ }\r
+ oCanvasCTX = oCanvas.getContext('2d');\r
+ oCanvasCTX.translate(radius, radius);\r
+ oCanvasCTX.rotate(self.deg2rad(-90)); // compensate for arc starting at EAST // http://stackoverflow.com/questions/319267/tutorial-for-html-canvass-arc-function\r
+ }\r
+ }\r
+ if (foundItems>0) {\r
+ self.addEventHandler(document,'click',self.handleClick);\r
+ if (self.config.autoPlay) {\r
+ self.handleClick({target:self.links[0],preventDefault:function(){}});\r
+ }\r
+ }\r
+ sm._writeDebug('threeSixtyPlayer.init(): Found '+foundItems+' relevant items.');\r
+\r
+ if (self.config.useFavIcon && typeof this.VUMeter !== 'undefined') {\r
+ this.vuMeter = new this.VUMeter(this);\r
+ }\r
+\r
+ };\r
+\r
+}\r
+\r
+// Optional: VU Meter component\r
+\r
+ThreeSixtyPlayer.prototype.VUMeter = function(oParent) {\r
+\r
+ var self = oParent,\r
+ me = this,\r
+ _head = document.getElementsByTagName('head')[0],\r
+ isOpera = (navigator.userAgent.match(/opera/i)),\r
+ isFirefox = (navigator.userAgent.match(/firefox/i));\r
+\r
+ this.vuMeterData = [];\r
+ this.vuDataCanvas = null;\r
+\r
+ this.setPageIcon = function(sDataURL) {\r
+\r
+ if (!self.config.useFavIcon || !self.config.usePeakData || !sDataURL) {\r
+ return false;\r
+ }\r
+\r
+ var link = document.getElementById('sm2-favicon');\r
+ if (link) {\r
+ _head.removeChild(link);\r
+ link = null;\r
+ }\r
+ if (!link) {\r
+ link = document.createElement('link');\r
+ link.id = 'sm2-favicon';\r
+ link.rel = 'shortcut icon';\r
+ link.type = 'image/png';\r
+ link.href = sDataURL;\r
+ document.getElementsByTagName('head')[0].appendChild(link);\r
+ }\r
+\r
+ };\r
+\r
+ this.resetPageIcon = function() {\r
+\r
+ if (!self.config.useFavIcon) {\r
+ return false;\r
+ }\r
+ var link = document.getElementById('favicon');\r
+ if (link) {\r
+ link.href = '/favicon.ico';\r
+ }\r
+\r
+ };\r
+\r
+ this.updateVU = function(oSound) {\r
+\r
+ if (soundManager.flashVersion >= 9 && self.config.useFavIcon && self.config.usePeakData) {\r
+ me.setPageIcon(me.vuMeterData[parseInt(16*oSound.peakData.left, 10)][parseInt(16*oSound.peakData.right, 10)]);\r
+ }\r
+\r
+ };\r
+\r
+ this.createVUData = function() {\r
+\r
+ var i=0, j=0,\r
+ canvas = me.vuDataCanvas.getContext('2d'),\r
+ vuGrad = canvas.createLinearGradient(0, 16, 0, 0),\r
+ bgGrad = canvas.createLinearGradient(0, 16, 0, 0),\r
+ outline = 'rgba(0,0,0,0.2)';\r
+\r
+ vuGrad.addColorStop(0,'rgb(0,192,0)');\r
+ vuGrad.addColorStop(0.30,'rgb(0,255,0)');\r
+ vuGrad.addColorStop(0.625,'rgb(255,255,0)');\r
+ vuGrad.addColorStop(0.85,'rgb(255,0,0)');\r
+ bgGrad.addColorStop(0,outline);\r
+ bgGrad.addColorStop(1,'rgba(0,0,0,0.5)');\r
+ for (i=0; i<16; i++) {\r
+ me.vuMeterData[i] = [];\r
+ }\r
+ for (i=0; i<16; i++) {\r
+ for (j=0; j<16; j++) {\r
+ // reset/erase canvas\r
+ me.vuDataCanvas.setAttribute('width',16);\r
+ me.vuDataCanvas.setAttribute('height',16);\r
+ // draw new stuffs\r
+ canvas.fillStyle = bgGrad;\r
+ canvas.fillRect(0,0,7,15);\r
+ canvas.fillRect(8,0,7,15);\r
+ /*\r
+ // shadow\r
+ canvas.fillStyle = 'rgba(0,0,0,0.1)';\r
+ canvas.fillRect(1,15-i,7,17-(17-i));\r
+ canvas.fillRect(9,15-j,7,17-(17-j));\r
+ */\r
+ canvas.fillStyle = vuGrad;\r
+ canvas.fillRect(0,15-i,7,16-(16-i));\r
+ canvas.fillRect(8,15-j,7,16-(16-j));\r
+ // and now, clear out some bits.\r
+ canvas.clearRect(0,3,16,1);\r
+ canvas.clearRect(0,7,16,1);\r
+ canvas.clearRect(0,11,16,1);\r
+ me.vuMeterData[i][j] = me.vuDataCanvas.toDataURL('image/png');\r
+ // for debugging VU images\r
+ /*\r
+ var o = document.createElement('img');\r
+ o.style.marginRight = '5px'; \r
+ o.src = vuMeterData[i][j];\r
+ document.documentElement.appendChild(o);\r
+ */\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ this.testCanvas = function() {\r
+\r
+ // canvas + toDataURL();\r
+ var c = document.createElement('canvas'),\r
+ ctx = null, ok;\r
+ if (!c || typeof c.getContext === 'undefined') {\r
+ return null;\r
+ }\r
+ ctx = c.getContext('2d');\r
+ if (!ctx || typeof c.toDataURL !== 'function') {\r
+ return null;\r
+ }\r
+ // just in case..\r
+ try {\r
+ ok = c.toDataURL('image/png');\r
+ } catch(e) {\r
+ // no canvas or no toDataURL()\r
+ return null;\r
+ }\r
+ // assume we're all good.\r
+ return c;\r
+\r
+ };\r
+\r
+ this.init = function() {\r
+\r
+ if (self.config.useFavIcon) {\r
+ me.vuDataCanvas = me.testCanvas();\r
+ if (me.vuDataCanvas && (isFirefox || isOpera)) {\r
+ // these browsers support dynamically-updating the favicon\r
+ me.createVUData();\r
+ } else {\r
+ // browser doesn't support doing this\r
+ self.config.useFavIcon = false;\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ this.init();\r
+\r
+};\r
+\r
+// completely optional: Metadata/annotations/segments code\r
+\r
+ThreeSixtyPlayer.prototype.Metadata = function(oSound, oParent) {\r
+\r
+ soundManager._wD('Metadata()');\r
+\r
+ var me = this,\r
+ oBox = oSound._360data.oUI360,\r
+ o = oBox.getElementsByTagName('ul')[0],\r
+ oItems = o.getElementsByTagName('li'),\r
+ isFirefox = (navigator.userAgent.match(/firefox/i)),\r
+ isAlt = false, i, oDuration;\r
+\r
+ this.lastWPExec = 0;\r
+ this.refreshInterval = 250;\r
+ this.totalTime = 0;\r
+\r
+ this.events = {\r
+\r
+ whileplaying: function() {\r
+\r
+ var width = oSound._360data.width,\r
+ radius = oSound._360data.radius,\r
+ fullDuration = (oSound.durationEstimate||(me.totalTime*1000)),\r
+ isAlt = null, i, j, d;\r
+\r
+ for (i=0,j=me.data.length; i<j; i++) {\r
+ isAlt = (i%2===0);\r
+ oParent.drawSolidArc(oSound._360data.oCanvas,(isAlt?oParent.config.segmentRingColorAlt:oParent.config.segmentRingColor),isAlt?width:width, isAlt?radius/2:radius/2, oParent.deg2rad(360*(me.data[i].endTimeMS/fullDuration)), oParent.deg2rad(360*((me.data[i].startTimeMS||1)/fullDuration)), true);\r
+ }\r
+ d = new Date();\r
+ if (d-me.lastWPExec>me.refreshInterval) {\r
+ me.refresh();\r
+ me.lastWPExec = d;\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ this.refresh = function() {\r
+\r
+ // Display info as appropriate\r
+ var i, j, index = null,\r
+ now = oSound.position,\r
+ metadata = oSound._360data.metadata.data;\r
+\r
+ for (i=0, j=metadata.length; i<j; i++) {\r
+ if (now >= metadata[i].startTimeMS && now <= metadata[i].endTimeMS) {\r
+ index = i;\r
+ break;\r
+ }\r
+ }\r
+ if (index !== metadata.currentItem && index < metadata.length) {\r
+ // update\r
+ oSound._360data.oLink.innerHTML = metadata.mainTitle+' <span class="metadata"><span class="sm2_divider"> | </span><span class="sm2_metadata">'+metadata[index].title+'</span></span>';\r
+ // self.setPageTitle(metadata[index].title+' | '+metadata.mainTitle);\r
+ metadata.currentItem = index;\r
+ }\r
+\r
+ };\r
+\r
+ this.strToTime = function(sTime) {\r
+ var segments = sTime.split(':'),\r
+ seconds = 0, i;\r
+ for (i=segments.length; i--;) {\r
+ seconds += parseInt(segments[i], 10)*Math.pow(60,segments.length-1-i); // hours, minutes\r
+ }\r
+ return seconds;\r
+ };\r
+\r
+ this.data = [];\r
+ this.data.givenDuration = null;\r
+ this.data.currentItem = null;\r
+ this.data.mainTitle = oSound._360data.oLink.innerHTML;\r
+\r
+ for (i=0; i<oItems.length; i++) {\r
+ this.data[i] = {\r
+ o: null,\r
+ title: oItems[i].getElementsByTagName('p')[0].innerHTML,\r
+ startTime: oItems[i].getElementsByTagName('span')[0].innerHTML,\r
+ startSeconds: me.strToTime(oItems[i].getElementsByTagName('span')[0].innerHTML.replace(/[()]/g,'')),\r
+ duration: 0,\r
+ durationMS: null,\r
+ startTimeMS: null,\r
+ endTimeMS: null,\r
+ oNote: null\r
+ };\r
+ }\r
+ oDuration = oParent.getElementsByClassName('duration','div',oBox);\r
+ this.data.givenDuration = (oDuration.length?me.strToTime(oDuration[0].innerHTML)*1000:0);\r
+ for (i=0; i<this.data.length; i++) {\r
+ this.data[i].duration = parseInt(this.data[i+1]?this.data[i+1].startSeconds:(me.data.givenDuration?me.data.givenDuration:oSound.durationEstimate)/1000, 10)-this.data[i].startSeconds;\r
+ this.data[i].startTimeMS = this.data[i].startSeconds*1000;\r
+ this.data[i].durationMS = this.data[i].duration*1000;\r
+ this.data[i].endTimeMS = this.data[i].startTimeMS+this.data[i].durationMS;\r
+ this.totalTime += this.data[i].duration;\r
+ }\r
+\r
+};\r
+\r
+if (navigator.userAgent.match(/webkit/i) && navigator.userAgent.match(/mobile/i)) {\r
+ // iPad, iPhone etc.\r
+ soundManager.setup({\r
+ useHTML5Audio: true\r
+ });\r
+}\r
+\r
+soundManager.setup({\r
+ html5PollingInterval: 50, // increased framerate for whileplaying() etc.\r
+ debugMode: (window.location.href.match(/debug=1/i)), // disable or enable debug output\r
+ consoleOnly: true,\r
+ flashVersion: 9,\r
+ useHighPerformance: true/*,\r
+ useFlashBlock: true*/\r
+});\r
+\r
+// FPS data, testing/debug only\r
+if (soundManager.debugMode) {\r
+ window.setInterval(function() {\r
+ var p = window.threeSixtyPlayer;\r
+ if (p && p.lastSound && p.lastSound._360data.fps && typeof window.isHome === 'undefined') {\r
+ soundManager._writeDebug('fps: ~'+p.lastSound._360data.fps);\r
+ p.lastSound._360data.fps = 0;\r
+ }\r
+ },1000);\r
+}\r
+\r
+window.ThreeSixtyPlayer = ThreeSixtyPlayer; // constructor\r
+\r
+}(window));\r
+\r
+threeSixtyPlayer = new ThreeSixtyPlayer();\r
+\r
+// hook into SM2 init\r
+soundManager.onready(threeSixtyPlayer.init);
\ No newline at end of file
--- /dev/null
+/** @license\r
+ Animator.js 1.1.9\r
+ \r
+ This library is released under the BSD license:\r
+\r
+ Copyright (c) 2006, Bernard Sumption. All rights reserved.\r
+ \r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions are met:\r
+ \r
+ Redistributions of source code must retain the above copyright notice, this\r
+ list of conditions and the following disclaimer. Redistributions in binary\r
+ form must reproduce the above copyright notice, this list of conditions and\r
+ the following disclaimer in the documentation and/or other materials\r
+ provided with the distribution. Neither the name BernieCode nor\r
+ the names of its contributors may be used to endorse or promote products\r
+ derived from this software without specific prior written permission. \r
+ \r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR\r
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH\r
+ DAMAGE.\r
+\r
+*/\r
+\r
+// http://www.berniecode.com/writing/animator.html\r
+\r
+// Applies a sequence of numbers between 0 and 1 to a number of subjects\r
+// construct - see setOptions for parameters\r
+function Animator(options) {\r
+ this.setOptions(options);\r
+ var _this = this;\r
+ this.timerDelegate = function(){_this.onTimerEvent()};\r
+ this.subjects = [];\r
+ this.subjectScopes = [];\r
+ this.target = 0;\r
+ this.state = 0;\r
+ this.lastTime = null;\r
+};\r
+Animator.prototype = {\r
+ // apply defaults\r
+ setOptions: function(options) {\r
+ this.options = Animator.applyDefaults({\r
+ interval: 20, // time between animation frames\r
+ duration: 400, // length of animation\r
+ onComplete: function(){},\r
+ onStep: function(){},\r
+ transition: Animator.tx.easeInOut\r
+ }, options);\r
+ },\r
+ // animate from the current state to provided value\r
+ seekTo: function(to) {\r
+ this.seekFromTo(this.state, to);\r
+ },\r
+ // animate from the current state to provided value\r
+ seekFromTo: function(from, to) {\r
+ this.target = Math.max(0, Math.min(1, to));\r
+ this.state = Math.max(0, Math.min(1, from));\r
+ this.lastTime = new Date().getTime();\r
+ if (!this.intervalId) {\r
+ this.intervalId = window.setInterval(this.timerDelegate, this.options.interval);\r
+ }\r
+ },\r
+ // animate from the current state to provided value\r
+ jumpTo: function(to) {\r
+ this.target = this.state = Math.max(0, Math.min(1, to));\r
+ this.propagate();\r
+ },\r
+ // seek to the opposite of the current target\r
+ toggle: function() {\r
+ this.seekTo(1 - this.target);\r
+ },\r
+ // add a function or an object with a method setState(state) that will be called with a number\r
+ // between 0 and 1 on each frame of the animation\r
+ addSubject: function(subject,scope) {\r
+ this.subjects[this.subjects.length] = subject;\r
+ this.subjectScopes[this.subjectScopes.length] = scope;\r
+ return this;\r
+ },\r
+ // remove all subjects\r
+ clearSubjects: function() {\r
+ this.subjects = [];\r
+ this.subjectScopes = [];\r
+ },\r
+ // forward the current state to the animation subjects\r
+ propagate: function() {\r
+ var value = this.options.transition(this.state);\r
+ for (var i=0; i<this.subjects.length; i++) {\r
+ if (this.subjects[i].setState) {\r
+ this.subjects[i].setState(value);\r
+ } else {\r
+ this.subjects[i].apply(this.subjectScopes[i],[value]);\r
+ }\r
+ }\r
+ },\r
+ // called once per frame to update the current state\r
+ onTimerEvent: function() {\r
+ var now = new Date().getTime();\r
+ var timePassed = now - this.lastTime;\r
+ this.lastTime = now;\r
+ var movement = (timePassed / this.options.duration) * (this.state < this.target ? 1 : -1);\r
+ if (Math.abs(movement) >= Math.abs(this.state - this.target)) {\r
+ this.state = this.target;\r
+ } else {\r
+ this.state += movement;\r
+ }\r
+ \r
+ try {\r
+ this.propagate();\r
+ } finally {\r
+ this.options.onStep.call(this);\r
+ if (this.target == this.state) {\r
+ window.clearInterval(this.intervalId);\r
+ this.intervalId = null;\r
+ this.options.onComplete.call(this);\r
+ }\r
+ }\r
+ },\r
+ // shortcuts\r
+ play: function() {this.seekFromTo(0, 1)},\r
+ reverse: function() {this.seekFromTo(1, 0)},\r
+ // return a string describing this Animator, for debugging\r
+ inspect: function() {\r
+ var str = "#<Animator:\n";\r
+ for (var i=0; i<this.subjects.length; i++) {\r
+ str += this.subjects[i].inspect();\r
+ }\r
+ str += ">";\r
+ return str;\r
+ }\r
+}\r
+// merge the properties of two objects\r
+Animator.applyDefaults = function(defaults, prefs) {\r
+ prefs = prefs || {};\r
+ var prop, result = {};\r
+ for (prop in defaults) result[prop] = prefs[prop] !== undefined ? prefs[prop] : defaults[prop];\r
+ return result;\r
+}\r
+// make an array from any object\r
+Animator.makeArray = function(o) {\r
+ if (o == null) return [];\r
+ if (!o.length) return [o];\r
+ var result = [];\r
+ for (var i=0; i<o.length; i++) result[i] = o[i];\r
+ return result;\r
+}\r
+// convert a dash-delimited-property to a camelCaseProperty (c/o Prototype, thanks Sam!)\r
+Animator.camelize = function(string) {\r
+ var oStringList = string.split('-');\r
+ if (oStringList.length == 1) return oStringList[0];\r
+ \r
+ var camelizedString = string.indexOf('-') == 0\r
+ ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)\r
+ : oStringList[0];\r
+ \r
+ for (var i = 1, len = oStringList.length; i < len; i++) {\r
+ var s = oStringList[i];\r
+ camelizedString += s.charAt(0).toUpperCase() + s.substring(1);\r
+ }\r
+ return camelizedString;\r
+}\r
+// syntactic sugar for creating CSSStyleSubjects\r
+Animator.apply = function(el, style, options) {\r
+ if (style instanceof Array) {\r
+ return new Animator(options).addSubject(new CSSStyleSubject(el, style[0], style[1]));\r
+ }\r
+ return new Animator(options).addSubject(new CSSStyleSubject(el, style));\r
+}\r
+// make a transition function that gradually accelerates. pass a=1 for smooth\r
+// gravitational acceleration, higher values for an exaggerated effect\r
+Animator.makeEaseIn = function(a) {\r
+ return function(state) {\r
+ return Math.pow(state, a*2); \r
+ }\r
+}\r
+// as makeEaseIn but for deceleration\r
+Animator.makeEaseOut = function(a) {\r
+ return function(state) {\r
+ return 1 - Math.pow(1 - state, a*2); \r
+ }\r
+}\r
+// make a transition function that, like an object with momentum being attracted to a point,\r
+// goes past the target then returns\r
+Animator.makeElastic = function(bounces) {\r
+ return function(state) {\r
+ state = Animator.tx.easeInOut(state);\r
+ return ((1-Math.cos(state * Math.PI * bounces)) * (1 - state)) + state; \r
+ }\r
+}\r
+// make an Attack Decay Sustain Release envelope that starts and finishes on the same level\r
+// \r
+Animator.makeADSR = function(attackEnd, decayEnd, sustainEnd, sustainLevel) {\r
+ if (sustainLevel == null) sustainLevel = 0.5;\r
+ return function(state) {\r
+ if (state < attackEnd) {\r
+ return state / attackEnd;\r
+ }\r
+ if (state < decayEnd) {\r
+ return 1 - ((state - attackEnd) / (decayEnd - attackEnd) * (1 - sustainLevel));\r
+ }\r
+ if (state < sustainEnd) {\r
+ return sustainLevel;\r
+ }\r
+ return sustainLevel * (1 - ((state - sustainEnd) / (1 - sustainEnd)));\r
+ }\r
+}\r
+// make a transition function that, like a ball falling to floor, reaches the target and/\r
+// bounces back again\r
+Animator.makeBounce = function(bounces) {\r
+ var fn = Animator.makeElastic(bounces);\r
+ return function(state) {\r
+ state = fn(state); \r
+ return state <= 1 ? state : 2-state;\r
+ }\r
+}\r
+ \r
+// pre-made transition functions to use with the 'transition' option\r
+Animator.tx = {\r
+ easeInOut: function(pos){\r
+ return ((-Math.cos(pos*Math.PI)/2) + 0.5);\r
+ },\r
+ linear: function(x) {\r
+ return x;\r
+ },\r
+ easeIn: Animator.makeEaseIn(1.5),\r
+ easeOut: Animator.makeEaseOut(1.5),\r
+ strongEaseIn: Animator.makeEaseIn(2.5),\r
+ strongEaseOut: Animator.makeEaseOut(2.5),\r
+ elastic: Animator.makeElastic(1),\r
+ veryElastic: Animator.makeElastic(3),\r
+ bouncy: Animator.makeBounce(1),\r
+ veryBouncy: Animator.makeBounce(3)\r
+}\r
+\r
+// animates a pixel-based style property between two integer values\r
+function NumericalStyleSubject(els, property, from, to, units) {\r
+ this.els = Animator.makeArray(els);\r
+ if (property == 'opacity' && window.ActiveXObject) {\r
+ this.property = 'filter';\r
+ } else {\r
+ this.property = Animator.camelize(property);\r
+ }\r
+ this.from = parseFloat(from);\r
+ this.to = parseFloat(to);\r
+ this.units = units != null ? units : 'px';\r
+}\r
+NumericalStyleSubject.prototype = {\r
+ setState: function(state) {\r
+ var style = this.getStyle(state);\r
+ var visibility = (this.property == 'opacity' && state == 0) ? 'hidden' : '';\r
+ var j=0;\r
+ for (var i=0; i<this.els.length; i++) {\r
+ try {\r
+ this.els[i].style[this.property] = style;\r
+ } catch (e) {\r
+ // ignore fontWeight - intermediate numerical values cause exeptions in firefox\r
+ if (this.property != 'fontWeight') throw e;\r
+ }\r
+ if (j++ > 20) return;\r
+ }\r
+ },\r
+ getStyle: function(state) {\r
+ state = this.from + ((this.to - this.from) * state);\r
+ if (this.property == 'filter') return "alpha(opacity=" + Math.round(state*100) + ")";\r
+ if (this.property == 'opacity') return state;\r
+ return Math.round(state) + this.units;\r
+ },\r
+ inspect: function() {\r
+ return "\t" + this.property + "(" + this.from + this.units + " to " + this.to + this.units + ")\n";\r
+ }\r
+}\r
+\r
+// animates a colour based style property between two hex values\r
+function ColorStyleSubject(els, property, from, to) {\r
+ this.els = Animator.makeArray(els);\r
+ this.property = Animator.camelize(property);\r
+ this.to = this.expandColor(to);\r
+ this.from = this.expandColor(from);\r
+ this.origFrom = from;\r
+ this.origTo = to;\r
+}\r
+\r
+ColorStyleSubject.prototype = {\r
+ // parse "#FFFF00" to [256, 256, 0]\r
+ expandColor: function(color) {\r
+ var hexColor, red, green, blue;\r
+ hexColor = ColorStyleSubject.parseColor(color);\r
+ if (hexColor) {\r
+ red = parseInt(hexColor.slice(1, 3), 16);\r
+ green = parseInt(hexColor.slice(3, 5), 16);\r
+ blue = parseInt(hexColor.slice(5, 7), 16);\r
+ return [red,green,blue]\r
+ }\r
+ if (window.DEBUG) {\r
+ alert("Invalid colour: '" + color + "'");\r
+ }\r
+ },\r
+ getValueForState: function(color, state) {\r
+ return Math.round(this.from[color] + ((this.to[color] - this.from[color]) * state));\r
+ },\r
+ setState: function(state) {\r
+ var color = '#'\r
+ + ColorStyleSubject.toColorPart(this.getValueForState(0, state))\r
+ + ColorStyleSubject.toColorPart(this.getValueForState(1, state))\r
+ + ColorStyleSubject.toColorPart(this.getValueForState(2, state));\r
+ for (var i=0; i<this.els.length; i++) {\r
+ this.els[i].style[this.property] = color;\r
+ }\r
+ },\r
+ inspect: function() {\r
+ return "\t" + this.property + "(" + this.origFrom + " to " + this.origTo + ")\n";\r
+ }\r
+}\r
+\r
+// return a properly formatted 6-digit hex colour spec, or false\r
+ColorStyleSubject.parseColor = function(string) {\r
+ var color = '#', match;\r
+ if(match = ColorStyleSubject.parseColor.rgbRe.exec(string)) {\r
+ var part;\r
+ for (var i=1; i<=3; i++) {\r
+ part = Math.max(0, Math.min(255, parseInt(match[i])));\r
+ color += ColorStyleSubject.toColorPart(part);\r
+ }\r
+ return color;\r
+ }\r
+ if (match = ColorStyleSubject.parseColor.hexRe.exec(string)) {\r
+ if(match[1].length == 3) {\r
+ for (var i=0; i<3; i++) {\r
+ color += match[1].charAt(i) + match[1].charAt(i);\r
+ }\r
+ return color;\r
+ }\r
+ return '#' + match[1];\r
+ }\r
+ return false;\r
+}\r
+// convert a number to a 2 digit hex string\r
+ColorStyleSubject.toColorPart = function(number) {\r
+ if (number > 255) number = 255;\r
+ var digits = number.toString(16);\r
+ if (number < 16) return '0' + digits;\r
+ return digits;\r
+}\r
+ColorStyleSubject.parseColor.rgbRe = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;\r
+ColorStyleSubject.parseColor.hexRe = /^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;\r
+\r
+// Animates discrete styles, i.e. ones that do not scale but have discrete values\r
+// that can't be interpolated\r
+function DiscreteStyleSubject(els, property, from, to, threshold) {\r
+ this.els = Animator.makeArray(els);\r
+ this.property = Animator.camelize(property);\r
+ this.from = from;\r
+ this.to = to;\r
+ this.threshold = threshold || 0.5;\r
+}\r
+\r
+DiscreteStyleSubject.prototype = {\r
+ setState: function(state) {\r
+ var j=0;\r
+ for (var i=0; i<this.els.length; i++) {\r
+ this.els[i].style[this.property] = state <= this.threshold ? this.from : this.to; \r
+ }\r
+ },\r
+ inspect: function() {\r
+ return "\t" + this.property + "(" + this.from + " to " + this.to + " @ " + this.threshold + ")\n";\r
+ }\r
+}\r
+\r
+// animates between two styles defined using CSS.\r
+// if style1 and style2 are present, animate between them, if only style1\r
+// is present, animate between the element's current style and style1\r
+function CSSStyleSubject(els, style1, style2) {\r
+ els = Animator.makeArray(els);\r
+ this.subjects = [];\r
+ if (els.length == 0) return;\r
+ var prop, toStyle, fromStyle;\r
+ if (style2) {\r
+ fromStyle = this.parseStyle(style1, els[0]);\r
+ toStyle = this.parseStyle(style2, els[0]);\r
+ } else {\r
+ toStyle = this.parseStyle(style1, els[0]);\r
+ fromStyle = {};\r
+ for (prop in toStyle) {\r
+ fromStyle[prop] = CSSStyleSubject.getStyle(els[0], prop);\r
+ }\r
+ }\r
+ // remove unchanging properties\r
+ var prop;\r
+ for (prop in fromStyle) {\r
+ if (fromStyle[prop] == toStyle[prop]) {\r
+ delete fromStyle[prop];\r
+ delete toStyle[prop];\r
+ }\r
+ }\r
+ // discover the type (numerical or colour) of each style\r
+ var prop, units, match, type, from, to;\r
+ for (prop in fromStyle) {\r
+ var fromProp = String(fromStyle[prop]);\r
+ var toProp = String(toStyle[prop]);\r
+ if (toStyle[prop] == null) {\r
+ if (window.DEBUG) alert("No to style provided for '" + prop + '"');\r
+ continue;\r
+ }\r
+ \r
+ if (from = ColorStyleSubject.parseColor(fromProp)) {\r
+ to = ColorStyleSubject.parseColor(toProp);\r
+ type = ColorStyleSubject;\r
+ } else if (fromProp.match(CSSStyleSubject.numericalRe)\r
+ && toProp.match(CSSStyleSubject.numericalRe)) {\r
+ from = parseFloat(fromProp);\r
+ to = parseFloat(toProp);\r
+ type = NumericalStyleSubject;\r
+ match = CSSStyleSubject.numericalRe.exec(fromProp);\r
+ var reResult = CSSStyleSubject.numericalRe.exec(toProp);\r
+ if (match[1] != null) {\r
+ units = match[1];\r
+ } else if (reResult[1] != null) {\r
+ units = reResult[1];\r
+ } else {\r
+ units = reResult;\r
+ }\r
+ } else if (fromProp.match(CSSStyleSubject.discreteRe)\r
+ && toProp.match(CSSStyleSubject.discreteRe)) {\r
+ from = fromProp;\r
+ to = toProp;\r
+ type = DiscreteStyleSubject;\r
+ units = 0; // hack - how to get an animator option down to here\r
+ } else {\r
+ if (window.DEBUG) {\r
+ alert("Unrecognised format for value of "\r
+ + prop + ": '" + fromStyle[prop] + "'");\r
+ }\r
+ continue;\r
+ }\r
+ this.subjects[this.subjects.length] = new type(els, prop, from, to, units);\r
+ }\r
+}\r
+\r
+CSSStyleSubject.prototype = {\r
+ // parses "width: 400px; color: #FFBB2E" to {width: "400px", color: "#FFBB2E"}\r
+ parseStyle: function(style, el) {\r
+ var rtn = {};\r
+ // if style is a rule set\r
+ if (style.indexOf(":") != -1) {\r
+ var styles = style.split(";");\r
+ for (var i=0; i<styles.length; i++) {\r
+ var parts = CSSStyleSubject.ruleRe.exec(styles[i]);\r
+ if (parts) {\r
+ rtn[parts[1]] = parts[2];\r
+ }\r
+ }\r
+ }\r
+ // else assume style is a class name\r
+ else {\r
+ var prop, value, oldClass;\r
+ oldClass = el.className;\r
+ el.className = style;\r
+ for (var i=0; i<CSSStyleSubject.cssProperties.length; i++) {\r
+ prop = CSSStyleSubject.cssProperties[i];\r
+ value = CSSStyleSubject.getStyle(el, prop);\r
+ if (value != null) {\r
+ rtn[prop] = value;\r
+ }\r
+ }\r
+ el.className = oldClass;\r
+ }\r
+ return rtn;\r
+ \r
+ },\r
+ setState: function(state) {\r
+ for (var i=0; i<this.subjects.length; i++) {\r
+ this.subjects[i].setState(state);\r
+ }\r
+ },\r
+ inspect: function() {\r
+ var str = "";\r
+ for (var i=0; i<this.subjects.length; i++) {\r
+ str += this.subjects[i].inspect();\r
+ }\r
+ return str;\r
+ }\r
+}\r
+// get the current value of a css property, \r
+CSSStyleSubject.getStyle = function(el, property){\r
+ var style;\r
+ if(document.defaultView && document.defaultView.getComputedStyle){\r
+ style = document.defaultView.getComputedStyle(el, "").getPropertyValue(property);\r
+ if (style) {\r
+ return style;\r
+ }\r
+ }\r
+ property = Animator.camelize(property);\r
+ if(el.currentStyle){\r
+ style = el.currentStyle[property];\r
+ }\r
+ return style || el.style[property]\r
+}\r
+\r
+\r
+CSSStyleSubject.ruleRe = /^\s*([a-zA-Z\-]+)\s*:\s*(\S(.+\S)?)\s*$/;\r
+CSSStyleSubject.numericalRe = /^-?\d+(?:\.\d+)?(%|[a-zA-Z]{2})?$/;\r
+CSSStyleSubject.discreteRe = /^\w+$/;\r
+\r
+// required because the style object of elements isn't enumerable in Safari\r
+/*\r
+CSSStyleSubject.cssProperties = ['background-color','border','border-color','border-spacing',\r
+'border-style','border-top','border-right','border-bottom','border-left','border-top-color',\r
+'border-right-color','border-bottom-color','border-left-color','border-top-width','border-right-width',\r
+'border-bottom-width','border-left-width','border-width','bottom','color','font-size','font-size-adjust',\r
+'font-stretch','font-style','height','left','letter-spacing','line-height','margin','margin-top',\r
+'margin-right','margin-bottom','margin-left','marker-offset','max-height','max-width','min-height',\r
+'min-width','orphans','outline','outline-color','outline-style','outline-width','overflow','padding',\r
+'padding-top','padding-right','padding-bottom','padding-left','quotes','right','size','text-indent',\r
+'top','width','word-spacing','z-index','opacity','outline-offset'];*/\r
+\r
+\r
+CSSStyleSubject.cssProperties = ['azimuth','background','background-attachment','background-color','background-image','background-position','background-repeat','border-collapse','border-color','border-spacing','border-style','border-top','border-top-color','border-right-color','border-bottom-color','border-left-color','border-top-style','border-right-style','border-bottom-style','border-left-style','border-top-width','border-right-width','border-bottom-width','border-left-width','border-width','bottom','clear','clip','color','content','cursor','direction','display','elevation','empty-cells','css-float','font','font-family','font-size','font-size-adjust','font-stretch','font-style','font-variant','font-weight','height','left','letter-spacing','line-height','list-style','list-style-image','list-style-position','list-style-type','margin','margin-top','margin-right','margin-bottom','margin-left','max-height','max-width','min-height','min-width','orphans','outline','outline-color','outline-style','outline-width','overflow','padding','padding-top','padding-right','padding-bottom','padding-left','pause','position','right','size','table-layout','text-align','text-decoration','text-indent','text-shadow','text-transform','top','vertical-align','visibility','white-space','width','word-spacing','z-index','opacity','outline-offset','overflow-x','overflow-y'];\r
+\r
+\r
+// chains several Animator objects together\r
+function AnimatorChain(animators, options) {\r
+ this.animators = animators;\r
+ this.setOptions(options);\r
+ for (var i=0; i<this.animators.length; i++) {\r
+ this.listenTo(this.animators[i]);\r
+ }\r
+ this.forwards = false;\r
+ this.current = 0;\r
+}\r
+\r
+AnimatorChain.prototype = {\r
+ // apply defaults\r
+ setOptions: function(options) {\r
+ this.options = Animator.applyDefaults({\r
+ // by default, each call to AnimatorChain.play() calls jumpTo(0) of each animator\r
+ // before playing, which can cause flickering if you have multiple animators all\r
+ // targeting the same element. Set this to false to avoid this.\r
+ resetOnPlay: true\r
+ }, options);\r
+ },\r
+ // play each animator in turn\r
+ play: function() {\r
+ this.forwards = true;\r
+ this.current = -1;\r
+ if (this.options.resetOnPlay) {\r
+ for (var i=0; i<this.animators.length; i++) {\r
+ this.animators[i].jumpTo(0);\r
+ }\r
+ }\r
+ this.advance();\r
+ },\r
+ // play all animators backwards\r
+ reverse: function() {\r
+ this.forwards = false;\r
+ this.current = this.animators.length;\r
+ if (this.options.resetOnPlay) {\r
+ for (var i=0; i<this.animators.length; i++) {\r
+ this.animators[i].jumpTo(1);\r
+ }\r
+ }\r
+ this.advance();\r
+ },\r
+ // if we have just play()'d, then call reverse(), and vice versa\r
+ toggle: function() {\r
+ if (this.forwards) {\r
+ this.seekTo(0);\r
+ } else {\r
+ this.seekTo(1);\r
+ }\r
+ },\r
+ // internal: install an event listener on an animator's onComplete option\r
+ // to trigger the next animator\r
+ listenTo: function(animator) {\r
+ var oldOnComplete = animator.options.onComplete;\r
+ var _this = this;\r
+ animator.options.onComplete = function() {\r
+ if (oldOnComplete) oldOnComplete.call(animator);\r
+ _this.advance();\r
+ }\r
+ },\r
+ // play the next animator\r
+ advance: function() {\r
+ if (this.forwards) {\r
+ if (this.animators[this.current + 1] == null) return;\r
+ this.current++;\r
+ this.animators[this.current].play();\r
+ } else {\r
+ if (this.animators[this.current - 1] == null) return;\r
+ this.current--;\r
+ this.animators[this.current].reverse();\r
+ }\r
+ },\r
+ // this function is provided for drop-in compatibility with Animator objects,\r
+ // but only accepts 0 and 1 as target values\r
+ seekTo: function(target) {\r
+ if (target <= 0) {\r
+ this.forwards = false;\r
+ this.animators[this.current].seekTo(0);\r
+ } else {\r
+ this.forwards = true;\r
+ this.animators[this.current].seekTo(1);\r
+ }\r
+ }\r
+}\r
+\r
+// an Accordion is a class that creates and controls a number of Animators. An array of elements is passed in,\r
+// and for each element an Animator and a activator button is created. When an Animator's activator button is\r
+// clicked, the Animator and all before it seek to 0, and all Animators after it seek to 1. This can be used to\r
+// create the classic Accordion effect, hence the name.\r
+// see setOptions for arguments\r
+function Accordion(options) {\r
+ this.setOptions(options);\r
+ var selected = this.options.initialSection, current;\r
+ if (this.options.rememberance) {\r
+ current = document.location.hash.substring(1);\r
+ }\r
+ this.rememberanceTexts = [];\r
+ this.ans = [];\r
+ var _this = this;\r
+ for (var i=0; i<this.options.sections.length; i++) {\r
+ var el = this.options.sections[i];\r
+ var an = new Animator(this.options.animatorOptions);\r
+ var from = this.options.from + (this.options.shift * i);\r
+ var to = this.options.to + (this.options.shift * i);\r
+ an.addSubject(new NumericalStyleSubject(el, this.options.property, from, to, this.options.units));\r
+ an.jumpTo(0);\r
+ var activator = this.options.getActivator(el);\r
+ activator.index = i;\r
+ activator.onclick = function(){_this.show(this.index)};\r
+ this.ans[this.ans.length] = an;\r
+ this.rememberanceTexts[i] = activator.innerHTML.replace(/\s/g, "");\r
+ if (this.rememberanceTexts[i] === current) {\r
+ selected = i;\r
+ }\r
+ }\r
+ this.show(selected);\r
+}\r
+\r
+Accordion.prototype = {\r
+ // apply defaults\r
+ setOptions: function(options) {\r
+ this.options = Object.extend({\r
+ // REQUIRED: an array of elements to use as the accordion sections\r
+ sections: null,\r
+ // a function that locates an activator button element given a section element.\r
+ // by default it takes a button id from the section's "activator" attibute\r
+ getActivator: function(el) {return document.getElementById(el.getAttribute("activator"))},\r
+ // shifts each animator's range, for example with options {from:0,to:100,shift:20}\r
+ // the animators' ranges will be 0-100, 20-120, 40-140 etc.\r
+ shift: 0,\r
+ // the first page to show\r
+ initialSection: 0,\r
+ // if set to true, document.location.hash will be used to preserve the open section across page reloads \r
+ rememberance: true,\r
+ // constructor arguments to the Animator objects\r
+ animatorOptions: {}\r
+ }, options || {});\r
+ },\r
+ show: function(section) {\r
+ for (var i=0; i<this.ans.length; i++) {\r
+ this.ans[i].seekTo(i > section ? 1 : 0);\r
+ }\r
+ if (this.options.rememberance) {\r
+ document.location.hash = this.rememberanceTexts[section];\r
+ }\r
+ }\r
+}\r
--- /dev/null
+// Excanvas (Explorer Canvas) R43\r
+// http://excanvas.sourceforge.net/\r
+// Copyright 2006 Google Inc.\r
+//\r
+// Licensed under the Apache License, Version 2.0 (the "License");\r
+// you may not use this file except in compliance with the License.\r
+// You may obtain a copy of the License at\r
+//\r
+// http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+// Unless required by applicable law or agreed to in writing, software\r
+// distributed under the License is distributed on an "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+// See the License for the specific language governing permissions and\r
+// limitations under the License.\r
+\r
+if(!document.createElement("canvas").getContext){(function(){var u=Math;var v=u.round;var r=u.sin;var C=u.cos;var l=u.abs;var B=u.sqrt;var a=10;var n=a/2;function g(){return this.context_||(this.context_=new p(this))}var t=Array.prototype.slice;function D(j,m,E){var i=t.call(arguments,2);return function(){return j.apply(m,i.concat(t.call(arguments)))}}var h={init:function(i){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var j=i||document;j.createElement("canvas");j.attachEvent("onreadystatechange",D(this.init_,this,j))}},init_:function(F){if(!F.namespaces.g_vml_){F.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML")}if(!F.namespaces.g_o_){F.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML")}if(!F.styleSheets.ex_canvas_){var E=F.createStyleSheet();E.owningElement.id="ex_canvas_";E.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}g_o_\\:*{behavior:url(#default#VML)}"}var m=F.getElementsByTagName("canvas");for(var j=0;j<m.length;j++){this.initElement(m[j])}},initElement:function(j){if(!j.getContext){j.getContext=g;j.innerHTML="";j.attachEvent("onpropertychange",A);j.attachEvent("onresize",b);var i=j.attributes;if(i.width&&i.width.specified){j.style.width=i.width.nodeValue+"px"}else{j.width=j.clientWidth}if(i.height&&i.height.specified){j.style.height=i.height.nodeValue+"px"}else{j.height=j.clientHeight}}return j}};function A(j){var i=j.srcElement;switch(j.propertyName){case"width":i.style.width=i.attributes.width.nodeValue+"px";i.getContext().clearRect();break;case"height":i.style.height=i.attributes.height.nodeValue+"px";i.getContext().clearRect();break}}function b(j){var i=j.srcElement;if(i.firstChild){i.firstChild.style.width=i.clientWidth+"px";i.firstChild.style.height=i.clientHeight+"px"}}h.init();var e=[];for(var y=0;y<16;y++){for(var x=0;x<16;x++){e[y*16+x]=y.toString(16)+x.toString(16)}}function q(){return[[1,0,0],[0,1,0],[0,0,1]]}function d(E,m){var j=q();for(var i=0;i<3;i++){for(var H=0;H<3;H++){var F=0;for(var G=0;G<3;G++){F+=E[i][G]*m[G][H]}j[i][H]=F}}return j}function w(j,i){i.fillStyle=j.fillStyle;i.lineCap=j.lineCap;i.lineJoin=j.lineJoin;i.lineWidth=j.lineWidth;i.miterLimit=j.miterLimit;i.shadowBlur=j.shadowBlur;i.shadowColor=j.shadowColor;i.shadowOffsetX=j.shadowOffsetX;i.shadowOffsetY=j.shadowOffsetY;i.strokeStyle=j.strokeStyle;i.globalAlpha=j.globalAlpha;i.arcScaleX_=j.arcScaleX_;i.arcScaleY_=j.arcScaleY_;i.lineScale_=j.lineScale_}function c(m){var G,F=1;m=String(m);if(m.substring(0,3)=="rgb"){var I=m.indexOf("(",3);var j=m.indexOf(")",I+1);var H=m.substring(I+1,j).split(",");G="#";for(var E=0;E<3;E++){G+=e[Number(H[E])]}if(H.length==4&&m.substr(3,1)=="a"){F=H[3]}}else{G=m}return{color:G,alpha:F}}function s(i){switch(i){case"butt":return"flat";case"round":return"round";case"square":default:return"square"}}function p(j){this.m_=q();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=a*1;this.globalAlpha=1;this.canvas=j;var i=j.ownerDocument.createElement("div");i.style.width=j.clientWidth+"px";i.style.height=j.clientHeight+"px";i.style.overflow="hidden";i.style.position="absolute";j.appendChild(i);this.element_=i;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var k=p.prototype;k.clearRect=function(){this.element_.innerHTML=""};k.beginPath=function(){this.currentPath_=[]};k.moveTo=function(j,i){var m=this.getCoords_(j,i);this.currentPath_.push({type:"moveTo",x:m.x,y:m.y});this.currentX_=m.x;this.currentY_=m.y};k.lineTo=function(j,i){var m=this.getCoords_(j,i);this.currentPath_.push({type:"lineTo",x:m.x,y:m.y});this.currentX_=m.x;this.currentY_=m.y};k.bezierCurveTo=function(m,j,J,I,H,F){var i=this.getCoords_(H,F);var G=this.getCoords_(m,j);var E=this.getCoords_(J,I);o(this,G,E,i)};function o(i,E,m,j){i.currentPath_.push({type:"bezierCurveTo",cp1x:E.x,cp1y:E.y,cp2x:m.x,cp2y:m.y,x:j.x,y:j.y});i.currentX_=j.x;i.currentY_=j.y}k.quadraticCurveTo=function(H,m,j,i){var G=this.getCoords_(H,m);var F=this.getCoords_(j,i);var I={x:this.currentX_+2/3*(G.x-this.currentX_),y:this.currentY_+2/3*(G.y-this.currentY_)};var E={x:I.x+(F.x-this.currentX_)/3,y:I.y+(F.y-this.currentY_)/3};o(this,I,E,F)};k.arc=function(K,I,J,F,j,m){J*=a;var O=m?"at":"wa";var L=K+C(F)*J-n;var N=I+r(F)*J-n;var i=K+C(j)*J-n;var M=I+r(j)*J-n;if(L==i&&!m){L+=0.125}var E=this.getCoords_(K,I);var H=this.getCoords_(L,N);var G=this.getCoords_(i,M);this.currentPath_.push({type:O,x:E.x,y:E.y,radius:J,xStart:H.x,yStart:H.y,xEnd:G.x,yEnd:G.y})};k.rect=function(m,j,i,E){this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+E);this.lineTo(m,j+E);this.closePath()};k.strokeRect=function(m,j,i,E){var F=this.currentPath_;this.beginPath();this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+E);this.lineTo(m,j+E);this.closePath();this.stroke();this.currentPath_=F};k.fillRect=function(m,j,i,E){var F=this.currentPath_;this.beginPath();this.moveTo(m,j);this.lineTo(m+i,j);this.lineTo(m+i,j+E);this.lineTo(m,j+E);this.closePath();this.fill();this.currentPath_=F};k.createLinearGradient=function(j,E,i,m){var F=new z("gradient");F.x0_=j;F.y0_=E;F.x1_=i;F.y1_=m;return F};k.createRadialGradient=function(E,G,m,j,F,i){var H=new z("gradientradial");H.x0_=E;H.y0_=G;H.r0_=m;H.x1_=j;H.y1_=F;H.r1_=i;return H};k.drawImage=function(R,m){var K,I,M,Z,P,N,T,ab;var L=R.runtimeStyle.width;var Q=R.runtimeStyle.height;R.runtimeStyle.width="auto";R.runtimeStyle.height="auto";var J=R.width;var X=R.height;R.runtimeStyle.width=L;R.runtimeStyle.height=Q;if(arguments.length==3){K=arguments[1];I=arguments[2];P=N=0;T=M=J;ab=Z=X}else{if(arguments.length==5){K=arguments[1];I=arguments[2];M=arguments[3];Z=arguments[4];P=N=0;T=J;ab=X}else{if(arguments.length==9){P=arguments[1];N=arguments[2];T=arguments[3];ab=arguments[4];K=arguments[5];I=arguments[6];M=arguments[7];Z=arguments[8]}else{throw Error("Invalid number of arguments")}}}var aa=this.getCoords_(K,I);var E=T/2;var j=ab/2;var Y=[];var i=10;var G=10;Y.push(" <g_vml_:group",' coordsize="',a*i,",",a*G,'"',' coordorigin="0,0"',' style="width:',i,"px;height:",G,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]){var F=[];F.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",v(aa.x/a),",","Dy=",v(aa.y/a),"");var V=aa;var U=this.getCoords_(K+M,I);var S=this.getCoords_(K,I+Z);var O=this.getCoords_(K+M,I+Z);V.x=u.max(V.x,U.x,S.x,O.x);V.y=u.max(V.y,U.y,S.y,O.y);Y.push("padding:0 ",v(V.x/a),"px ",v(V.y/a),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",F.join(""),", sizingmethod='clip');")}else{Y.push("top:",v(aa.y/a),"px;left:",v(aa.x/a),"px;")}Y.push(' ">','<g_vml_:image src="',R.src,'"',' style="width:',a*M,"px;"," height:",a*Z,'px;"',' cropleft="',P/J,'"',' croptop="',N/X,'"',' cropright="',(J-P-T)/J,'"',' cropbottom="',(X-N-ab)/X,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",Y.join(""))};k.stroke=function(ae){var J=[];var K=false;var ap=c(ae?this.fillStyle:this.strokeStyle);var aa=ap.color;var ak=ap.alpha*this.globalAlpha;var F=10;var M=10;J.push("<g_vml_:shape",' filled="',!!ae,'"',' style="position:absolute;width:',F,"px;height:",M,'px;"',' coordorigin="0 0" coordsize="',a*F," ",a*M,'"',' stroked="',!ae,'"',' path="');var L=false;var ao={x:null,y:null};var V={x:null,y:null};for(var aj=0;aj<this.currentPath_.length;aj++){var ai=this.currentPath_[aj];var an;switch(ai.type){case"moveTo":an=ai;J.push(" m ",v(ai.x),",",v(ai.y));break;case"lineTo":J.push(" l ",v(ai.x),",",v(ai.y));break;case"close":J.push(" x ");ai=null;break;case"bezierCurveTo":J.push(" c ",v(ai.cp1x),",",v(ai.cp1y),",",v(ai.cp2x),",",v(ai.cp2y),",",v(ai.x),",",v(ai.y));break;case"at":case"wa":J.push(" ",ai.type," ",v(ai.x-this.arcScaleX_*ai.radius),",",v(ai.y-this.arcScaleY_*ai.radius)," ",v(ai.x+this.arcScaleX_*ai.radius),",",v(ai.y+this.arcScaleY_*ai.radius)," ",v(ai.xStart),",",v(ai.yStart)," ",v(ai.xEnd),",",v(ai.yEnd));break}if(ai){if(ao.x==null||ai.x<ao.x){ao.x=ai.x}if(V.x==null||ai.x>V.x){V.x=ai.x}if(ao.y==null||ai.y<ao.y){ao.y=ai.y}if(V.y==null||ai.y>V.y){V.y=ai.y}}}J.push(' ">');if(!ae){var U=this.lineScale_*this.lineWidth;if(U<1){ak*=U}J.push("<g_vml_:stroke",' opacity="',ak,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',s(this.lineCap),'"',' weight="',U,'px"',' color="',aa,'" />')}else{if(typeof this.fillStyle=="object"){var N=this.fillStyle;var S=0;var ah={x:0,y:0};var ab=0;var Q=1;if(N.type_=="gradient"){var P=N.x0_/this.arcScaleX_;var m=N.y0_/this.arcScaleY_;var O=N.x1_/this.arcScaleX_;var aq=N.y1_/this.arcScaleY_;var am=this.getCoords_(P,m);var al=this.getCoords_(O,aq);var I=al.x-am.x;var G=al.y-am.y;S=Math.atan2(I,G)*180/Math.PI;if(S<0){S+=360}if(S<0.000001){S=0}}else{var am=this.getCoords_(N.x0_,N.y0_);var j=V.x-ao.x;var E=V.y-ao.y;ah={x:(am.x-ao.x)/j,y:(am.y-ao.y)/E};j/=this.arcScaleX_*a;E/=this.arcScaleY_*a;var ag=u.max(j,E);ab=2*N.r0_/ag;Q=2*N.r1_/ag-ab}var Z=N.colors_;Z.sort(function(H,i){return H.offset-i.offset});var T=Z.length;var Y=Z[0].color;var X=Z[T-1].color;var ad=Z[0].alpha*this.globalAlpha;var ac=Z[T-1].alpha*this.globalAlpha;var af=[];for(var aj=0;aj<T;aj++){var R=Z[aj];af.push(R.offset*Q+ab+" "+R.color)}J.push('<g_vml_:fill type="',N.type_,'"',' method="none" focus="100%"',' color="',Y,'"',' color2="',X,'"',' colors="',af.join(","),'"',' opacity="',ac,'"',' g_o_:opacity2="',ad,'"',' angle="',S,'"',' focusposition="',ah.x,",",ah.y,'" />')}else{J.push('<g_vml_:fill color="',aa,'" opacity="',ak,'" />')}}J.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",J.join(""))};k.fill=function(){this.stroke(true)};k.closePath=function(){this.currentPath_.push({type:"close"})};k.getCoords_=function(E,j){var i=this.m_;return{x:a*(E*i[0][0]+j*i[1][0]+i[2][0])-n,y:a*(E*i[0][1]+j*i[1][1]+i[2][1])-n}};k.save=function(){var i={};w(this,i);this.aStack_.push(i);this.mStack_.push(this.m_);this.m_=d(q(),this.m_)};k.restore=function(){w(this.aStack_.pop(),this);this.m_=this.mStack_.pop()};k.translate=function(m,j){var i=[[1,0,0],[0,1,0],[m,j,1]];this.m_=d(i,this.m_)};k.rotate=function(j){var E=C(j);var m=r(j);var i=[[E,m,0],[-m,E,0],[0,0,1]];this.m_=d(i,this.m_)};k.scale=function(G,F){this.arcScaleX_*=G;this.arcScaleY_*=F;var j=[[G,0,0],[0,F,0],[0,0,1]];var i=this.m_=d(j,this.m_);var E=i[0][0]*i[1][1]-i[0][1]*i[1][0];this.lineScale_=B(l(E))};k.clip=function(){};k.arcTo=function(){};k.createPattern=function(){return new f};function z(i){this.type_=i;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}z.prototype.addColorStop=function(j,i){i=c(i);this.colors_.push({offset:j,color:i.color,alpha:i.alpha})};function f(){}G_vmlCanvasManager=h;CanvasRenderingContext2D=p;CanvasGradient=z;CanvasPattern=f})()};
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Copyright : Generated in 2010 by FontLab Studio Copyright info pending
+</metadata>
+<defs>
+<font id="ChunkFiveRegular" horiz-adv-x="696" >
+<font-face units-per-em="2048" ascent="1536" descent="-512" />
+<missing-glyph horiz-adv-x="500" />
+<glyph unicode="!" horiz-adv-x="630" d="M57 209q0 84 64.5 150.5t169.5 66.5q106 0 175 -63.5t69 -153.5q0 -88 -68 -149.5t-176 -61.5q-98 0 -166 64.5t-68 146.5zM66 1042v390h489v-390l-109 -516h-270z" />
+<glyph unicode=""" horiz-adv-x="1032" d="M72 1436h393l-62 -613h-256zM567 1436h394l-74 -613h-256z" />
+<glyph unicode="#" horiz-adv-x="1536" d="M31 375v278h299l59 234h-246v278h316l96 375h270l-96 -375h275l96 375h270l-96 -375h231v-278h-301l-59 -234h248v-278h-320l-94 -377l-270 4l94 373h-275l-94 -377l-270 4l94 373h-227zM600 653h274l60 234h-275z" />
+<glyph unicode="$" horiz-adv-x="1234" d="M31 35v493h321q0 -57 27 -98t70 -60.5t78.5 -27.5t72.5 -10q150 0 150 100q0 41 -69 74t-166 66.5t-195.5 81.5t-167 141.5t-68.5 220.5q0 188 113.5 289.5t261.5 111.5v172h289v-213q78 -37 114 -100l17 115h299v-480h-316q0 104 -63.5 166t-163.5 62q-43 0 -82 -28 t-39 -77q0 -47 51 -84t128 -62.5t166 -64.5t166 -84t128 -128t51 -189.5t-41 -186t-109.5 -123.5t-144 -64.5t-161.5 -22.5v-211h-289v268q-55 31 -107 76l-22 -123h-299z" />
+<glyph unicode="%" horiz-adv-x="1906" d="M31 1051q0 180 125 298.5t288 118.5q199 0 310.5 -114.5t111.5 -309.5q0 -184 -110.5 -300.5t-302.5 -116.5q-186 0 -304 115.5t-118 308.5zM336 1051q0 -104 37 -170t80 -66q47 0 76.5 62.5t29.5 166.5q0 100 -32.5 166t-80.5 66q-41 2 -75.5 -60.5t-34.5 -164.5zM387 0 l885 1432h233l-887 -1432h-231zM1040 424q0 180 125 299t289 119q199 0 310.5 -115t111.5 -309q0 -184 -110.5 -301t-303.5 -117q-186 0 -304 115.5t-118 308.5zM1346 424q0 -104 36.5 -170t79.5 -66q47 0 77 62.5t30 167.5q0 100 -33 165.5t-80 65.5q-41 2 -75.5 -60.5 t-34.5 -164.5z" />
+<glyph unicode="&" horiz-adv-x="1579" d="M20 420q0 264 302 418q-63 41 -106.5 115.5t-43.5 154.5q0 135 125 241.5t313 106.5q219 0 333 -106.5t114 -241.5q0 -111 -67.5 -184.5t-166.5 -114.5l191 -191q59 111 106 273h439v-258h-201q-47 -135 -117 -242l127 -125h119v-266h-305l-133 131q-80 -74 -210 -116 t-276 -42q-250 0 -396.5 126t-146.5 321zM403 432q0 -70 51.5 -113t114.5 -43q145 0 242 86l-260 256h-8q-51 -33 -95.5 -84t-44.5 -102zM506 1114q0 -94 123 -147q6 -4 29.5 14t46 52t22.5 69q0 51 -28.5 88t-90.5 37q-43 0 -72.5 -35t-29.5 -78z" />
+<glyph unicode="'" horiz-adv-x="559" d="M74 1436h405l-73 -613h-256z" />
+<glyph unicode="(" horiz-adv-x="794" d="M51 639q0 170 50.5 341t128 303t154.5 227.5t148 158.5l211 -217q-59 -74 -94 -122t-96 -156.5t-93 -243.5t-32 -291q0 -162 29.5 -301t85 -245.5t97.5 -168t103 -133.5l-211 -219q-193 174 -337 459.5t-144 607.5z" />
+<glyph unicode=")" horiz-adv-x="794" d="M51 -211q61 72 103.5 133.5t97.5 168t85 245.5t30 301q0 156 -32 291t-93.5 243.5t-96 156.5t-94.5 122l211 217q72 -63 148.5 -158.5t154.5 -227.5t128 -303t50 -341q0 -322 -144 -607.5t-337 -459.5z" />
+<glyph unicode="*" horiz-adv-x="845" d="M10 1085l84 201l234 -108l-27 254h252l-33 -261l232 115l84 -201l-248 -81l184 -197l-186 -143l-162 227l-170 -234l-180 152l178 192z" />
+<glyph unicode="+" horiz-adv-x="1120" d="M51 625v266h377v377h266v-377h375v-266h-375v-375h-266v375h-377z" />
+<glyph unicode="," horiz-adv-x="557" d="M-12 -264q115 145 162 294.5t32 370.5l373 -98q6 -195 -82 -376t-250 -324z" />
+<glyph unicode="-" d="M51 352v273h594v-273h-594z" />
+<glyph unicode="." horiz-adv-x="528" d="M31 213q0 86 63.5 159.5t168 73.5t170 -73.5t65.5 -159.5q0 -96 -62.5 -158.5t-173.5 -62.5q-98 0 -164.5 67.5t-66.5 153.5z" />
+<glyph unicode="/" horiz-adv-x="1073" d="M10 -160l762 1700h291l-762 -1704z" />
+<glyph unicode="0" horiz-adv-x="1226" d="M31 723q0 326 160.5 530.5t416.5 204.5q293 0 440.5 -199.5t147.5 -549.5q0 -344 -150.5 -539t-427.5 -195q-266 0 -426.5 190.5t-160.5 557.5zM436 723q0 -186 57.5 -308t124.5 -122q72 0 119 115.5t47 300.5q0 182 -51 300.5t-127 118.5q-61 2 -115.5 -113.5 t-54.5 -291.5z" />
+<glyph unicode="1" horiz-adv-x="1015" d="M51 1163l42 21l44 21l39 21q29 15 43 26l41 31q27 19 47 40l48 48q28 28 55 61h364v-1160h191v-272h-820v272h205v760l-205 -96z" />
+<glyph unicode="2" horiz-adv-x="1208" d="M51 0v297q82 135 140.5 201.5t158.5 146.5q47 43 150.5 111.5t158 121t54.5 109.5q0 135 -172 135q-51 0 -103.5 -29.5t-77 -53t-71.5 -72.5l-221 233q219 254 532 254q209 0 348 -123t139 -325q0 -164 -70.5 -251t-256.5 -208q-86 -55 -180.5 -136t-126.5 -139h360v164 h344v-436h-1106z" />
+<glyph unicode="3" horiz-adv-x="1105" d="M31 205l209 217q133 -133 270 -133q86 0 135 41t49 116q0 150 -170 150h-153v244h149q76 0 125 36.5t49 104.5q0 78 -54 120t-126 42q-123 0 -240 -123l-198 240q66 72 188.5 133t249.5 61q248 0 385 -117.5t137 -316.5q0 -143 -151 -260q190 -137 190 -336 q0 -213 -170 -332t-397 -119q-141 0 -278.5 70t-198.5 162z" />
+<glyph unicode="4" horiz-adv-x="1196" d="M20 403v293l590 736h424v-807h109v-222h-109v-133h111v-270h-664v270h129v133h-590zM307 625h303v379z" />
+<glyph unicode="5" horiz-adv-x="1181" d="M31 221l223 232q147 -152 287 -152q102 0 163.5 57.5t61.5 147.5q0 82 -60.5 140.5t-148.5 58.5q-102 0 -192 -95l-263 117l125 705h811v-306h-551l-34 -198q76 49 221 49q193 0 335 -130t142 -355q0 -125 -53.5 -225.5t-141.5 -163t-195.5 -96.5t-221.5 -34 q-150 0 -296 75t-212 173z" />
+<glyph unicode="6" horiz-adv-x="1189" d="M33 623q-2 96 8 191t47 213t99.5 207t178 152.5t269.5 67.5q109 4 253 -42t230 -120l-139 -266q-178 104 -299 104q-111 -2 -181.5 -80.5t-86.5 -197.5q41 41 115.5 71.5t152.5 32.5q201 8 340 -121.5t139 -334.5q0 -213 -143.5 -361.5t-386.5 -156.5q-256 -8 -422 165 t-174 476zM416 545q0 -88 50 -165t140 -77q78 0 133.5 51.5t53.5 124.5q-2 72 -42 128.5t-124 54.5q-121 -6 -211 -117z" />
+<glyph unicode="7" horiz-adv-x="1159" d="M31 1026v406h1108v-273l-551 -1159h-443l549 1159h-336v-133h-327z" />
+<glyph unicode="8" horiz-adv-x="1144" d="M31 420q0 102 61.5 206.5t159.5 153.5q-74 45 -114 120t-40 153q0 176 131 289.5t357 113.5q231 0 360 -113.5t129 -289.5q0 -96 -49 -170t-123 -109q100 -49 155.5 -147.5t55.5 -206.5q0 -193 -148.5 -320t-392.5 -127q-250 0 -396 126t-146 321zM385 432 q0 -72 56.5 -120t133.5 -48q80 0 133.5 44t55.5 124q0 94 -81 136t-179 46q-49 -29 -84 -79t-35 -103zM434 1069q0 -51 39 -84t79 -41t85 -10q98 47 98 135q0 55 -46 92t-107 37q-59 0 -103.5 -39t-44.5 -90z" />
+<glyph unicode="9" horiz-adv-x="1202" d="M31 936q0 213 143 361.5t387 156.5q258 8 429 -166t179 -475q2 -106 -8 -205.5t-50 -215.5t-104.5 -202t-181 -145t-270.5 -63q-109 -4 -253 42t-230 119l139 267q178 -104 299 -105q117 4 184.5 76t65.5 203q-98 -98 -250 -105q-201 -8 -340 122t-139 335zM397 956 q2 -72 42 -128t124 -54q102 4 193 117q0 94 -42 168t-130 74q-78 0 -133.5 -51.5t-53.5 -125.5z" />
+<glyph unicode=":" horiz-adv-x="520" d="M31 201q0 86 62.5 157.5t164.5 71.5q104 0 167.5 -72.5t63.5 -156.5q0 -92 -64.5 -154.5t-166.5 -62.5q-96 0 -161.5 66.5t-65.5 150.5zM31 823q0 86 62.5 158t164.5 72q104 0 167.5 -73t63.5 -157q0 -94 -62 -155.5t-169 -61.5q-92 0 -159.5 67.5t-67.5 149.5z" />
+<glyph unicode=";" horiz-adv-x="618" d="M10 -264l236 -133q162 143 250 324.5t82 375.5l-373 98q14 -221 -33 -370.5t-162 -294.5zM121 788q0 86 63.5 160t168 74t170 -74t65.5 -160q0 -94 -63.5 -157.5t-172.5 -63.5q-94 0 -162.5 68.5t-68.5 152.5z" />
+<glyph unicode="<" horiz-adv-x="1124" d="M72 694v256l880 363l101 -250l-627 -240l627 -241l-101 -250z" />
+<glyph unicode="=" horiz-adv-x="946" d="M51 352v273h844v-273h-844zM51 805v272h844v-272h-844z" />
+<glyph unicode=">" horiz-adv-x="1124" d="M72 584l626 239l-626 242l100 250l881 -363v-256l-881 -362z" />
+<glyph unicode="?" horiz-adv-x="1064" d="M4 1200q227 264 533 264q213 0 350 -109.5t137 -310.5q0 -74 -34 -136t-82 -104t-95 -77t-81 -69.5t-34 -67.5v-113h-379l-2 164q0 63 51.5 126.5t112 105.5t111.5 90.5t51 85.5q0 96 -151 96q-61 0 -134 -49t-133 -119zM264 209q0 84 64.5 150.5t169.5 66.5 q106 0 174.5 -63.5t68.5 -153.5q0 -88 -67.5 -149.5t-175.5 -61.5q-98 0 -166 64.5t-68 146.5z" />
+<glyph unicode="@" horiz-adv-x="1595" d="M10 465q0 106 28 218t89 221.5t148 195.5t217.5 139t283.5 53q369 0 589 -207.5t220 -521.5q0 -57 -10 -116.5t-37 -126t-66.5 -116.5t-108.5 -83t-155 -33q-129 16 -184 68q-135 -98 -270 -99q-143 0 -257 119t-114 299q0 100 45 199.5t143.5 174.5t225.5 75 q113 0 200 -107l13 82l202 -27l-82 -583q2 0 3 -2q41 -25 75 -25q109 0 158 96.5t49 204.5q0 238 -174 396.5t-465 158.5q-147 0 -266 -63.5t-187.5 -163.5t-104.5 -210t-36 -216q0 -254 183.5 -433t449.5 -179q270 0 455 133l20 16l99 -141q-8 -8 -24.5 -19.5t-72 -43 t-118 -55.5t-159.5 -43t-200 -19q-326 0 -565.5 221t-239.5 563zM608 475q0 -92 44 -152.5t102 -60.5q88 0 172 49l39 267q-68 141 -168 141q-86 0 -137.5 -78t-51.5 -166z" />
+<glyph unicode="A" horiz-adv-x="1685" d="M31 0v268h139l276 899h-84v265h787l362 -1164h144v-268h-821v268h194l-43 140h-420l-43 -140h160v-268h-651zM641 653h268l-135 443z" />
+<glyph unicode="B" horiz-adv-x="1406" d="M51 0v266h119v901h-119v265h764q502 0 502 -351q0 -131 -44 -201.5t-157 -115.5q121 -33 195.5 -120t74.5 -228q0 -217 -131 -316.5t-426 -99.5h-778zM594 266h164q68 0 117 48t49 128t-45 130.5t-127 50.5h-158v-357zM594 854h125q78 0 108.5 40t30.5 118 q0 70 -38 109.5t-97 39.5h-129v-307z" />
+<glyph unicode="C" horiz-adv-x="1404" d="M31 702q0 168 59.5 314.5t151.5 240t200.5 146.5t210.5 53q211 0 316 -139l47 115h321v-582h-366q-4 109 -59.5 183.5t-157.5 74.5q-109 0 -176.5 -117t-67.5 -289q0 -162 80 -273.5t219 -111.5q31 0 62.5 8.5t58 20.5t53.5 29.5t46.5 34t40 36t30.5 31.5l22 27l13 14 l239 -262q-262 -289 -620 -289q-328 0 -525.5 197.5t-197.5 537.5z" />
+<glyph unicode="D" horiz-adv-x="1474" d="M51 0v272h127v889h-127v271h625q362 0 570 -197t208 -500q0 -350 -205 -542.5t-581 -192.5h-617zM598 272h78q156 2 231.5 130t75.5 333q0 180 -77 303t-230 123h-78v-889z" />
+<glyph unicode="E" horiz-adv-x="1337" d="M51 0v272h129v889h-129v271h1235v-453h-354v182h-328v-282h389v-273h-389v-334h328v191h354v-463h-1235z" />
+<glyph unicode="F" horiz-adv-x="1306" d="M51 0v272h127v889h-127v271h1225v-453h-363v182h-309v-356h389v-273h-389v-260h209v-272h-762z" />
+<glyph unicode="G" horiz-adv-x="1589" d="M31 702q0 324 189.5 539t438.5 215q70 0 130.5 -11t98.5 -25.5t70.5 -37t48 -38t32 -36t20.5 -24.5l43 148h305v-605h-367q-4 121 -71.5 190.5t-161.5 69.5q-121 0 -201 -113.5t-80 -271.5q0 -162 76 -269t205 -107q139 0 197 100v86h-125v219h680v-219h-82v-512h-410 l-63 129q-37 -61 -127.5 -104t-202.5 -43q-274 0 -458.5 197t-184.5 523z" />
+<glyph unicode="H" horiz-adv-x="1572" d="M51 0v270h113v891h-113v271h664v-271h-127v-309h389v309h-121v271h666v-271h-119v-891h119v-270h-666v270h121v310h-389v-310h127v-270h-664z" />
+<glyph unicode="I" horiz-adv-x="782" d="M51 0v272h129v889h-129v271h680v-271h-127v-889h127v-272h-680z" />
+<glyph unicode="J" horiz-adv-x="948" d="M41 -125q41 -18 92 -18q170 0 170 295v1011h-176v269h770v-269h-170v-1011q0 -283 -135 -426.5t-442 -143.5q-51 0 -107 23z" />
+<glyph unicode="K" horiz-adv-x="1669" d="M51 0v266h111v901h-111v265h645v-265h-110v-333l381 333h-148v265h682v-265h-119l-297 -256l414 -645h119v-266h-799v266h139l-221 348l-151 -129v-219h110v-266h-645z" />
+<glyph unicode="L" horiz-adv-x="1249" d="M51 0v272h113v889h-113v271h647v-271h-108v-889h264v260h344v-532h-1147z" />
+<glyph unicode="M" horiz-adv-x="2064" d="M51 0v264h111v903h-109v265h776l207 -766l197 766h780v-265h-112v-901h112v-266h-647v266h117l-2 684v121h-8q-35 -190 -60 -274l-215 -797h-428l-229 817q-35 119 -43 254h-9v-807h117v-264h-555z" />
+<glyph unicode="N" horiz-adv-x="1671" d="M51 0v264h121v903h-119v265h588l504 -752l-2 487h-139v265h616v-265h-135v-1167h-441l-522 780v-516h158v-264h-629z" />
+<glyph unicode="O" horiz-adv-x="1515" d="M31 723q0 332 200.5 539.5t518.5 207.5q367 0 551 -202.5t184 -558.5q0 -350 -188.5 -548t-532.5 -198q-334 0 -533.5 193.5t-199.5 566.5zM537 723q0 -199 63.5 -318.5t163.5 -119.5q96 0 152.5 115.5t56.5 308.5q0 199 -56.5 322.5t-168.5 123.5h-4q-92 0 -149 -120 q-58 -122 -58 -312z" />
+<glyph unicode="P" horiz-adv-x="1310" d="M51 0v270h115v893h-115v269h664q172 0 287.5 -34t174 -99.5t81 -137t22.5 -168.5q0 -195 -153.5 -300t-385.5 -105h-155v-318h125v-270h-660zM586 809h92q90 0 145.5 45t55.5 125q0 90 -50.5 138t-140.5 48h-102v-356z" />
+<glyph unicode="Q" horiz-adv-x="1546" d="M31 725q0 315 190.5 514t497.5 199q350 0 525 -193.5t175 -533.5q0 -326 -170 -512q35 -133 90 -133q41 0 41 92v59h136v-104q0 -143 -80 -235.5t-228 -92.5q-119 0 -199.5 64.5t-117.5 162.5q-74 -12 -160 -12q-319 0 -509.5 186.5t-190.5 538.5zM481 725q0 -66 8 -113 q94 98 242 99q119 0 230 -80q4 49 4 80q0 182 -69 305t-179 123h-3q-92 0 -162 -118q-71 -120 -71 -296zM594 375q61 -68 137 -68q57 0 109 45q-12 86 -36 129t-73 43q-84 1 -137 -149z" />
+<glyph unicode="R" horiz-adv-x="1509" d="M51 0v270h115v893h-115v269h666q172 0 287.5 -32t175 -93.5t82 -131t22.5 -165.5q0 -117 -83 -198t-214 -99q109 -16 188.5 -99.5t79.5 -191.5q0 -139 50 -139q47 0 47 65v68h137v-113q0 -143 -70.5 -235.5t-228.5 -92.5q-199 0 -298 99.5t-99 281.5q0 143 -36 187.5 t-169 44.5v-318h125v-270h-662zM588 817h92q90 0 143.5 43t53.5 123q0 182 -187 182h-102v-348z" />
+<glyph unicode="S" horiz-adv-x="1454" d="M51 0v516h381q0 -61 26.5 -103t71.5 -62.5t82 -29t78 -10.5q174 0 174 103q0 37 -58 65.5t-145.5 48t-189.5 57.5t-189 87t-145.5 141t-58.5 215q0 109 47 196t122 139t156.5 78.5t161.5 26.5q317 0 428 -208l21 172h352v-514h-371q0 111 -74.5 174t-187.5 63 q-51 0 -96 -29.5t-45 -78.5q0 -57 84 -100.5t202.5 -81.5t237.5 -87t203 -145t84 -230q0 -115 -49 -201.5t-131 -136t-174.5 -73t-188.5 -23.5q-268 0 -428 189l-22 -158h-359z" />
+<glyph unicode="T" horiz-adv-x="1435" d="M31 899v533h1374v-533h-301v262h-172v-889h170v-272h-762v272h168v889h-176v-262h-301z" />
+<glyph unicode="U" horiz-adv-x="1509" d="M31 1165v267h651v-265h-111v-442q0 -233 49.5 -316t155.5 -83q70 0 111 25.5t68.5 116.5t27.5 259v434h-111v271h607v-265h-111v-497q0 -705 -588 -705q-635 18 -635 694v506h-114z" />
+<glyph unicode="V" horiz-adv-x="1583" d="M-20 1165v267h755l-2 -267h-110l174 -458q59 -180 63 -248h10q6 92 74 260l186 446h-106l-2 267h582v-267h-101l-491 -1165h-377l-543 1165h-112z" />
+<glyph unicode="W" horiz-adv-x="2078" d="M-20 1165v267h675v-267h-118l53 -299q29 -123 65 -403h11q4 47 100 508l102 461h426l129 -566q39 -182 62 -403h10q16 178 61 391l70 311h-113v267h586v-267h-112l-306 -1165h-485l-123 487q-27 98 -51 254h-8q-14 -102 -49 -249l-125 -492h-475l-271 1165h-114z" />
+<glyph unicode="X" horiz-adv-x="1710" d="M51 0v264h178l301 391l-370 510h-107v267h811v-267h-119l201 -272l209 272h-180v267h680v-267h-174l-310 -395l369 -504h119v-266h-817v266h116l-155 209l-43 57l-211 -268h182v-264h-680z" />
+<glyph unicode="Y" horiz-adv-x="1370" d="M-20 1169v263h700v-263h-107l119 -217q6 -16 33 -81.5t31 -84.5h8q4 18 76 177l112 206h-112v263h551v-263h-111l-379 -665v-238h115v-266h-656v266h117v242l-397 661h-100z" />
+<glyph unicode="Z" horiz-adv-x="1462" d="M51 0v266l746 895l-387 -2l2 -266h-349v539h1344l4 -273l-749 -889h378l2 262h363v-532h-1354z" />
+<glyph unicode="[" horiz-adv-x="1474" d="M59 0v270h115v893h-115v271h664q170 0 286.5 -39t175 -108.5t81 -145.5t22.5 -174q0 -215 -221 -338l229 -363h119v-266h-393l-340 549h-88v-279h125v-270h-660zM594 809h92q90 0 145.5 45t55.5 125q0 90 -50.5 138t-140.5 48h-102v-356z" />
+<glyph unicode="\" horiz-adv-x="1073" d="M10 1540h291l762 -1700l-291 -4z" />
+<glyph unicode="]" horiz-adv-x="1325" d="M61 0v266h84v1002h-84v268h474v-926l237 142h-147v272h573v-272h-158l-129 -76l285 -408h84v-268h-332l-344 489l-72 -49v-172h146v-268h-617z" />
+<glyph unicode="^" horiz-adv-x="1222" d="M20 621l445 813h297l440 -813h-364l-224 458l-229 -458h-365z" />
+<glyph unicode="_" horiz-adv-x="1431" d="M51 -2v170h1329v-170h-1329z" />
+<glyph unicode="a" horiz-adv-x="1228" d="M31 303q0 170 124 273.5t302 103.5q55 0 103 -16.5t69.5 -31t29.5 -24.5v72q0 115 -194 115q-135 0 -305 -95l-86 238q242 145 446 145q100 0 191.5 -20.5t176.5 -65.5t136 -132t51 -203v-400h123v-262h-438l-49 92q-51 -70 -129 -100.5t-148 -30.5q-162 0 -282.5 88 t-120.5 254zM420 324q0 -43 30.5 -70t77.5 -27q43 0 79 20.5t52 47.5v78q-35 59 -120 59q-119 1 -119 -108z" />
+<glyph unicode="b" horiz-adv-x="1343" d="M63 0v266h87v1002h-87v268h496v-592q33 39 113 67.5t155 28.5q223 0 350 -158q122 -154 122 -364q0 -7 -1 -14q-4 -240 -131 -383.5t-342 -143.5q-74 0 -128 14.5t-80.5 31t-61.5 47.5l-31 -70h-461zM555 489q0 -102 44 -173.5t103 -71.5q66 0 106 69.5t40 186.5 q0 98 -41 175t-107 77q-63 0 -107 -73q-39 -64 -39 -162q0 -14 1 -28z" />
+<glyph unicode="c" horiz-adv-x="1087" d="M2 518q0 256 145.5 390t358.5 134q158 0 256 -116l35 98h241v-463h-301q-4 88 -34.5 151.5t-94.5 63.5q-86 0 -133 -76.5t-47 -185.5q0 -102 57.5 -171t153.5 -71h5q136 0 243 117l180 -209q-80 -88 -213 -148.5t-289 -60.5q-240 0 -401.5 143.5t-161.5 403.5z" />
+<glyph unicode="d" horiz-adv-x="1298" d="M20 522q0 231 139.5 376.5t336.5 145.5q135 0 258 -77v303h-95v266h510v-1270h99v-266h-480l-34 76q-102 -94 -258 -94q-211 0 -343.5 159.5t-132.5 380.5zM461 522q0 -98 41 -175t106 -77q63 0 108 73q39 64 38 162v27q0 102 -44 174t-104 72q-66 0 -105.5 -69.5 t-39.5 -186.5z" />
+<glyph unicode="e" horiz-adv-x="1110" d="M10 518q0 246 156 390.5t395 144.5q180 0 312.5 -83t177.5 -214q23 -66 27 -156q1 -14 1 -27q0 -78 -24 -163h-645q6 -31 14 -51.5t29.5 -52.5t64.5 -48t103 -16q168 0 286 98l172 -199q-207 -178 -528 -178q-215 0 -378 141.5t-163 413.5zM416 612h309q-2 74 -32.5 119 t-119.5 45q-82 0 -117.5 -53.5t-39.5 -110.5z" />
+<glyph unicode="f" horiz-adv-x="790" d="M51 758v266h84v174q0 43 6 84t31 97.5t66 96.5t119.5 68.5t183.5 28.5q80 0 170 -15.5t131 -35.5l-123 -236q-45 20 -113 21q-66 0 -65 -109v-174h186v-266h-186v-490h123v-268h-611v268h82v490h-84z" />
+<glyph unicode="g" horiz-adv-x="1310" d="M20 518q0 244 133.5 385t381.5 141q63 0 123.5 -25.5t93.5 -57.5l41 63h487v-268h-123v-613q0 -262 -161.5 -411.5t-477.5 -151.5q-152 2 -272.5 56.5t-196.5 123.5l109 228q49 -43 151.5 -87t204.5 -44q125 0 181.5 57t56.5 135v70q-88 -113 -240 -113 q-246 0 -369 148.5t-123 363.5zM457 522q0 -98 41 -175t106 -77q63 0 108 73q39 64 38 162v27q0 102 -44 174t-104 72q-66 0 -105.5 -69.5t-39.5 -186.5z" />
+<glyph unicode="h" horiz-adv-x="1353" d="M51 0v268h86v1002h-86v266h496v-639q25 41 124 102.5t197 61.5q113 0 189 -38t110.5 -108.5t47 -140t12.5 -164.5v-342h96v-268h-526v557q0 39 -2 61.5t-12.5 57.5t-37 53.5t-69.5 18.5q-129 0 -129 -191v-289h147v-268h-643z" />
+<glyph unicode="i" horiz-adv-x="675" d="M51 0v268h86v490h-86v266h475v-756h99v-268h-574zM109 1323q0 78 60 143.5t160.5 65.5t163 -65.5t62.5 -143.5q0 -88 -60.5 -147.5t-164.5 -59.5q-92 0 -156.5 64.5t-64.5 142.5z" />
+<glyph unicode="j" horiz-adv-x="737" d="M29 -154q68 0 114.5 24t69.5 51.5t35 77.5t13 74.5t1 69.5v615h-86v266h475v-881q0 -86 -12 -157.5t-51 -151.5t-104.5 -135t-181.5 -91t-273 -36v274zM233 1323q0 78 60.5 143.5t161 65.5t163 -65.5t62.5 -143.5q0 -88 -60.5 -147.5t-164.5 -59.5q-92 0 -157 64.5 t-65 142.5z" />
+<glyph unicode="k" horiz-adv-x="1339" d="M78 0v266h84v1002h-84v268h473v-926l237 142h-147v270h573v-270h-157l-139 -88l276 -396h102v-268h-606v268h86l-155 221l-72 -49v-172h76v-268h-547z" />
+<glyph unicode="l" horiz-adv-x="679" d="M51 0v268h88v1004h-86v264h475v-1268h121v-268h-598z" />
+<glyph unicode="m" horiz-adv-x="1859" d="M51 0v268h86v484h-86v270h387l45 -121q125 150 256 150q72 0 128.5 -14.5t92 -42t51 -46t33.5 -45.5q131 147 302 148q119 0 198.5 -40t117.5 -115t52.5 -152.5t14.5 -184.5v-283h100v-276h-520v502q0 12 1 44t1 50t-2 46t-7.5 45.5t-13.5 34.5t-22.5 25.5t-34.5 8.5 q-61 0 -85 -38t-24 -112v-332h123v-274h-530v522q0 137 -14.5 185.5t-71.5 48.5q-92 0 -92 -123v-365h122v-268h-608z" />
+<glyph unicode="n" horiz-adv-x="1325" d="M51 0v268h86v490h-86v266h436l48 -127q119 164 292 164q92 0 161 -26.5t108 -68.5t62.5 -104.5t31.5 -121t8 -130.5v-342h96v-268h-516v559v48q0 11 -5 47t-16.5 50.5t-35 30t-57.5 15.5q-129 0 -129 -191v-291h147v-268h-631z" />
+<glyph unicode="o" horiz-adv-x="1175" d="M191 904q167 144 393 145q250 -4 407.5 -147.5t161.5 -393.5v-6q0 -243 -158 -385q-160 -143 -401 -144q-238 0 -406 143q-166 141 -165 394q-1 248 168 394zM442 514q0 -125 43 -201.5t109 -76.5q63 0 101 76.5t38 195.5t-40 195.5t-109 78.5q-59 0 -100.5 -77.5 t-41.5 -190.5z" />
+<glyph unicode="p" horiz-adv-x="1306" d="M51 -150h86v902h-86v272h469l35 -72q119 88 248 88q229 0 356 -153.5t127 -382.5q0 -240 -132 -383.5t-335 -143.5q-172 0 -266 80v-207h111v-268h-613v268zM553 489q0 -102 44 -173.5t103 -71.5q66 0 106 69.5t40 186.5q0 98 -41 175t-107 77q-63 0 -107 -73 q-39 -64 -39 -162q0 -14 1 -28z" />
+<glyph unicode="q" horiz-adv-x="1351" d="M51 518q0 256 137.5 391t352.5 135q88 0 155.5 -27.5t87.5 -53.5l39 61h477v-266h-100v-955h100v-274h-649v268h133v271q-104 -86 -262 -86q-201 0 -336 147t-135 389zM492 516q0 -102 44 -174t103 -72q66 0 105.5 70t39.5 186q0 98 -41 175t-106 77q-63 0 -108 -72 q-39 -64 -38 -162q0 -14 1 -28z" />
+<glyph unicode="r" horiz-adv-x="847" d="M51 0v268h90v490h-88v266h385l62 -131q25 45 44 70.5t54 55.5t89 43t130 13v-368q-147 0 -218 -49.5t-71 -178.5v-211h103v-268h-580z" />
+<glyph unicode="s" horiz-adv-x="1040" d="M31 0v369h274q0 -49 44 -83t89 -44.5t84 -10.5q90 0 90 70q0 18 -16 31.5t-48 24t-66 19.5l-84 22q-50 13 -87 26q-272 96 -272 328q0 143 115.5 220t244.5 77q102 0 187.5 -46.5t118.5 -113.5l16 135h252v-369h-266q0 63 -64.5 109.5t-144.5 46.5t-80 -74 q0 -16 12 -29.5t41 -26.5t51.5 -21.5t72.5 -24.5l75 -25q80 -27 120.5 -45t98 -56t84 -94.5t26.5 -131.5q0 -139 -112.5 -223.5t-268.5 -84.5q-104 0 -189 43t-124 107l-18 -125h-256z" />
+<glyph unicode="t" horiz-adv-x="743" d="M31 758v266h110v188l377 121v-309h195v-266h-195v-365q0 -8 -1 -29.5t0 -34t2 -29.5t5 -27.5t11.5 -21.5t19.5 -16.5t29 -5.5q47 0 129 35v-262q-41 -16 -122 -27.5t-126 -11.5q-90 0 -150.5 21.5t-94.5 52.5t-51 94.5t-21.5 114.5t-6.5 147v365h-110z" />
+<glyph unicode="u" horiz-adv-x="1292" d="M31 754v270h495v-494q0 -135 24.5 -196.5t86.5 -61.5q55 0 92 44t37 112v326h-135v270h530v-752h101v-272h-388l-55 129l-20 -23q-20 -25 -28 -31l-30 -29q-23 -22 -41 -30t-44.5 -21t-58.5 -18.5t-69 -5.5q-227 0 -319 119t-92 381v283h-86z" />
+<glyph unicode="v" horiz-adv-x="1255" d="M0 764v260h623v-260h-103l94 -217q45 -133 54 -215h8q4 94 61 225l99 207h-109v260h528v-260h-106l-354 -764h-318l-381 764h-96z" />
+<glyph unicode="w" horiz-adv-x="1785" d="M0 758v266h551v-266h-70l45 -150q41 -139 52 -295h4q20 268 84 482l65 229h379l78 -266q59 -188 88 -445h4q18 193 55 324l35 121h-84v266h500v-266h-84l-240 -758h-432l-141 463l-148 -463h-422l-231 758h-88z" />
+<glyph unicode="x" horiz-adv-x="1329" d="M41 0v254h137l209 235l-254 279h-92v256h664v-256h-97l144 -156l153 156h-137v256h522v-256h-135l-217 -219l258 -295h96v-254h-653v254h96l-155 166l-148 -166h133v-254h-524z" />
+<glyph unicode="y" horiz-adv-x="1187" d="M-18 762v262h630v-260h-96l133 -320l133 320h-94v260h520v-254h-98l-389 -946q-23 -49 -40 -80t-54 -76t-80 -70.5t-111.5 -44t-154.5 -18.5q-139 8 -248 103l153 241q68 -59 119 -69q9 -2 18 -2q34 0 62 26q35 33 51 84l29 86l-399 758h-84z" />
+<glyph unicode="z" horiz-adv-x="1132" d="M51 0v268l494 492h-228v-146h-266v410h1014v-264l-487 -492h215v140h288v-408h-1030z" />
+<glyph unicode="|" horiz-adv-x="681" d="M205 -418v1854h272v-1854h-272z" />
+<glyph unicode="­" d="M51 352v273h594v-273h-594z" />
+<glyph unicode=" " horiz-adv-x="833" />
+<glyph unicode=" " horiz-adv-x="1669" />
+<glyph unicode=" " horiz-adv-x="833" />
+<glyph unicode=" " horiz-adv-x="1669" />
+<glyph unicode=" " horiz-adv-x="555" />
+<glyph unicode=" " horiz-adv-x="415" />
+<glyph unicode=" " horiz-adv-x="276" />
+<glyph unicode=" " horiz-adv-x="276" />
+<glyph unicode=" " horiz-adv-x="206" />
+<glyph unicode=" " horiz-adv-x="333" />
+<glyph unicode=" " horiz-adv-x="92" />
+<glyph unicode="‐" d="M51 352v273h594v-273h-594z" />
+<glyph unicode="‑" d="M51 352v273h594v-273h-594z" />
+<glyph unicode="‒" d="M51 352v273h594v-273h-594z" />
+<glyph unicode="–" horiz-adv-x="915" d="M66 352v273h772v-273h-772z" />
+<glyph unicode="—" horiz-adv-x="1292" d="M86 352v273h1104v-273h-1104z" />
+<glyph unicode="’" horiz-adv-x="559" d="M74 1436h405l-73 -613h-256z" />
+<glyph unicode="“" horiz-adv-x="1032" d="M72 1436h393l-62 -613h-256zM567 1436h394l-74 -613h-256z" />
+<glyph unicode="”" horiz-adv-x="1032" d="M72 1436h393l-62 -613h-256zM567 1436h394l-74 -613h-256z" />
+<glyph unicode="…" horiz-adv-x="1585" d="M1088 213q0 86 63.5 159.5t168 73.5t170 -73.5t65.5 -159.5q0 -96 -62.5 -158.5t-173.5 -62.5q-98 0 -164.5 67.5t-66.5 153.5zM559 213q0 86 63.5 159.5t168 73.5t170 -73.5t65.5 -159.5q0 -96 -62.5 -158.5t-173.5 -62.5q-98 0 -164.5 67.5t-66.5 153.5zM31 213 q0 86 63.5 159.5t168 73.5t170 -73.5t65.5 -159.5q0 -96 -62.5 -158.5t-173.5 -62.5q-98 0 -164.5 67.5t-66.5 153.5z" />
+<glyph unicode=" " horiz-adv-x="333" />
+<glyph unicode=" " horiz-adv-x="415" />
+<glyph unicode="" horiz-adv-x="1025" d="M0 1025h1025v-1025h-1025v1025z" />
+</font>
+</defs></svg>
\ No newline at end of file
--- /dev/null
+body {\r
+ font-size:75%;\r
+}\r
+\r
+h1, h2, h3 {\r
+ font:normal 3em "Helvetica Neue",helvetica,georgia,"times new roman","Arial Rounded MT Bold",verdana,tahoma,arial,"sans serif";\r
+ font-weight:normal;\r
+ margin-bottom:0px;\r
+}\r
+\r
+h1, h2 {\r
+ letter-spacing:-1px; /* zomg web x.0! ;) */ \r
+}\r
+\r
+h1, h2, h3 {\r
+ padding-bottom:1px;\r
+ margin-bottom:0.25em;\r
+}\r
+\r
+h1 {\r
+ margin-top:0px;\r
+ margin-bottom:0px;\r
+ background-color:#666;\r
+ color:#ccc;\r
+ margin-left:-5px;\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+ padding-bottom:5px;\r
+}\r
+\r
+h1,\r
+h1 a {\r
+ color:#fff;\r
+ text-decoration:none;\r
+}\r
+\r
+h1 a:hover {\r
+ text-decoration:underline;\r
+}\r
+\r
+h2 {\r
+ font-size:2em;\r
+ margin-top:1em;\r
+ background-color:#aaa;\r
+ color:#fff;\r
+ padding:5px;\r
+ margin-left:-5px;\r
+ min-width:23em;\r
+}\r
+\r
+h3 {\r
+ font-size:1.65em;\r
+ margin-top:0.5em;\r
+ margin-bottom:0.25em;\r
+ color:#333;\r
+ min-width:28em;\r
+}\r
+\r
+h3 a {\r
+ font-size:small;\r
+}\r
+\r
+h4 {\r
+ color:#444;\r
+}\r
+p {\r
+ font:normal 1em/2em verdana,tahoma,arial,"sans serif";\r
+}\r
+\r
+.balls img {\r
+ position:absolute;\r
+ width:12px;\r
+ height:12px;\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<link rel="stylesheet" href="../template/template.css" media="screen" />\r
+<link rel="stylesheet" href="css/animation.css" media="screen" />\r
+<script type="text/javascript" src="../../script/soundmanager2-nodebug-jsmin.js"></script>\r
+<script type="text/javascript" src="script/animation.js"></script>\r
+</head>\r
+<body>\r
+\r
+<div style="margin-right:43em">\r
+ \r
+<h1>Interval-based animation (with sound)</h1>\r
+\r
+<p>\r
+ Click + drag for fun.\r
+</p>\r
+\r
+<h2>Speeding Up ExternalInterface: Keep .swf in view</h2>\r
+\r
+<p>SoundManager 2 now incorporates a "high performance" mode, which has been shown to noticeably improve timing and frequency of flash callbacks. This is important for timing, reducing delay between a JS call and the sound being played, etc.</p>\r
+\r
+<p>To reduce audio delay and timing issues from slow JS/Flash communication, SM2 will try to ensure that the flash movie is visible on screen at all times. If hidden or otherwise off-screen, Flash will be given lower priority and thus JS/flash "lag" (ie., delay) will be introduced when trying to play audio "in sync."</p>\r
+\r
+<p>Generally, positioning the flash movie using position:fixed and bottom/left or bottom/right 0px is the less-intrusive option.</p>\r
+\r
+<p style="margin:0px;padding:0px">\r
+ <input id="useMouse" name="usemouse" value="usemouse" type="checkbox"> Throw from mouse\r
+</p>\r
+<p style="margin:0px;padding:0px">\r
+ <button id="b-start" onclick="startAnimation()" disabled="disabled">Start</button>\r
+ <button id="b-stop" onclick="stopAnimation()" disabled="disabled">Stop</button>\r
+</p>\r
+\r
+\r
+<p>Sound source: <a href="http://www.freesound.org/search/?q=19987">"Acclivity"</a>, freesound.org</p>\r
+\r
+</div>\r
+\r
+<div id="ball-container" class="balls">\r
+ <img src="image/ball.gif" alt="" />\r
+</div>\r
+\r
+</body>\r
+</html>
--- /dev/null
+var balls = [];\r
+var canvasX = 0;\r
+var canvasY = 0;\r
+var timer = null;\r
+var m_lastX = 0;\r
+var m_lastY = 0;\r
+var M_SPACE = 24;\r
+var B_VMIN = 5;\r
+var B_VMAX = 5;\r
+var B_WIDTH = 13;\r
+var B_HEIGHT = 13;\r
+var useMouse = null;\r
+var ballSound = null;\r
+var ballPopSound = null;\r
+\r
+function rnd(n) {\r
+ return Math.random()*n;\r
+}\r
+\r
+function rndI(n) {\r
+ return parseInt(rnd(n));\r
+}\r
+\r
+function createBall(oParent) {\r
+ oParent.appendChild(balls[0].cloneNode(true));\r
+ initBall(balls[balls.length-1],balls.length);\r
+}\r
+\r
+function createBallAtMouse(e) {\r
+ e = e?e:event;\r
+ createBall(document.getElementById('ball-container'));\r
+ with (balls[balls.length-1]) {\r
+ _x = e.clientX;\r
+ _y = e.clientY;\r
+ if (useMouse.checked != false) {\r
+ _vX = (m_lastX-e.clientX)*-0.7;\r
+ _vY = (m_lastY-e.clientY)*-0.7;\r
+ } else {\r
+ _vX = 0;\r
+ _vY = 0;\r
+ }\r
+ }\r
+ moveBall(balls[balls.length-1]);\r
+}\r
+\r
+function initBall(oBall,i) {\r
+ oBall._id = 'ball'+i;\r
+ oBall._active = true;\r
+ oBall._x = rnd(canvasX);\r
+ oBall._y = rnd(canvasY);\r
+ oBall._vX = B_VMIN+rnd(B_VMAX)*(Math.random()>0.5?1:-1);\r
+ oBall._vY = B_VMIN+rnd(B_VMAX);\r
+ oBall.style.display = 'block';\r
+}\r
+\r
+function moveBall(oBall) {\r
+ oBall._x += oBall._vX;\r
+ oBall._y += (oBall._vY++); // gravity!\r
+ var bounce = false;\r
+ if ((oBall._vX>0 && oBall._x+oBall._vX+B_WIDTH>canvasX) || (oBall._vX<0 && oBall._x+oBall._vX<0)) {\r
+ oBall._vX *= -1;\r
+ bounce = true;\r
+ }\r
+ if ((oBall._vY>0 && oBall._y+oBall._vY+B_HEIGHT>canvasY) || (oBall._vY<0 && oBall._y+oBall._vY<0)) {\r
+ // bounce on Y axis - with resistance on both axes\r
+ if (oBall._vY>0) oBall._y = canvasY-B_HEIGHT; // bounce exactly from bottom\r
+ oBall._vY *= -(oBall._vY>1?0.6:1);\r
+ bounce = true;\r
+ if (Math.abs(oBall._vX)>0.5) {\r
+ oBall._vX *= 0.85;\r
+ } else {\r
+ oBall._vX = 0;\r
+ }\r
+ if (Math.abs(oBall._vY)<=3 && Math.abs(oBall._vX==0)) {\r
+ oBall._active = false;\r
+ bounce = false;\r
+ ballPopSound.play();\r
+ oBall.style.display = 'none';\r
+ }\r
+ }\r
+ oBall.style.left = oBall._x+'px';\r
+ oBall.style.top = oBall._y+'px';\r
+ if (bounce) ballSound.play({pan:getPan(oBall._x,canvasX)});\r
+}\r
+\r
+function getPan(x,canvasX) {\r
+ var pos = x/canvasX;\r
+ var pan = null;\r
+ if (pos<=0.4) {\r
+ pan = Math.floor(-100+(pos/0.4*100));\r
+ } else if (pos>0.4 && pos<=0.5) {\r
+ pan = 0;\r
+ } else {\r
+ pan = Math.floor(pos*100);\r
+ }\r
+ return pan;\r
+}\r
+\r
+function animateStuff() {\r
+ for (var i=balls.length; i--;) {\r
+ if (balls[i]._active) moveBall(balls[i]);\r
+ }\r
+}\r
+\r
+function startAnimation() {\r
+ if (!timer) timer = setInterval(animateStuff,20);\r
+ document.getElementById('b-start').disabled = true;\r
+ document.getElementById('b-stop').disabled = false;\r
+}\r
+\r
+function stopAnimation() {\r
+ if (!timer) return false;\r
+ clearInterval(timer);\r
+ timer = null;\r
+ document.getElementById('b-start').disabled = false;\r
+ document.getElementById('b-stop').disabled = true;\r
+}\r
+\r
+function mouseDown(e) {\r
+ e = e?e:event;\r
+ m_lastX = e.clientX;\r
+ m_lastY = e.clientY;\r
+ document.onmousemove = mouseMove;\r
+ document.onmouseup = mouseUp;\r
+ return false;\r
+}\r
+\r
+function mouseMove(e) {\r
+ e = e?e:event;\r
+ if (Math.abs(e.clientX-m_lastX)>M_SPACE || Math.abs(e.clientY-m_lastY)>M_SPACE) {\r
+ createBallAtMouse(e);\r
+ m_lastX = e.clientX;\r
+ m_lastY = e.clientY;\r
+ }\r
+ return false;\r
+}\r
+\r
+function mouseUp() {\r
+ document.onmousemove = null;\r
+ document.onmouseup = null;\r
+}\r
+\r
+function init() {\r
+ ballSound = soundManager.createSound({\r
+ id: 'ballSound',\r
+ url: '../animation/audio/fingerplop.mp3',\r
+ volume: 50,\r
+ multiShot: true,\r
+ autoLoad: true\r
+ });\r
+ ballPopSound = soundManager.createSound({\r
+ id: 'ballPopSound',\r
+ url: '../animation/audio/fingerplop2.mp3',\r
+ volume: 50,\r
+ multiShot: true,\r
+ autoLoad: true\r
+ });\r
+ balls = document.getElementById('ball-container').getElementsByTagName('img');\r
+ for (var i=balls.length; i--;) {\r
+ initBall(balls[i],i);\r
+ }\r
+ useMouse = document.getElementById('useMouse');\r
+ useMouse.checked = true;\r
+ getWindowCoords();\r
+ startAnimation();\r
+ document.onmousedown = mouseDown;\r
+}\r
+\r
+// I know this is kinda broken in Opera.\r
+getWindowCoords = (navigator.userAgent.toLowerCase().indexOf('opera')>0||navigator.appVersion.toLowerCase().indexOf('safari')!=-1)?function() {\r
+ canvasX = window.innerWidth;\r
+ canvasY = window.innerHeight;\r
+}:function() {\r
+ canvasX = document.documentElement.clientWidth||document.body.clientWidth||document.body.scrollWidth;\r
+ canvasY = document.documentElement.clientHeight||document.body.clientHeight||document.body.scrollHeight;\r
+}\r
+\r
+window.onresize = getWindowCoords;\r
+\r
+soundManager.setup({\r
+ preferFlash: true,\r
+ flashVersion: 9,\r
+ url: '../../swf/',\r
+ useHighPerformance: true,\r
+ debugMode: false, // disable debug mode\r
+ onready: function() {\r
+ // soundManager is ready to use (create sounds and so on)\r
+ init();\r
+ }\r
+});\r
--- /dev/null
+<html>\r
+<head>\r
+<title>SoundManager Demo</title>
+<meta name="robots" content="noindex" />\r
+<style type="text/css">\r
+\r
+html, body {\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+body {\r
+ color:#fff;\r
+ font-size:75%;\r
+ text-shadow:0 0 0 #fff; /* Safari nonsense */\r
+ font-family:verdana,arial,tahoma,"sans serif";\r
+}\r
+\r
+h1, h2, h3 {\r
+ font:300 3em "Helvetica Neue",georgia,"times new roman","Arial Rounded MT Bold",helvetica,verdana,tahoma,arial,"sans serif";\r
+ font-weight:normal;\r
+ margin-bottom:0px;\r
+}\r
+\r
+\r
+h1 {\r
+ margin-top:0px;\r
+}\r
+\r
+h1, h2 {\r
+ letter-spacing:-1px; /* zomg web x.0! ;) */ \r
+}\r
+\r
+h2 {\r
+ font-size:2em;\r
+ margin-top:0px;\r
+ color:#fff;\r
+}\r
+\r
+h2 span {\r
+ text-indent:1em;\r
+ font-family:verdana,tahoma,arial;\r
+ font-size:small;\r
+}\r
+\r
+p {\r
+ position:absolute;\r
+ left:1em;\r
+ bottom:0px;\r
+ font-size:x-small;\r
+ opacity:0.5;\r
+}\r
+\r
+#instructions {\r
+ position:absolute;\r
+ left:1em;\r
+ top:0px;\r
+}\r
+\r
+#canvas {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:100%;\r
+ height:100%;\r
+ overflow:hidden;\r
+}\r
+\r
+#horizon {\r
+ position:relative;\r
+ height:50%;\r
+ background:transparent url(bg-sky.png) 0px 0px repeat-x;\r
+}\r
+\r
+#land {\r
+ position:absolute;\r
+ bottom:0px;\r
+ left:0px;\r
+ width:100%;\r
+ height:50%;\r
+ border-top:1px solid #339933;\r
+ margin-bottom:0px;\r
+ background:#669966 url(bg-land.png) 0px 0px repeat-x;\r
+}\r
+\r
+#content {\r
+ position:relative;\r
+ border-top:1px solid #ccc;\r
+}\r
+\r
+#cursor-shade {\r
+ position:absolute;\r
+ left:-100px;\r
+ top:-100px;\r
+ margin:0px 0px 0px -2px;\r
+ width:20px;\r
+ height:24px;\r
+ opacity:0.75;\r
+}\r
+\r
+#sun {\r
+ position:absolute;\r
+ top:50%;\r
+ width:100%;\r
+ height:128px;\r
+ margin-top:-66px;\r
+ background:transparent url(sun-test.png) 50% 0px no-repeat;\r
+ display:none;\r
+}\r
+\r
+.dot {\r
+ position:absolute;\r
+ width:32px;\r
+ height:32px;\r
+}\r
+\r
+#overlay {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:100%;\r
+ height:100%;\r
+ cursor:url(cursor-11.cur),default;\r
+}\r
+\r
+</style>\r
+<script type="text/javascript" src="../../script/soundmanager2-nodebug-jsmin.js"></script>\r
+<script type="text/javascript">\r
+\r
+function _id(sID) {return document.getElementById(sID);}\r
+\r
+function Cursor() {\r
+ var self = this;\r
+ this.o = null;\r
+ this.offX = 20;\r
+ this.offY = 40;\r
+ this.screenX = null;\r
+ this.screenY = null;\r
+ this.screenXHalf = null;\r
+ this.screenYHalf = null;\r
+ this.lastCursor = null;\r
+ this.cursorRange = 9;\r
+ this.oDots = _id('dots');\r
+\r
+ this.painting = 0;\r
+\r
+ this.sounds = [];\r
+ this.soundIndex = 0;\r
+ this.soundTimer = null;\r
+\r
+ this.oDot = document.createElement('img');\r
+ this.oDot.className = 'dot';\r
+ this.oDot.src = 'dot.png';\r
+\r
+ this.refreshCoords = function() {\r
+ self.screenX = (window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth);\r
+ self.screenY = (window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight);\r
+ self.screenXHalf = parseInt(self.screenX/2);\r
+ self.screenYHalf = parseInt(self.screenY/2);\r
+ }\r
+\r
+ this.mousedown = function(e) {\r
+ self.painting = true;\r
+ return false;\r
+ }\r
+\r
+ this.mouseup = function(e) {\r
+ self.painting = false;\r
+ return false;\r
+ }\r
+\r
+ this.mousemove = function(e) {\r
+ var evt = e?e:event;\r
+ var x = evt.clientX;\r
+ var y = evt.clientY;\r
+ var xHalf = self.screenXHalf;\r
+ var yHalf = self.screenYHalf;\r
+ var scaleX = (x>xHalf?(x-xHalf)/xHalf:-((xHalf-x)/xHalf));\r
+ var scaleY = (y>yHalf?(y-yHalf)/yHalf:0);\r
+ var xScale = (self.offX*scaleY)*scaleX;\r
+ var yScale = self.offY*scaleY;\r
+ var cursor = parseInt(self.cursorRange*scaleY);\r
+ if (cursor != self.lastCursor) {\r
+ var curString = 'cursor-'+(Math.min(11,cursor+3))+'.cur';\r
+ document.documentElement.style.cursor = 'url("'+curString+'"),default';\r
+ _id('overlay').style.cursor = 'url("'+curString+'"),default';\r
+ self.lastCursor = cursor;\r
+ }\r
+ var xDiff = (x+xScale);\r
+ self.o.style.left = (xDiff)+'px';\r
+ self.o.style.top = (y+yScale)+'px';\r
+ self.o.style.width = ((20*scaleY)+'px');\r
+ self.o.style.height = ((24*scaleY)+'px');\r
+ self.o.style.opacity = Math.max((scaleY-0.33),0.33);\r
+ if (self.painting && scaleY>0) self.paint(x,y,scaleX,scaleY);\r
+ return false;\r
+ }\r
+\r
+ this.paint = function(x,y,scaleX,scaleY) {\r
+ var oD = self.oDot.cloneNode(false);\r
+ var size = 32*scaleY;\r
+ oD.style.left = (x-size)+'px';\r
+ oD.style.top = (y-size)+'px';\r
+ oD.style.width = (size+'px');\r
+ oD.style.height = (size+'px');\r
+ oD.style.opacity = Math.min(1,Math.max(scaleY*1.5,0.1));\r
+ self.oDots.appendChild(oD);\r
+\r
+ // var sID = self.sounds[0].id;\r
+ if (!self.soundTimer) {\r
+ // self.soundTimer = window.setTimeout(function(){soundManager.play(sID,{volume:100*scaleY,pan:100*scaleX});self.soundTimer=null;},20);\r
+ self.sounds[Math.random()>0.5?1:0].play({pan:100*scaleX,volume:100*scaleY});\r
+ }\r
+ // if (self.soundIndex++>=self.sounds.length-1) self.soundIndex = 0;\r
+ }\r
+\r
+ this.createSounds = function() {\r
+ self.sounds[0] = soundManager.createSound('paint','../animation/audio/fingerplop.mp3');\r
+ self.sounds[1] = soundManager.createSound('paint2','../animation/audio/fingerplop2.mp3');\r
+ }\r
+\r
+ this.createSounds();\r
+\r
+ this.o = _id('cursor-shade');\r
+ this.refreshCoords();\r
+\r
+ window.onresize = this.refreshCoords;\r
+ _id('overlay').onmousedown = this.mousedown;\r
+ _id('overlay').onmouseup = this.mouseup; \r
+ document.onmousemove = this.mousemove;\r
+\r
+}\r
+\r
+var cursor = null;\r
+\r
+var sounds = [];\r
+\r
+function doEvil() {\r
+\r
+// HIGHLY EXPERIMENTAL (and dangerous) optimation testing - attempting to override Flash's ExternalInterface JS. :D - The below may have only been relevant to Flash 8.\r
+\r
+if (typeof window.__flash__argumentsToXML !== 'undefined') {\r
+\r
+ window.__flash__argumentsToXML = function(obj,index) {\r
+ var s = ["<arguments>"];\r
+ for (var i=index, j=obj.length; i<j; i++) {\r
+ s[s.length] = __flash__toXML(obj[i]);\r
+ }\r
+ s[s.length] = "</arguments>";\r
+ // console.log('argumentsToXML: '+s.length+' items');\r
+ return s.join('');\r
+ }\r
+\r
+ window.__flash__arrayToXML = function(obj) {\r
+ var s = ["<array>"];\r
+ for (var i=0,j=obj.length; i<j; i++) {\r
+ s[s.length] = "<property id=\"" + i + "\">" + __flash__toXML(obj[i]) + "</property>";\r
+ }\r
+ s[s.length] = "</array>";\r
+ // console.log('arrayToXML: '+s.length+' items');\r
+ return s.join('');\r
+ }\r
+\r
+ window.__flash__escapeXML = function(s) {\r
+ // console.log('escapeXML'); // '+s.length);\r
+ return s; // s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");\r
+ }\r
+\r
+ window.__flash__objectToXML = function(obj) {\r
+ console.log('objectToXML');\r
+ var s = ["<object>"];\r
+ for (var prop in obj) {\r
+ s[s.length] = "<property id=\"" + prop + "\">" + __flash__toXML(obj[prop]) + "</property>";\r
+ }\r
+ s[s.length] = "</object>";\r
+ return s.join('');\r
+ }\r
+\r
+ window.__flash__toXML = function(value) {\r
+ // console.log('toXML');\r
+ var type = typeof(value);\r
+ if (type == "string") {\r
+ return "<string>" + __flash__escapeXML(value) + "</string>";\r
+ } else if (type == "undefined") {\r
+ return "<undefined/>";\r
+ } else if (type == "number") {\r
+ return "<number>" + value + "</number>";\r
+ } else if (value == null) {\r
+ return "<null/>";\r
+ } else if (type == "boolean") {\r
+ return value ? "<true/>" : "<false/>";\r
+ } else if (value instanceof Date) {\r
+ return "<date>" + value.getTime() + "</date>";\r
+ } else if (value instanceof Array) {\r
+ return __flash__arrayToXML(value);\r
+ } else if (type == "object") {\r
+ return __flash__objectToXML(value);\r
+ } else {\r
+ return "<null/>"; //???\r
+ }\r
+ }\r
+\r
+ // this one non-IE, only?\r
+\r
+ if (!navigator.userAgent.match(/MSIE/i)) {\r
+ window.__flash__request.prototype = function(name) {\r
+ return "<invoke name=\"" + name + "\" returntype=\"javascript\">" + __flash__argumentstoXML(arguments, 1) + "</invoke>";\r
+ }\r
+ }\r
+}\r
+\r
+}\r
+\r
+function doInit() {\r
+ doEvil(); // NOTE: highly experimental, only a performance test; probably doesn't apply to Flash 9, and/or does nothing, or bad things.\r
+ cursor = new Cursor();\r
+}\r
+\r
+soundManager.setup({\r
+ preferFlash: true,\r
+ flashVersion: 9,\r
+ url: '../../swf/',\r
+ useHighPerformance: true,\r
+ wmode: 'transparent',\r
+ debugMode: false,\r
+ onready: doInit\r
+});\r
+\r
+</script>\r
+</head>\r
+\r
+<body>\r
+\r
+<div>\r
+\r
+<div id="canvas">\r
+\r
+ <div id="horizon"></div>\r
+ <div id="land">\r
+ <div id="content">\r
+ </div>\r
+ </div>\r
+\r
+ <div id="sun"></div>\r
+ <div id="dots"></div>\r
+ <img id="cursor-shade" src="cursor-shadow.png" alt="" />\r
+\r
+</div>\r
+\r
+<div id="instructions">\r
+ <h1>SoundManager 2: JS/DOM + Sound Demo</h1>\r
+ <h2>Heavy DOM manipulation + Javascript Sound <span>(see code for experimental ideas)</code></h2>\r
+</div>\r
+\r
+<p>Click and drag to draw.. Noisily.</p>\r
+<div id="overlay"></div>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>
--- /dev/null
+body {\r
+ font-size:75%;\r
+ background:#667788;\r
+ color:#fff;\r
+ text-shadow:0 0 0 #fff; /* Safari nonsense */\r
+}\r
+\r
+h1, h2, h3 {\r
+ font:normal 3em "Helvetica Neue",georgia,"times new roman","Arial Rounded MT Bold",helvetica,verdana,tahoma,arial,"sans serif";\r
+ font-weight:normal;\r
+ margin-bottom:0px;\r
+}\r
+\r
+\r
+h1 {\r
+ margin-top:0px;\r
+}\r
+\r
+h1, h2 {\r
+ letter-spacing:-1px; /* zomg web x.0! ;) */ \r
+}\r
+\r
+h2 {\r
+ font-size:2em;\r
+ margin-top:0.25em;\r
+}\r
+\r
+p {\r
+ font:normal 1em verdana,tahoma,arial,"sans serif";\r
+}\r
+\r
+.point {\r
+ position:absolute;\r
+ width:32px;\r
+ height:32px;\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<link rel="stylesheet" href="css/animation.css" media="screen" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/animation.js"></script>\r
+</head>\r
+<body>\r
+\r
+<div>\r
+\r
+ <h1>SoundManager 2 demo: A Noisy Page</h1>\r
+ <h2>Example of sound tied to javascript/DOM event handlers</h2>\r
+\r
+ <p>Click and drag for fun.</p>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>
--- /dev/null
+soundManager.setup({\r
+ preferFlash: true,\r
+ flashVersion: 9,\r
+ url: '../../swf/',\r
+ useHighPerformance: true,\r
+ wmode: 'transparent',\r
+ debugMode: false\r
+});\r
+\r
+var points = [];\r
+var o = null;\r
+var lastX = 0;\r
+var lastY = 0;\r
+var threshhold = 4;\r
+var threshMax = 32;\r
+var noise = null;\r
+var screenX = 0;\r
+\r
+function doPaint(e) {\r
+ var x = (e||event).clientX;\r
+ var y = (e||event).clientY;\r
+ var diff = Math.max(Math.abs(x-lastX),Math.abs(y-lastY));\r
+ if (diff>threshhold) {\r
+ lastX = x;\r
+ lastY = y;\r
+ points.push(new Point(x,y,Math.min(diff/(32),3)));\r
+ }\r
+ return false;\r
+}\r
+\r
+function stopPaint() {\r
+ document.onmousemove = null;\r
+ document.onmouseup = null;\r
+ // soundManager.play('up');\r
+}\r
+\r
+function startPaint(e) {\r
+ // soundManager.play('down');\r
+ document.onmousemove = doPaint;\r
+ document.onmouseup = stopPaint;\r
+ lastX = (e||event).clientX;\r
+ lastY = (e||event).clientY;\r
+ screenX = (window.innerWidth?window.innerWidth:document.documentElement.clientWidth||document.body.clientWidth);\r
+ e?e.stopPropagation():event.returnValue = false;\r
+ return false;\r
+}\r
+\r
+function initPoints() {\r
+ o = document.createElement('img');\r
+ o.src = 'image/point.png';\r
+ o.className = 'point';\r
+ document.onmousedown = startPaint;\r
+ document.onmouseup = stopPaint;\r
+}\r
+\r
+function Point(x,y,scale) {\r
+ var self = this;\r
+ this.data = {\r
+ x: x,\r
+ y: y,\r
+ scale: scale,\r
+ scalePX: parseInt(32*scale)\r
+ }\r
+ this.o = o.cloneNode(false);\r
+ this.o.style.left = (x-(this.data.scalePX/2))+'px';\r
+ this.o.style.top = (y-(this.data.scalePX/2))+'px';\r
+ this.o.style.width = this.o.style.height = this.data.scalePX+'px';\r
+ var screenX2 = parseInt(screenX/2);\r
+ noise.play({volume:parseInt(Math.min(1,scale/3)*100),pan:(x<screenX2?(screenX2-x)/screenX2*-100:(x-screenX2)/screenX2*100)});\r
+ document.body.appendChild(this.o);\r
+}\r
+\r
+soundManager.onready(function() {\r
+ noise = soundManager.createSound({\r
+ id:'noise',\r
+ url:'../animation/audio/fingerplop.mp3',\r
+ multiShot: true,\r
+ autoLoad: true\r
+ });\r
+ soundManager.createSound({\r
+ id:'down',\r
+ url:'../_mp3/click-low.mp3',\r
+ multiShot: true,\r
+ autoLoad: true\r
+ });\r
+ soundManager.createSound({\r
+ id:'up',\r
+ url:'../_mp3/click-high.mp3',\r
+ multiShot: true,\r
+ autoLoad: true\r
+ });\r
+ initPoints();\r
+});\r
+\r
+soundManager.onerror = function() {\r
+ alert('d\'oh, something didn\'t work - SM2 failed to start.');\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Animation + Sound Demos</title>
+<meta name="robots" content="noindex" />\r
+<link rel="stylesheet" href="../index.css" media="screen" />\r
+</head>\r
+<body>\r
+\r
+<div style="margin:1em">\r
+\r
+<h1>Javascript Animation + Sound Demos using <a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2</a></h1>\r
+\r
+<ol>\r
+ <li><a href="../animation-1/">Interval-based animation (with sound)</a></li>\r
+ <li><a href="../christmas-lights/">Smashable Christmas Lights</a></li>\r
+ <li><a href="../animation-2a/">JS-DOM "painting" + Sound, V1</a></li>\r
+ <li><a href="../animation-2b/">JS-DOM "painting" + Sound, V2</a></li>\r
+</ol>\r
+\r
+<p>External demo: <a href="http://www.schillmania.com/content/demos/yui-sm2/noisy-events/">A Noisy DOM</a> - part of a Yahoo! User Interface blog post, <a href="http://www.yuiblog.com/blog/2009/06/30/yui-soundmanager/">Enhancing YUI-based Apps with Audio</a>.</p>\r
+\r
+<script type="text/javascript">\r
+function fixLinks() {\r
+ if (document.location.protocol.match(/http/i)) {\r
+ return false;\r
+ }\r
+ // presumably offline - add index.html to local links, so offline browsing is seamless\r
+ var l = document.getElementsByTagName('a');\r
+ var s = null;\r
+ var tmp = null;\r
+ var cn = null;\r
+ for (var i=l.length; i--;) {\r
+ s = l[i].href.toString();\r
+ cn = l[i].className;\r
+ if (!s.match(/http/i) && !cn.match(/norewrite/i) && (s.match(/doc/i) || s.match(/demo/i) || s.match(/../))) {\r
+ // yep, local.\r
+ tmp = Math.max(s.lastIndexOf('?'),-1);\r
+ tmp = Math.max(s.lastIndexOf('#'),tmp);\r
+ tmp = Math.max(s.lastIndexOf('/')+1,tmp);\r
+ // console.log(s+' '+s.lastIndexOf('?')+', '+s.lastIndexOf('#')+', '+s.lastIndexOf('/')+' = '+tmp);\r
+ if (tmp == -1) {\r
+ tmp = s.length;\r
+ }\r
+ if (!s.match(/\.html/i)) {\r
+ l[i].setAttribute('href',s.substr(0,tmp)+'index.html'+s.substr(tmp));\r
+ }\r
+ }\r
+ }\r
+}\r
+fixLinks();\r
+</script>\r
+\r
+</div>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Live API Demos and Code Examples</title>
+<meta name="robots" content="noindex" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta name="language" content="en-us" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<meta name="keywords" content="javascript sound library api" />\r
+<meta name="description" content="Live API demos and code examples for SoundManager 2, Javascript Sound method calls and functions etc." />\r
+<link rel="stylesheet" href="../index.css" media="screen" />\r
+<!-- soundManager.useFlashBlock: related CSS -->\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+<style type="text/css">\r
+\r
+h1 {\r
+ padding-top:0.2em;\r
+ padding-bottom:0.1em;\r
+ border-bottom:4px solid #000;\r
+ letter-spacing:-0.03em;\r
+}\r
+\r
+h2 {\r
+ margin-top:1em;\r
+ padding-bottom:0.1em;\r
+ border-bottom:2px solid #000;\r
+}\r
+\r
+pre,\r
+code,\r
+.code,\r
+dt,\r
+#soundmanager-debug {\r
+ color:#336699;\r
+ line-height:1.5em;\r
+}\r
+\r
+p {\r
+ line-height:1.5em;\r
+ margin-bottom:1em;\r
+}\r
+\r
+#soundmanager-debug {\r
+ position: relative;\r
+ padding: 0.5em 0.25em;\r
+ height: 13.5em;\r
+ overflow: auto;\r
+ opacity: 0.97;\r
+ color: #333;\r
+ border: 1px solid #ccddee;\r
+ border-radius: 3px;\r
+ background: #f3f9ff;\r
+}\r
+\r
+/*\r
+#soundmanager-debug code {\r
+ font-size:1.1em;\r
+ *font-size:1em;\r
+}\r
+*/\r
+\r
+#soundmanager-debug div {\r
+ font-size:x-small;\r
+ padding:0.5em;\r
+ margin:0px;\r
+}\r
+\r
+.c3 h3 {\r
+ min-height: 26px;\r
+}\r
+\r
+.c3 ul li a:hover code {\r
+ background-color: transparent;\r
+ color: #fff;\r
+}\r
+\r
+#sm2-container.swf_unblocked {\r
+ /* if initially blocked (and then unblocked), stay relative so JS <-> Flash doesn't break. */\r
+ position: relative;\r
+}\r
+\r
+#sm2-container.high_performance.swf_unblocked {\r
+ /* ...unless high performance, in which case stay in corner (unless old IE) */\r
+ _position: relative;\r
+ position: fixed;\r
+}\r
+\r
+</style>\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript">\r
+\r
+// flash version URL switch (for this demo page)\r
+var winLoc = window.location.toString();\r
+\r
+if (winLoc.match(/flash9/i)) {\r
+\r
+ soundManager.setup({\r
+ preferFlash: true,\r
+ flashVersion: 9\r
+ });\r
+\r
+ if (winLoc.match(/highperformance/i)) {\r
+ soundManager.setup({\r
+ useHighPerformance: true\r
+ });\r
+\r
+ }\r
+\r
+} else if (winLoc.match(/flash8/i)) {\r
+\r
+ soundManager.setup({\r
+ preferFlash: true,\r
+ flashVersion: 8\r
+ });\r
+\r
+}\r
+\r
+soundManager.setup({\r
+ useFlashBlock: true,\r
+ // path to SoundManager2 SWF files (note trailing slash)\r
+ url: '../../swf/',\r
+ // optional: HTML5 polling rate - for whileplaying() events, etc.\r
+ html5PollingInterval: (winLoc.match(/html5PollingInterval/i) ? 20 : null),\r
+ debugMode: true,\r
+ consoleOnly: false\r
+});\r
+\r
+soundManager.onready(function(oStatus) {\r
+ if (!oStatus.success) {\r
+ return false; \r
+ }\r
+ // soundManager is initialised, ready to use. Create a sound for this demo page.\r
+\r
+ if (soundManager.flashVersion > 8) {\r
+ t = window.setInterval(checkRAM,500);\r
+ document.getElementById('flash-ram-use').style.display = 'inline';\r
+ checkRAM();\r
+ }\r
+\r
+ soundManager.createSound({\r
+ id: 'aDrumSound',\r
+ url: '../mpc/audio/AMB_SN13.mp3'\r
+ });\r
+\r
+ soundManager.createSound({\r
+ id: 'aCymbalSound',\r
+ url: '../mpc/audio/SPLASH_1.mp3',\r
+ autoLoad: true\r
+ });\r
+\r
+ soundManager.createSound({\r
+ id: 'chinaCymbal',\r
+ url: '../mpc/audio/CHINA_1.mp3',\r
+ autoLoad: true\r
+ });\r
+\r
+ soundManager.createSound({\r
+ id: 's440hz',\r
+ url: '../_mp3/440hz.mp3',\r
+ autoLoad: true,\r
+ volume:50\r
+ });\r
+\r
+});\r
+\r
+function checkRAM() {\r
+ if (soundManager.supported()) {\r
+ var ram = (soundManager.getMemoryUse()/1024/1024).toFixed(2);\r
+ if (!isNaN(ram)) {\r
+ document.getElementById('flash-ram-use').innerHTML = ram+' MB';\r
+ } else {\r
+ document.getElementById('flash-ram-use').style.display = 'none';\r
+ }\r
+ }\r
+}\r
+\r
+var t = null;\r
+\r
+function doEval(sHTML) {\r
+ var html = sHTML.replace(/\<(span|code)\>/gi,'');\r
+ html = html.replace(/\<[\/](span|code)\>/gi,'');\r
+ html = html.replace(/>/gi,'>');\r
+ eval(html);\r
+ return false;\r
+}\r
+\r
+function getRandomMP3URL() {\r
+ return 'http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3?rnd='+parseInt(Math.random()*1048576);\r
+}\r
+\r
+</script>\r
+</head>\r
+\r
+<body>\r
+\r
+<div id="flash9" style="margin-left:32em;padding-left:1em;margin-right:2em">\r
+\r
+ <h1 id="start"><a href="http://www.schillmania.com/projects/soundmanager2/" style="color:#000;text-decoration:none">SoundManager 2</a> / API Demo and Code Examples</h1>\r
+\r
+ <p>Wondering where to start? This page has inline executable code examples using the SoundManager 2 API.</p>\r
+\r
+ <p>If you're wondering how to include SM2 in your page, the <a href="../template/" title="SoundManager 2 bare-bones template" onclick="if (!document.domain && !this.href.match(/index/i)) this.href=this.href+'index.html'">basic template</a> will get you started.</p>\r
+\r
+ <h2>SoundManager 2 Configurations</h2>\r
+\r
+ <p>SM2's API features and behaviour can vary somewhat depending on client support, so it can be helpful to test under different configurations. The following are different configuration defaults for SoundManager 2. Clicking will change URL parameters and reload the page, causing SM2 to start up with the new options applied. Look at JS console output for details.</p>\r
+\r
+ <p><b>HTML5 options</b>: <a href="#sm2-usehtml5audio=1" onclick="window.location.replace(this.href);window.location.reload()">HTML5-only mode</a> (API default, where supported) | <a href="#sm2-html5PollingInterval=20" onclick="window.location.replace(this.href);window.location.reload()">HTML5 + fast polling</a> | <a href="#sm2-preferflash=1" onclick="window.location.replace(this.href);window.location.reload()">HTML5 + prefer flash</a> for MP3/MP4 formats | <a href="#sm2-usehtml5audio=0" onclick="window.location.replace(this.href);window.location.reload()">disable HTML5</a></p>\r
+ \r
+ <p><b>Flash options</b>: <a href="#flash8" onclick="window.location.replace(this.href);window.location.reload()">Flash 8</a> | <a href="#flash9" onclick="window.location.replace(this.href);window.location.reload()">Flash 9</a> (normal) | <a href="#flash9-highperformance" onclick="window.location.replace(this.href);window.location.reload()">Flash 9 + highPerformance + fastPolling</a> modes (higher JS callback frequency)</p>\r
+\r
+ <div id="sm2-container">\r
+ <!-- flash is appended here -->\r
+ </div>\r
+\r
+ <h2>The <code>soundManager.setup()</code> method</h2>\r
+\r
+ <p>In order to configure SoundManager 2 for use, you must first call the <code>setup()</code> method. The <code>url</code> property and an <code>onready</code> function callback are commonly used together here.</p>\r
+\r
+<pre class="block"><code>soundManager.setup({\r
+\r
+ <span><span>// where to find the SWF files, if needed</span></span>\r
+ url: '<span>/path/to/swf-directory/</span>',\r
+\r
+ onready: function() {\r
+ <span><span>// SM2 has loaded, API ready to use e.g., createSound() etc.</span></span>\r
+ },\r
+\r
+ ontimeout: function() {\r
+ <span><span>// Uh-oh. No HTML5 support, SWF missing, Flash blocked or other issue</span></span>\r
+ }\r
+\r
+});\r
+</code></pre>\r
+\r
+<p>SoundManager processes the <code>onready</code> and <code>ontimeout</code> queue in the order items were added. You can also add callbacks via <code>soundManager.onready()</code> and <code>soundManager.ontimeout()</code>, respectively. If you add listeners for these events after SM2 has loaded, your callback will be fired immediately.</p>\r
+\r
+ <h2>A note about initialization</h2>\r
+ \r
+ <p class="compact">Keep in mind SoundManager's core methods (createSound, etc.) will not be available until soundManager's <code>onready()</code> event fires. The initialization time for SM2 can vary across browsers/platforms, and should effectively be assumed to be "asynchronous." Because of this, it is recommended you write your code to handle <code>onready</code> being fired either before or after window.onload().</p>\r
+ <p class="compact">If you wish to have SM2 always wait for window.onload() before calling <code>onready()</code> or <code>ontimeout()</code>, you can pass <code>waitForWindowLoad: true</code> to <code>soundManager.setup()</code>.</p>\r
+\r
+ <h2 id="debug-output">Debug Output, disabling and minified versions</h2>\r
+ <p class="compact">SoundManager 2 has debug mode enabled by default and will write to agents supporting <em>console.log</em>-style debugging, and/or a custom <div> element in the absence of a console.</p>\r
+ <p>To disable debug output, pass <code>debugMode: false</code> to <code>soundManager.setup()</code>.</p>\r
+ <p>Alternately, you may use the no-debug, minified version of the SM2 javascript library (which has internal debug code removed, and will silently return false.)</p>\r
+\r
+ <h2 id="create">Demo 1: Create + play a sound</h2>\r
+\r
+<pre class="block"><code>var mySound = soundManager.createSound({\r
+ url: '<span>../mpc/audio/CHINA_1.mp3</span>'\r
+});\r
+mySound.play();</code></pre>\r
+ <button onclick="soundManager._writeDebug('Demo 1',1);var mySound = soundManager.createSound({url: '../mpc/audio/CHINA_1.mp3'});mySound.play()">Do this</button>\r
+ <p>Creates a new sound object with a <code>url</code>, and calls its <code>play()</code> method.</p>\r
+ <p><b>Note</b>: It is recommended you make one sound object per <code>url</code>, generally speaking, that you wish to play. Expressed another way: "Reduce, reuse, recycle."</p>\r
+\r
+ <h3>Variant: Create + play sound with an <code>id</code></h3>\r
+\r
+<pre class="block"><code>soundManager.createSound({\r
+ id: '<span>mySound2</span>',\r
+ url: '<span>../mpc/audio/CHINA_1.mp3</span>'\r
+});\r
+soundManager.play('<span>mySound2</span>');</code></pre>\r
+ <button onclick="soundManager._writeDebug('Demo 1b variant',1);soundManager.createSound({id:'mySound2', url: '../mpc/audio/CHINA_1.mp3'});soundManager.play('mySound2')">Do this</button>\r
+\r
+ <p>Creates a new sound object with the given <code>id</code>, and then calls <code>soundManager.play()</code>, specifying the <code>id</code> of the desired sound.</p>\r
+\r
+ <p>If omitted, an <code>id</code> will be automatically generated. If a sound object with the provided <code>id</code> already exists, the existing object will be returned.</p>\r
+\r
+ <p><b>Cases for providing your own <code>id</code></b></p>\r
+\r
+ <p>The <code>id</code> parameter is optional, but makes sound objects easier to look up. It's also helpful when the object returned from <code>createSound()</code> wasn't stored, or isn't in scope. Calling <code>soundManager.getSoundById('<span>mySound2</span>')</code> will return the matching sound object, or <code>null</code> if none is found.</p>\r
+\r
+ <p><code>soundManager.play()</code> and related convenience methods take an <code>id</code> string, and call the method on the given sound object. Thus, <code>soundManager.play('<span>foo</span>')</code> is functionally equivalent to <code>soundManager.getSoundById('<span>foo</span>').play()</code></p>\r
+\r
+ <p><b>Reduce, reuse, recycle</b></p>\r
+\r
+ <p>Unless you need to track separate instances of a sound playing simultaneously, it's best to create and re-use one sound object for each unique sound resource (URL) you have. If you want to play a single sound multiple times, layered on top of itself in an overlapping/chorus style, look at the <code>multiShot</code> sound option (Flash 9 + HTML5 only).</p>\r
+\r
+ <h2 id="create-with-onfinish">Demo 2: Create with <code>onfinish</code> event handler + play with volume argument</h2>\r
+<pre id="demo2" class="block"><code>var demo2Sound = soundManager.createSound({\r
+ url: '<span>../mpc/audio/CHINA_1.mp3</span>',\r
+ onfinish: function() {\r
+ soundManager._writeDebug(this.id + '<span> finished playing</span>');\r
+ }\r
+});\r
+demo2Sound.play({\r
+ volume: 50\r
+});\r
+</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo2').innerHTML)">Do this</button>\r
+ <p>(creates, then plays a new sound - a function is called when the sound finishes playing)</p>\r
+\r
+ <h2 id="create-with-onload">Demo 2a: Create with <code>onload</code> event handler</h2>\r
+<pre id="demo2a" class="block"><code>soundManager.createSound({\r
+ url: '<span>../mpc/audio/CHINA_1.mp3</span>',\r
+ <span><span>// callback for when the sound has loaded</span></span>\r
+ onload: function() {\r
+ soundManager._writeDebug(this.id + '<span> loaded</span>');\r
+ this.play();\r
+ }\r
+}).load();</code></pre>\r
+ <button onclick="return doEval(document.getElementById('demo2a').innerHTML)">Do this</button>\r
+ <p>This creates and loads a sound, using the <code>onload</code> event callback to begin playback once the sound has loaded.</p>\r
+\r
+ <h2 id="create-with-whileloading">Demo 2b: Create and load with <code>whileloading</code> event handler</h2>\r
+<pre id="demo2b" class="block"><code>soundManager.createSound({\r
+ url: '<span>http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3?rnd='</span> + Math.random(),\r
+ <span><span>// begin loading right away</span></span>\r
+ autoLoad: true,\r
+ whileloading: function() {\r
+ soundManager._writeDebug(this.id + '<span>: loading '</span> + this.bytesLoaded + ' <span>/</span> ' + this.bytesTotal);\r
+ }\r
+});</code></pre>\r
+ <button onclick="return doEval(document.getElementById('demo2b').innerHTML)">Do this</button>\r
+ <p>This creates and auto-loads a sound, showing load progress where applicable.</p>\r
+\r
+ <h2 id="play-by-id">Demo 3: Play a pre-existing sound by <code>id</code></h2>\r
+<pre class="block"><code>soundManager.play('<span>aDrumSound</span>');</code></pre>\r
+ <button onclick="soundManager._writeDebug('Demo 3',1);soundManager.play('aDrumSound')">Do this</button>\r
+ <p>This plays an existing sound made earlier using <code>soundManager.createSound()</code>, specifying an <code>id</code> parameter of <code><span>aDrumSound</span></code>.</p>\r
+ <p>Alternately, you can reference a sound by <code>id</code> and call methods directly on the object itself - for example, <code>soundManager.getSoundById('<span>aDrumSound</span>').play();</code></p>\r
+\r
+ <h2 id="onfinish-with-multishot-events">Demo 4a: Play a sequence of sounds via <code>onfinish</code>, with <code>multiShot</code> (Flash 9 + HTML5 only)</h2>\r
+<pre class="block"><code>soundManager.play('<span>aDrumSound</span>', {\r
+ <span><span>// allow onfinish() to fire for each "shot", instead of only last shot</span></span>\r
+ multiShotEvents: true,\r
+ onfinish: function() {\r
+ soundManager.play('<span>aCymbalSound</span>');\r
+ }\r
+});</code></pre>\r
+ <button onclick="soundManager._writeDebug('Demo 4a',1);soundManager.play('aDrumSound',{multiShotEvents:true,onfinish:function(){soundManager.play('aCymbalSound');}})">Do this</button>\r
+ <p>This will play an existing sound (created in-page), and uses the <code>onfinish()</code> callback to play a second, pre-existing sound.</p>\r
+ <p>Also note that the button can be clicked multiple times, and the sound will be "layered" as multiShot is enabled for both of these sounds when using Flash 9 or HTML5. An onfinish event will also fire as each sound finishes.</p>\r
+ <p><strong>Bug/behaviour note:</strong> Whenever "play" is called on a SMSound object, any parameters passed in will apply to all currently-playing instances of the sound if multiShot is allowed. For example, the onfinish handler from demo 4a will apply to demo 3 if 4a is started while 3 is still playing.</p>\r
+ <p class="note">* Multishot is Flash 9+ and HTML5 only.</p>\r
+\r
+ <h2 id="create-play-onfinish">Demo 4b: Create and play a sequence of new sounds via <code>onfinish()</code></h2>\r
+<pre id="demo-4b" class="block"><code>soundManager.createSound({\r
+ id: '<span>aBassDrum</span>',\r
+ url: '<span>../mpc/audio/AMB_BD_1.mp3</span>',\r
+ multiShot: false,\r
+ <span><span>// when the first sound finishes...</span></span>\r
+ onfinish: function() {\r
+ <span><span>// create and play the second.</span></span>\r
+ soundManager.createSound({\r
+ id: '<span>aRimSound</span>',\r
+ url: '<span>../mpc/audio/AMB_RIM1.mp3</span>'\r
+ }).play();\r
+ }\r
+});\r
+soundManager.play('<span>aBassDrum</span>');</code></pre>\r
+ <button onclick="soundManager._writeDebug('Demo 4b',1);return doEval(document.getElementById('demo-4b').innerHTML)">Do this</button>\r
+ <p>This will create and play a new sound, using the <code>onfinish()</code> callback to create and play a second, new sound.</p>\r
+ <p>Note that <code>createSound()</code> will return an existing sound object if one already exists with the given <code>id</code>. You can test this by running the demo more than once.</p>\r
+\r
+<h2 id="looping-conventional">Demo 4c: Looping a sound (conventional, <code>onfinish()</code>-based)</h2>\r
+<pre id="demo4c" class="block"><code>var s = soundManager.createSound({\r
+ id: '<span>hhCymbal</span>',\r
+ url: '<span>../mpc/audio/AMB_HHOP.mp3</span>'\r
+});\r
+\r
+function loopSound(sound) {\r
+ sound.play({\r
+ onfinish: function() {\r
+ loopSound(sound);\r
+ }\r
+ });\r
+}\r
+\r
+loopSound(s);\r
+</code></pre>\r
+\r
+<button onclick="return doEval(document.getElementById('demo4c').innerHTML)">Do this</button> | <button onclick="soundManager.stop('hhCymbal')">make it stop!</button>\r
+<p>Note that there are issues with seamlessly-looping sounds, it is "close, but not perfect" with Flash 8/9 at this point.</p>\r
+\r
+<h2 id="looping">Demo 4d: Looping a sound (<code>loops</code> parameter method)</h2>\r
+<pre id="demo4d" class="block"><code>var s = soundManager.createSound({\r
+ id: '<span>hhCymbal</span>',\r
+ url: '<span>../mpc/audio/AMB_HHOP.mp3</span>'\r
+});\r
+\r
+s.play({\r
+ loops: 3\r
+});\r
+</code></pre>\r
+\r
+<button onclick="return doEval(document.getElementById('demo4d').innerHTML);return false">Do this</button> | <button onclick="soundManager.stop('hhCymbal')">make it stop!</button>\r
+<p>Looping is possible as shown above using Flash 9. <b>With flash 8, the sound must be preloaded before looping can begin</b> - eg. <code>autoLoad: true, onload: function() { this.play{loops: 3} }</code>. For tighter looping, see See <a href="http://www.flickr.com/photos/schill/4499319436/" title="Seamless looping MP3 sounds in Flash">Seamless Looping MP3 in Flash</a> for further details.</p>\r
+\r
+<p><b>HTML5 support note:</b> Native HTML5 looping is infinite when enabled, and does not support arbitrary loop counts. For now, consider using your own function with <code>onfinish()</code> -> <code>play()</code> if you want to loop a sound a certain number of times. Refer to the above <code>onfinish()</code> example for a basic idea.</p>\r
+\r
+<h2 id="onposition">Demo 4e: Sound timing notifications using <code>onPosition()</code></h2>\r
+<pre id="demo4e" class="block"><code>var s = soundManager.getSoundById('<span>aCymbalSound</span>'); <span><span>// existing sound object</span></span>\r
+\r
+<span><span>// register some listeners (only do this once, they will work for subsequent plays)</span></span>\r
+\r
+if (typeof addedListeners === '<span>undefined</span>') {\r
+ addedListeners = true;\r
+\r
+ s.onPosition(<span>500</span>, function(eventPosition) { <span><span>// fire at 0.5 seconds</span></span>\r
+ soundManager._writeDebug('<span>Sound </span>' + this.id + ' <span>has reached position </span>' + eventPosition);\r
+ });\r
+\r
+ s.onPosition(<span>1000</span>, function(eventPosition) { <span><span>// fire at 1 second</span></span>\r
+ soundManager._writeDebug('<span>Sound </span>' + this.id + '<span> has reached position </span>' + eventPosition);\r
+ });\r
+}\r
+\r
+s.play({\r
+ multiShot: false,\r
+ whileplaying: function() {\r
+ <span><span>// demo only: show sound position while playing, for context</span></span>\r
+ soundManager._writeDebug('<span>position = </span>' + this.position);\r
+ }\r
+});\r
+</code></pre>\r
+\r
+<button onclick="return doEval(document.getElementById('demo4e').innerHTML);return false">Do this</button>\r
+<p><code>onPosition()</code> allows you to add an event listener for a given time (in miliseconds, watching the position property); the event fires when that time has been reached while a sound is playing.</p>\r
+<p>Note that for multiShot cases, the listeners will only fire for the original (first) shot because its position is the only one that is tracked within Flash.</p>\r
+\r
+<h2 id="onposition-2">Demo 4f: Sound timing with <code>onPosition()</code> and <code>clearOnPosition()</code></h2>\r
+<pre id="demo4f" class="block"><code>var s = soundManager.getSoundById('<span>aCymbalSound</span>'); <span><span>// existing sound object</span></span>\r
+\r
+<span><span>// clear listeners from prior demo, if they were assigned...</span></span>\r
+\r
+if (typeof addedListeners !== '<span>undefined</span>') {\r
+\r
+ soundManager._writeDebug(<span>'Removing previous demo listeners...'</span>);\r
+ s.clearOnPosition(<span>500</span>);<span><span> // remove 500 msec listener</span></span>\r
+ s.clearOnPosition(<span>1000</span>);<span><span> // remove 1000 msec listener</span></span>\r
+\r
+}\r
+\r
+s.onPosition(<span>750</span>, function(eventPosition) { <span><span>// fire at 0.75 seconds</span></span>\r
+\r
+ soundManager._writeDebug('<span>Sound </span>' + this.id + '<span> has reached position </span>' + eventPosition);\r
+ <span><span>// and now, remove the listener using the eventPosition specified in this callback</span></span>\r
+ <span><span>// so next time the sound plays, this listener will not fire</span></span>\r
+ this.clearOnPosition(eventPosition);\r
+\r
+});\r
+\r
+s.play({\r
+ whileplaying: function() {\r
+ <span><span>// demo only: show sound position while playing, for context</span></span>\r
+ soundManager._writeDebug('<span>position = </span>' + this.position);\r
+ },\r
+ onfinish: function() {\r
+ <span><span>// when the sound finishes, play it once more to show that the listener does not fire.</span></span>\r
+ soundManager._writeDebug('<span>Playing once more, onPosition() should not fire</span>');\r
+ this.play({\r
+ onfinish: function() {\r
+ soundManager._writeDebug('<span>"</span>' + this.id + '<span>" finished.</span>');\r
+ }\r
+ });\r
+ }\r
+});\r
+</code></pre>\r
+\r
+<button onclick="return doEval(document.getElementById('demo4f').innerHTML);return false">Do this</button>\r
+<p>When <code>onPosition()</code> is used, a listener is added and a callback is fired when the sound reaches the desired position. To remove the listener, <code>clearOnPosition()</code> is called using the same position value.</p>\r
+\r
+<h2 id="from-to">Demo 4g: Sound splicing / sampling with <code>from:</code> and <code>to:</code> parameters</h2>\r
+<pre id="demo4g" class="block"><code>var spliceDemo = soundManager.createSound({\r
+ id: '<span>spliceSound</span>',\r
+ url: '<span>../mpc/audio/AMB_HHOP.mp3</span>'\r
+});\r
+\r
+<span><span>// optional: stop before re-starting sound (covers overlapping play attempts)</span></span>\r
+spliceDemo.stop();\r
+\r
+spliceDemo.play({\r
+ <span><span>// start position</span></span>\r
+ from: <span>500</span>,\r
+ <span><span>// end position</span></span>\r
+ to: <span>1200</span>,\r
+ onstop: function() {\r
+ soundManager._writeDebug('<span>sound stopped at position </span>' + this.position);\r
+ <span><span>// note that the "to" target may be over-shot by 200+ msec, depending on polling and other factors.</span></span>\r
+ }\r
+});\r
+</code></pre>\r
+\r
+<button onclick="return doEval(document.getElementById('demo4g').innerHTML);return false">Do this</button> | <button onclick="soundManager.stop('spliceSound');soundManager.play('spliceSound','../mpc/audio/AMB_HHOP.mp3');return false">Play full sound</button>\r
+<p>By specifying "from" and "to" parameters to methods like play() and createSound(), you may play a sample (or segment) of audio from a larger file. An audio "sprite" of one file with many sounds is one way to think of this. Given timing accuracy of the "to" target may vary a lot, it is safest to have perhaps 500-msec gaps of silence between distinct sounds to ensure that no accidental overlaps occur.</p>\r
+<p>To tighten the accuracy of the "to" timing, <a href="?flash9-highperformance#from-to" onclick="window.location.replace(this.href);window.location.reload()">try using soundManager.useHighPerformance</a>.</p>\r
+<p>If HTML5 audio is being used, the sound should begin playing once a "canplay" event fires (after a connection has established), and the sound will then seek to the correct start position. When using flash, the whole audio file will be loaded before playback can begin.</p>\r
+<p>Given limitations, Flash 9's multiShot (chorusing) mode does not apply here. If you wish to trigger a sound numerous times, call stop() before play() to reset the sound each time, or make multiple sound objects that reuse the same sprite.</p>\r
+\r
+<h2 id="fitter-happier">Demo 4g: "Fitter, Happier" example using <code>from:</code> and <code>to:</code> parameters</h2>\r
+\r
+<p>\r
+ <img src="../_image/fitter-happier-waveform.png" alt="Fitter, Happier waveform showing sound samples" />\r
+</p>\r
+\r
+<p>Portions of a sound can be played by specifying <b>from</b> and <b>to</b> when calling <code>play()</code>. This can be useful for performance, i.e., having an "audio sprite" that loads in a single HTTP request.</p>\r
+\r
+<pre id="demo4h" class="block"><code>var fhDemo = soundManager.createSound({\r
+ url: '<span>http://freshly-ground.com/data/audio/sm2/fitter-happier-64kbps.mp3</span>'\r
+});\r
+\r
+function playFromTo(nFrom, nTo) {\r
+ fhDemo.stop(); <span><span>// optional: stop before re-starting sound (covers overlapping play attempts)</span></span>\r
+ fhDemo.play({\r
+ from: nFrom,\r
+ to: nTo,\r
+ onstop: function() {\r
+ soundManager._writeDebug('<span>sound stopped at position </span>' + this.position);\r
+ <span><span>// note that the "to" target may be over-shot by 200+ msec, depending on polling and other factors.</span></span>\r
+ }\r
+ });\r
+}\r
+\r
+function fitterHappier() {\r
+ playFromTo(<span>128, 2100</span>);\r
+}\r
+\r
+function moreProductive() {\r
+ playFromTo(<span>2500, 3850</span>);\r
+}\r
+\r
+function comfortable() {\r
+ playFromTo(<span>4275, 5200</span>);\r
+}\r
+\r
+function notDrinkingTooMuch() {\r
+ playFromTo(<span>5500, 7250</span>);\r
+}\r
+\r
+function regularExerciseAtTheGymThreeDaysAWeek() {\r
+ playFromTo(<span>7500, 11500</span>);\r
+}\r
+\r
+function atEase() {\r
+ <span><span>// interesting edge case: flash may cut off sound near end.\r
+ // workarounds: use play({position:x}), or specify "to" time > duration eg. 99999.</span></span>\r
+ playFromTo(<span>11600, 99999</span>);\r
+}\r
+\r
+<span><span>// demo-specific hack: assign to the window object, so demo buttons work</span></span>\r
+window.fitterHappier = fitterHappier;\r
+window.moreProductive = moreProductive;\r
+window.comfortable = comfortable;\r
+window.notDrinkingTooMuch = notDrinkingTooMuch;\r
+window.regularExerciseAtTheGymThreeDaysAWeek = regularExerciseAtTheGymThreeDaysAWeek;\r
+window.atEase = atEase;\r
+</code></pre>\r
+\r
+<script>\r
+// do this work up front\r
+soundManager.onready(function() {\r
+ doEval(document.getElementById('demo4h').innerHTML);\r
+});\r
+</script>\r
+\r
+<button onclick="fitterHappier();return false">fitterHappier()</button> | <button onclick="moreProductive();return false">moreProductive()</button> | <button onclick="comfortable();return false">comfortable()</button> | <button onclick="notDrinkingTooMuch();return false">notDrinkingTooMuch()</button> | <button onclick="regularExerciseAtTheGymThreeDaysAWeek();return false">regularExerciseAtTheGymThreeDaysAWeek()</button> | <button onclick="atEase();return false">atEase()</button>\r
+\r
+<h2 id="sound-parameters">Demo 5a: Set sound parameters, then play</h2>\r
+<pre id="demo5a" class="block"><code><span><span>// predefined/preloaded sound</span></span>\r
+var sound = soundManager.getSoundById('<span>chinaCymbal</span>');\r
+\r
+<span><span>// volume at 85%</span></span>\r
+sound.setVolume(<span>85</span>);\r
+\r
+<span><span>// 0.25 seconds into sound</span></span>\r
+sound.setPosition(<span>250</span>);\r
+\r
+<span><span>// pan 75% to the left</span></span>\r
+sound.setPan(<span>-75</span>);\r
+\r
+<span><span>// begin playback with new settings</span></span>\r
+sound.play();\r
+</code></pre>\r
+<button onclick="soundManager._writeDebug('Demo 5a',1);return doEval(document.getElementById('demo5a').innerHTML)">Do this</button>\r
+<p>This will set the position and pan of an existing, pre-loaded sound, then play it. Where applicable, these settings become the new defaults for the sound.</p>\r
+\r
+<h3 id="play-with-sound-options"><code>play()</code> with sound options</h3>\r
+<pre class="block"><code id="demo-5a1">var sound = soundManager.getSoundById('<span>chinaCymbal</span>');\r
+sound.play({\r
+ volume: <span>100</span>,\r
+ position: <span>0</span>,\r
+ pan: <span>75</span>\r
+});</code></pre>\r
+<p>This is an elegant way of playing a sound with specific parameters "just one time", overriding the defaults applied when the sound was created.</p>\r
+<button onclick="soundManager._writeDebug('Demo 5 variant',1);return doEval(document.getElementById('demo-5a1').innerHTML)">Do this</button>\r
+<p>Note that if planning to layer sounds with multiShot (Flash 9 only), this variant method will give best results as each new "channel" is started with parameters.</p>\r
+\r
+<h2 id="global-muting">Demo 5b: Global sound muting</h2>\r
+<p>If not passed a sound ID, soundManager.mute() will mute all existing and newly-created sounds. soundManager.unmute() can also be passed a sound ID, and performs the inverse either on a single sound or all sounds.</p>\r
+<p>In this demo, all sounds are globally muted and unmuted a few times. Different parameters are used to help audibly separate the sounds.</p>\r
+<pre id="demo5b-1" class="block"><code>soundManager.mute(); <span><span>// mute all sounds</span></span>\r
+\r
+soundManager.createSound({\r
+ id: '<span>880hz</span>',\r
+ url: '<span>../_mp3/880hz.mp3</span>',\r
+ autoLoad: true,\r
+ onload: function() {\r
+ <span><span>// soundManager.mute(); // mute all sounds</span></span>\r
+ <span><span>// play (muted) cymbal sound..</span></span>\r
+ this.play({\r
+ volume: 75, <span><span>// volume for when un-muted</span></span>\r
+ pan: -75, <span><span>// mostly on left channel</span></span> \r
+ <span><span>// .. and clean-up afterwards</span></span>\r
+ onfinish: function() {\r
+ this.destruct();\r
+ }\r
+ });\r
+\r
+ this.setVolume(25); <span><span>// new volume for when un-muted..</span></span>\r
+\r
+ soundManager.play('<span>s440hz</span>', {\r
+ pan: <span>75</span>,\r
+ onfinish: function() {\r
+ document.getElementById('<span>btn-d5b</span>').disabled = false;\r
+ }\r
+ });\r
+\r
+ <span><span>// once playing, toggle all sounds some more</span></span>\r
+ setTimeout(soundManager.unmute, 500);\r
+ setTimeout(soundManager.mute, 1000);\r
+ setTimeout(soundManager.unmute, 1500);\r
+ setTimeout(soundManager.mute, 2000);\r
+ setTimeout(soundManager.unmute, 2500);\r
+ }\r
+});</code></pre>\r
+<button id="btn-d5b" onclick="this.disabled=true;return doEval(document.getElementById('demo5b-1').innerHTML)">Do this</button>\r
+<script type="text/javascript">document.getElementById('btn-d5b').disabled = false;</script>\r
+\r
+<h2 id="muting">Demo 5c: Per-object sound muting</h2>\r
+<pre id="demo5c-1" class="block"><code>soundManager.createSound({\r
+ id: '<span>880hz</span>',\r
+ url: '<span>../_mp3/880hz.mp3</span>',\r
+ autoLoad: true,\r
+ onload: function() {\r
+ soundManager.mute('<span>880hz</span>'); <span><span>// mute this - alternately, this.mute() would work here</span></span>\r
+ soundManager.play('<span>s440hz</span>', { <span><span>// play another sound to demo muting</span></span>\r
+ onfinish: function() {\r
+ document.getElementById('<span>btn-d5c</span>').disabled = false;\r
+ }\r
+ });\r
+\r
+ <span><span>// play 880hz (muted)..</span></span>\r
+ this.play({\r
+ volume: 75,\r
+ <span><span>// .. and clean-up afterwards</span></span>\r
+ onfinish: function() {\r
+ this.destruct();\r
+ }\r
+ });\r
+\r
+ this.setVolume(50); <span><span>// still muted, however..</span></span>\r
+\r
+ <span><span>// mute/unmute china cymbal some more</span></span>\r
+ <span><span>// mute sound calls: soundManager.mute('<span>880hz</span>'), or soundManager.getSoundById('<span>880hz</span>').mute();</span></span>\r
+ setTimeout(this.unmute, 250);\r
+ setTimeout(this.mute, 500);\r
+ setTimeout(this.unmute, 750);\r
+ setTimeout(this.mute, 1000);\r
+ setTimeout(this.unmute, 1250);\r
+ }\r
+});</code></pre>\r
+<button id="btn-d5c" onclick="this.disabled=true;return doEval(document.getElementById('demo5c-1').innerHTML)">Do this</button>\r
+<script type="text/javascript">document.getElementById('btn-d5c').disabled = false;</script>\r
+\r
+<h2 id="create-play-unload-destroy">Demo 6: Create, play, unload and destroy a sound</h2>\r
+<pre id="demo6" class="block"><code>var foo = soundManager.createSound({\r
+ id: '<span>fooSound</span>',\r
+ url: '<span>../mpc/audio/AMB_BD_1.mp3</span>'\r
+});\r
+\r
+<span><span>// soundManager.play('<span>fooSound</span>');\r
+\r
+// (Some time later on...)\r
+// soundManager.unload('<span>fooSound</span>'); - release the loaded MP3\r
+// soundManager.destroySound('<span>fooSound</span>'); - destroy the sound, freeing up memory etc. Also calls unload().\r
+\r
+// Alternate (demo) approach, call methods directly on sound object itself:</span></span>\r
+foo.play({\r
+ onfinish: function() {\r
+ <span><span>// once sound has loaded and played, unload and destroy it.</span></span>\r
+ this.destruct(); <span><span>// will also try to unload before destroying.</span></span>\r
+ }\r
+});</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo6').innerHTML)">Do this</button>\r
+\r
+\r
+<h2>Demo 7: Create, manually pre-load and finally play a sound</h2>\r
+<pre id="demo7" class="block"><code>var preload = soundManager.createSound({\r
+ id: '<span>preloadSound</span>',\r
+ url: '<span>../mpc/audio/AMB_HHOP.mp3</span>'\r
+});\r
+\r
+<span><span>// load the sound ahead of time</span></span>\r
+preload.load({\r
+ <span><span>// and start playing it at onload</span></span>\r
+ onload: function() {\r
+ this.play();\r
+ }\r
+});\r
+</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo7').innerHTML)">Do this</button>\r
+\r
+<h2 id="load-404">Demo 8: Create and play an invalid sound (404)</h2>\r
+<pre id="demo8" class="block"><code>var bad = soundManager.createSound({\r
+ id: '<span>badSound</span>',\r
+ url: '<span>badurl.mp3</span>',\r
+ onload: function(bSuccess) {\r
+ soundManager._writeDebug('<span>sound </span>'+(bSuccess?'<span>loaded!</span>': '<span>did NOT load.</span>'));\r
+ }\r
+});\r
+bad.play();\r
+</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo8').innerHTML)">Do this</button>\r
+\r
+<h2>Demo 9: Create and destroy a sound at once (unusual crash testcase)</h2>\r
+<pre id="demo9" class="block"><code>var s = soundManager.createSound({\r
+ url: '<span>../mpc/audio/AMB_HHOP.mp3</span>'\r
+});\r
+s.play();\r
+s.destruct();\r
+</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo9').innerHTML)">Do this</button>\r
+\r
+<h2 id="sound-timing-accuracy">Demo 10: Sound timing (position accuracy testcase)</h2>\r
+<p>The Flash 9 version seems to resume the sound 1 msec earlier than it should, perhaps related to the timing/delay issue most noticeable on Windows.</p>\r
+<pre id="demo10" class="block"><code>var count = 0;\r
+var pos = -1;\r
+var s = soundManager.createSound({\r
+ url: '<span>../mpc/audio/CHINA_1.mp3</span>',\r
+ whileplaying: function() {\r
+ if (count == 0) {\r
+ if (this.position > 1000) {\r
+ this.pause();\r
+ pos = this.position;\r
+ count++;\r
+ this.resume();\r
+ }\r
+ } else if (count == 1) {\r
+ soundManager._writeDebug('<span>old position: </span>' + pos);\r
+ soundManager._writeDebug('<span>new position: </span>' + this.position);\r
+ <span><span>// See that this.position is less than pos!</span></span>\r
+ count++;\r
+ }\r
+ },\r
+ onfinish: function() {\r
+ this.destruct();\r
+ }\r
+});\r
+s.play();</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo10').innerHTML)">Do this</button>\r
+\r
+<h2>Demo 11: Inline <code>whileplaying()</code> event assignment</h2>\r
+<p class="in">Note that when using the Flash 9 version of SM2 with Flash 9 and 10 plugins, flash/OS-related delay conditions may result in the <code>position</code> property being less than the <code>duration</code> property, even by the end of the sound.</p>\r
+<pre id="demo11" class="block"><code>var foo = soundManager.createSound({\r
+ url: '<span>../mpc/audio/CRASH_1.mp3</span>'\r
+});\r
+foo.options.whileplaying = function() {\r
+ soundManager._writeDebug('<span>whileplaying(): </span>'+this.position+'<span> / </span>'+this.duration);\r
+}\r
+foo.play();\r
+\r
+<span><span>// note: assign .options before calling .play(), as that "bakes" the options into a play instance object.\r
+// the below "late" event handler assignment will have no effect on the already-playing instance.</span></span>\r
+foo.options.onfinish = function() { soundManager._writeDebug(this.id + '<span> stopped.</span>'); }\r
+</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo11').innerHTML)">Do this</button>\r
+\r
+<h2>Demo 12: 48 KHz MP3 sampling rate playback issue workaround</h2>\r
+<p>To work around a known "chipmunk" <a href="http://bugs.adobe.com/jira/browse/FP-862">sampling rate issue with 48 KHz MP3s</a> in Flash, one can apparently load a sound using Flash 9 with stream = false, and then call play() once the sound has fully-loaded. Exactly why this works is not known.</p>\r
+<pre id="demo12" class="block"><code>var fortyeight = soundManager.createSound({\r
+ url: '<span>http://freshly-ground.com/data/audio/48khz-test.mp3</span>'\r
+});\r
+\r
+if (!fortyeight.loaded) {\r
+ <span><span>// first time loading/playing</span></span>\r
+ fortyeight.load({\r
+ stream: false,\r
+ onload: function() {\r
+ <span><span>// sound has fully-loaded</span></span>\r
+ this.play();\r
+ }\r
+ });\r
+} else {\r
+ <span><span>// sound has already loaded</span></span>\r
+ fortyeight.play();\r
+}\r
+</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo12').innerHTML)">Do this</button> <button onclick="soundManager.stop('s-48khz')">Make it stop!</button>\r
+\r
+<h2>Demo 13: <code>autoLoad:true</code> + <code>play()</code> testcase</h2>\r
+<p>Bug testcase (Flash 8 version-specific): creating a sound with autoLoad:true and immediately calling play() does not work.</p>\r
+<pre id="demo13" class="block"><code>var autoLoadTest = soundManager.createSound({\r
+ id: '<span>autoLoadTest</span>',\r
+ url: getRandomMP3URL(),\r
+ onload: function() {\r
+ soundManager._writeDebug(this.id + '<span> loaded.</span>');\r
+ },\r
+ onplay: function() {\r
+ soundManager._writeDebug('<span>Starting sound: </span>'+this.id);\r
+ },\r
+ autoPlay: false,\r
+ autoLoad: true,\r
+ stream: true\r
+ });\r
+ <span><span>// autoLoadTest.play(); // sound will not start</span></span>\r
+ setTimeout(autoLoadTest.play,1000); <span><span>// may work with a delay?</span></span>\r
+</code></pre>\r
+<p>Under Flash 8, this case does not work as expected. Even with the delay, the sound does not begin playing as soon as expected - sometimes it fires after the sound loads, in fact. For this reason, avoid using <code class="in">autoLoad:true</code> if you intend to play the sound shortly after creating it when using Flash 8.</p>\r
+<button onclick="return doEval(document.getElementById('demo13').innerHTML)">Do this</button> <button onclick="soundManager.stop('autoLoadTest')">Make it stop!</button>\r
+\r
+<h2>Demo 14: <code>autoPlay</code> + <code>onfinish()</code> testcase</h2>\r
+<p>Bug testcase (Flash 8 version-specific): onfinish() does not fire with autoPlay:true</p>\r
+<pre id="demo14" class="block"><code>var sound = soundManager.createSound({\r
+ id: '<span>demo14</span>',\r
+ url: '<span>../mpc/audio/AMB_SN13.mp3</span>',\r
+ onfinish: function() {\r
+ soundManager._writeDebug(this.id + '<span> finished (now destroying)</span>');\r
+ <span><span>// destroy this sound</span></span>\r
+ this.destruct();\r
+ },\r
+ autoPlay: true,\r
+ multiShot: false\r
+});\r
+</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo14').innerHTML)">Do this</button>\r
+\r
+<h2>Demo 15: <code>onstop()</code> -> <code>unload()</code> testcase</h2>\r
+<p>Bug testcase: unload() from onstop() does not work</p>\r
+<pre id="demo15" class="block"><code>var sound16 = soundManager.createSound({\r
+ id: '<span>demo15</span>',\r
+ url: getRandomMP3URL(),\r
+ onstop: function() {\r
+ soundManager.unload(this.id);\r
+ },\r
+ onload: function() {\r
+ soundManager._writeDebug('<span>loaded</span>');\r
+ }\r
+});\r
+sound15.play();\r
+setTimeout(sound15.stop, 1500);\r
+</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo15').innerHTML)">Do this</button>\r
+\r
+<h2 id="buffering">Demo 16: Buffering event handler/property example (Flash 9 only)</h2>\r
+<p>Reporting the isBuffering property of a SMSound object</p>\r
+<pre id="demo16" class="block"><code>if (soundManager.flashVersion != 8) {\r
+ var sound16 = soundManager.createSound({\r
+ id: '<span>demo16</span>',\r
+ url: getRandomMP3URL(),\r
+ onbufferchange: function() {\r
+ soundManager._writeDebug('<span>Buffering </span>'+(this.isBuffering?'<span>started</span>': '<span>stopped</span>')+'<span>.</span>');\r
+ },\r
+ onload: function() {\r
+ soundManager._writeDebug(this.id + '<span> loaded.</span>');\r
+ }\r
+ });\r
+ sound16.play();\r
+}\r
+</code></pre>\r
+<button onclick="return doEval(document.getElementById('demo16').innerHTML)">Do this</button> <button onclick="soundManager.stop('demo16')">Make it stop!</button>\r
+\r
+<h2 id="html5-data-uri"><b>data:</b> URIs (HTML5 only, experimental)</h2>\r
+<p>Subject to browser support, a data: URI should work when provided to a native HTML5 <code>Audio()</code> instance.</p>\r
+<p>You should not use this unless you know what you're doing and are willing to rely only on HTML5 support.</p>\r
+<p>Additionally, data: URIs appear not to work on mobile devices (iOS: iPad, iPhone in particular.)</p>\r
+<p>IE 9 + 10 do not support WAV under HTML5 <code>Audio()</code>. In addition to being the only major browser lacking .WAV support, irony is not lost on the fact that MSFT co-created the WAV/RIFF spec with IBM. (See <a href="http://en.wikipedia.org/wiki/Wav" title=""WAV" on Wikipedia">yonder</a>.)</p>\r
+<script>\r
+function getWaveDataURI() {\r
+ return 'data:audio/wav;base64,UklGRiQEAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAEAAD//20GygwqE2QZlh+cJYIrOzHCNhE8KEH3RYVKxU62UlZWnlmKXBxfTGEaY4hkjGUuZmVmOWajZatkSWOGYV9f21z2WbtWI1M8TwVLfka6QaQ8ZDfbMSssTCZDIB8a3BOHDSUHugBQ+uzzku1O5xzhFNsj1W7P2MmKxGa/lLr5tbaxtK0TqrqmyqMnofGeE52em4ya4ZmZmcCZQ5o3m4icQ55boNmisaXiqHKsSrCCtPW4v72+wgbIfs0t0wnZCd8w5WzrwPEg+Iv+9QRcC7YR/hcuHkIkLSr0L4Q14joEQOZEgknUTdpRh1XrWORbkV7UYLpiP2RYZRNmYWZNZs5l62SjY/Vh5l91XaZaf1f7UyhQ/0uOR9NC0z2ZOCMzeS2oJ6EhihtIFfoOmgguAsj7W/UG77XohOJw3HnWttAYy7jFjsCluwG3pLKZrtyqeKdqpLqhaJ94nembw5r8maOZrJkdmveaMpzWndmfP6IEpR+onatjr4Wz7LehvJjBzMY8zN3Rsteo3cnj/OlR8Kr2Gf18A+sJRBCSFswc3yLcKKUuRzStOeI+zEOASNxM+VC6VCpYQlv8XVlgVmLuYyBl9GVVZl5m8mUoZfdjXWJpYAleU1s+WM5UD1H4TJZI7EP8Ps85ZTTJLvkoCCPsHLgWahAMCqcDOP3W9m/wKOrl49PdzNcG0lfM78azwb28CLics36vras3qBGlUqLjn+KdOpz9miGarpmgmfyZuprkm2ydXJ+soVmkZafIqoCuj7Lltom7ccCYxfrKk9Ba1kncY+KP6OHuOPWg+woCdQjUDiYVYRuEIYEnWS0EM3c4uT20QnRH5UsSUOVTaleYWmJd3V/nYZpj5mTKZUxmYWYWZl5lRWTGYt9gnl75W/hYoFXuUe1NnEkBRSNA/jqnNRIwUCpmJFAeJRjZEYELGgWx/kX45vGQ61PlLd8s2U3Tos0hyODC170WuZW0Z7CDrPmowqXmomygTJ6TnDubSpq/mZuZ3pmFmpmbCJ3lnhuhtqOspvqpo62aseK1d7pKv2vEuclMzwPV7tr94CXnce3D8y76kgADB18NuhP4GSIgJiYNLLkxRDeIPJpBZkbpSiVPD1OkVuhZx1xUX3thP2OlZJxlOWZlZjFmkGWPZCNjWWEpX5pcsFlqVstS4E6bShVGQ0EvPOQ2WjGjK8Eltx+MGUsT8QyRBiUAu/lX8//su+aS4ITaoNTozlvJDsT2viO6lrVSsWCtvql2poSj8qDBnuychZtymtuZlpnHmViaTpuvnG6ekqAYo/SlN6nCrK+w4LRnuS2+OcOCyP/NttOR2ZrfvOUC7FDyuvgd/4wF8AtHEpIYux7OJLcqdDAGNls7';\r
+}\r
+</script>\r
+<div style="max-width:50em;overflow:auto">\r
+<pre id="demo17" class="block"><code>if (soundManager.html5) {\r
+ soundManager.createSound({\r
+ <span><span>// explicit type, SM2 doesn't detect MIME type in data: URIs yet</span></span>\r
+ type: '<span>audio/wav</span>',\r
+ <span><span>// view source (or console) for the full URI.</span></span>\r
+ url: getWaveDataURI()\r
+ }).play();\r
+}</code></pre>\r
+</div>\r
+<button onclick="return doEval(document.getElementById('demo17').innerHTML)">Do this</button>\r
+\r
+<br />\r
+<br />\r
+\r
+<span id="flash-ram-use" title="Flash plugin RAM use (across this browser)" style="position:fixed;_position:absolute;top:0.5em;right:0.5em;background:#666;color:#fff;font-weight:bold;padding:0.3em 0.4em;cursor:pointer;cursor:hand;display:none" onclick="this.style.display='none';window.clearTimeout(t)">N/A</span>\r
+\r
+<div id="col3" style="position:absolute;position:fixed;_position:absolute;left:0px;top:0px;margin-top:0px;width:30em;padding:0px 0.5em;height:100%;border-right:1px solid #eee;overflow:auto;xbackground-color:#eee;z-index:2" class="c3">\r
+\r
+ <div id="shortcuts" style="padding:16px">\r
+\r
+ <h2>\r
+ SoundManager 2: Live API Demos\r
+ <span class="l"></span>\r
+ <span class="r"></span>\r
+ </h2>\r
+\r
+ <p>See your JS console for live debug/log output.</p>\r
+\r
+ <h3 class="wedge">\r
+ Getting Started\r
+ <span class="l"></span>\r
+ <span class="r"></span>\r
+ </h3>\r
+\r
+ <ul>\r
+ <li>\r
+\r
+ <ul>\r
+ <li><a href="#start"><code>soundManager.setup()</code> (url, onready etc.)</a></li>\r
+ <li><a href="#create">Create + play a sound</a></li>\r
+ <li><a href="#play-by-id"><code>soundManager.play()</code></a></li>\r
+ <li><a href="#play-with-sound-options"><code>play()</code> with sound options</a></li>\r
+ <li><a href="#debug-output">Debug output, minified versions</a></li>\r
+ </ul>\r
+ <h3 class="wedge">\r
+ Basic Events\r
+ <span class="l"></span>\r
+ <span class="r"></span>\r
+ </h3>\r
+ <ul>\r
+ <li><a href="#create-with-onload">Loading: <code>onload()</code> event</a></li>\r
+ <li><a href="#create-with-whileloading">Load progress: <code>whileloading()</code> event</a></li>\r
+ <li><a href="#create-play-onfinish">Play with <code>onfinish()</code></a></li>\r
+ <li><a href="#looping-conventional">Looping with <code>onfinish()</code></a></li>\r
+ <li><a href="#create-with-onfinish"><code>CreateSound()</code> and <code>play()</code> with events</a></li>\r
+ <li><a href="#onfinish-with-multishot-events">play() with <code>multiShotEvents</code></a></li>\r
+ <li><a href="#looping">Looping via <code>loops</code></a></li>\r
+ <li><a href="#buffering">Buffering: <code>onbufferchange()</code>, <code>isBuffering</code></a></li>\r
+ </ul>\r
+ <h3 class="wedge">\r
+ Timing / Audio Sprites\r
+ <span class="l"></span>\r
+ <span class="r"></span>\r
+ </h3>\r
+ <ul>\r
+ <li><a href="#onposition">Timing notifications via <code>onPosition()</code></a></li>\r
+ <li><a href="#onposition-2">Timing: <code>onPosition()</code> + <code>clearOnPosition()</code></a></li>\r
+ <li><a href="#from-to">Sound splicing with <code>from</code> + <code>to</code></a></li>\r
+ <li><a href="#fitter-happier">"Fitter, Happier" demo using <code>from</code> and <code>to</code></a></li>\r
+ <li><a href="#sound-timing-accuracy">Sound position accuracy test</a></li>\r
+ </ul>\r
+ <h3 class="wedge">\r
+ Miscellaneous\r
+ <span class="l"></span>\r
+ <span class="r"></span>\r
+ </h3>\r
+ <ul>\r
+ <li><a href="#muting">Muting a single sound</a></li>\r
+ <li><a href="#global-muting">Muting all sounds</a></li>\r
+ <li><a href="#create-play-unload-destroy">Create, play, unload, destroy</a></li>\r
+ <li><a href="#load-404">Playing a 404 (bad URL)</a></li>\r
+ </ul>\r
+\r
+ </li>\r
+ </ul>\r
+\r
+ <div id="live-debug-wrapper" style="display:none">\r
+\r
+ <h3 id="debug-logging" class="wedge">\r
+ Debug / Console Logging\r
+ <span class="l"></span>\r
+ <span class="r"></span>\r
+ </h3>\r
+\r
+ <p>This is live debug output; use your JS console for best detail.</p>\r
+\r
+ <div id="soundmanager-debug"></div>\r
+\r
+ </div>\r
+\r
+ <script>\r
+ // show live debug output if no console available.\r
+ soundManager.onready(function() {\r
+ var wrapper = document.getElementById('live-debug-wrapper');\r
+ if (typeof console === 'undefined' || typeof console.log === 'undefined' || navigator.userAgent.match(/mobile/i)) {\r
+ wrapper.style.display = 'block';\r
+ }\r
+ });\r
+ </script>\r
+\r
+ </div>\r
+</div>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>
--- /dev/null
+/**\r
+ * SoundManager 2: "Bar UI" player - CSS\r
+ * Copyright (c) 2014, Scott Schiller. All rights reserved.\r
+ * http://www.schillmania.com/projects/soundmanager2/\r
+ * Code provided under BSD license.\r
+ * http://schillmania.com/projects/soundmanager2/license.txt\r
+ */\r
+\r
+.sm2-bar-ui {\r
+ position: relative;\r
+ display: inline-block;\r
+ width: 100%;\r
+ font-family: helvetica, arial, verdana, sans-serif;\r
+ font-weight: normal;\r
+ /* prevent background border bleed */\r
+ -webkit-background-clip: padding-box;\r
+ background-clip: padding-box;\r
+ /* because indeed, fonts do look pretty "fat" otherwise in this case. */\r
+ -moz-osx-font-smoothing: grayscale;\r
+ -webkit-font-smoothing: antialiased;\r
+ /* general font niceness? */\r
+ font-smoothing: antialiased;\r
+ text-rendering: optimizeLegibility;\r
+ min-width: 20em;\r
+ max-width: 30em;\r
+ /* take out overflow if you want an absolutely-positioned playlist dropdown. */\r
+ border-radius: 2px;\r
+ overflow: hidden;\r
+ /* just for fun (animate normal / full-width) */\r
+ transition: max-width 0.2s ease-in-out;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist li {\r
+ text-align: center;\r
+ margin-top: -2px;\r
+ font-size: 95%;\r
+ line-height: 1em;\r
+}\r
+\r
+.sm2-bar-ui.compact {\r
+ min-width: 1em;\r
+ max-width: 15em;\r
+}\r
+\r
+.sm2-bar-ui ul {\r
+ line-height: 1em;\r
+}\r
+\r
+/* want things left-aligned? */\r
+.sm2-bar-ui.left .sm2-playlist li {\r
+ text-align: left;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist li .load-error {\r
+ cursor: help;\r
+}\r
+\r
+.sm2-bar-ui.full-width {\r
+ max-width: 100%;\r
+ z-index: 5;\r
+}\r
+\r
+.sm2-bar-ui.fixed {\r
+ position: fixed;\r
+ top: auto;\r
+ bottom: 0px;\r
+ left: 0px;\r
+ border-radius: 0px;\r
+ /* so the absolutely-positioned playlist can show... */\r
+ overflow: visible;\r
+ /* and this should probably have a high z-index. tweak as needed. */\r
+ z-index: 999;\r
+}\r
+\r
+.sm2-bar-ui.fixed .bd,\r
+.sm2-bar-ui.bottom .bd {\r
+ /* display: table; */\r
+ border-radius: 0px;\r
+ border-bottom: none;\r
+}\r
+\r
+.sm2-bar-ui.bottom {\r
+ /* absolute bottom-aligned UI */\r
+ top: auto;\r
+ bottom: 0px;\r
+ left: 0px;\r
+ border-radius: 0px;\r
+ /* so the absolutely-positioned playlist can show... */\r
+ overflow: visible;\r
+}\r
+\r
+.sm2-bar-ui.playlist-open .bd {\r
+ border-bottom-left-radius: 0px;\r
+ border-bottom-right-radius: 0px;\r
+ border-bottom-color: transparent;\r
+}\r
+\r
+.sm2-bar-ui .bd,\r
+.sm2-bar-ui .sm2-extra-controls {\r
+ position: relative;\r
+ background-color: #2288cc;\r
+ /*\r
+ transition: background 0.2s ease-in-out;\r
+ */\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-gradient {\r
+ /* gradient */\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 100%;\r
+ height: 100%;\r
+ background-image: -moz-linear-gradient(to bottom, rgba(255,255,255,0.125) 5%, rgba(255,255,255,0.125) 45%, rgba(255,255,255,0.15) 52%, rgba(0,0,0,0.01) 51%, rgba(0,0,0,0.1) 95%); /* W3C */\r
+ background-image: linear-gradient(to bottom, rgba(255,255,255,0.125) 5%, rgba(255,255,255,0.125) 45%, rgba(255,255,255,0.15) 50%, rgba(0,0,0,0.1) 51%, rgba(0,0,0,0.1) 95%); /* W3C */\r
+}\r
+\r
+.sm2-bar-ui.flat .sm2-inline-gradient {\r
+ background-image: none;\r
+}\r
+\r
+.sm2-bar-ui.flat .sm2-box-shadow {\r
+ display: none;\r
+ box-shadow: none;\r
+}\r
+\r
+.sm2-bar-ui.no-volume .sm2-volume {\r
+ /* mobile devices (android + iOS) ignore attempts to set volume. */\r
+ display: none;\r
+}\r
+\r
+.sm2-bar-ui.textured .sm2-inline-texture {\r
+ position: absolute;\r
+ top: 0px;\r
+ left: 0px;\r
+ width: 100%;\r
+ height: 100%;\r
+ /* for example */\r
+ /* background-image: url(../image/wood_pattern_dark.png); */\r
+ /* additional opacity effects can be applied here. */\r
+ opacity: 0.75;\r
+\r
+}\r
+\r
+.sm2-bar-ui.textured.dark-text .sm2-inline-texture {\r
+ /* dark text + textured case: use light wood background (for example.) */\r
+ /* background-image: url(../image/patterns/wood_pattern.png); */\r
+}\r
+\r
+.sm2-bar-ui.textured.dark-text .sm2-playlist-wrapper {\r
+ /* dark text + textured case: ditch 10% dark on playlist body. */\r
+ background-color: transparent;\r
+}\r
+\r
+.sm2-bar-ui.textured.dark-text .sm2-playlist-wrapper ul li:hover a,\r
+.sm2-bar-ui.textured.dark-text .sm2-playlist-wrapper ul li.selected a {\r
+ /* dark + textured case: dark highlights */\r
+ background-color: rgba(0,0,0,0.1);\r
+ background-image: url(../image/black-10.png);\r
+ /* modern browsers don't neeed the image */\r
+ background-image: none, none;\r
+}\r
+\r
+.sm2-bar-ui .bd {\r
+ display: table;\r
+ border-bottom: none;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist-wrapper {\r
+ background-color: rgba(0,0,0,0.1);\r
+}\r
+\r
+.sm2-bar-ui .sm2-extra-controls .bd {\r
+ background-color: rgba(0,0,0,0.2);\r
+}\r
+\r
+\r
+.sm2-bar-ui.textured .sm2-extra-controls .bd {\r
+ /* lighten extra color overlays */\r
+ background-color: rgba(0,0,0,0.05);\r
+}\r
+\r
+.sm2-bar-ui .sm2-extra-controls {\r
+ background-color: transparent;\r
+ border: none;\r
+}\r
+\r
+.sm2-bar-ui .sm2-extra-controls .bd {\r
+ /* override full-width table behaviour */\r
+ display: block;\r
+ border: none;\r
+}\r
+\r
+.sm2-bar-ui .sm2-extra-controls .sm2-inline-element {\r
+ display: inline-block;\r
+}\r
+\r
+.sm2-bar-ui,\r
+.sm2-bar-ui .bd a {\r
+ color: #fff;\r
+}\r
+\r
+.sm2-bar-ui.dark-text,\r
+.sm2-bar-ui.dark-text .bd a {\r
+ color: #000;\r
+}\r
+\r
+.sm2-bar-ui.dark-text .sm2-inline-button {\r
+ /* Warning/disclaimer: SVG might be fuzzy when inverted on Chrome, losing resolution on hi-DPI displays. */\r
+ -webkit-filter: invert(1);\r
+ /* SVG-based invert filter for Firefox */\r
+ filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'invert\'><feColorMatrix in='SourceGraphic' type='matrix' values='-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0'/></filter></svg>#invert");\r
+ /* IE 8 inverse filter, may only match pure black/white */\r
+ /* filter: xray; */\r
+ /* pending W3 standard */\r
+ filter: invert(1);\r
+ /* not you, IE < 10. */\r
+ filter: none\9;\r
+}\r
+\r
+.sm2-bar-ui .bd a {\r
+ text-decoration: none;\r
+}\r
+\r
+.sm2-bar-ui .bd .sm2-button-element:hover {\r
+ background-color: rgba(0,0,0,0.1);\r
+ background-image: url(../image/black-10.png);\r
+ background-image: none, none;\r
+}\r
+\r
+.sm2-bar-ui .bd .sm2-button-element:active {\r
+ background-color: rgba(0,0,0,0.25);\r
+ background-image: url(../image/black-25.png);\r
+ background-image: none, none;\r
+}\r
+\r
+.sm2-bar-ui .bd .sm2-extra-controls .sm2-button-element:active .sm2-inline-button,\r
+.sm2-bar-ui .bd .active .sm2-inline-button/*,\r
+.sm2-bar-ui.playlist-open .sm2-menu a */{\r
+ -ms-transform: scale(0.9);\r
+ -webkit-transform: scale(0.9);\r
+ -webkit-transform-origin: 50% 50%;\r
+ /* firefox doesn't scale quite right. */\r
+ transform: scale(0.9);\r
+ transform-origin: 50% 50%;\r
+ /* firefox doesn't scale quite right. */\r
+ -moz-transform: none;\r
+}\r
+\r
+.sm2-bar-ui .bd .sm2-extra-controls .sm2-button-element:hover,\r
+.sm2-bar-ui .bd .sm2-extra-controls .sm2-button-element:active,\r
+.sm2-bar-ui .bd .active {\r
+ background-color: rgba(0,0,0,0.1);\r
+ background-image: url(../image/black-10.png);\r
+ background-image: none, none;\r
+}\r
+\r
+.sm2-bar-ui .bd .sm2-extra-controls .sm2-button-element:active {\r
+ /* box shadow is excessive on smaller elements. */\r
+ box-shadow: none;\r
+}\r
+\r
+.sm2-bar-ui {\r
+ /* base font size */\r
+ font-size: 15px;\r
+ text-shadow: none;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-element {\r
+ position: relative;\r
+ display: inline-block;\r
+ vertical-align: middle;\r
+ padding: 0px;\r
+ overflow: hidden;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-element,\r
+.sm2-bar-ui .sm2-button-element .sm2-button-bd {\r
+ position: relative;\r
+ /**\r
+ * .sm2-button-bd exists because of a Firefox bug from 2000\r
+ * re: nested relative / absolute elements inside table cells.\r
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=63895\r
+ */\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-element,\r
+.sm2-bar-ui .sm2-button-element .sm2-button-bd {\r
+ /**\r
+ * if you play with UI width/height, these are the important ones.\r
+ * NOTE: match these values if you want square UI buttons.\r
+ */\r
+ min-width: 2.8em;\r
+ min-height: 2.8em;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-button {\r
+ position: absolute;\r
+ top: 0px;\r
+ left: 0px;\r
+ width: 100%;\r
+ height: 100%;\r
+}\r
+\r
+.sm2-bar-ui .sm2-extra-controls .bd {\r
+ /* don't double-layer. */\r
+ background-image: none;\r
+ background-color: rgba(0,0,0,0.15);\r
+}\r
+\r
+.sm2-bar-ui .sm2-extra-controls .sm2-inline-element {\r
+ width: 25px; /* bare minimum */\r
+ min-height: 1.75em;\r
+ min-width: 2.5em;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-status {\r
+ line-height: 100%;\r
+ /* how much to allow before truncating song artist / title with ellipsis */\r
+ display: inline-block;\r
+ min-width: 200px;\r
+ max-width: 20em;\r
+ /* a little more spacing */\r
+ padding-left: 0.75em;\r
+ padding-right: 0.75em;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-element {\r
+ /* extra-small em scales up nicely, vs. 1px which gets fat */\r
+ border-right: 0.075em dotted #666; /* legacy */\r
+ border-right: 0.075em solid rgba(0,0,0,0.1);\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-element.noborder {\r
+ border-right: none;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-element.compact {\r
+ min-width: 2em;\r
+ padding: 0px 0.25em;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-element:first-of-type {\r
+ border-top-left-radius: 3px;\r
+ border-bottom-left-radius: 3px;\r
+ overflow: hidden;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-element:last-of-type {\r
+ border-right: none;\r
+ border-top-right-radius: 3px;\r
+ border-bottom-right-radius: 3px;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-status a:hover {\r
+ background-color: transparent;\r
+ text-decoration: underline;\r
+}\r
+\r
+.sm2-inline-time,\r
+.sm2-inline-duration {\r
+ display: table-cell;\r
+ width: 1%;\r
+ font-size: 75%;\r
+ line-height: 0.9em;\r
+ min-width: 2em; /* if you have sounds > 10:00 in length, make this bigger. */\r
+ vertical-align: middle;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist {\r
+ position: relative;\r
+ height: 1.45em;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist-target {\r
+ /* initial render / empty case */\r
+ position: relative;\r
+ min-height: 1em;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist ul {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 100%;\r
+ list-style-type: none;\r
+ overflow: hidden;\r
+ white-space: nowrap;\r
+ text-overflow: ellipsis;\r
+}\r
+\r
+.sm2-bar-ui p,\r
+.sm2-bar-ui .sm2-playlist ul,\r
+.sm2-bar-ui .sm2-playlist ul li {\r
+ margin: 0px;\r
+ padding: 0px;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist ul li {\r
+ position: relative;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist ul li,\r
+.sm2-bar-ui .sm2-playlist ul li a {\r
+ position: relative;\r
+ display: block;\r
+ /* prevent clipping of characters like "g" */\r
+ height: 1.5em;\r
+ white-space: nowrap;\r
+ overflow: hidden;\r
+ text-overflow: ellipsis;\r
+ text-align: center;\r
+}\r
+\r
+.sm2-row {\r
+ position: relative;\r
+ display: table-row;\r
+}\r
+\r
+.sm2-progress-bd {\r
+ /* spacing between progress track/ball and time (position) */\r
+ padding: 0px 0.8em;\r
+}\r
+\r
+.sm2-progress .sm2-progress-track,\r
+.sm2-progress .sm2-progress-ball,\r
+.sm2-progress .sm2-progress-bar {\r
+ position: relative;\r
+ width: 100%;\r
+ height: 0.65em;\r
+ border-radius: 0.65em;\r
+}\r
+\r
+.sm2-progress .sm2-progress-bar {\r
+ /* element which follows the progres "ball" as it moves */\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 0px;\r
+ background-color: rgba(0,0,0,0.33);\r
+ background-image: url(../image/black-33.png);\r
+ background-image: none, none;\r
+}\r
+\r
+.volume-shade,\r
+.playing .sm2-progress .sm2-progress-track,\r
+.paused .sm2-progress .sm2-progress-track {\r
+ cursor: pointer;\r
+}\r
+\r
+.playing .sm2-progress .sm2-progress-ball {\r
+ cursor: -moz-grab;\r
+ cursor: -webkit-grab;\r
+ cursor: grab;\r
+}\r
+\r
+.sm2-progress .sm2-progress-ball {\r
+ position: absolute;\r
+ top: 0px;\r
+ left: 0px;\r
+ width: 1em;\r
+ height: 1em;\r
+ margin: -0.2em 0px 0px -0.5em;\r
+ width: 14px;\r
+ height: 14px;\r
+ margin: -2px 0px 0px -7px;\r
+ width: 0.9333em;\r
+ height: 0.9333em;\r
+ margin: -0.175em 0px 0px -0.466em;\r
+ background-color: #fff;\r
+ padding: 0px;\r
+/*\r
+ z-index: 1;\r
+*/\r
+ -webkit-transition: -webkit-transform 0.15s ease-in-out;\r
+ transition: transform 0.15s ease-in-out;\r
+}\r
+\r
+/*\r
+.sm2-bar-ui.dark-text .sm2-progress .sm2-progress-ball {\r
+ background-color: #000;\r
+}\r
+*/\r
+\r
+.sm2-progress .sm2-progress-track {\r
+ background-color: rgba(0,0,0,0.4);\r
+ background-image: url(../image/black-33.png); /* legacy */\r
+ background-image: none, none; /* modern browsers */\r
+}\r
+\r
+/* scrollbar rules have to be separate, browsers not supporting this syntax will skip them when combined. */\r
+.sm2-playlist-wrapper ul::-webkit-scrollbar-track {\r
+ background-color: rgba(0,0,0,0.4);\r
+}\r
+\r
+.playing.grabbing .sm2-progress .sm2-progress-track,\r
+.playing.grabbing .sm2-progress .sm2-progress-ball {\r
+ cursor: -moz-grabbing;\r
+ cursor: -webkit-grabbing;\r
+ cursor: grabbing;\r
+}\r
+\r
+.sm2-bar-ui.grabbing .sm2-progress .sm2-progress-ball {\r
+ -webkit-transform: scale(1.15);\r
+ transform: scale(1.15);\r
+}\r
+\r
+.sm2-inline-button {\r
+ background-position: 50% 50%;\r
+ background-repeat: no-repeat;\r
+ /* hide inner text */\r
+ line-height: 10em;\r
+ /**\r
+ * image-rendering seems to apply mostly to Firefox in this case. Use with caution.\r
+ * https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering#Browser_compatibility\r
+ */\r
+ image-rendering: -moz-crisp-edges;\r
+ image-rendering: -webkit-optimize-contrast;\r
+ image-rendering: crisp-edges;\r
+ -ms-interpolation-mode: nearest-neighbor;\r
+ -ms-interpolation-mode: bicubic;\r
+}\r
+\r
+.play-pause,\r
+.play-pause:hover,\r
+.paused .play-pause:hover {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/play.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/play.svg);\r
+ background-size: 67.5%;\r
+ background-position: 40% 53%;\r
+}\r
+\r
+.playing .play-pause {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/pause.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/pause.svg);\r
+ background-size: 57.6%;\r
+ background-position: 50% 53%;\r
+}\r
+\r
+.sm2-volume-control {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/volume.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/volume.svg);\r
+}\r
+\r
+.sm2-volume-control,\r
+.sm2-volume-shade {\r
+ background-position: 42% 50%;\r
+ background-size: 56%;\r
+}\r
+\r
+.volume-shade {\r
+ filter: alpha(opacity=33); /* <= IE 8 */\r
+ opacity: 0.33;\r
+/* -webkit-filter: invert(1);*/\r
+ background-image: url(../image/icomoon/entypo-25px-000000/PNG/volume.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-000000/SVG/volume.svg);\r
+}\r
+\r
+.menu {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/list2.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/list2.svg);\r
+ background-size: 58%;\r
+ background-position: 54% 51%;\r
+}\r
+\r
+.previous {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/first.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/first.svg);\r
+}\r
+\r
+.next {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/last.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/last.svg);\r
+}\r
+\r
+.previous,\r
+.next {\r
+ background-size: 49.5%;\r
+ background-position: 50% 50%;\r
+}\r
+\r
+\r
+.sm2-extra-controls .previous,\r
+.sm2-extra-controls .next {\r
+ backgound-size: 53%;\r
+}\r
+\r
+.shuffle {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/shuffle.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/shuffle.svg);\r
+ background-size: 45%;\r
+ background-position: 50% 50%;\r
+}\r
+\r
+.repeat {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/loop.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/loop.svg);\r
+ background-position: 50% 43%;\r
+ background-size: 54%;\r
+}\r
+\r
+.sm2-extra-controls .repeat {\r
+ background-position: 50% 45%;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-row {\r
+ display: table;\r
+ width: 100%;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-col {\r
+ display: table-cell;\r
+ vertical-align: top;\r
+ /* by default, collapse. */\r
+ width: 0%;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-col.sm2-wide {\r
+ /* take 100% width. */\r
+ width: 100%;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-icon {\r
+ display: inline-block;\r
+ overflow: hidden;\r
+ width: 2em;\r
+ color: transparent !important; /* hide text */\r
+ white-space: nowrap; /* don't let text affect height */\r
+ padding-left: 0px;\r
+ padding-right: 0px;\r
+ text-indent: 2em; /* IE 8, mostly */\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-icon,\r
+.sm2-playlist-wrapper ul li:hover .sm2-icon,\r
+.sm2-playlist-wrapper ul li.selected .sm2-icon {\r
+ background-size: 55%;\r
+ background-position: 50% 50%;\r
+ background-repeat: no-repeat;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-col {\r
+ /* sibling table cells get borders. */\r
+ border-right: 1px solid rgba(0,0,0,0.075);\r
+}\r
+\r
+.sm2-playlist-wrapper ul li.selected .sm2-col {\r
+ border-color: rgba(255,255,255,0.075);\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-col:last-of-type {\r
+ border-right: none;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-cart,\r
+.sm2-playlist-wrapper ul li:hover .sm2-cart,\r
+.sm2-playlist-wrapper ul li.selected .sm2-cart {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/cart.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/cart.svg);\r
+ /* slight alignment tweak */\r
+ background-position: 48% 50%;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-music,\r
+.sm2-playlist-wrapper ul li:hover .sm2-music,\r
+.sm2-playlist-wrapper ul li.selected .sm2-music {\r
+ background-image: url(../image/icomoon/entypo-25px-ffffff/PNG/music.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-ffffff/SVG/music.svg);\r
+}\r
+\r
+.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li .sm2-cart,\r
+.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li:hover .sm2-cart,\r
+.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li.selected .sm2-cart {\r
+ background-image: url(../image/icomoon/entypo-25px-000000/PNG/cart.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-000000/SVG/cart.svg);\r
+}\r
+\r
+.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li .sm2-music,\r
+.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li:hover .sm2-music,\r
+.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li.selected .sm2-music {\r
+ background-image: url(../image/icomoon/entypo-25px-000000/PNG/music.png);\r
+ background-image: none, url(../image/icomoon/entypo-25px-000000/SVG/music.svg);\r
+}\r
+\r
+\r
+.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li .sm2-col {\r
+ border-left-color: rgba(0,0,0,0.15);\r
+}\r
+\r
+.sm2-playlist-wrapper ul li .sm2-icon:hover {\r
+ background-color: rgba(0,0,0,0.33);\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist-wrapper ul li .sm2-icon:hover {\r
+ background-color: rgba(0,0,0,0.45);\r
+}\r
+\r
+.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li.selected .sm2-icon:hover {\r
+ background-color: rgba(255,255,255,0.25);\r
+ border-color: rgba(0,0,0,0.125);\r
+}\r
+\r
+.sm2-progress-ball .icon-overlay {\r
+ position: absolute;\r
+ width: 100%;\r
+ height: 100%;\r
+ top: 0px;\r
+ left: 0px;\r
+ background: none, url(../image/icomoon/free-25px-000000/SVG/spinner.svg);\r
+ background-size: 72%;\r
+ background-position: 50%;\r
+ background-repeat: no-repeat;\r
+ display: none; \r
+}\r
+\r
+.playing.buffering .sm2-progress-ball .icon-overlay {\r
+ display: block;\r
+ -webkit-animation: spin 0.6s linear infinite;\r
+ animation: spin 0.6s linear infinite;\r
+}\r
+\r
+@-webkit-keyframes spin {\r
+ 0% {\r
+ -webkit-transform: rotate(0deg);\r
+ }\r
+ 100% {\r
+ -webkit-transform: rotate(360deg);\r
+ }\r
+}\r
+\r
+@-moz-keyframes spin {\r
+ 0% {\r
+ transform: rotate(0deg);\r
+ }\r
+ 100% {\r
+ transform: rotate(360deg);\r
+ }\r
+}\r
+\r
+@keyframes spin {\r
+ 0% {\r
+ transform: rotate(0deg);\r
+ }\r
+ 100% {\r
+ transform: rotate(360deg);\r
+ }\r
+}\r
+\r
+.sm2-element ul {\r
+ font-size: 95%;\r
+ list-style-type: none;\r
+}\r
+\r
+.sm2-element ul,\r
+.sm2-element ul li {\r
+ margin: 0px;\r
+ padding: 0px;\r
+}\r
+\r
+.bd.sm2-playlist-drawer {\r
+ /* optional: absolute positioning */\r
+ /* position: absolute; */\r
+ z-index: 3;\r
+ border-radius: 0px;\r
+ width: 100%;\r
+ height: 0px;\r
+ border: none;\r
+ background-image: none;\r
+ display: block;\r
+ overflow: hidden;\r
+ transition: height 0.2s ease-in-out;\r
+}\r
+\r
+.sm2-bar-ui.fixed .bd.sm2-playlist-drawer,\r
+.sm2-bar-ui.bottom .bd.sm2-playlist-drawer {\r
+ position: absolute;\r
+}\r
+\r
+.sm2-bar-ui.fixed .sm2-playlist-wrapper,\r
+.sm2-bar-ui.bottom .sm2-playlist-wrapper {\r
+ padding-bottom: 0px;\r
+}\r
+\r
+.sm2-bar-ui.fixed .bd.sm2-playlist-drawer,\r
+.sm2-bar-ui.bottom .bd.sm2-playlist-drawer {\r
+ /* show playlist on top */\r
+ bottom: 2.8em;\r
+}\r
+\r
+.sm2-bar-ui .bd.sm2-playlist-drawer {\r
+ opacity: 0.5;\r
+ /* redraw fix for Chrome, background color doesn't always draw when playlist drawer open. */\r
+ transform: translateZ(0);\r
+}\r
+\r
+/* experimental, may not perform well. */\r
+/*\r
+.sm2-bar-ui .bd.sm2-playlist-drawer a {\r
+ -webkit-filter: blur(5px);\r
+}\r
+*/\r
+\r
+.sm2-bar-ui.playlist-open .bd.sm2-playlist-drawer {\r
+ height: auto;\r
+ opacity: 1;\r
+}\r
+\r
+.sm2-bar-ui.playlist-open .bd.sm2-playlist-drawer a {\r
+ -webkit-filter: none; /* blur(0px) was still blurred on retina displays, as of 07/2014 */\r
+}\r
+\r
+.sm2-bar-ui.fixed.playlist-open .bd.sm2-playlist-drawer .sm2-playlist-wrapper,\r
+.sm2-bar-ui.bottom.playlist-open .bd.sm2-playlist-drawer .sm2-playlist-wrapper {\r
+ /* extra padding when open */\r
+ padding-bottom: 0.5em;\r
+ box-shadow: none;\r
+}\r
+\r
+.sm2-bar-ui .bd.sm2-playlist-drawer {\r
+ transition: all 0.2s ease-in-out;\r
+ transition-property: transform, height, opacity, background-color, -webkit-filter;\r
+}\r
+\r
+.sm2-bar-ui .bd.sm2-playlist-drawer a {\r
+ transition: -webkit-filter 0.2s ease-in-out;\r
+}\r
+\r
+.sm2-bar-ui .bd.sm2-playlist-drawer .sm2-inline-texture {\r
+ /* negative offset for height of top bar, so background is seamless. */\r
+ background-position: 0px -2.8em;\r
+}\r
+\r
+.sm2-box-shadow {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 100%;\r
+ height: 100%;\r
+ box-shadow: inset 0px 1px 6px rgba(0,0,0,0.15);\r
+}\r
+\r
+.sm2-playlist-wrapper {\r
+ position: relative;\r
+ padding: 0.5em 0.5em 0.5em 0.25em;\r
+ background-image: none, none;\r
+}\r
+\r
+.sm2-playlist-wrapper ul {\r
+ max-height: 9.25em;\r
+ overflow: auto;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li {\r
+ border-bottom: 1px solid rgba(0,0,0,0.05);\r
+}\r
+\r
+.sm2-playlist-wrapper ul li:nth-child(odd) {\r
+ background-color: rgba(255,255,255,0.03);\r
+}\r
+\r
+.sm2-playlist-wrapper ul li a {\r
+ display: block;\r
+ padding: 0.5em 0.25em 0.5em 0.75em;\r
+ margin-right: 0px;\r
+ font-size: 90%;\r
+ vertical-align: middle;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li a.sm2-exclude {\r
+ display: inline-block;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li a.sm2-exclude .label {\r
+ font-size: 95%;\r
+ line-height: 1em;\r
+ margin-left: 0px;\r
+ padding: 2px 4px;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li:hover a {\r
+ background-color: rgba(0,0,0,0.20);\r
+ background-image: url(../image/black-20.png);\r
+ background-image: none, none;\r
+}\r
+\r
+.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li:hover a {\r
+ background-color: rgba(255,255,255,0.1);\r
+ background-image: url(../image/black-10.png);\r
+ background-image: none, none;\r
+}\r
+\r
+.sm2-playlist-wrapper ul li.selected a {\r
+ background-color: rgba(0,0,0,0.25);\r
+ background-image: url(../image/black-20.png);\r
+ background-image: none, none;\r
+}\r
+\r
+.sm2-bar-ui.dark-text ul li.selected a {\r
+ background-color: rgba(255,255,255,0.1);\r
+ background-image: url(../image/black-10.png);\r
+ background-image: none, none; \r
+}\r
+\r
+.sm2-bar-ui .disabled {\r
+ filter: alpha(opacity=33); /* <= IE 8 */\r
+ opacity: 0.33;\r
+}\r
+\r
+.sm2-bar-ui .bd .sm2-button-element.disabled:hover {\r
+ background-color: transparent;\r
+}\r
+\r
+.sm2-bar-ui .active,\r
+/*.sm2-bar-ui.playlist-open .sm2-menu,*/\r
+.sm2-bar-ui.playlist-open .sm2-menu:hover {\r
+ /* depressed / "on" state */\r
+ box-shadow: inset 0px 0px 2px rgba(0,0,0,0.1);\r
+ background-image: none;\r
+}\r
+\r
+.firefox-fix {\r
+ /**\r
+ * This exists because of a Firefox bug from 2000\r
+ * re: nested relative / absolute elements inside table cells.\r
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=63895\r
+ */\r
+ position: relative;\r
+ display: inline-block;\r
+ width: 100%;\r
+ height: 100%;\r
+}\r
+\r
+/* some custom scrollbar trickery, where supported */\r
+\r
+.sm2-playlist-wrapper ul::-webkit-scrollbar {\r
+ width: 10px;\r
+}\r
+\r
+.sm2-playlist-wrapper ul::-webkit-scrollbar-track {\r
+ background: rgba(0,0,0,0.33);\r
+ border-radius: 10px;\r
+}\r
+ \r
+.sm2-playlist-wrapper ul::-webkit-scrollbar-thumb {\r
+ border-radius: 10px;\r
+ background: #fff;\r
+}\r
+\r
+.sm2-extra-controls {\r
+ font-size: 0px;\r
+ text-align: center;\r
+}\r
+\r
+.sm2-bar-ui .label {\r
+ position: relative;\r
+ display: inline-block;\r
+ font-size: 0.7em;\r
+ margin-left: 0.25em;\r
+ vertical-align: top;\r
+ background-color: rgba(0,0,0,0.25);\r
+ border-radius: 3px;\r
+ padding: 0px 3px;\r
+ box-sizing: padding-box;\r
+}\r
+\r
+.sm2-bar-ui.dark-text .label {\r
+ background-color: rgba(0,0,0,0.1);\r
+ background-image: url(../image/black-10.png);\r
+ background-image: none, none;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist-drawer .label {\r
+ font-size: 0.8em;\r
+ padding: 0px 3px;\r
+}\r
+\r
+/* --- full width stuff --- */\r
+\r
+.sm2-bar-ui .sm2-inline-element {\r
+ display: table-cell;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-element {\r
+ /* collapse */\r
+ width: 1%;\r
+}\r
+\r
+.sm2-bar-ui .sm2-inline-status {\r
+ /* full width */\r
+ width: 100%;\r
+ min-width: 100%;\r
+ max-width: 100%;\r
+}\r
+\r
+.sm2-bar-ui > .bd {\r
+ width: 100%;\r
+}\r
+\r
+.sm2-bar-ui .sm2-playlist-drawer {\r
+ /* re-hide playlist */\r
+ display: block;\r
+ overflow: hidden;\r
+}\r
--- /dev/null
+/* demo only */\r
+\r
+html {\r
+ position: relative;\r
+ width: 100%;\r
+ height: 100%;\r
+ min-width: 980px; /* enough for two-column demo UI */\r
+ -moz-osx-font-smoothing: grayscale;\r
+ -webkit-font-smoothing: antialiased;\r
+ /* http://files.christophzillgens.com/webkit-font-smoothing.html */\r
+ /* font-smoothing: subpixel-antialiased; */\r
+ /* general font niceness? */\r
+ font-smoothing: antialiased;\r
+ text-rendering: optimizeLegibility;\r
+ background: #fff;\r
+ color: #000;\r
+ transition: background 0.2s ease-in-out;\r
+}\r
+\r
+body {\r
+ font-family: helvetica, verdana, tahoma, arial, sans-serif;\r
+ font-weight: 300;\r
+ margin: 0px;\r
+ padding: 0.5em;\r
+ transition: color 0.2s ease-in-out;\r
+ padding-bottom: 64px; /* room for the bottom bar UI player */\r
+}\r
+\r
+h1 {\r
+ display: inline-block;\r
+ font-family: "helvetica neue", helvetica, verdana, tahoma, arial, sans-serif;\r
+ font-size: 2em;\r
+ font-weight: 300;\r
+ margin: 0px 0px 0.25em 0px;\r
+ padding: 0px 0px 0.15em 0px;\r
+ border-bottom: 1px dotted #ccc;\r
+}\r
+\r
+h1 a {\r
+ font-size: 100%;\r
+ text-decoration: none;\r
+ color: #000;\r
+}\r
+\r
+h1 a:hover {\r
+ color: #336699;\r
+ text-decoration: underline;\r
+}\r
+\r
+h2 {\r
+ margin: 0px;\r
+ padding: 0px;\r
+ font-weight: 300;\r
+}\r
+\r
+h3 {\r
+ font-weight: 300;\r
+ margin: 1em 0px 0.5em 0px;\r
+ padding: 0px;\r
+}\r
+\r
+p {\r
+ margin-top: 0.5em;\r
+}\r
+\r
+.demo-wrapper {\r
+ position: relative;\r
+ width: 100%;\r
+ /* whitespace trickery */\r
+ font-size: 0px;\r
+}\r
+\r
+.demo-left,\r
+.demo-right {\r
+ font-size: 16px;\r
+ font-size: 1rem;\r
+ position: relative;\r
+ display: inline-block;\r
+ width: 48%;\r
+ vertical-align: top;\r
+}\r
+\r
+.demo-left {\r
+ margin-right: 2%;\r
+ border-right: 1px dotted transparent;\r
+}\r
+\r
+.demo-wrapper .demo-bd {\r
+ padding-right: 1em;\r
+}\r
+\r
+.demo-right {\r
+ left: -1px; /* sneaky */\r
+ margin-left: -2%;\r
+ border-left: 1px dotted transparent;\r
+}\r
+\r
+.demo-left,\r
+.demo-right {\r
+ border-color: #ccc;\r
+}\r
+\r
+.demo-right .demo-bd {\r
+ padding-left: 1em;\r
+ padding-right: 0.5em;\r
+}\r
+\r
+.about {\r
+ color: #333;\r
+ font-size: small;\r
+ line-height: 1.5em;\r
+ margin-bottom: 0.5em;\r
+}\r
+\r
+.about a {\r
+ text-decoration: none;\r
+}\r
+\r
+.note {\r
+ font-size: 0.5em;\r
+ color: #333;\r
+}\r
+\r
+#size-field {\r
+ vertical-align: middle;\r
+}\r
+\r
+#colors {\r
+ margin-bottom: 0.5em;\r
+}\r
+\r
+#colors * {\r
+ vertical-align: middle;\r
+}\r
+\r
+.sm2-bar-ui {\r
+ /* demo silliness */\r
+ transition: all 0.2s ease-in-out;\r
+}
\ No newline at end of file
--- /dev/null
+SVG icons via Icomoon
+https://icomoon.io/app
+
+Icons used from the following sets:
+* Entypo - Creative Commons BY-SA 3.0 http://creativecommons.org/licenses/by-sa/3.0/us/
+* IcoMoon - Free (GPL) http://www.gnu.org/licenses/gpl.html
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M20.002 7.75h-13.5v-2.75l-5.25 4.5 5.25 4.5v-2.75h12.5v5.25h-16.25v3.5h17.25c1.38 0 2.5-1.12 2.5-2.5v-7.25c0-1.381-1.121-2.5-2.5-2.5z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M5 21.25c0 1.38 1.12 2.5 2.5 2.5 1.381 0 2.5-1.12 2.5-2.5s-1.119-2.5-2.5-2.5c-1.38 0-2.5 1.12-2.5 2.5zM17.5 21.25c0 1.38 1.12 2.5 2.5 2.5 1.381 0 2.5-1.12 2.5-2.5s-1.119-2.5-2.5-2.5c-1.38 0-2.5 1.12-2.5 2.5zM9.434 15.34l13.836-3.952c0.264-0.076 0.48-0.363 0.48-0.638v-6.875h-17.625v-2.125c0-0.275-0.224-0.5-0.5-0.5h-3.875c-0.275 0-0.5 0.225-0.5 0.5v2h2.429l2.46 11.321 0.238 1.179v1.875c0 0.275 0.225 0.5 0.499 0.5h16.376c0.274 0 0.499-0.225 0.499-0.5v-1.875h-14.060c-1.436 0-1.466-0.562-0.256-0.91z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M9.356 12.5c0 0.323 0.327 0.552 0.327 0.552l9.094 5.711c0.674 0.441 1.223 0.116 1.223-0.719v-11.090c0-0.836-0.549-1.161-1.223-0.72l-9.094 5.713c0 0.001-0.327 0.23-0.327 0.552zM5 6.696v11.607c0 1.11 0.765 1.45 1.875 1.45s1.875-0.34 1.875-1.449v-11.609c0-1.111-0.765-1.451-1.875-1.451s-1.875 0.341-1.875 1.451z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M15.316 11.948l-9.094-5.713c-0.673-0.44-1.223-0.116-1.223 0.721v11.089c0 0.837 0.55 1.16 1.223 0.72l9.094-5.711c0 0 0.329-0.231 0.329-0.552s-0.329-0.554-0.329-0.554zM18.125 5.245c-1.11 0-1.875 0.341-1.875 1.451v11.607c0 1.111 0.765 1.452 1.875 1.452s1.875-0.341 1.875-1.452v-11.607c0-1.11-0.765-1.451-1.875-1.451z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M6.25 16.25h-1.25c-0.69 0-1.25 0.559-1.25 1.25s0.56 1.25 1.25 1.25h1.25c0.69 0 1.25-0.559 1.25-1.25s-0.56-1.25-1.25-1.25zM6.25 11.25h-1.25c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25h1.25c0.69 0 1.25-0.56 1.25-1.25s-0.56-1.25-1.25-1.25zM6.25 6.25h-1.25c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25h1.25c0.69 0 1.25-0.56 1.25-1.25s-0.56-1.25-1.25-1.25zM11.25 8.75h8.75c0.691 0 1.25-0.56 1.25-1.25s-0.559-1.25-1.25-1.25h-8.75c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25zM20 11.25h-8.75c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25h8.75c0.691 0 1.25-0.56 1.25-1.25s-0.559-1.25-1.25-1.25zM20 16.25h-8.75c-0.69 0-1.25 0.559-1.25 1.25s0.56 1.25 1.25 1.25h8.75c0.691 0 1.25-0.559 1.25-1.25s-0.559-1.25-1.25-1.25z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M20 11.25h-15c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25h15c0.691 0 1.25-0.56 1.25-1.25s-0.559-1.25-1.25-1.25zM5 8.75h15c0.691 0 1.25-0.56 1.25-1.25s-0.559-1.25-1.25-1.25h-15c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25zM20 16.25h-15c-0.69 0-1.25 0.559-1.25 1.25s0.56 1.25 1.25 1.25h15c0.691 0 1.25-0.559 1.25-1.25s-0.559-1.25-1.25-1.25z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M21.25 7.75h-4.75v3.5h3.75v5.25h-15.5v-5.25h5.25v2.75l5-4.5-5-4.5v2.75h-6.25c-1.38 0-2.5 1.119-2.5 2.5v7.25c0 1.38 1.12 2.5 2.5 2.5h17.5c1.381 0 2.5-1.12 2.5-2.5v-7.25c0-1.381-1.119-2.5-2.5-2.5z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M18.75 1.25h-12.5c-1.375 0-2.5 1.125-2.5 2.5v17.5c0 1.375 1.125 2.5 2.5 2.5h12.5c1.376 0 2.5-1.125 2.5-2.5v-17.5c0-1.375-1.124-2.5-2.5-2.5zM15.995 13.151c-0.296 0.463-0.454 0.265-0.365 0 0.235-0.698 0.226-2.809-1.74-3.118v6.516c0 1.215-0.7 1.977-2.188 2.455-1.445 0.462-3.063-0.019-3.441-1.057-0.377-1.037 0.473-2.3 1.899-2.82 0.796-0.289 1.604-0.286 2.226-0.045v-9.193h1.504c0 1.579 4.226 3.961 2.105 7.261z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M16.875 3.75c-1.243 0-2.25 0.382-2.25 1.625v14.25c0 1.243 1.007 1.625 2.25 1.625s2.25-0.382 2.25-1.625v-14.25c0-1.243-1.007-1.625-2.25-1.625zM8.125 3.75c-1.243 0-2.25 0.382-2.25 1.625v14.25c0 1.243 1.007 1.625 2.25 1.625s2.25-0.382 2.25-1.625v-14.25c0-1.243-1.007-1.625-2.25-1.625z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M20.873 11.859l-10.701-6.63c-0.78-0.511-1.418-0.134-1.418 0.838v12.87c0 0.971 0.639 1.348 1.418 0.836l10.702-6.63c0 0 0.38-0.268 0.38-0.643-0.001-0.374-0.381-0.641-0.381-0.641z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M18.866 8.368h0.884v2.516l5.25-4.5-5.25-4.5v2.984h-0.884c-4.616 0-7.22 3.421-9.518 6.44-2.066 2.715-3.85 5.060-6.732 5.060h-2.616v3.501h2.616c4.618 0 7.22-3.423 9.519-6.441 2.065-2.716 3.849-5.060 6.731-5.060zM6.764 10.573c0.196-0.255 0.395-0.515 0.596-0.779 0.489-0.643 1.005-1.32 1.564-1.995-1.651-1.543-3.644-2.681-6.307-2.681h-2.616v3.5h2.616c1.659 0 2.954 0.779 4.148 1.955zM19.75 16.616h-0.884c-1.759 0-3.107-0.874-4.363-2.173-0.126 0.164-0.251 0.33-0.379 0.498-0.551 0.723-1.145 1.501-1.799 2.27 1.696 1.655 3.751 2.905 6.54 2.905h0.884v3l5.25-4.5-5.25-4.502v2.502z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M23.709 16.798c0 1.101-0.901 2-2.001 2h-19.5c-1.1 0-1.229-0.461-0.285-1.027l20.070-11.318c0.944-0.566 1.716-0.129 1.716 0.971v9.374z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M20.002 7.75h-13.5v-2.75l-5.25 4.5 5.25 4.5v-2.75h12.5v5.25h-16.25v3.5h17.25c1.38 0 2.5-1.12 2.5-2.5v-7.25c0-1.381-1.121-2.5-2.5-2.5z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M5 21.25c0 1.38 1.12 2.5 2.5 2.5 1.381 0 2.5-1.12 2.5-2.5s-1.119-2.5-2.5-2.5c-1.38 0-2.5 1.12-2.5 2.5zM17.5 21.25c0 1.38 1.12 2.5 2.5 2.5 1.381 0 2.5-1.12 2.5-2.5s-1.119-2.5-2.5-2.5c-1.38 0-2.5 1.12-2.5 2.5zM9.434 15.34l13.836-3.952c0.264-0.076 0.48-0.363 0.48-0.638v-6.875h-17.625v-2.125c0-0.275-0.224-0.5-0.5-0.5h-3.875c-0.275 0-0.5 0.225-0.5 0.5v2h2.429l2.46 11.321 0.238 1.179v1.875c0 0.275 0.225 0.5 0.499 0.5h16.376c0.274 0 0.499-0.225 0.499-0.5v-1.875h-14.060c-1.436 0-1.466-0.562-0.256-0.91z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M9.356 12.5c0 0.323 0.327 0.552 0.327 0.552l9.094 5.711c0.674 0.441 1.223 0.116 1.223-0.719v-11.090c0-0.836-0.549-1.161-1.223-0.72l-9.094 5.713c0 0.001-0.327 0.23-0.327 0.552zM5 6.696v11.607c0 1.11 0.765 1.45 1.875 1.45s1.875-0.34 1.875-1.449v-11.609c0-1.111-0.765-1.451-1.875-1.451s-1.875 0.341-1.875 1.451z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M15.316 11.948l-9.094-5.713c-0.673-0.44-1.223-0.116-1.223 0.721v11.089c0 0.837 0.55 1.16 1.223 0.72l9.094-5.711c0 0 0.329-0.231 0.329-0.552s-0.329-0.554-0.329-0.554zM18.125 5.245c-1.11 0-1.875 0.341-1.875 1.451v11.607c0 1.111 0.765 1.452 1.875 1.452s1.875-0.341 1.875-1.452v-11.607c0-1.11-0.765-1.451-1.875-1.451z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M6.25 16.25h-1.25c-0.69 0-1.25 0.559-1.25 1.25s0.56 1.25 1.25 1.25h1.25c0.69 0 1.25-0.559 1.25-1.25s-0.56-1.25-1.25-1.25zM6.25 11.25h-1.25c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25h1.25c0.69 0 1.25-0.56 1.25-1.25s-0.56-1.25-1.25-1.25zM6.25 6.25h-1.25c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25h1.25c0.69 0 1.25-0.56 1.25-1.25s-0.56-1.25-1.25-1.25zM11.25 8.75h8.75c0.691 0 1.25-0.56 1.25-1.25s-0.559-1.25-1.25-1.25h-8.75c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25zM20 11.25h-8.75c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25h8.75c0.691 0 1.25-0.56 1.25-1.25s-0.559-1.25-1.25-1.25zM20 16.25h-8.75c-0.69 0-1.25 0.559-1.25 1.25s0.56 1.25 1.25 1.25h8.75c0.691 0 1.25-0.559 1.25-1.25s-0.559-1.25-1.25-1.25z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M20 11.25h-15c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25h15c0.691 0 1.25-0.56 1.25-1.25s-0.559-1.25-1.25-1.25zM5 8.75h15c0.691 0 1.25-0.56 1.25-1.25s-0.559-1.25-1.25-1.25h-15c-0.69 0-1.25 0.56-1.25 1.25s0.56 1.25 1.25 1.25zM20 16.25h-15c-0.69 0-1.25 0.559-1.25 1.25s0.56 1.25 1.25 1.25h15c0.691 0 1.25-0.559 1.25-1.25s-0.559-1.25-1.25-1.25z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M21.25 7.75h-4.75v3.5h3.75v5.25h-15.5v-5.25h5.25v2.75l5-4.5-5-4.5v2.75h-6.25c-1.38 0-2.5 1.119-2.5 2.5v7.25c0 1.38 1.12 2.5 2.5 2.5h17.5c1.381 0 2.5-1.12 2.5-2.5v-7.25c0-1.381-1.119-2.5-2.5-2.5z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M18.75 1.25h-12.5c-1.375 0-2.5 1.125-2.5 2.5v17.5c0 1.375 1.125 2.5 2.5 2.5h12.5c1.376 0 2.5-1.125 2.5-2.5v-17.5c0-1.375-1.124-2.5-2.5-2.5zM15.995 13.151c-0.296 0.463-0.454 0.265-0.365 0 0.235-0.698 0.226-2.809-1.74-3.118v6.516c0 1.215-0.7 1.977-2.188 2.455-1.445 0.462-3.063-0.019-3.441-1.057-0.377-1.037 0.473-2.3 1.899-2.82 0.796-0.289 1.604-0.286 2.226-0.045v-9.193h1.504c0 1.579 4.226 3.961 2.105 7.261z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M16.875 3.75c-1.243 0-2.25 0.382-2.25 1.625v14.25c0 1.243 1.007 1.625 2.25 1.625s2.25-0.382 2.25-1.625v-14.25c0-1.243-1.007-1.625-2.25-1.625zM8.125 3.75c-1.243 0-2.25 0.382-2.25 1.625v14.25c0 1.243 1.007 1.625 2.25 1.625s2.25-0.382 2.25-1.625v-14.25c0-1.243-1.007-1.625-2.25-1.625z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M20.873 11.859l-10.701-6.63c-0.78-0.511-1.418-0.134-1.418 0.838v12.87c0 0.971 0.639 1.348 1.418 0.836l10.702-6.63c0 0 0.38-0.268 0.38-0.643-0.001-0.374-0.381-0.641-0.381-0.641z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M18.866 8.368h0.884v2.516l5.25-4.5-5.25-4.5v2.984h-0.884c-4.616 0-7.22 3.421-9.518 6.44-2.066 2.715-3.85 5.060-6.732 5.060h-2.616v3.501h2.616c4.618 0 7.22-3.423 9.519-6.441 2.065-2.716 3.849-5.060 6.731-5.060zM6.764 10.573c0.196-0.255 0.395-0.515 0.596-0.779 0.489-0.643 1.005-1.32 1.564-1.995-1.651-1.543-3.644-2.681-6.307-2.681h-2.616v3.5h2.616c1.659 0 2.954 0.779 4.148 1.955zM19.75 16.616h-0.884c-1.759 0-3.107-0.874-4.363-2.173-0.126 0.164-0.251 0.33-0.379 0.498-0.551 0.723-1.145 1.501-1.799 2.27 1.696 1.655 3.751 2.905 6.54 2.905h0.884v3l5.25-4.5-5.25-4.502v2.502z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M23.709 16.798c0 1.101-0.901 2-2.001 2h-19.5c-1.1 0-1.229-0.461-0.285-1.027l20.070-11.318c0.944-0.566 1.716-0.129 1.716 0.971v9.374z" fill="#ffffff" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M25 12.5c-0.031-1.632-0.385-3.26-1.039-4.748-0.652-1.489-1.598-2.838-2.76-3.953-1.161-1.116-2.538-1.998-4.028-2.579-1.489-0.584-3.091-0.863-4.673-0.829-1.582 0.031-3.158 0.375-4.598 1.010-1.442 0.632-2.748 1.55-3.827 2.675-1.080 1.125-1.933 2.459-2.495 3.901-0.564 1.442-0.833 2.991-0.799 4.523 0.031 1.532 0.365 3.055 0.98 4.448 0.612 1.394 1.501 2.657 2.591 3.7 1.089 1.044 2.38 1.868 3.775 2.41 1.394 0.545 2.892 0.803 4.374 0.77 1.482-0.031 2.953-0.355 4.299-0.95 1.346-0.593 2.566-1.452 3.573-2.506 1.008-1.053 1.803-2.301 2.326-3.648 0.318-0.817 0.534-1.67 0.648-2.534 0.030 0.002 0.061 0.003 0.092 0.003 0.863 0 1.563-0.7 1.563-1.563 0-0.044-0.002-0.087-0.006-0.13h0.006zM22.517 16.649c-0.573 1.299-1.403 2.476-2.421 3.447-1.017 0.972-2.222 1.738-3.522 2.241-1.3 0.505-2.693 0.743-4.074 0.71-1.382-0.032-2.749-0.335-4-0.89-1.251-0.553-2.385-1.355-3.32-2.337-0.936-0.981-1.673-2.143-2.156-3.395-0.485-1.252-0.714-2.593-0.68-3.925 0.032-1.332 0.325-2.647 0.861-3.85 0.534-1.204 1.306-2.294 2.252-3.194 0.946-0.9 2.064-1.608 3.268-2.072 1.205-0.465 2.494-0.684 3.775-0.65 1.282 0.032 2.545 0.315 3.7 0.831 1.156 0.514 2.204 1.257 3.067 2.168 0.864 0.91 1.543 1.985 1.987 3.142 0.446 1.157 0.654 2.394 0.621 3.625h0.006c-0.004 0.043-0.006 0.086-0.006 0.13 0 0.806 0.61 1.469 1.394 1.553-0.152 0.85-0.404 1.68-0.751 2.466z" fill="#000000" />
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generated by IcoMoon.io -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="25" height="25" viewBox="0 0 25 25">
+<g>
+</g>
+ <path d="M25 12.5c-0.031-1.632-0.385-3.26-1.039-4.748-0.652-1.489-1.598-2.838-2.76-3.953-1.161-1.116-2.538-1.998-4.028-2.579-1.489-0.584-3.091-0.863-4.673-0.829-1.582 0.031-3.158 0.375-4.598 1.010-1.442 0.632-2.748 1.55-3.827 2.675-1.080 1.125-1.933 2.459-2.495 3.901-0.564 1.442-0.833 2.991-0.799 4.523 0.031 1.532 0.365 3.055 0.98 4.448 0.612 1.394 1.501 2.657 2.591 3.7 1.089 1.044 2.38 1.868 3.775 2.41 1.394 0.545 2.892 0.803 4.374 0.77 1.482-0.031 2.953-0.355 4.299-0.95 1.346-0.593 2.566-1.452 3.573-2.506 1.008-1.053 1.803-2.301 2.326-3.648 0.318-0.817 0.534-1.67 0.648-2.534 0.030 0.002 0.061 0.003 0.092 0.003 0.863 0 1.563-0.7 1.563-1.563 0-0.044-0.002-0.087-0.006-0.13h0.006zM22.517 16.649c-0.573 1.299-1.403 2.476-2.421 3.447-1.017 0.972-2.222 1.738-3.522 2.241-1.3 0.505-2.693 0.743-4.074 0.71-1.382-0.032-2.749-0.335-4-0.89-1.251-0.553-2.385-1.355-3.32-2.337-0.936-0.981-1.673-2.143-2.156-3.395-0.485-1.252-0.714-2.593-0.68-3.925 0.032-1.332 0.325-2.647 0.861-3.85 0.534-1.204 1.306-2.294 2.252-3.194 0.946-0.9 2.064-1.608 3.268-2.072 1.205-0.465 2.494-0.684 3.775-0.65 1.282 0.032 2.545 0.315 3.7 0.831 1.156 0.514 2.204 1.257 3.067 2.168 0.864 0.91 1.543 1.985 1.987 3.142 0.446 1.157 0.654 2.394 0.621 3.625h0.006c-0.004 0.043-0.006 0.086-0.006 0.13 0 0.806 0.61 1.469 1.394 1.553-0.152 0.85-0.404 1.68-0.751 2.466z" fill="#ffffff" />
+</svg>
--- /dev/null
+Patterns from subtlepatterns.com.\r
+"If you need more, that's where to get 'em."
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>\r
+<head>\r
+<meta charset="UTF-8" />\r
+<title>SoundManager 2: Bar UI Player (prototype)</title>
+<meta name="robots" content="noindex" />\r
+<meta name="viewport" content="width=500, initial-scale=1">\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script src="script/bar-ui.js"></script>\r
+<link rel="stylesheet" href="css/bar-ui.css" />\r
+\r
+<!-- demo for this page only, you don't need this stuff -->\r
+<script src="script/demo.js"></script>\r
+<link rel="stylesheet" href="css/demo.css" />\r
+\r
+</head>\r
+\r
+<body>\r
+\r
+<h1><a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2</a>: Bar UI <span class="note">("second draft" version)</span></h1>\r
+\r
+<p class="about">A configurable, resolution-independent HTML + SVG-based UI for playing collections of sounds.</p>\r
+\r
+<div class="demo-wrapper">\r
+\r
+<div class="demo-left">\r
+\r
+<div class="demo-bd">\r
+\r
+<h3>Standard UI</h3>\r
+\r
+<div class="sm2-bar-ui">\r
+\r
+ <div class="bd sm2-main-controls">\r
+\r
+ <div class="sm2-inline-texture"></div>\r
+ <div class="sm2-inline-gradient"></div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#play" class="sm2-inline-button play-pause">Play / pause</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-inline-status">\r
+\r
+ <div class="sm2-playlist">\r
+ <div class="sm2-playlist-target">\r
+ <!-- playlist <ul> + <li> markup will be injected here -->\r
+ <!-- if you want default / non-JS content, you can put that here. -->\r
+ <noscript><p>JavaScript is required.</p></noscript>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-progress">\r
+ <div class="sm2-row">\r
+ <div class="sm2-inline-time">0:00</div>\r
+ <div class="sm2-progress-bd">\r
+ <div class="sm2-progress-track">\r
+ <div class="sm2-progress-bar"></div>\r
+ <div class="sm2-progress-ball"><div class="icon-overlay"></div></div>\r
+ </div>\r
+ </div>\r
+ <div class="sm2-inline-duration">0:00</div>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-volume">\r
+ <div class="sm2-button-bd">\r
+ <span class="sm2-inline-button sm2-volume-control volume-shade"></span>\r
+ <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-menu">\r
+ <div class="sm2-button-bd">\r
+ <a href="#menu" class="sm2-inline-button menu">menu</a>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="bd sm2-playlist-drawer sm2-element">\r
+\r
+ <div class="sm2-inline-texture">\r
+ <div class="sm2-box-shadow"></div>\r
+ </div>\r
+\r
+ <!-- playlist content is mirrored here -->\r
+\r
+ <div class="sm2-playlist-wrapper">\r
+ \r
+ <ul class="sm2-playlist-bd">\r
+\r
+ <!-- example: playable link, "buy" link, "download" link -->\r
+ <li>\r
+ <div class="sm2-row">\r
+ <div class="sm2-col sm2-wide">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/Figub%20Brazlevi%C4%8D%20-%20Bosnian%20Syndicate.mp3" class="exclude button-exclude inline-exclude"><b>Figub Brazlevič</b> - Bosnian Syndicate <span title="Published under a Creative Commons BY-NC-ND license" class="label">(BY-CC-ND license)</span></a>\r
+ </div>\r
+ <div class="sm2-col">\r
+ <a href="http://figubbrazlevic.bandcamp.com/track/bosnian-syndicate" target="_blank" title="Buy "Bosnian Syndicate"" class="sm2-icon sm2-cart">Buy this track</a>\r
+ </div>\r
+ <div class="sm2-col">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/Figub%20Brazlevi%C4%8D%20-%20Bosnian%20Syndicate.mp3" target="_blank" title="Download "Bosnian Syndicate"" class="sm2-icon sm2-music sm2-exclude">Download this track</a>\r
+ </div>\r
+ </div>\r
+ </li>\r
+\r
+ <!-- example: playable link, "download" link -->\r
+ <li>\r
+ <div class="sm2-row">\r
+ <div class="sm2-col sm2-wide">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Let%20Me%20%28Prod%202oolman%29.mp3"><b>SonReal</b> - Let Me <span class="label">Explicit</span></a>\r
+ </div>\r
+ <div class="sm2-col">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Let%20Me%20%28Prod%202oolman%29.mp3" target="_blank" title="Download "Let Me"" class="sm2-icon sm2-music sm2-exclude">Download this track</a>\r
+ </div>\r
+ </div>\r
+ </li>\r
+\r
+ <!-- standard one-line items, no extra links -->\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3"><b>SonReal</b> - LA (Prod. Chin Injetti)<span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20People%20Asking.mp3"><b>SonReal</b> - People Asking <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Already%20There%20Remix%20ft.%20Rich%20Kidd,%20Saukrates.mp3"><b>SonReal</b> - Already There Remix ft. Rich Kidd, Saukrates <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/The%20Fugitives%20-%20Graffiti%20Sex.mp3"><b>The Fugitives</b> - Graffiti Sex</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Seven%20Or%20Eight%20Days.mp3"><b>Adrian Glynn</b> - Seven Or Eight Days</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20I%20Tried.mp3"><b>SonReal</b> - I Tried</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/gong-192kbps.mp3">32" Gong Sounds (rubber + standard mallets)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3">Armstrong Beat</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20090119%20-%20Untitled%20Groove.mp3">Untitled Groove</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/birds-in-kauai-128kbps-aac-lc.mp4">Birds In Kaua'i (AAC)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/20130320%20-%20Po%27ipu%20Beach%20Waves.ogg">Po'ipu Beach Waves (OGG)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/bottle-pop.wav">A corked beer bottle (WAV)</a></li>\r
+ <li><a href="../../demo/_mp3/rain.mp3">Rain</a></li>\r
+ \r
+ </ul>\r
+ \r
+ </div>\r
+\r
+ <div class="sm2-extra-controls">\r
+\r
+ <div class="bd">\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <a href="#prev" title="Previous" class="sm2-inline-button previous">< previous</a>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <a href="#next" title="Next" class="sm2-inline-button next">> next</a>\r
+ </div>\r
+\r
+ <!-- not implemented -->\r
+ <!--\r
+ <div class="sm2-inline-element sm2-button-element disabled">\r
+ <div class="sm2-button-bd">\r
+ <a href="#repeat" title="Repeat playlist" class="sm2-inline-button repeat">∞ repeat</a>\r
+ </div>\r
+ </div>\r
+ -->\r
+\r
+ <!-- not implemented -->\r
+ <!--\r
+ <div class="sm2-inline-element sm2-button-element disabled">\r
+ <a href="#shuffle" title="Shuffle" class="sm2-inline-button shuffle">shuffle</a>\r
+ </div>\r
+ -->\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+<!-- player #2 -->\r
+\r
+<h3>Extra controls inline, playlist open by default</h3>\r
+\r
+<div class="sm2-bar-ui playlist-open">\r
+\r
+ <div class="bd sm2-main-controls">\r
+\r
+ <div class="sm2-inline-texture"></div>\r
+ <div class="sm2-inline-gradient"></div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#play" class="sm2-inline-button play-pause">Play / pause</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-inline-status">\r
+\r
+ <div class="sm2-playlist">\r
+ <div class="sm2-playlist-target">\r
+ <!-- playlist <ul> + <li> markup will be injected here -->\r
+ <!-- if you want default / non-JS content, you can put that here. -->\r
+ <noscript><p>JavaScript is required.</p></noscript>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-progress">\r
+ <div class="sm2-row">\r
+ <div class="sm2-inline-time">0:00</div>\r
+ <div class="sm2-progress-bd">\r
+ <div class="sm2-progress-track">\r
+ <div class="sm2-progress-bar"></div>\r
+ <div class="sm2-progress-ball"><div class="icon-overlay"></div></div>\r
+ </div>\r
+ </div>\r
+ <div class="sm2-inline-duration">0:00</div>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-volume">\r
+ <div class="sm2-button-bd">\r
+ <span class="sm2-inline-button sm2-volume-control volume-shade"></span>\r
+ <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#prev" title="Previous" class="sm2-inline-button previous">< previous</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#next" title="Next" class="sm2-inline-button next">> next</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-menu">\r
+ <div class="sm2-button-bd">\r
+ <a href="#menu" class="sm2-inline-button menu">menu</a>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="bd sm2-playlist-drawer sm2-element">\r
+\r
+ <div class="sm2-inline-texture">\r
+ <div class="sm2-box-shadow"></div>\r
+ </div>\r
+\r
+ <!-- playlist content is mirrored here -->\r
+\r
+ <div class="sm2-playlist-wrapper">\r
+ \r
+ <ul class="sm2-playlist-bd">\r
+ \r
+ <!-- item with "download" link -->\r
+ <li>\r
+ <div class="sm2-row">\r
+ <div class="sm2-col sm2-wide">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3"><b>SonReal</b> - LA<span class="label">Explicit</span></a>\r
+ </div>\r
+ <div class="sm2-col">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3" target="_blank" title="Download "LA"" class="sm2-icon sm2-music sm2-exclude">Download this track</a>\r
+ </div>\r
+ </div>\r
+ </li>\r
+ \r
+ <!-- standard one-line items -->\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20People%20Asking.mp3"><b>SonReal</b> - People Asking <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Already%20There%20Remix%20ft.%20Rich%20Kidd%2C%20Saukrates.mp3"><b>SonReal</b> - Already There Remix ft. Rich Kidd, Saukrates <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/The%20Fugitives%20-%20Graffiti%20Sex.mp3"><b>The Fugitives</b> - Graffiti Sex</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Seven%20Or%20Eight%20Days.mp3"><b>Adrian Glynn</b> - Seven Or Eight Days</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20I%20Tried.mp3"><b>SonReal</b> - I Tried</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/gong-192kbps.mp3">32" Gong Sounds (rubber + standard mallets)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3">Armstrong Beat</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20090119%20-%20Untitled%20Groove.mp3">Untitled Groove</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/birds-in-kauai-128kbps-aac-lc.mp4">Birds In Kaua'i (AAC)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/20130320%20-%20Po%27ipu%20Beach%20Waves.ogg">Po'ipu Beach Waves (OGG)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/bottle-pop.wav">A corked beer bottle (WAV)</a></li>\r
+ <li><a href="../../demo/_mp3/rain.mp3">Rain</a></li>\r
+ \r
+ </ul>\r
+ \r
+ </div>\r
+\r
+ <div class="sm2-extra-controls">\r
+\r
+ <div class="bd">\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <a href="#prev" title="Previous" class="sm2-inline-button previous">< previous</a>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <a href="#next" title="Next" class="sm2-inline-button next">> next</a>\r
+ </div>\r
+\r
+ <!-- not implemented -->\r
+ <!--\r
+ <div class="sm2-inline-element sm2-button-element disabled">\r
+ <div class="sm2-button-bd">\r
+ <a href="#repeat" title="Repeat playlist" class="sm2-inline-button repeat">∞ repeat</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element disabled">\r
+ <a href="#shuffle" title="Shuffle" class="sm2-inline-button shuffle">shuffle</a>\r
+ </div>\r
+ -->\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+<!-- player 3 -->\r
+\r
+<h3>Compact UI, single item</h3>\r
+\r
+<div class="sm2-bar-ui compact">\r
+\r
+ <div class="bd sm2-main-controls">\r
+\r
+ <div class="sm2-inline-texture"></div>\r
+ <div class="sm2-inline-gradient"></div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#play" class="sm2-inline-button play-pause">Play / pause</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-inline-status">\r
+\r
+ <div class="sm2-playlist">\r
+ <div class="sm2-playlist-target">\r
+ <!-- playlist <ul> + <li> markup will be injected here -->\r
+ <!-- if you want default / non-JS content, you can put that here. -->\r
+ <noscript><p>JavaScript is required.</p></noscript>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-progress">\r
+ <div class="sm2-row">\r
+ <div class="sm2-inline-time">0:00</div>\r
+ <div class="sm2-progress-bd">\r
+ <div class="sm2-progress-track">\r
+ <div class="sm2-progress-bar"></div>\r
+ <div class="sm2-progress-ball"><div class="icon-overlay"></div></div>\r
+ </div>\r
+ </div>\r
+ <div class="sm2-inline-duration">0:00</div>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-volume">\r
+ <div class="sm2-button-bd">\r
+ <span class="sm2-inline-button sm2-volume-control volume-shade"></span>\r
+ <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="bd sm2-playlist-drawer sm2-element">\r
+\r
+ <div class="sm2-inline-texture">\r
+ <div class="sm2-box-shadow"></div>\r
+ </div>\r
+\r
+ <!-- playlist content is mirrored here -->\r
+\r
+ <div class="sm2-playlist-wrapper">\r
+ <ul class="sm2-playlist-bd">\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/gong-192kbps.mp3">32" Gong Sounds</a></li>\r
+ </ul>\r
+ </div>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+<!-- player 4 -->\r
+\r
+<h3>Compact UI, full width</h3>\r
+\r
+<div class="sm2-bar-ui compact full-width">\r
+\r
+ <div class="bd sm2-main-controls">\r
+\r
+ <div class="sm2-inline-texture"></div>\r
+ <div class="sm2-inline-gradient"></div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#play" class="sm2-inline-button play-pause">Play / pause</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-inline-status">\r
+\r
+ <div class="sm2-playlist">\r
+ <div class="sm2-playlist-target">\r
+ <!-- playlist <ul> + <li> markup will be injected here -->\r
+ <!-- if you want default / non-JS content, you can put that here. -->\r
+ <noscript><p>JavaScript is required.</p></noscript>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-progress">\r
+ <div class="sm2-row">\r
+ <div class="sm2-inline-time">0:00</div>\r
+ <div class="sm2-progress-bd">\r
+ <div class="sm2-progress-track">\r
+ <div class="sm2-progress-bar"></div>\r
+ <div class="sm2-progress-ball"><div class="icon-overlay"></div></div>\r
+ </div>\r
+ </div>\r
+ <div class="sm2-inline-duration">0:00</div>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-volume">\r
+ <div class="sm2-button-bd">\r
+ <span class="sm2-inline-button sm2-volume-control volume-shade"></span>\r
+ <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="bd sm2-playlist-drawer sm2-element">\r
+\r
+ <div class="sm2-inline-texture">\r
+ <div class="sm2-box-shadow"></div>\r
+ </div>\r
+\r
+ <!-- playlist content is mirrored here -->\r
+\r
+ <div class="sm2-playlist-wrapper">\r
+ <ul class="sm2-playlist-bd">\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Seven%20Or%20Eight%20Days.mp3"><b>Adrian Glynn</b> - Seven Or Eight Days</a></li>\r
+ </ul>\r
+ </div>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+ <h3>JavaScript API</h3>\r
+\r
+ <p class="about">Once initialized, players will be added to the array <code>window.sm2BarPlayers</code>. You can access and control players in this fashion. For example, <code>window.sm2BarPlayers[0].actions.play()</code> will start the first player UI. You can also toggle the playlist "drawer" via <code>window.sm2BarPlayers[0].actions.menu()</code>.</p>\r
+\r
+ <h3>Credits</h3>\r
+\r
+ <p class="about">Thanks to <a href="http://iamsonreal.com/" title="SonReal, Vancouver-based hip-hop artist">SonReal</a> and <a href="http://www.adrianglynn.com/" title="Adrian Glynn, Vancouver-based Singer/Songwriter">Adrian Glynn</a> for making these demos sound notably better.</p>\r
+ <p class="about">Sample textures are from <a href="http://subtlepatterns.com/">subtlepatterns.com</a>. "If you need more, that's where to get 'em."</p>\r
+ <p class="about">SVG icons are from <a href="http://icomoon.io/app/">IcoMoon</a>, "Entypo" (CC-BY SA 3.0) and "IcoMoon Free" (GPL) sets.</p>\r
+ <p class="about"><i>Missing button images?</i> Make sure your server is returning an appropriate MIME type for SVG assets. An .htaccess example: <code>AddType image/svg+xml svg svgz</code></p>\r
+\r
+<!-- end left wrapper -->\r
+</div>\r
+\r
+<!-- end left -->\r
+\r
+</div>\r
+\r
+<div class="demo-right">\r
+\r
+<div class="demo-bd">\r
+\r
+<h2 style="padding-top:1em">Live UI options</h2>\r
+\r
+<div style="font-size:13px">\r
+\r
+ <div style="display:inline-block;margin-right:1em;vertical-align:top">\r
+ <p><b>Color</b></p>\r
+ <input name="color-input" id="color-field" type="color" value="#2288cc" title="Color picker" />\r
+ </div>\r
+\r
+ <div style="display:inline-block;margin-right:1em;vertical-align:top">\r
+ <p><b>Color opacity</b></p>\r
+ <input name="opacity-input" id="opacity-field" type="range" value="100" min="0" max="100" style="display:block;width:100px" />\r
+ </div>\r
+\r
+ <div style="display:inline-block;margin-right:1em;vertical-align:top">\r
+ <p><b>Player texture</b></p>\r
+ <select id="player-background">\r
+ <option value="transparent">transparent</option>\r
+ <option value="#fff">white</option>\r
+ <option value="#666" data-dark="true">grey</option>\r
+ <option value="#000" data-dark="true">black</option>\r
+ <option value="url(image/patterns/wood_pattern_dark.png)" data-dark="true">dark wood</option>\r
+ <option value="url(image/patterns/wood_pattern.png)">light wood</option>\r
+ <option value="url(image/patterns/tweed.png)" data-dark="true">tweed</option>\r
+ <option value="url(image/patterns/textured_paper.png)" data-dark="true">textured paper</option>\r
+ <option value="url(image/patterns/pinstriped_suit_vertical.png)" data-dark="true">pinstripe</option>\r
+ <option value="url(image/patterns/pool_table.png)" data-dark="true">pool table</option>\r
+ <option value="url(image/patterns/rubber_grip.png)" data-dark="true">rubber grip</option>\r
+ <option value="url(image/patterns/tasky_pattern.png)" data-dark="true">tasky_pattern</option>\r
+ <option value="url(image/patterns/woven.png)" data-dark="true">woven</option>\r
+ </select>\r
+ </div>\r
+\r
+ <div style="display:inline-block;margin-right:1em;vertical-align:top">\r
+ <p><b>Page background</b></p>\r
+ <select id="page-background">\r
+ <option value="transparent">transparent</option>\r
+ <option value="#fff">white</option>\r
+ <option value="#666" data-dark="true">grey</option>\r
+ <option value="#000" data-dark="true">black</option>\r
+ <option value="url(image/patterns/wood_pattern_dark.png)" data-dark="true">dark wood</option>\r
+ <option value="url(image/patterns/wood_pattern.png)">light wood</option>\r
+ <option value="url(image/paterns/tweed.png)" data-dark="true">tweed</option>\r
+ <option value="url(image/patterns/textured_paper.png)" data-dark="true">textured paper</option>\r
+ <option value="url(image/patterns/pinstriped_suit_vertical.png)" data-dark="true">pinstripe</option>\r
+ <option value="url(image/patterns/pool_table.png)" data-dark="true">pool table</option>\r
+ <option value="url(image/patterns/rubber_grip.png)" data-dark="true">rubber grip</option>\r
+ <option value="url(image/patterns/tasky_pattern.png)" data-dark="true">tasky_pattern.png</option>\r
+ <option value="url(image/patterns/woven.png)" data-dark="true">woven.png</option>\r
+ </select>\r
+ </div>\r
+\r
+ <div style="display:inline-block;vertical-align:top">\r
+ <p><b>Font size</b></p>\r
+ 12 <input name="size-input" id="size-field" type="range" value="15" min="12" max="64" style="display:inline-block;width:48px" /> 64\r
+ </div>\r
+\r
+ <p>Try combinations of color, opacity and texture.</p>\r
+\r
+ <h3>HTML classname options</h3>\r
+\r
+ <div style="margin-top:1em">\r
+ <button id="fullwidth">full width</button> \r
+ <!-- <button id="fixed">fixed</button> -->\r
+ <button id="textured">texture</button>\r
+ <button id="dark">dark/light text</button>\r
+ <button id="flat">flat</button>\r
+ <button id="playlist-open">playlist open</button>\r
+ </div>\r
+\r
+ <div>\r
+\r
+ <div style="display:inline-block;margin-top:0.5em;margin-right:1em;vertical-align:top">\r
+\r
+ <p>CSS for these options:</p>\r
+\r
+<pre>\r
+.sm2-bar-ui {\r
+ font-size: <span id="fontsize-output">16px;</span>\r
+}\r
+.sm2-bar-ui .sm2-main-controls,\r
+.sm2-bar-ui .sm2-playlist-drawer {\r
+ <span id="color-output">background-color: #2288cc;</span>\r
+}\r
+.sm2-bar-ui .sm2-inline-texture {\r
+ <span id="texture-output">background: transparent;</span>\r
+}\r
+</pre>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+<p>HTML for these options:</p>\r
+\r
+ <div>\r
+<pre><div class="<span id="player-code-example" style="color:#666">sm2-bar-ui</span>">\r
+ <span style="color:#666;font-size:x-small"><!-- player HTML goes here --></span>\r
+</div></pre>\r
+ </div>\r
+\r
+ <h3>Fixed-position, full-width player via <code style="font-size:x-small"><div class="sm2-bar-ui fixed full-width"> ... </div></code> below ↓</h3>\r
+\r
+</div>\r
+\r
+<!-- end right bd -->\r
+\r
+</div>\r
+\r
+<!-- end right -->\r
+\r
+</div>\r
+\r
+<!-- end demo -->\r
+\r
+</div>\r
+\r
+<!-- fixed, bottom-aligned, full-width player -->\r
+\r
+<div class="sm2-bar-ui full-width fixed">\r
+\r
+ <div class="bd sm2-main-controls">\r
+\r
+ <div class="sm2-inline-texture"></div>\r
+ <div class="sm2-inline-gradient"></div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#play" class="sm2-inline-button play-pause">Play / pause</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-inline-status">\r
+\r
+ <div class="sm2-playlist">\r
+ <div class="sm2-playlist-target">\r
+ <!-- playlist <ul> + <li> markup will be injected here -->\r
+ <!-- if you want default / non-JS content, you can put that here. -->\r
+ <noscript><p>JavaScript is required.</p></noscript>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-progress">\r
+ <div class="sm2-row">\r
+ <div class="sm2-inline-time">0:00</div>\r
+ <div class="sm2-progress-bd">\r
+ <div class="sm2-progress-track">\r
+ <div class="sm2-progress-bar"></div>\r
+ <div class="sm2-progress-ball"><div class="icon-overlay"></div></div>\r
+ </div>\r
+ </div>\r
+ <div class="sm2-inline-duration">0:00</div>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-volume">\r
+ <div class="sm2-button-bd">\r
+ <span class="sm2-inline-button sm2-volume-control volume-shade"></span>\r
+ <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#prev" title="Previous" class="sm2-inline-button previous">< previous</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#next" title="Next" class="sm2-inline-button next">> next</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#repeat" title="Repeat playlist" class="sm2-inline-button repeat">∞ repeat</a>\r
+ </div>\r
+ </div>\r
+\r
+ <!-- not implemented -->\r
+ <!--\r
+ <div class="sm2-inline-element sm2-button-element disabled">\r
+ <div class="sm2-button-bd">\r
+ <a href="#shuffle" title="Shuffle" class="sm2-inline-button shuffle">shuffle</a>\r
+ </div>\r
+ </div>\r
+ -->\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-menu">\r
+ <div class="sm2-button-bd">\r
+ <a href="#menu" class="sm2-inline-button menu">menu</a>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="bd sm2-playlist-drawer sm2-element">\r
+\r
+ <div class="sm2-inline-texture">\r
+ <div class="sm2-box-shadow"></div>\r
+ </div>\r
+\r
+ <!-- playlist content is mirrored here -->\r
+\r
+ <div class="sm2-playlist-wrapper">\r
+\r
+ <ul class="sm2-playlist-bd">\r
+\r
+ <!-- item with "download" link -->\r
+ <li>\r
+ <div class="sm2-row">\r
+ <div class="sm2-col sm2-wide">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3"><b>SonReal</b> - LA<span class="label">Explicit</span></a>\r
+ </div>\r
+ <div class="sm2-col">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3" target="_blank" title="Download "LA"" class="sm2-icon sm2-music sm2-exclude">Download this track</a>\r
+ </div>\r
+ </div>\r
+ </li>\r
+\r
+ <!-- standard one-line items -->\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Let%20Me%20%28Prod%202oolman%29.mp3"><b>SonReal</b> - Let Me <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20People%20Asking.mp3"><b>SonReal</b> - People Asking <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Already%20There%20Remix%20ft.%20Rich%20Kidd%2C%20Saukrates.mp3"><b>SonReal</b> - Already There Remix ft. Rich Kidd, Saukrates <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/The%20Fugitives%20-%20Graffiti%20Sex.mp3"><b>The Fugitives</b> - Graffiti Sex</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Seven%20Or%20Eight%20Days.mp3"><b>Adrian Glynn</b> - Seven Or Eight Days</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20I%20Tried.mp3"><b>SonReal</b> - I Tried</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3">Armstrong Beat</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20090119%20-%20Untitled%20Groove.mp3">Untitled Groove</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/birds-in-kauai-128kbps-aac-lc.mp4">Birds In Kaua'i (AAC)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/20130320%20-%20Po%27ipu%20Beach%20Waves.ogg">Po'ipu Beach Waves (OGG)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/bottle-pop.wav">A corked beer bottle (WAV)</a></li>\r
+ <li><a href="../../demo/_mp3/rain.mp3">Rain</a></li>\r
+ \r
+ </ul>\r
+ \r
+ </div>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+/*jslint plusplus: true, white: true, nomen: true */\r
+/*global console, document, navigator, soundManager, window */\r
+\r
+(function(window) {\r
+\r
+ /**\r
+ * SoundManager 2: "Bar UI" player\r
+ * Copyright (c) 2014, Scott Schiller. All rights reserved.\r
+ * http://www.schillmania.com/projects/soundmanager2/\r
+ * Code provided under BSD license.\r
+ * http://schillmania.com/projects/soundmanager2/license.txt\r
+ */\r
+\r
+ "use strict";\r
+\r
+ var Player,\r
+ players = [],\r
+ // CSS selector that will get us the top-level DOM node for the player UI.\r
+ playerSelector = '.sm2-bar-ui',\r
+ playerOptions,\r
+ utils;\r
+\r
+ /**\r
+ * Slightly hackish: event callbacks.\r
+ * Override globally by setting window.sm2BarPlayers.on = {}, or individually by window.sm2BarPlayers[0].on = {} etc.\r
+ */\r
+ players.on = {\r
+ /*\r
+ play: function(player) {\r
+ console.log('playing', player);\r
+ },\r
+ finish: function(player) {\r
+ // each sound\r
+ console.log('finish', player);\r
+ },\r
+ pause: function(player) {\r
+ console.log('pause', player);\r
+ },\r
+ error: function(player) {\r
+ console.log('error', player);\r
+ }\r
+ end: function(player) {\r
+ // end of playlist\r
+ console.log('end', player);\r
+ }\r
+ */\r
+ };\r
+\r
+ playerOptions = {\r
+ // useful when multiple players are in use, or other SM2 sounds are active etc.\r
+ stopOtherSounds: true,\r
+ // CSS class to let the browser load the URL directly e.g., <a href="foo.mp3" class="sm2-exclude">download foo.mp3</a>\r
+ excludeClass: 'sm2-exclude'\r
+ };\r
+\r
+ soundManager.setup({\r
+ // trade-off: higher UI responsiveness (play/progress bar), but may use more CPU.\r
+ html5PollingInterval: 50,\r
+ flashVersion: 9\r
+ });\r
+\r
+ soundManager.onready(function() {\r
+\r
+ var nodes, i, j;\r
+\r
+ nodes = utils.dom.getAll(playerSelector);\r
+\r
+ if (nodes && nodes.length) {\r
+ for (i=0, j=nodes.length; i<j; i++) {\r
+ players.push(new Player(nodes[i]));\r
+ }\r
+ }\r
+ \r
+ });\r
+\r
+ /**\r
+ * player bits\r
+ */\r
+\r
+ Player = function(playerNode) {\r
+\r
+ var css, dom, extras, playlistController, soundObject, actions, actionData, defaultItem, defaultVolume, firstOpen, exports;\r
+\r
+ css = {\r
+ disabled: 'disabled',\r
+ selected: 'selected',\r
+ active: 'active',\r
+ legacy: 'legacy',\r
+ noVolume: 'no-volume',\r
+ playlistOpen: 'playlist-open'\r
+ };\r
+\r
+ dom = {\r
+ o: null,\r
+ playlist: null,\r
+ playlistTarget: null,\r
+ playlistContainer: null,\r
+ time: null,\r
+ player: null,\r
+ progress: null,\r
+ progressTrack: null,\r
+ progressBar: null,\r
+ duration: null,\r
+ volume: null\r
+ };\r
+\r
+ // prepended to tracks when a sound fails to load/play\r
+ extras = {\r
+ loadFailedCharacter: '<span title="Failed to load/play." class="load-error">✖</span>'\r
+ };\r
+\r
+ function stopOtherSounds() {\r
+\r
+ if (playerOptions.stopOtherSounds) {\r
+ soundManager.stopAll();\r
+ }\r
+\r
+ }\r
+\r
+ function callback(method) {\r
+ if (method) {\r
+ // fire callback, passing current turntable object\r
+ if (exports.on && exports.on[method]) {\r
+ exports.on[method](exports);\r
+ } else if (players.on[method]) {\r
+ players.on[method](exports);\r
+ }\r
+ }\r
+ }\r
+\r
+ function getTime(msec, useString) {\r
+\r
+ // convert milliseconds to hh:mm:ss, return as object literal or string\r
+\r
+ var nSec = Math.floor(msec/1000),\r
+ hh = Math.floor(nSec/3600),\r
+ min = Math.floor(nSec/60) - Math.floor(hh * 60),\r
+ sec = Math.floor(nSec -(hh*3600) -(min*60));\r
+\r
+ // if (min === 0 && sec === 0) return null; // return 0:00 as null\r
+\r
+ return (useString ? ((hh ? hh + ':' : '') + (hh && min < 10 ? '0' + min : min) + ':' + ( sec < 10 ? '0' + sec : sec ) ) : { 'min': min, 'sec': sec });\r
+\r
+ }\r
+\r
+ function setTitle(item) {\r
+\r
+ // given a link, update the "now playing" UI.\r
+\r
+ // if this is an <li> with an inner link, grab and use the text from that.\r
+ var links = item.getElementsByTagName('a');\r
+\r
+ if (links.length) {\r
+ item = links[0];\r
+ }\r
+\r
+ // remove any failed character sequence, also\r
+ dom.playlistTarget.innerHTML = '<ul class="sm2-playlist-bd"><li>' + item.innerHTML.replace(extras.loadFailedCharacter, '') + '</li></ul>';\r
+\r
+ if (dom.playlistTarget.getElementsByTagName('li')[0].scrollWidth > dom.playlistTarget.offsetWidth) {\r
+ // this item can use <marquee>, in fact.\r
+ dom.playlistTarget.innerHTML = '<ul class="sm2-playlist-bd"><li><marquee>' + item.innerHTML + '</marquee></li></ul>';\r
+ }\r
+\r
+ }\r
+\r
+ function makeSound(url) {\r
+\r
+ var sound = soundManager.createSound({\r
+\r
+ url: url,\r
+\r
+ volume: defaultVolume,\r
+\r
+ whileplaying: function() {\r
+\r
+ var progressMaxLeft = 100,\r
+ left,\r
+ width;\r
+ \r
+ left = Math.min(progressMaxLeft, Math.max(0, (progressMaxLeft * (this.position / this.durationEstimate)))) + '%';\r
+ width = Math.min(100, Math.max(0, (100 * this.position / this.durationEstimate))) + '%';\r
+ \r
+ if (this.duration) {\r
+\r
+ dom.progress.style.left = left;\r
+ dom.progressBar.style.width = width;\r
+ \r
+ // TODO: only write changes\r
+ dom.time.innerHTML = getTime(this.position, true);\r
+\r
+ }\r
+\r
+ },\r
+\r
+ onbufferchange: function(isBuffering) {\r
+\r
+ if (isBuffering) {\r
+ utils.css.add(dom.o, 'buffering');\r
+ } else {\r
+ utils.css.remove(dom.o, 'buffering');\r
+ }\r
+\r
+ },\r
+\r
+ onplay: function() {\r
+ utils.css.swap(dom.o, 'paused', 'playing');\r
+ callback('play');\r
+ },\r
+\r
+ onpause: function() {\r
+ utils.css.swap(dom.o, 'playing', 'paused');\r
+ callback('pause');\r
+ },\r
+\r
+ onresume: function() {\r
+ utils.css.swap(dom.o, 'paused', 'playing');\r
+ },\r
+\r
+ whileloading: function() {\r
+\r
+ if (!this.isHTML5) {\r
+ dom.duration.innerHTML = getTime(this.durationEstimate, true);\r
+ }\r
+\r
+ },\r
+\r
+ onload: function(ok) {\r
+\r
+ if (ok) {\r
+\r
+ dom.duration.innerHTML = getTime(this.duration, true);\r
+\r
+ } else if (this._iO && this._iO.onerror) {\r
+\r
+ this._iO.onerror();\r
+\r
+ }\r
+\r
+ },\r
+\r
+ onerror: function() {\r
+\r
+ // sound failed to load.\r
+ var item, element, html;\r
+\r
+ item = playlistController.getItem();\r
+\r
+ if (item) {\r
+\r
+ // note error, delay 2 seconds and advance?\r
+ // playlistTarget.innerHTML = '<ul class="sm2-playlist-bd"><li>' + item.innerHTML + '</li></ul>';\r
+\r
+ if (extras.loadFailedCharacter) {\r
+ dom.playlistTarget.innerHTML = dom.playlistTarget.innerHTML.replace('<li>' ,'<li>' + extras.loadFailedCharacter + ' ');\r
+ if (playlistController.data.playlist && playlistController.data.playlist[playlistController.data.selectedIndex]) {\r
+ element = playlistController.data.playlist[playlistController.data.selectedIndex].getElementsByTagName('a')[0];\r
+ html = element.innerHTML;\r
+ if (html.indexOf(extras.loadFailedCharacter) === -1) {\r
+ element.innerHTML = extras.loadFailedCharacter + ' ' + html;\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ callback('error');\r
+\r
+ // load next, possibly with delay.\r
+ \r
+ if (navigator.userAgent.match(/mobile/i)) {\r
+ // mobile will likely block the next play() call if there is a setTimeout() - so don't use one here.\r
+ actions.next();\r
+ } else {\r
+ if (playlistController.data.timer) {\r
+ window.clearTimeout(playlistController.data.timer);\r
+ }\r
+ playlistController.data.timer = window.setTimeout(actions.next, 2000);\r
+ }\r
+\r
+ },\r
+\r
+ onstop: function() {\r
+\r
+ utils.css.remove(dom.o, 'playing');\r
+\r
+ },\r
+\r
+ onfinish: function() {\r
+\r
+ var lastIndex, item;\r
+\r
+ utils.css.remove(dom.o, 'playing');\r
+\r
+ dom.progress.style.left = '0%';\r
+\r
+ lastIndex = playlistController.data.selectedIndex;\r
+\r
+ callback('finish');\r
+\r
+ // next track?\r
+ item = playlistController.getNext();\r
+\r
+ // don't play the same item over and over again, if at end of playlist etc.\r
+ if (item && playlistController.data.selectedIndex !== lastIndex) {\r
+\r
+ playlistController.select(item);\r
+\r
+ setTitle(item);\r
+\r
+ stopOtherSounds();\r
+\r
+ // play next\r
+ this.play({\r
+ url: playlistController.getURL()\r
+ });\r
+\r
+ } else {\r
+\r
+ // end of playlist case\r
+\r
+ // explicitly stop?\r
+ // this.stop();\r
+\r
+ callback('end');\r
+\r
+ }\r
+\r
+ }\r
+\r
+ });\r
+\r
+ return sound;\r
+\r
+ }\r
+\r
+ function playLink(link) {\r
+\r
+ // if a link is OK, play it.\r
+\r
+ if (soundManager.canPlayURL(link.href)) {\r
+\r
+ // if there's a timer due to failure to play one track, cancel it.\r
+ // catches case when user may use previous/next after an error.\r
+ if (playlistController.data.timer) {\r
+ window.clearTimeout(playlistController.data.timer);\r
+ playlistController.data.timer = null;\r
+ }\r
+\r
+ if (!soundObject) {\r
+ soundObject = makeSound(link.href);\r
+ }\r
+\r
+ // required to reset pause/play state on iOS so whileplaying() works? odd.\r
+ soundObject.stop();\r
+\r
+ playlistController.select(link.parentNode);\r
+\r
+ setTitle(link.parentNode);\r
+\r
+ // reset the UI\r
+ // TODO: function that also resets/hides timing info.\r
+ dom.progress.style.left = '0px';\r
+ dom.progressBar.style.width = '0px';\r
+\r
+ stopOtherSounds();\r
+\r
+ soundObject.play({\r
+ url: link.href,\r
+ position: 0\r
+ });\r
+\r
+ }\r
+\r
+ }\r
+\r
+ function PlaylistController() {\r
+\r
+ var data;\r
+\r
+ data = {\r
+\r
+ // list of nodes?\r
+ playlist: [],\r
+\r
+ // NOTE: not implemented yet.\r
+ // shuffledIndex: [],\r
+ // shuffleMode: false,\r
+\r
+ // selection\r
+ selectedIndex: 0,\r
+\r
+ loopMode: false,\r
+\r
+ timer: null\r
+\r
+ };\r
+\r
+ function getPlaylist() {\r
+\r
+ return data.playlist;\r
+\r
+ }\r
+\r
+ function getItem(offset) {\r
+\r
+ var list,\r
+ item;\r
+\r
+ // given the current selection (or an offset), return the current item.\r
+\r
+ // if currently null, may be end of list case. bail.\r
+ if (data.selectedIndex === null) {\r
+ return offset;\r
+ }\r
+\r
+ list = getPlaylist();\r
+\r
+ // use offset if provided, otherwise take default selected.\r
+ offset = (offset !== undefined ? offset : data.selectedIndex);\r
+\r
+ // safety check - limit to between 0 and list length\r
+ offset = Math.max(0, Math.min(offset, list.length));\r
+\r
+ item = list[offset];\r
+\r
+ return item;\r
+\r
+ }\r
+\r
+ function findOffsetFromItem(item) {\r
+\r
+ // given an <li> item, find it in the playlist array and return the index.\r
+ var list,\r
+ i,\r
+ j,\r
+ offset;\r
+\r
+ offset = -1;\r
+\r
+ list = getPlaylist();\r
+\r
+ if (list) {\r
+\r
+ for (i=0, j=list.length; i<j; i++) {\r
+ if (list[i] === item) {\r
+ offset = i;\r
+ break;\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ return offset;\r
+\r
+ }\r
+\r
+ function getNext() {\r
+\r
+ // don't increment if null.\r
+ if (data.selectedIndex !== null) {\r
+ data.selectedIndex++;\r
+ }\r
+\r
+ if (data.playlist.length > 1) {\r
+\r
+ if (data.selectedIndex >= data.playlist.length) {\r
+\r
+ if (data.loopMode) {\r
+\r
+ // loop to beginning\r
+ data.selectedIndex = 0;\r
+\r
+ } else {\r
+\r
+ // no change\r
+ data.selectedIndex--;\r
+\r
+ // end playback\r
+ // data.selectedIndex = null;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ data.selectedIndex = null;\r
+\r
+ }\r
+\r
+ return getItem();\r
+\r
+ }\r
+\r
+ function getPrevious() {\r
+\r
+ data.selectedIndex--;\r
+\r
+ if (data.selectedIndex < 0) {\r
+ // wrapping around beginning of list? loop or exit.\r
+ if (data.loopMode) {\r
+ data.selectedIndex = data.playlist.length - 1;\r
+ } else {\r
+ // undo\r
+ data.selectedIndex++;\r
+ }\r
+ }\r
+\r
+ return getItem();\r
+\r
+ }\r
+\r
+ function resetLastSelected() {\r
+\r
+ // remove UI highlight(s) on selected items.\r
+ var items,\r
+ i, j;\r
+\r
+ items = utils.dom.getAll(dom.playlist, '.' + css.selected);\r
+\r
+ for (i=0, j=items.length; i<j; i++) {\r
+ utils.css.remove(items[i], css.selected);\r
+ }\r
+\r
+ }\r
+\r
+ function select(item) {\r
+\r
+ var offset,\r
+ itemTop,\r
+ itemBottom,\r
+ containerHeight,\r
+ scrollTop,\r
+ itemPadding,\r
+ liElement;\r
+\r
+ // remove last selected, if any\r
+ resetLastSelected();\r
+\r
+ if (item) {\r
+\r
+ liElement = utils.dom.ancestor('li', item);\r
+\r
+ utils.css.add(liElement, css.selected);\r
+\r
+ itemTop = item.offsetTop;\r
+ itemBottom = itemTop + item.offsetHeight;\r
+ containerHeight = dom.playlistContainer.offsetHeight;\r
+ scrollTop = dom.playlist.scrollTop;\r
+ itemPadding = 8;\r
+\r
+ if (itemBottom > containerHeight + scrollTop) {\r
+ // bottom-align\r
+ dom.playlist.scrollTop = itemBottom - containerHeight + itemPadding;\r
+ } else if (itemTop < scrollTop) {\r
+ // top-align\r
+ dom.playlist.scrollTop = item.offsetTop - itemPadding;\r
+ }\r
+\r
+ }\r
+\r
+ // update selected offset, too.\r
+ offset = findOffsetFromItem(item);\r
+\r
+ data.selectedIndex = offset;\r
+\r
+ }\r
+\r
+ function playItemByOffset(offset) {\r
+\r
+ var item;\r
+\r
+ offset = (offset || 0);\r
+\r
+ item = getItem(offset);\r
+ \r
+ if (item) {\r
+ playLink(item.getElementsByTagName('a')[0]);\r
+ }\r
+\r
+ }\r
+\r
+ function getURL() {\r
+\r
+ // return URL of currently-selected item\r
+ var item, url;\r
+\r
+ item = getItem();\r
+ \r
+ if (item) {\r
+ url = item.getElementsByTagName('a')[0].href;\r
+ }\r
+\r
+ return url;\r
+\r
+ }\r
+\r
+ function refreshDOM() {\r
+\r
+ // get / update playlist from DOM\r
+\r
+ if (!dom.playlist) {\r
+ if (window.console && console.warn) {\r
+ console.warn('refreshDOM(): playlist node not found?');\r
+ }\r
+ return false;\r
+ }\r
+\r
+ data.playlist = dom.playlist.getElementsByTagName('li');\r
+\r
+ }\r
+\r
+ function initDOM() {\r
+\r
+ dom.playlistTarget = utils.dom.get(dom.o, '.sm2-playlist-target');\r
+ dom.playlistContainer = utils.dom.get(dom.o, '.sm2-playlist-drawer');\r
+ dom.playlist = utils.dom.get(dom.o, '.sm2-playlist-bd');\r
+\r
+ }\r
+\r
+ function init() {\r
+\r
+ // inherit the default SM2 volume\r
+ defaultVolume = soundManager.defaultOptions.volume;\r
+\r
+ initDOM();\r
+ refreshDOM();\r
+\r
+ // animate playlist open, if HTML classname indicates so.\r
+ if (utils.css.has(dom.o, css.playlistOpen)) {\r
+ // hackish: run this after API has returned\r
+ window.setTimeout(function() {\r
+ actions.menu(true);\r
+ }, 1);\r
+ }\r
+\r
+ }\r
+\r
+ init();\r
+\r
+ return {\r
+ data: data,\r
+ refresh: refreshDOM,\r
+ getNext: getNext,\r
+ getPrevious: getPrevious,\r
+ getItem: getItem,\r
+ getURL: getURL,\r
+ playItemByOffset: playItemByOffset,\r
+ select: select\r
+ };\r
+\r
+ }\r
+\r
+ function isRightClick(e) {\r
+\r
+ // only pay attention to left clicks. old IE differs where there's no e.which, but e.button is 1 on left click.\r
+ if (e && ((e.which && e.which === 2) || (e.which === undefined && e.button !== 1))) {\r
+ // http://www.quirksmode.org/js/events_properties.html#button\r
+ return true;\r
+ }\r
+\r
+ }\r
+\r
+ function getActionData(target) {\r
+\r
+ // DOM measurements for volume slider\r
+\r
+ if (!target) {\r
+ return false;\r
+ }\r
+\r
+ actionData.volume.x = utils.position.getOffX(target);\r
+ actionData.volume.y = utils.position.getOffY(target);\r
+\r
+ actionData.volume.width = target.offsetWidth;\r
+ actionData.volume.height = target.offsetHeight;\r
+\r
+ // potentially dangerous: this should, but may not be a percentage-based value.\r
+ actionData.volume.backgroundSize = parseInt(utils.style.get(target, 'background-size'), 10);\r
+\r
+ // IE gives pixels even if background-size specified as % in CSS. Boourns.\r
+ if (window.navigator.userAgent.match(/msie|trident/i)) {\r
+ actionData.volume.backgroundSize = (actionData.volume.backgroundSize / actionData.volume.width) * 100;\r
+ }\r
+\r
+ }\r
+\r
+ function handleMouseDown(e) {\r
+\r
+ var links,\r
+ target;\r
+\r
+ target = e.target || e.srcElement;\r
+\r
+ if (isRightClick(e)) {\r
+ return true;\r
+ }\r
+\r
+ // normalize to <a>, if applicable.\r
+ if (target.nodeName.toLowerCase() !== 'a') {\r
+\r
+ links = target.getElementsByTagName('a');\r
+ if (links && links.length) {\r
+ target = target.getElementsByTagName('a')[0];\r
+ }\r
+\r
+ }\r
+\r
+ if (utils.css.has(target, 'sm2-volume-control')) {\r
+\r
+ // drag case for volume\r
+\r
+ getActionData(target);\r
+\r
+ utils.events.add(document, 'mousemove', actions.adjustVolume);\r
+ utils.events.add(document, 'mouseup', actions.releaseVolume);\r
+\r
+ // and apply right away\r
+ return actions.adjustVolume(e);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ function handleClick(e) {\r
+\r
+ var evt,\r
+ target,\r
+ offset,\r
+ targetNodeName,\r
+ methodName,\r
+ href,\r
+ handled;\r
+\r
+ evt = (e || window.event);\r
+\r
+ target = evt.target || evt.srcElement;\r
+\r
+ if (target && target.nodeName) {\r
+\r
+ targetNodeName = target.nodeName.toLowerCase();\r
+\r
+ if (targetNodeName !== 'a') {\r
+\r
+ // old IE (IE 8) might return nested elements inside the <a>, eg., <b> etc. Try to find the parent <a>.\r
+\r
+ if (target.parentNode) {\r
+\r
+ do {\r
+ target = target.parentNode;\r
+ targetNodeName = target.nodeName.toLowerCase();\r
+ } while (targetNodeName !== 'a' && target.parentNode);\r
+\r
+ if (!target) {\r
+ // something went wrong. bail.\r
+ return false;\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ if (targetNodeName === 'a') {\r
+\r
+ // yep, it's a link.\r
+\r
+ href = target.href;\r
+\r
+ if (soundManager.canPlayURL(href)) {\r
+\r
+ // not excluded\r
+ if (!utils.css.has(target, playerOptions.excludeClass)) {\r
+\r
+ // find this in the playlist\r
+\r
+ playLink(target);\r
+\r
+ handled = true;\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ // is this one of the action buttons, eg., play/pause, volume, etc.?\r
+ offset = target.href.lastIndexOf('#');\r
+\r
+ if (offset !== -1) {\r
+\r
+ methodName = target.href.substr(offset+1);\r
+\r
+ if (methodName && actions[methodName]) {\r
+ handled = true;\r
+ actions[methodName](e);\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ // fall-through case\r
+\r
+ if (handled) {\r
+ // prevent browser fall-through\r
+ return utils.events.preventDefault(evt);\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ function handleMouse(e) {\r
+\r
+ var target, barX, barWidth, x, newPosition, sound;\r
+\r
+ target = dom.progressTrack;\r
+\r
+ barX = utils.position.getOffX(target);\r
+ barWidth = target.offsetWidth;\r
+\r
+ x = (e.clientX - barX);\r
+\r
+ newPosition = (x / barWidth);\r
+\r
+ sound = soundObject;\r
+\r
+ if (sound && sound.duration) {\r
+\r
+ sound.setPosition(sound.duration * newPosition);\r
+\r
+ // a little hackish: ensure UI updates immediately with current position, even if audio is buffering and hasn't moved there yet.\r
+ if (sound._iO && sound._iO.whileplaying) {\r
+ sound._iO.whileplaying.apply(sound);\r
+ }\r
+\r
+ }\r
+\r
+ if (e.preventDefault) {\r
+ e.preventDefault();\r
+ }\r
+\r
+ return false;\r
+\r
+ }\r
+\r
+ function releaseMouse(e) {\r
+\r
+ utils.events.remove(document, 'mousemove', handleMouse);\r
+\r
+ utils.css.remove(dom.o, 'grabbing');\r
+\r
+ utils.events.remove(document, 'mouseup', releaseMouse);\r
+\r
+ utils.events.preventDefault(e);\r
+\r
+ return false;\r
+\r
+ }\r
+\r
+ function init() {\r
+\r
+ // init DOM?\r
+\r
+ if (!playerNode) {\r
+ console.warn('init(): No playerNode element?');\r
+ }\r
+\r
+ dom.o = playerNode;\r
+\r
+ // are we dealing with a crap browser? apply legacy CSS if so.\r
+ if (window.navigator.userAgent.match(/msie [678]/i)) {\r
+ utils.css.add(dom.o, css.legacy);\r
+ }\r
+\r
+ if (window.navigator.userAgent.match(/mobile/i)) {\r
+ // majority of mobile devices don't let HTML5 audio set volume.\r
+ utils.css.add(dom.o, css.noVolume);\r
+ }\r
+\r
+ dom.progress = utils.dom.get(dom.o, '.sm2-progress-ball');\r
+\r
+ dom.progressTrack = utils.dom.get(dom.o, '.sm2-progress-track');\r
+\r
+ dom.progressBar = utils.dom.get(dom.o, '.sm2-progress-bar');\r
+\r
+ dom.volume = utils.dom.get(dom.o, 'a.sm2-volume-control');\r
+\r
+ // measure volume control dimensions\r
+ if (dom.volume) {\r
+ getActionData(dom.volume);\r
+ }\r
+\r
+ dom.duration = utils.dom.get(dom.o, '.sm2-inline-duration');\r
+\r
+ dom.time = utils.dom.get(dom.o, '.sm2-inline-time');\r
+\r
+ playlistController = new PlaylistController();\r
+\r
+ defaultItem = playlistController.getItem(0);\r
+\r
+ playlistController.select(defaultItem);\r
+\r
+ if (defaultItem) {\r
+ setTitle(defaultItem);\r
+ }\r
+\r
+ utils.events.add(dom.o, 'mousedown', handleMouseDown);\r
+\r
+ utils.events.add(dom.o, 'click', handleClick);\r
+\r
+ utils.events.add(dom.progressTrack, 'mousedown', function(e) {\r
+\r
+ if (isRightClick(e)) {\r
+ return true;\r
+ }\r
+\r
+ utils.css.add(dom.o, 'grabbing');\r
+ utils.events.add(document, 'mousemove', handleMouse);\r
+ utils.events.add(document, 'mouseup', releaseMouse);\r
+\r
+ return handleMouse(e);\r
+\r
+ });\r
+\r
+ }\r
+\r
+ // ---\r
+\r
+ actionData = {\r
+\r
+ volume: {\r
+ x: 0,\r
+ y: 0,\r
+ width: 0,\r
+ height: 0,\r
+ backgroundSize: 0\r
+ }\r
+\r
+ };\r
+\r
+ actions = {\r
+\r
+ play: function(offsetOrEvent) {\r
+\r
+ /**\r
+ * This is an overloaded function that takes mouse/touch events or offset-based item indices.\r
+ * Remember, "auto-play" will not work on mobile devices unless this function is called immediately from a touch or click event.\r
+ * If you have the link but not the offset, you can also pass a fake event object with a target of an <a> inside the playlist - e.g. { target: someMP3Link } \r
+ */\r
+\r
+ var target,\r
+ href,\r
+ e;\r
+\r
+ if (offsetOrEvent !== undefined && !isNaN(offsetOrEvent)) {\r
+ // smells like a number.\r
+ return playlistController.playItemByOffset(offsetOrEvent);\r
+ }\r
+\r
+ // DRY things a bit\r
+ e = offsetOrEvent;\r
+\r
+ if (e && e.target) {\r
+\r
+ target = e.target || e.srcElement;\r
+\r
+ href = target.href;\r
+\r
+ }\r
+\r
+ // haaaack - if null due to no event, OR '#' due to play/pause link, get first link from playlist\r
+ if (!href || href.indexOf('#') !== -1) {\r
+ href = dom.playlist.getElementsByTagName('a')[0].href;\r
+ }\r
+\r
+ if (!soundObject) {\r
+ soundObject = makeSound(href);\r
+ }\r
+\r
+ // edge case: if the current sound is not playing, stop all others.\r
+ if (!soundObject.playState) {\r
+ stopOtherSounds();\r
+ }\r
+\r
+ // TODO: if user pauses + unpauses a sound that had an error, try to play next?\r
+ soundObject.togglePause();\r
+\r
+ // special case: clear "play next" timeout, if one exists.\r
+ // edge case: user pauses after a song failed to load.\r
+ if (soundObject.paused && playlistController.data.timer) {\r
+ window.clearTimeout(playlistController.data.timer);\r
+ playlistController.data.timer = null;\r
+ }\r
+\r
+ },\r
+\r
+ pause: function() {\r
+\r
+ if (soundObject && soundObject.readyState) {\r
+ soundObject.pause();\r
+ }\r
+\r
+ },\r
+\r
+ resume: function() {\r
+\r
+ if (soundObject && soundObject.readyState) {\r
+ soundObject.resume();\r
+ }\r
+\r
+ },\r
+\r
+ stop: function() {\r
+\r
+ // just an alias for pause, really.\r
+ // don't actually stop because that will mess up some UI state, i.e., dragging the slider.\r
+ return actions.pause();\r
+\r
+ },\r
+\r
+ next: function(/* e */) {\r
+\r
+ var item, lastIndex;\r
+\r
+ // special case: clear "play next" timeout, if one exists.\r
+ if (playlistController.data.timer) {\r
+ window.clearTimeout(playlistController.data.timer);\r
+ playlistController.data.timer = null;\r
+ }\r
+\r
+ lastIndex = playlistController.data.selectedIndex;\r
+\r
+ item = playlistController.getNext(true);\r
+\r
+ // don't play the same item again\r
+ if (item && playlistController.data.selectedIndex !== lastIndex) {\r
+ playLink(item.getElementsByTagName('a')[0]);\r
+ }\r
+\r
+ },\r
+\r
+ prev: function(/* e */) {\r
+\r
+ var item, lastIndex;\r
+\r
+ lastIndex = playlistController.data.selectedIndex;\r
+\r
+ item = playlistController.getPrevious();\r
+\r
+ // don't play the same item again\r
+ if (item && playlistController.data.selectedIndex !== lastIndex) {\r
+ playLink(item.getElementsByTagName('a')[0]);\r
+ }\r
+\r
+ },\r
+\r
+ shuffle: function(e) {\r
+\r
+ // NOTE: not implemented yet.\r
+\r
+ var target = (e ? e.target || e.srcElement : utils.dom.get(dom.o, '.shuffle'));\r
+\r
+ if (target && !utils.css.has(target, css.disabled)) {\r
+ utils.css.toggle(target.parentNode, css.active);\r
+ playlistController.data.shuffleMode = !playlistController.data.shuffleMode;\r
+ }\r
+\r
+ },\r
+\r
+ repeat: function(e) {\r
+\r
+ var target = (e ? e.target || e.srcElement : utils.dom.get(dom.o, '.repeat'));\r
+\r
+ if (target && !utils.css.has(target, css.disabled)) {\r
+ utils.css.toggle(target.parentNode, css.active);\r
+ playlistController.data.loopMode = !playlistController.data.loopMode;\r
+ }\r
+\r
+ },\r
+\r
+ menu: function(ignoreToggle) {\r
+\r
+ var isOpen;\r
+\r
+ isOpen = utils.css.has(dom.o, css.playlistOpen);\r
+\r
+ // hackish: reset scrollTop in default first open case. odd, but some browsers have a non-zero scroll offset the first time the playlist opens.\r
+ if (playlistController && !playlistController.data.selectedIndex && !firstOpen) {\r
+ dom.playlist.scrollTop = 0;\r
+ firstOpen = true;\r
+ }\r
+\r
+ // sniff out booleans from mouse events, as this is referenced directly by event handlers.\r
+ if (typeof ignoreToggle !== 'boolean' || !ignoreToggle) {\r
+\r
+ if (!isOpen) {\r
+ // explicitly set height:0, so the first closed -> open animation runs properly\r
+ dom.playlistContainer.style.height = '0px';\r
+ }\r
+\r
+ isOpen = utils.css.toggle(dom.o, css.playlistOpen);\r
+\r
+ }\r
+\r
+ // playlist\r
+ dom.playlistContainer.style.height = (isOpen ? dom.playlistContainer.scrollHeight : 0) + 'px';\r
+\r
+ },\r
+\r
+ adjustVolume: function(e) {\r
+\r
+ /**\r
+ * NOTE: this is the mousemove() event handler version.\r
+ * Use setVolume(50), etc., to assign volume directly.\r
+ */\r
+\r
+ var backgroundMargin,\r
+ pixelMargin,\r
+ target,\r
+ value,\r
+ volume;\r
+\r
+ value = 0;\r
+\r
+ target = dom.volume;\r
+\r
+ // safety net\r
+ if (e === undefined) {\r
+ return false;\r
+ }\r
+\r
+ if (!e || e.clientX === undefined) {\r
+ // called directly or with a non-mouseEvent object, etc.\r
+ // proxy to the proper method.\r
+ if (arguments.length && window.console && window.console.warn) {\r
+ console.warn('Bar UI: call setVolume(' + e + ') instead of adjustVolume(' + e + ').');\r
+ }\r
+ return actions.setVolume.apply(this, arguments);\r
+ }\r
+\r
+ // based on getStyle() result\r
+ // figure out spacing around background image based on background size, eg. 60% background size.\r
+ // 60% wide means 20% margin on each side.\r
+ backgroundMargin = (100 - actionData.volume.backgroundSize) / 2;\r
+\r
+ // relative position of mouse over element\r
+ value = Math.max(0, Math.min(1, (e.clientX - actionData.volume.x) / actionData.volume.width));\r
+\r
+ target.style.clip = 'rect(0px, ' + (actionData.volume.width * value) + 'px, ' + actionData.volume.height + 'px, ' + (actionData.volume.width * (backgroundMargin/100)) + 'px)';\r
+\r
+ // determine logical volume, including background margin\r
+ pixelMargin = ((backgroundMargin/100) * actionData.volume.width);\r
+\r
+ volume = Math.max(0, Math.min(1, ((e.clientX - actionData.volume.x) - pixelMargin) / (actionData.volume.width - (pixelMargin*2)))) * 100;\r
+\r
+ // set volume\r
+ if (soundObject) {\r
+ soundObject.setVolume(volume);\r
+ }\r
+\r
+ defaultVolume = volume;\r
+\r
+ return utils.events.preventDefault(e);\r
+\r
+ },\r
+\r
+ releaseVolume: function(/* e */) {\r
+\r
+ utils.events.remove(document, 'mousemove', actions.adjustVolume);\r
+ utils.events.remove(document, 'mouseup', actions.releaseVolume);\r
+\r
+ },\r
+\r
+ setVolume: function(volume) {\r
+\r
+ // set volume (0-100) and update volume slider UI.\r
+\r
+ var backgroundSize,\r
+ backgroundMargin,\r
+ backgroundOffset,\r
+ target,\r
+ from,\r
+ to;\r
+\r
+ if (volume === undefined || isNaN(volume)) {\r
+ return;\r
+ }\r
+\r
+ if (dom.volume) {\r
+\r
+ target = dom.volume;\r
+\r
+ // based on getStyle() result\r
+ backgroundSize = actionData.volume.backgroundSize;\r
+\r
+ // figure out spacing around background image based on background size, eg. 60% background size.\r
+ // 60% wide means 20% margin on each side.\r
+ backgroundMargin = (100 - backgroundSize) / 2;\r
+\r
+ // margin as pixel value relative to width\r
+ backgroundOffset = actionData.volume.width * (backgroundMargin/100);\r
+\r
+ from = backgroundOffset;\r
+ to = from + ((actionData.volume.width - (backgroundOffset*2)) * (volume/100));\r
+\r
+ target.style.clip = 'rect(0px, ' + to + 'px, ' + actionData.volume.height + 'px, ' + from + 'px)';\r
+\r
+ }\r
+\r
+ // apply volume to sound, as applicable\r
+ if (soundObject) {\r
+ soundObject.setVolume(volume);\r
+ }\r
+\r
+ defaultVolume = volume;\r
+\r
+ }\r
+\r
+ };\r
+\r
+ init();\r
+\r
+ // TODO: mixin actions -> exports\r
+\r
+ exports = {\r
+ // Per-instance events: window.sm2BarPlayers[0].on = { ... } etc. See global players.on example above for reference.\r
+ on: null,\r
+ actions: actions,\r
+ dom: dom,\r
+ playlistController: playlistController\r
+ };\r
+\r
+ return exports;\r
+\r
+ };\r
+\r
+ // barebones utilities for logic, CSS, DOM, events etc.\r
+\r
+ utils = {\r
+\r
+ array: (function() {\r
+\r
+ function compare(property) {\r
+\r
+ var result;\r
+\r
+ return function(a, b) {\r
+\r
+ if (a[property] < b[property]) {\r
+ result = -1;\r
+ } else if (a[property] > b[property]) {\r
+ result = 1;\r
+ } else {\r
+ result = 0;\r
+ }\r
+ return result;\r
+ };\r
+\r
+ }\r
+\r
+ function shuffle(array) {\r
+\r
+ // Fisher-Yates shuffle algo\r
+\r
+ var i, j, temp;\r
+\r
+ for (i = array.length - 1; i > 0; i--) {\r
+ j = Math.floor(Math.random() * (i+1));\r
+ temp = array[i];\r
+ array[i] = array[j];\r
+ array[j] = temp;\r
+ }\r
+\r
+ return array;\r
+\r
+ }\r
+\r
+ return {\r
+ compare: compare,\r
+ shuffle: shuffle\r
+ };\r
+\r
+ }()),\r
+\r
+ css: (function() {\r
+\r
+ function hasClass(o, cStr) {\r
+\r
+ return (o.className !== undefined ? new RegExp('(^|\\s)' + cStr + '(\\s|$)').test(o.className) : false);\r
+\r
+ }\r
+\r
+ function addClass(o, cStr) {\r
+\r
+ if (!o || !cStr || hasClass(o, cStr)) {\r
+ return false; // safety net\r
+ }\r
+ o.className = (o.className ? o.className + ' ' : '') + cStr;\r
+\r
+ }\r
+\r
+ function removeClass(o, cStr) {\r
+\r
+ if (!o || !cStr || !hasClass(o, cStr)) {\r
+ return false;\r
+ }\r
+ o.className = o.className.replace(new RegExp('( ' + cStr + ')|(' + cStr + ')', 'g'), '');\r
+\r
+ }\r
+\r
+ function swapClass(o, cStr1, cStr2) {\r
+\r
+ var tmpClass = {\r
+ className: o.className\r
+ };\r
+\r
+ removeClass(tmpClass, cStr1);\r
+ addClass(tmpClass, cStr2);\r
+\r
+ o.className = tmpClass.className;\r
+\r
+ }\r
+\r
+ function toggleClass(o, cStr) {\r
+\r
+ var found,\r
+ method;\r
+\r
+ found = hasClass(o, cStr);\r
+\r
+ method = (found ? removeClass : addClass);\r
+\r
+ method(o, cStr);\r
+\r
+ // indicate the new state...\r
+ return !found;\r
+\r
+ }\r
+\r
+ return {\r
+ has: hasClass,\r
+ add: addClass,\r
+ remove: removeClass,\r
+ swap: swapClass,\r
+ toggle: toggleClass\r
+ };\r
+\r
+ }()),\r
+\r
+ dom: (function() {\r
+\r
+ function getAll(param1, param2) {\r
+\r
+ var node,\r
+ selector,\r
+ results;\r
+\r
+ if (arguments.length === 1) {\r
+\r
+ // .selector case\r
+ node = document.documentElement;\r
+ // first param is actually the selector\r
+ selector = param1;\r
+\r
+ } else {\r
+\r
+ // node, .selector\r
+ node = param1;\r
+ selector = param2;\r
+\r
+ }\r
+\r
+ // sorry, IE 7 users; IE 8+ required.\r
+ if (node && node.querySelectorAll) {\r
+\r
+ results = node.querySelectorAll(selector);\r
+\r
+ }\r
+\r
+ return results;\r
+\r
+ }\r
+\r
+ function get(/* parentNode, selector */) {\r
+\r
+ var results = getAll.apply(this, arguments);\r
+\r
+ // hackish: if an array, return the last item.\r
+ if (results && results.length) {\r
+ return results[results.length-1];\r
+ }\r
+\r
+ // handle "not found" case\r
+ return results && results.length === 0 ? null : results;\r
+\r
+ }\r
+\r
+ function ancestor(nodeName, element, checkCurrent) {\r
+\r
+ var result;\r
+\r
+ if (!element || !nodeName) {\r
+ return element;\r
+ }\r
+\r
+ nodeName = nodeName.toUpperCase();\r
+\r
+ // return if current node matches.\r
+ if (checkCurrent && element && element.nodeName === nodeName) {\r
+ return element;\r
+ }\r
+\r
+ while (element && element.nodeName !== nodeName && element.parentNode) {\r
+ element = element.parentNode;\r
+ }\r
+\r
+ return (element && element.nodeName === nodeName ? element : null);\r
+\r
+ }\r
+\r
+ return {\r
+ ancestor: ancestor,\r
+ get: get,\r
+ getAll: getAll\r
+ };\r
+\r
+ }()),\r
+\r
+ position: (function() {\r
+\r
+ function getOffX(o) {\r
+\r
+ // http://www.xs4all.nl/~ppk/js/findpos.html\r
+ var curleft = 0;\r
+\r
+ if (o.offsetParent) {\r
+\r
+ while (o.offsetParent) {\r
+\r
+ curleft += o.offsetLeft;\r
+\r
+ o = o.offsetParent;\r
+\r
+ }\r
+\r
+ } else if (o.x) {\r
+\r
+ curleft += o.x;\r
+\r
+ }\r
+\r
+ return curleft;\r
+\r
+ }\r
+\r
+ function getOffY(o) {\r
+\r
+ // http://www.xs4all.nl/~ppk/js/findpos.html\r
+ var curtop = 0;\r
+\r
+ if (o.offsetParent) {\r
+\r
+ while (o.offsetParent) {\r
+\r
+ curtop += o.offsetTop;\r
+\r
+ o = o.offsetParent;\r
+\r
+ }\r
+\r
+ } else if (o.y) {\r
+\r
+ curtop += o.y;\r
+\r
+ }\r
+\r
+ return curtop;\r
+\r
+ }\r
+\r
+ return {\r
+ getOffX: getOffX,\r
+ getOffY: getOffY\r
+ };\r
+\r
+ }()),\r
+\r
+ style: (function() {\r
+\r
+ function get(node, styleProp) {\r
+\r
+ // http://www.quirksmode.org/dom/getstyles.html\r
+ var value;\r
+\r
+ if (node.currentStyle) {\r
+\r
+ value = node.currentStyle[styleProp];\r
+\r
+ } else if (window.getComputedStyle) {\r
+\r
+ value = document.defaultView.getComputedStyle(node, null).getPropertyValue(styleProp);\r
+\r
+ }\r
+\r
+ return value;\r
+\r
+ }\r
+\r
+ return {\r
+ get: get\r
+ };\r
+\r
+ }()),\r
+\r
+ events: (function() {\r
+\r
+ var add, remove, preventDefault;\r
+\r
+ add = function(o, evtName, evtHandler) {\r
+ // return an object with a convenient detach method.\r
+ var eventObject = {\r
+ detach: function() {\r
+ return remove(o, evtName, evtHandler);\r
+ }\r
+ };\r
+ if (window.addEventListener) {\r
+ o.addEventListener(evtName, evtHandler, false);\r
+ } else {\r
+ o.attachEvent('on' + evtName, evtHandler);\r
+ }\r
+ return eventObject;\r
+ };\r
+\r
+ remove = (window.removeEventListener !== undefined ? function(o, evtName, evtHandler) {\r
+ return o.removeEventListener(evtName, evtHandler, false);\r
+ } : function(o, evtName, evtHandler) {\r
+ return o.detachEvent('on' + evtName, evtHandler);\r
+ });\r
+\r
+ preventDefault = function(e) {\r
+ if (e.preventDefault) {\r
+ e.preventDefault();\r
+ } else {\r
+ e.returnValue = false;\r
+ e.cancelBubble = true;\r
+ }\r
+ return false;\r
+ };\r
+\r
+ return {\r
+ add: add,\r
+ preventDefault: preventDefault,\r
+ remove: remove\r
+ };\r
+\r
+ }()),\r
+\r
+ features: (function() {\r
+\r
+ var getAnimationFrame,\r
+ localAnimationFrame,\r
+ localFeatures,\r
+ prop,\r
+ styles,\r
+ testDiv,\r
+ transform;\r
+\r
+ testDiv = document.createElement('div');\r
+\r
+ /**\r
+ * hat tip: paul irish\r
+ * http://paulirish.com/2011/requestanimationframe-for-smart-animating/\r
+ * https://gist.github.com/838785\r
+ */\r
+\r
+ localAnimationFrame = (window.requestAnimationFrame\r
+ || window.webkitRequestAnimationFrame\r
+ || window.mozRequestAnimationFrame\r
+ || window.oRequestAnimationFrame\r
+ || window.msRequestAnimationFrame\r
+ || null);\r
+\r
+ // apply to window, avoid "illegal invocation" errors in Chrome\r
+ getAnimationFrame = localAnimationFrame ? function() {\r
+ return localAnimationFrame.apply(window, arguments);\r
+ } : null;\r
+\r
+ function has(prop) {\r
+\r
+ // test for feature support\r
+ var result = testDiv.style[prop];\r
+\r
+ return (result !== undefined ? prop : null);\r
+\r
+ }\r
+\r
+ // note local scope.\r
+ localFeatures = {\r
+\r
+ transform: {\r
+ ie: has('-ms-transform'),\r
+ moz: has('MozTransform'),\r
+ opera: has('OTransform'),\r
+ webkit: has('webkitTransform'),\r
+ w3: has('transform'),\r
+ prop: null // the normalized property value\r
+ },\r
+\r
+ rotate: {\r
+ has3D: false,\r
+ prop: null\r
+ },\r
+\r
+ getAnimationFrame: getAnimationFrame\r
+\r
+ };\r
+\r
+ localFeatures.transform.prop = (\r
+ localFeatures.transform.w3 ||\r
+ localFeatures.transform.moz ||\r
+ localFeatures.transform.webkit ||\r
+ localFeatures.transform.ie ||\r
+ localFeatures.transform.opera\r
+ );\r
+\r
+ function attempt(style) {\r
+\r
+ try {\r
+ testDiv.style[transform] = style;\r
+ } catch(e) {\r
+ // that *definitely* didn't work.\r
+ return false;\r
+ }\r
+ // if we can read back the style, it should be cool.\r
+ return !!testDiv.style[transform];\r
+\r
+ }\r
+\r
+ if (localFeatures.transform.prop) {\r
+\r
+ // try to derive the rotate/3D support.\r
+ transform = localFeatures.transform.prop;\r
+ styles = {\r
+ css_2d: 'rotate(0deg)',\r
+ css_3d: 'rotate3d(0,0,0,0deg)'\r
+ };\r
+\r
+ if (attempt(styles.css_3d)) {\r
+ localFeatures.rotate.has3D = true;\r
+ prop = 'rotate3d';\r
+ } else if (attempt(styles.css_2d)) {\r
+ prop = 'rotate';\r
+ }\r
+\r
+ localFeatures.rotate.prop = prop;\r
+\r
+ }\r
+\r
+ testDiv = null;\r
+\r
+ return localFeatures;\r
+\r
+ }())\r
+\r
+ };\r
+\r
+ // ---\r
+\r
+ // expose to global\r
+ window.sm2BarPlayers = players;\r
+ window.sm2BarPlayerOptions = playerOptions;\r
+ window.SM2BarPlayer = Player;\r
+\r
+}(window));
\ No newline at end of file
--- /dev/null
+(function() {\r
+\r
+ var utils;\r
+\r
+ var playerSelector = '.sm2-bar-ui';\r
+\r
+ var players = window.sm2BarPlayers;\r
+\r
+ var Player = window.SM2BarPlayer;\r
+\r
+ // the demo may need flash, we'll set that up here.\r
+ soundManager.setup({\r
+ url: '../../swf/'\r
+ });\r
+\r
+ // minimal utils for demo\r
+ utils = {\r
+\r
+ css: (function() {\r
+\r
+ function hasClass(o, cStr) {\r
+\r
+ return (o.className !== undefined ? new RegExp('(^|\\s)' + cStr + '(\\s|$)').test(o.className) : false);\r
+\r
+ }\r
+\r
+ function addClass(o, cStr) {\r
+\r
+ if (!o || !cStr || hasClass(o, cStr)) {\r
+ return false; // safety net\r
+ }\r
+ o.className = (o.className ? o.className + ' ' : '') + cStr;\r
+\r
+ }\r
+\r
+ function removeClass(o, cStr) {\r
+\r
+ if (!o || !cStr || !hasClass(o, cStr)) {\r
+ return false;\r
+ }\r
+ o.className = o.className.replace(new RegExp('( ' + cStr + ')|(' + cStr + ')', 'g'), '');\r
+\r
+ }\r
+\r
+ function swapClass(o, cStr1, cStr2) {\r
+\r
+ var tmpClass = {\r
+ className: o.className\r
+ };\r
+\r
+ removeClass(tmpClass, cStr1);\r
+ addClass(tmpClass, cStr2);\r
+\r
+ o.className = tmpClass.className;\r
+\r
+ }\r
+\r
+ function toggleClass(o, cStr) {\r
+\r
+ var found,\r
+ method;\r
+\r
+ found = hasClass(o, cStr);\r
+\r
+ method = (found ? removeClass : addClass);\r
+\r
+ method(o, cStr);\r
+\r
+ // indicate the new state...\r
+ return !found;\r
+\r
+ }\r
+\r
+ return {\r
+ has: hasClass,\r
+ add: addClass,\r
+ remove: removeClass,\r
+ swap: swapClass,\r
+ toggle: toggleClass\r
+ };\r
+\r
+ }()),\r
+\r
+ dom: (function() {\r
+\r
+ function getAll(/* parentNode, selector */) {\r
+\r
+ var node,\r
+ selector,\r
+ results;\r
+\r
+ if (arguments.length === 1) {\r
+\r
+ // .selector case\r
+ node = document.documentElement;\r
+ selector = arguments[0];\r
+\r
+ } else {\r
+\r
+ // node, .selector\r
+ node = arguments[0];\r
+ selector = arguments[1];\r
+\r
+ }\r
+\r
+ if (node) {\r
+\r
+ results = node.querySelectorAll(selector);\r
+\r
+ }\r
+\r
+ return results;\r
+\r
+ }\r
+\r
+ function get() {\r
+\r
+ var results = getAll.apply(this, arguments);\r
+\r
+ // hackish: if more than one match, return the last.\r
+ if (results && results.length) {\r
+ results = results[results.length-1];\r
+ }\r
+\r
+ return results;\r
+\r
+ }\r
+\r
+ function getFirst() {\r
+\r
+ var results = getAll.apply(this, arguments);\r
+\r
+ // hackish: if more than one match, return the first.\r
+ if (results && results.length) {\r
+ results = results[0];\r
+ }\r
+\r
+ return results;\r
+\r
+ }\r
+\r
+ return {\r
+ get: get,\r
+ getAll: getAll,\r
+ getFirst: getFirst\r
+ };\r
+\r
+ }()),\r
+\r
+ events: (function() {\r
+\r
+ var add, remove, preventDefault;\r
+\r
+ add = function(o, evtName, evtHandler) {\r
+ // return an object with a convenient detach method.\r
+ var eventObject = {\r
+ detach: function() {\r
+ return remove(o, evtName, evtHandler);\r
+ }\r
+ }\r
+ if (window.addEventListener) {\r
+ o.addEventListener(evtName, evtHandler, false);\r
+ } else {\r
+ o.attachEvent('on' + evtName, evtHandler);\r
+ }\r
+ return eventObject;\r
+ };\r
+\r
+ remove = (window.removeEventListener !== undefined ? function(o, evtName, evtHandler) {\r
+ return o.removeEventListener(evtName, evtHandler, false);\r
+ } : function(o, evtName, evtHandler) {\r
+ return o.detachEvent('on' + evtName, evtHandler);\r
+ });\r
+\r
+ preventDefault = function(e) {\r
+ if (e.preventDefault) {\r
+ e.preventDefault();\r
+ } else {\r
+ e.returnValue = false;\r
+ e.cancelBubble = true;\r
+ }\r
+ return false;\r
+ };\r
+\r
+ return {\r
+ add: add,\r
+ preventDefault: preventDefault,\r
+ remove: remove\r
+ };\r
+\r
+ }())\r
+\r
+ };\r
+\r
+ soundManager.onready(function() {\r
+\r
+ // initialize all players\r
+\r
+ var demoData = {\r
+ pageBackgroundPicker: document.getElementById('page-background'),\r
+ playerBackgroundPicker: document.getElementById('player-background'),\r
+ colorPicker: document.getElementById('color-field'),\r
+ opacityPicker: document.getElementById('opacity-field'),\r
+ sizePicker: document.getElementById('size-field'),\r
+ colorOutput: document.getElementById('color-output'),\r
+ backgroundValue: null,\r
+ opacityValue: null,\r
+ sizeValue: null\r
+ };\r
+\r
+ // initial values\r
+ demoData.backgroundValue = demoData.colorPicker.value;\r
+ demoData.opacityValue = demoData.opacityPicker.value;\r
+ demoData.sizeValue = demoData.sizePicker.value;\r
+\r
+ function hexToRGB(hex) {\r
+ // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb/11508164#11508164\r
+ var bigint = parseInt(hex, 16);\r
+ var r = (bigint >> 16) & 255;\r
+ var g = (bigint >> 8) & 255;\r
+ var b = bigint & 255;\r
+ return [r, g, b];\r
+ }\r
+\r
+ function updateColor() {\r
+\r
+ var colorValue = demoData.backgroundValue,\r
+ opacityValue = parseInt(demoData.opacityValue, 10);\r
+\r
+ if (colorValue.charAt(0) !== '#') {\r
+ colorValue = '#' + colorValue;\r
+ }\r
+\r
+ if (opacityValue === 0) {\r
+ colorString = 'transparent';\r
+ } else if (opacityValue < 100) {\r
+ // rgba\r
+ colorString = 'rgba(' + hexToRGB(colorValue.substr(1)).concat([opacityValue/100]).join(', ') + ')';\r
+ } else {\r
+ colorString = demoData.backgroundValue;\r
+ }\r
+\r
+ applyToNodes('.sm2-main-controls, .sm2-playlist-drawer', function(node) {\r
+ node.style.backgroundColor = colorString;\r
+ });\r
+\r
+ if (opacityValue === 0) {\r
+ demoData.colorOutput.innerHTML = 'background-color: transparent;';\r
+ } else if (opacityValue < 100) {\r
+ demoData.colorOutput.innerHTML = 'background-color: ' + colorValue + '; /* non-RGBA fallback */\n background-color: ' + colorString + ';';\r
+ } else {\r
+ demoData.colorOutput.innerHTML = 'background-color: ' + colorString + ';'\r
+ }\r
+\r
+ }\r
+\r
+ utils.events.add(demoData.colorPicker, 'change', function(e) {\r
+\r
+ var target = e.target || e.srcElement,\r
+ color = target.value;\r
+\r
+ if (color) {\r
+ demoData.backgroundValue = color;\r
+ }\r
+\r
+ updateColor();\r
+\r
+ });\r
+\r
+ utils.events.add(demoData.opacityPicker, 'change', function(e) {\r
+\r
+ var target = e.target || e.srcElement,\r
+ opacity = target.value;\r
+\r
+ if (opacity !== undefined) {\r
+ demoData.opacityValue = opacity;\r
+ }\r
+\r
+ updateColor();\r
+\r
+ });\r
+\r
+ utils.events.add(demoData.sizePicker, 'change', function(e) {\r
+\r
+ var target = e.target || e.srcElement,\r
+ size = target.value;\r
+\r
+ if (size !== undefined) {\r
+ demoData.sizeValue = size;\r
+ }\r
+\r
+ applyToNodes(playerSelector, function(node) {\r
+ node.style.fontSize = size + 'px';\r
+ });\r
+\r
+ });\r
+\r
+ function changeBackground(e, isPage) {\r
+\r
+ var target = e.target || e.srcElement,\r
+ styleTarget = document.documentElement,\r
+ backgroundValue = target.value,\r
+ isTransparent = target.value.match(/transparent/i),\r
+ isDark = target.options[target.selectedIndex].getAttribute('data-dark');\r
+\r
+ // apply to <html>, or UI texture\r
+ if (isPage) {\r
+\r
+ styleTarget.style.background = backgroundValue;\r
+\r
+ if (isDark) {\r
+ document.body.style.color = '#fff';\r
+ } else {\r
+ document.body.style.color = '#000';\r
+ }\r
+\r
+ } else {\r
+\r
+ applyToNodes('.sm2-inline-texture', function(node) {\r
+ node.style.background = backgroundValue;\r
+ });\r
+\r
+ document.getElementById('texture-output').innerHTML = 'background: ' + backgroundValue + ';';\r
+\r
+ if (!isTransparent) {\r
+\r
+ // ensure texture mode is on\r
+ applyToNodes(playerSelector, function(node) {\r
+ utils.css.add(node, 'textured');\r
+ });\r
+\r
+ } else {\r
+\r
+ // ensure texture mode is off\r
+ applyToNodes(playerSelector, function(node) {\r
+ utils.css.remove(node, 'textured');\r
+ });\r
+\r
+ }\r
+\r
+ updateDemoCode();\r
+\r
+ }\r
+\r
+ }\r
+\r
+ utils.events.add(demoData.pageBackgroundPicker, 'change', function(e) {\r
+ changeBackground(e, true);\r
+ });\r
+\r
+ utils.events.add(demoData.playerBackgroundPicker, 'change', function(e) {\r
+ changeBackground(e, false);\r
+ });\r
+\r
+ function handleOpacityMouseMove() {\r
+\r
+ var currentValue = demoData.opacityPicker.value;\r
+\r
+ if (currentValue !== demoData.sizeValue) {\r
+\r
+ demoData.opacityValue = currentValue;\r
+ updateColor();\r
+\r
+ }\r
+\r
+ }\r
+\r
+ function handleFontMouseMove() {\r
+\r
+ var currentValue = demoData.sizePicker.value;\r
+\r
+ if (currentValue !== demoData.sizeValue) {\r
+\r
+ demoData.sizeValue = currentValue;\r
+\r
+ applyToNodes(playerSelector, function(node) {\r
+ node.style.fontSize = currentValue + 'px';\r
+ });\r
+\r
+ document.getElementById('fontsize-output').innerHTML = currentValue + 'px;';\r
+\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Dumb hacks for certain browsers that don't fire onchange() for input type="range" while user is dragging the slider.\r
+ * Also, input type="color".\r
+ * Applies to Firefox Nightly at time of writing (03/2014.)\r
+ */\r
+\r
+ utils.events.add(demoData.opacityPicker, 'mousedown', function(e) {\r
+\r
+ var moveHandler,\r
+ upHandler;\r
+\r
+ // only pay attention to left clicks.\r
+ if (e.button === 0) {\r
+\r
+ moveHandler = utils.events.add(document, 'mousemove', handleOpacityMouseMove);\r
+\r
+ upHandler = utils.events.add(document, 'mouseup', function(e) {\r
+ moveHandler.detach();\r
+ upHandler.detach();\r
+ });\r
+\r
+ }\r
+\r
+ });\r
+\r
+ utils.events.add(demoData.sizePicker, 'mousedown', function(e) {\r
+\r
+ var moveHandler,\r
+ upHandler;\r
+\r
+ // only pay attention to left clicks.\r
+ if (e.button === 0) {\r
+\r
+ moveHandler = utils.events.add(document, 'mousemove', handleFontMouseMove);\r
+\r
+ upHandler = utils.events.add(document, 'mouseup', function(e) {\r
+ moveHandler.detach();\r
+ upHandler.detach();\r
+ });\r
+\r
+ }\r
+\r
+ });\r
+\r
+ utils.events.add(demoData.colorPicker, 'click', function(e) {\r
+\r
+ var colorTimer,\r
+ changeHandler;\r
+\r
+ // this is dumb: resort to polling until change event fires.\r
+\r
+ changeHandler = utils.events.add(demoData.colorPicker, 'change', function(e) {\r
+\r
+ // now that the change event has finally fired, cancel the timer.\r
+\r
+ if (colorTimer) {\r
+ window.clearInterval(colorTimer);\r
+ colorTimer = null;\r
+ }\r
+\r
+ changeHandler.detach();\r
+\r
+ });\r
+\r
+ // regularly poll, update as applicable\r
+ colorTimer = window.setInterval(function() {\r
+\r
+ var color = demoData.colorPicker.value;\r
+\r
+ if (demoData.backgroundValue !== color) {\r
+ demoData.backgroundValue = color;\r
+ updateColor();\r
+ }\r
+\r
+ }, 50);\r
+\r
+ moveHandler = utils.events.add(document, 'mousemove', handleFontMouseMove);\r
+\r
+ upHandler = utils.events.add(document, 'mouseup', function(e) {\r
+ moveHandler.detach();\r
+ upHandler.detach();\r
+ });\r
+\r
+ });\r
+\r
+ function applyToNodes(selector, method) {\r
+ var i, j, nodes = utils.dom.getAll((selector || playerSelector));\r
+ for (i=0, j=nodes.length; i<j; i++) {\r
+ method(nodes[i]);\r
+ }\r
+ }\r
+\r
+ function updateDemoCode() {\r
+\r
+ var className = utils.dom.getFirst(playerSelector).className;\r
+\r
+ // remove dynamic state bits from the live demo\r
+ className = className.replace(/[ ]playing|[ ]paused|[ ]buffering/ig, '');\r
+\r
+ document.getElementById('player-code-example').innerHTML = className;\r
+\r
+ }\r
+\r
+ utils.events.add(document.getElementById('fullwidth'), 'click', function(e) {\r
+ applyToNodes(null, function(node) {\r
+ utils.css.toggle(node, 'full-width');\r
+ updateDemoCode();\r
+ });\r
+ });\r
+\r
+ utils.events.add(document.getElementById('textured'), 'click', function(e) {\r
+ applyToNodes(null, function(node) {\r
+ utils.css.toggle(node, 'textured');\r
+ updateDemoCode();\r
+ });\r
+ });\r
+\r
+ utils.events.add(document.getElementById('dark'), 'click', function(e) {\r
+ applyToNodes(null, function(node) {\r
+ utils.css.toggle(node, 'dark-text');\r
+ updateDemoCode();\r
+ });\r
+ });\r
+\r
+ utils.events.add(document.getElementById('flat'), 'click', function(e) {\r
+ applyToNodes(null, function(node) {\r
+ utils.css.toggle(node, 'flat');\r
+ updateDemoCode();\r
+ });\r
+ });\r
+\r
+ utils.events.add(document.getElementById('playlist-open'), 'click', function(e) {\r
+ var i, j;\r
+ for (i=0, j=players.length; i<j; i++) {\r
+ players[i].actions.menu();\r
+ }\r
+ updateDemoCode();\r
+ });\r
+\r
+ });\r
+\r
+}());
\ No newline at end of file
--- /dev/null
+/**
+ * Cassette Tape UI Prototype (09/2012)
+ * Non-JS view
+ * ALPHA build / experimental state, unsupported; use at own risk
+ * Requires CSS3 border-radius + <canvas> support
+ * --------------------------------------------------
+ * http://www.schillmania.com/projects/soundmanager2/
+ *
+ * Tape UI elements (spokes, reels, textures) by Brian Scates
+ * http://sxates.com/
+ */
+
+#tape-loader {
+ display: none;
+}
+
+#demo-header-wrapper {
+ opacity: 1 !important;
+}
+
+.tape.draggable {
+ top: 50%;
+ left: 50%;
+ margin: -150px 0px 0px -240px;
+ opacity: 1;
+}
+
+.tape.draggable .controls {
+ display: none;
+}
\ No newline at end of file
--- /dev/null
+/**\r
+ * Cassette Tape UI Prototype (09/2012)\r
+ * ALPHA build / experimental state, unsupported; use at own risk\r
+ * Requires CSS3 border-radius + <canvas> support\r
+ * --------------------------------------------------\r
+ * http://www.schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Tape UI elements (spokes, reels, textures) by Brian Scates\r
+ * http://sxates.com/\r
+ */\r
+\r
+html {\r
+ position: relative;\r
+ width: 100%;\r
+ height: 100%;\r
+ /* prevent scrollbars within the draggable case. */\r
+ overflow: hidden;\r
+ background: #000 url(../image/demo_backgrounds/sfatnight_1600.jpg) no-repeat 0px 0px;\r
+}\r
+\r
+body {\r
+ color: #fff;\r
+}\r
+\r
+.tape.draggable {\r
+ position: absolute;\r
+ display: inline-block;\r
+ margin: 0px;\r
+ box-shadow: 0px 0px 16px rgba(0,0,0,0.1);\r
+ border-color: rgba(0,0,0,0.25);\r
+ background: transparent;\r
+ border: 1px solid rgba(0,0,0,0.1);\r
+}\r
+\r
+.tape.draggable .rail-left,\r
+.tape.draggable .rail-right {\r
+ /* hack: would reuse metal texture, but not dark enough due to dynamically-applied gradient. */\r
+ display: none;\r
+}\r
+\r
+.tape.draggable .reel-mask {\r
+ background-color: rgba(255,255,255,0.1);\r
+ background-color: transparent;\r
+}\r
+\r
+.tape.draggable .blur-image-wrapper {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 100%;\r
+ border-radius: 12px;\r
+ overflow: hidden;\r
+ z-index: -1;\r
+}\r
+\r
+.tape.draggable .blur-image {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 100%;\r
+ height: 100%;\r
+ border-radius: 12px;\r
+ /* hack for now */\r
+ margin-left: 100%;\r
+ margin-right: 100%;\r
+}\r
+\r
+.tape.draggable .transparency-sheet {\r
+ /* wash out everything slightly */\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 100%;\r
+ background: rgba(255,255,255,0.25);\r
+ border-radius: 12px;\r
+}\r
+\r
+.tape.draggable .blur-image-wrapper,\r
+.tape.draggable .transparency-sheet {\r
+ /* fade and blur, same height */\r
+ height: 81%;\r
+}\r
+\r
+.tape.draggable .tape-shell {\r
+ background: transparent url(../image/ma-r90-metal-pattern-v2.png);\r
+ background-size: normal;\r
+}\r
+\r
+.tape.draggable .tape-gradient {\r
+ background: transparent url(../image/gradient.png) no-repeat 0px 0px;\r
+ /* TODO: use a native CSS gradient. Save 2 KB image request, but maybe slower to draw? */\r
+ /* display: none; */\r
+}\r
+\r
+.tape.draggable .tape-shell,\r
+.tape.draggable .tape-gradient {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 100%;\r
+ height: 100%;\r
+ border-radius: 12px;\r
+ /**\r
+ * TODO: consider using webkit-mask-box-image where supported, and canvas otherwise?\r
+ */\r
+ /*\r
+ -webkit-mask-box-image: url(../image/ma-r90-mask.png);\r
+ -moz-mask-image: url(../image/ma-r90-mask.png);\r
+ -moz-mask-image: -moz-linear-gradient(bottom, rgba(255,0,0,1), rgba(0,255,0,1), rgba(0,0,255,0), rgba(128,0,128,0));\r
+ -moz-mask-size: 480px 300px;\r
+ */\r
+}\r
+\r
+.tape.draggable .tape-pad-holder {\r
+ background: transparent;\r
+ bottom: 0px;\r
+ height: 7px;\r
+}\r
+\r
+.tape.draggable .tape-pad {\r
+ background: rgba(96,48,0,0.9);\r
+ height: 100%;\r
+ top: -1px;\r
+}\r
+\r
+.tape.draggable .tape-pad-line {\r
+ display: block;\r
+ border-top: 1px solid rgba(64,32,0,0.5);\r
+ bottom: auto;\r
+ top: 0px;\r
+ margin-left: -46%;\r
+ width: 188%;\r
+}\r
+\r
+.tape.draggable .controls {\r
+ top: 0px;\r
+}\r
+\r
+/* a few loading transition bits */\r
+\r
+.tape.draggable {\r
+ opacity: 0;\r
+}\r
+\r
+.tape.draggable.ready {\r
+ opacity: 1;\r
+}\r
+\r
+.tape.draggable.dropin {\r
+ -o-animation: dropin 0.75s;\r
+ -moz-animation: dropin 0.75s;\r
+ -ms-animation: dropin 0.75s;\r
+ -webkit-animation: dropin 0.75s;\r
+}\r
+\r
+@-o-keyframes dropin {\r
+ 0% {\r
+ opacity: 0;\r
+ -o-transform: scale(2);\r
+ -o-animation-timing-function: ease-out;\r
+ }\r
+ 33% {\r
+ opacity: 0.5;\r
+ -o-transform: scale(0.85);\r
+ -o-animation-timing-function: ease-in-out;\r
+ }\r
+ 55% {\r
+ opacity: 1;\r
+ -o-transform: scale(1);\r
+ -o-animation-timing-function: ease-in-out;\r
+ }\r
+ 77% {\r
+ opacity: 1;\r
+ -o-transform: scale(0.98);\r
+ -o-animation-timing-function: ease-in-out;\r
+ }\r
+ 100% {\r
+ opacity: 1;\r
+ -o-transform: scale(1);\r
+ -o-animation-timing-function: ease-in-out;\r
+ }\r
+}\r
+\r
+@-moz-keyframes dropin {\r
+ 0% {\r
+ opacity: 0;\r
+ -moz-transform: scale3d(2, 2, 1);\r
+ -moz-animation-timing-function: ease-out;\r
+ }\r
+ 33% {\r
+ opacity: 0.5;\r
+ -moz-transform: scale3d(0.85, 0.85, 1);\r
+ -moz-animation-timing-function: ease-in-out;\r
+ }\r
+ 55% {\r
+ opacity: 1;\r
+ -moz-transform: scale3d(1.05, 1.05, 1);\r
+ -moz-animation-timing-function: ease-in-out;\r
+ }\r
+ 77% {\r
+ opacity: 1;\r
+ -moz-transform: scale3d(0.98, 0.98, 1);\r
+ -moz-animation-timing-function: ease-in-out;\r
+ }\r
+ 100% {\r
+ opacity: 1;\r
+ -moz-transform: scale3d(1, 1, 1);\r
+ -moz-animation-timing-function: ease-in-out;\r
+ }\r
+}\r
+\r
+@-ms-keyframes dropin {\r
+ 0% {\r
+ opacity: 0;\r
+ -ms-transform: scale3d(2, 2, 1);\r
+ -ms-animation-timing-function: ease-out;\r
+ }\r
+ 33% {\r
+ opacity: 0.5;\r
+ -ms-transform: scale3d(0.85, 0.85, 1);\r
+ -ms-animation-timing-function: ease-in-out;\r
+ }\r
+ 55% {\r
+ opacity: 1;\r
+ -ms-transform: scale3d(1.05, 1.05, 1);\r
+ -ms-animation-timing-function: ease-in-out;\r
+ }\r
+ 77% {\r
+ opacity: 1;\r
+ -ms-transform: scale3d(0.98, 0.98, 1);\r
+ -ms-animation-timing-function: ease-in-out;\r
+ }\r
+ 100% {\r
+ opacity: 1;\r
+ -ms-transform: scale3d(1, 1, 1);\r
+ -ms-animation-timing-function: ease-in-out;\r
+ }\r
+}\r
+\r
+@-webkit-keyframes dropin {\r
+ 0% {\r
+ opacity: 0;\r
+ -webkit-transform: scale3d(2, 2, 1);\r
+ -webkit-animation-timing-function: ease-out;\r
+ }\r
+ 33% {\r
+ opacity: 0.5;\r
+ -webkit-transform: scale3d(0.85, 0.85, 1);\r
+ -webkit-animation-timing-function: ease-in-out;\r
+ }\r
+ 55% {\r
+ opacity: 1;\r
+ -webkit-transform: scale3d(1.05, 1.05, 1);\r
+ -webkit-animation-timing-function: ease-in-out;\r
+ }\r
+ 77% {\r
+ opacity: 1;\r
+ -webkit-transform: scale3d(0.98, 0.98, 1);\r
+ -webkit-animation-timing-function: ease-in-out;\r
+ }\r
+ 100% {\r
+ opacity: 1;\r
+ -webkit-transform: scale3d(1, 1, 1);\r
+ -webkit-animation-timing-function: ease-in-out;\r
+ }\r
+}\r
+\r
+.tape.draggable .blur-image-wrapper {\r
+ opacity: 0;\r
+ -moz-transition: opacity 0.1s ease-out;\r
+ -webkit-transition: opacity 0.1s ease-out;\r
+ transition: opacity 0.1s ease-out;\r
+}\r
+\r
+.tape.draggable.ready .blur-image-wrapper {\r
+ opacity: 1;\r
+}\r
+\r
+.tape.draggable {\r
+ -moz-transition: -moz-transform 0.1s ease-out;\r
+ -moz-transform: scale3d(1, 1, 1);\r
+ -ms-transition: -ms-transform 0.1s ease-out;\r
+ -ms-transform: scale3d(1, 1, 1);\r
+ -o-transition: -o-transform 0.1s ease-out;\r
+ -o-transform: scale(1);\r
+ -webkit-transition: -webkit-transform 0.1s ease-out;\r
+ -webkit-transform: scale3d(1, 1, 1);\r
+}\r
+\r
+.tape.draggable.dragging {\r
+ -ms-transform: scale3d(1.025, 1.025, 1);\r
+ -moz-transform: scale3d(1.025, 1.025, 1);\r
+ -o-transform: scale(1.025);\r
+ -webkit-transform: scale3d(1.025, 1.025, 1);\r
+}\r
+\r
+.tape.draggable.dropping {\r
+ -o-animation: dragdrop 0.5s;\r
+ -ms-animation: dragdrop 0.5s;\r
+ -moz-animation: dragdrop 0.5s;\r
+ -webkit-animation: dragdrop 0.5s;\r
+}\r
+\r
+@-ms-keyframes dragdrop {\r
+ 0% {\r
+ -ms-transform: scale3d(1.025, 1,025, 1);\r
+ -ms-animation-timing-function: ease-in-out;\r
+ }\r
+ 33% {\r
+ -ms-transform: scale3d(0.99, 0.99, 1);\r
+ -ms-animation-timing-function: ease-in-out;\r
+ }\r
+ 55% {\r
+ -ms-transform: scale3d(1.005, 1.005, 1);\r
+ -ms-animation-timing-function: ease-in-out;\r
+ }\r
+ 77% {\r
+ -ms-transform: scale3d(0.997, 0.997, 1);\r
+ -ms-animation-timing-function: ease-in-out;\r
+ }\r
+ 100% {\r
+ -ms-transform: scale3d(1, 1, 1);\r
+ -ms-animation-timing-function: ease-in-out;\r
+ }\r
+}\r
+\r
+@-moz-keyframes dragdrop {\r
+ 0% {\r
+ -moz-transform: scale3d(1.025, 1,025, 1);\r
+ -moz-animation-timing-function: ease-in-out;\r
+ }\r
+ 33% {\r
+ -moz-transform: scale3d(0.99, 0.99, 1);\r
+ -moz-animation-timing-function: ease-in-out;\r
+ }\r
+ 55% {\r
+ -moz-transform: scale3d(1.005, 1.005, 1);\r
+ -moz-animation-timing-function: ease-in-out;\r
+ }\r
+ 77% {\r
+ -moz-transform: scale3d(0.997, 0.997, 1);\r
+ -moz-animation-timing-function: ease-in-out;\r
+ }\r
+ 100% {\r
+ -moz-transform: scale3d(1, 1, 1);\r
+ -moz-animation-timing-function: ease-in-out;\r
+ }\r
+}\r
+\r
+@-o-keyframes dragdrop {\r
+ 0% {\r
+ -o-transform: scale(1.025);\r
+ -o-animation-timing-function: ease-in-out;\r
+ }\r
+ 33% {\r
+ -o-transform: scale(0.99);\r
+ -o-animation-timing-function: ease-in-out;\r
+ }\r
+ 55% {\r
+ -o-transform: scale(1.005);\r
+ -o-animation-timing-function: ease-in-out;\r
+ }\r
+ 77% {\r
+ -o-transform: scale(0.997);\r
+ -o-animation-timing-function: ease-in-out;\r
+ }\r
+ 100% {\r
+ -o-transform: scale(1);\r
+ -o-animation-timing-function: ease-in-out;\r
+ }\r
+}\r
+\r
+\r
+@-webkit-keyframes dragdrop {\r
+ 0% {\r
+ -webkit-transform: scale3d(1.025, 1,025, 1);\r
+ -webkit-animation-timing-function: ease-in-out;\r
+ }\r
+ 33% {\r
+ -webkit-transform: scale3d(0.99, 0.99, 1);\r
+ -webkit-animation-timing-function: ease-in-out;\r
+ }\r
+ 55% {\r
+ -webkit-transform: scale3d(1.005, 1.005, 1);\r
+ -webkit-animation-timing-function: ease-in-out;\r
+ }\r
+ 77% {\r
+ -webkit-transform: scale3d(0.997, 0.997, 1);\r
+ -webkit-animation-timing-function: ease-in-out;\r
+ }\r
+ 100% {\r
+ -webkit-transform: scale3d(1, 1, 1);\r
+ -webkit-animation-timing-function: ease-in-out;\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/**\r
+ * Cassette Tape UI Prototype (09/2012)\r
+ * ALPHA build / experimental state, unsupported; use at own risk\r
+ * Requires CSS3 border-radius + <canvas> support\r
+ * --------------------------------------------------\r
+ * http://www.schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Tape UI elements (spokes, reels, textures) by Brian Scates\r
+ * http://sxates.com/\r
+ */\r
+\r
+@font-face {\r
+ font-family: 'JustAnotherHandRegular';\r
+ src: url('../font/justanotherhand-webfont.eot');\r
+ src: url('../font/justanotherhand-webfont.eot?#iefix') format('embedded-opentype'),\r
+ url('../font/justanotherhand-webfont.woff') format('woff'),\r
+ url('../font/justanotherhand-webfont.ttf') format('truetype');\r
+ font-weight: normal;\r
+ font-style: normal;\r
+}\r
+\r
+.tape {\r
+ position: relative;\r
+ display: inline-block;\r
+ width: 480px;\r
+ height: 300px;\r
+ border: 1px solid rgba(0,0,0,0.1);\r
+ cursor: pointer;\r
+ margin: 0.5em;\r
+ z-index: 1;\r
+}\r
+\r
+.tape,\r
+.tape .rail-middle {\r
+ border-radius: 12px;\r
+}\r
+\r
+.tape .rail-middle {\r
+ border-top-left-radius: 0px;\r
+ border-top-right-radius: 0px;\r
+}\r
+\r
+.tape .left,\r
+.tape .right {\r
+ position: absolute;\r
+ top: 45%;\r
+}\r
+\r
+.tape .left {\r
+ /* the left side */\r
+ left: 29%;\r
+}\r
+\r
+.tape .right {\r
+ /* the right side */\r
+ left: 71%;\r
+}\r
+\r
+.tape .window {\r
+ position: absolute;\r
+ top: 11%;\r
+ left: 0px;\r
+ width: 100%;\r
+ height: 69%;\r
+ background: rgba(0,0,0,0.033);\r
+}\r
+\r
+.tape .reel,\r
+.tape .spokes {\r
+ border-radius: 100%;\r
+}\r
+\r
+.tape .spokes {\r
+ width: 93px;\r
+ height: 93px;\r
+}\r
+\r
+.tape .reel {\r
+ width: 91px;\r
+ height: 91px;\r
+ background: transparent url(../image/tape-texture.png) no-repeat 50% 50%;\r
+ border: 76px solid transparent;\r
+ border-radius: 100%;\r
+ margin-left: -121px;\r
+ margin-top: -121px;\r
+}\r
+\r
+.tape .reel-mask {\r
+ position: absolute;\r
+ top: 2.4%;\r
+ width: 256px;\r
+ height: 256px;\r
+ background: #fff;\r
+ border-radius: 100%;\r
+ margin-left: -128px;\r
+ display: none\9; /* IE 8 */\r
+}\r
+\r
+.tape .reel.right {\r
+ border-width: 0px;\r
+ margin-left: -45px;\r
+ margin-top: -45px;\r
+}\r
+\r
+.tape .spokes {\r
+ margin-left: -46px;\r
+ margin-top: -46px;\r
+ background: transparent url(../image/tape-spokes-sxates.png) no-repeat 50% 50%;\r
+ background-size: 100% 100%;\r
+ z-index: 5;\r
+}\r
+\r
+.tape.dark .spokes {\r
+ /* hack: override */\r
+ background-color: #ccc;\r
+}\r
+\r
+.tape .spokes-overlay {\r
+ position: absolute;\r
+ top: 50%;\r
+ left: 50%;\r
+ width: 160px;\r
+ height: 160px;\r
+ background: #fff;\r
+ border-radius: 100%;\r
+ margin: -80px 0px 0px -80px;\r
+ background: transparent url(../image/tape-reel.png) no-repeat 50% 50%;\r
+ background-size: contain;\r
+}\r
+\r
+.tape.clear .spokes {\r
+ background: transparent url(../image/spool-metal-black.png) no-repeat 50% 50%;\r
+}\r
+\r
+.tape.clear .spokes.right {\r
+ background: transparent url(../image/spool-metal.png) no-repeat 50% 50%;\r
+}\r
+\r
+.tape .label {\r
+ position: absolute;\r
+ top: 59%;\r
+ left: 11%;\r
+ width: 78.5%;\r
+ height: 16%;\r
+ background-color: #fff;\r
+ background-color: rgba(0,0,0,0.1);\r
+ border-radius: 5px;\r
+ text-indent: 0.25em;\r
+ font: normal 36px JustAnotherHandRegular, helvetica, sans-serif;\r
+ line-height: 140%;\r
+ color: #111;\r
+ text-shadow: 0px 1px 0px rgba(255,255,255,0.5);\r
+ box-shadow: 1px 1px 0px rgba(0,0,0,0.05);\r
+ /* a slightly-human element */\r
+ /*\r
+ -moz-transform: rotate(-0.25deg);\r
+ -webkit-transform: rotate(-0.25deg);\r
+ -o-transform: rotate(-0.25deg);\r
+ transform: rotate(-0.25deg);\r
+ */\r
+ white-space: nowrap;\r
+ text-overflow: ellipsis;\r
+ overflow: hidden;\r
+ z-index: 6;\r
+}\r
+\r
+.tape.ma-r90 .label {\r
+ top: 62%;\r
+ width: 75%;\r
+ left: 13%;\r
+}\r
+\r
+.tape.playing .tape-guide,\r
+.tape.playing .spokes {\r
+ -moz-animation-duration: 5s;\r
+ -moz-animation-name: spin;\r
+ -moz-animation-iteration-count: infinite;\r
+ -moz-animation-timing-function: linear;\r
+ -webkit-animation-duration: 5s;\r
+ -webkit-animation-name: spin;\r
+ -webkit-animation-iteration-count: infinite;\r
+ -webkit-animation-timing-function: linear;\r
+ -ms-animation-duration: 5s;\r
+ -ms-animation-name: spin;\r
+ -ms-animation-iteration-count: infinite;\r
+ -ms-animation-timing-function: linear;\r
+ -o-animation-duration: 5s;\r
+ -o-animation-name: spin;\r
+ -o-animation-iteration-count: infinite;\r
+ -o-animation-timing-function: linear;\r
+ animation-duration: 5s;\r
+ animation-name: spin;\r
+ animation-iteration-count: infinite;\r
+ animation-timing-function: linear;\r
+}\r
+\r
+.tape.playing .tape-guide {\r
+ -moz-animation-duration: 4.5s;\r
+ -webkit-animation-duration: 4.5s;\r
+ -ms-animation-duration: 4.5s;\r
+ -o-animation-duration: 4.5s;\r
+ animation-duration: 4.5s;\r
+ z-index: 2;\r
+}\r
+\r
+.tape.stopped .tape-guide,\r
+.tape.stopped .spokes {\r
+ -moz-animation: none;\r
+ -webkit-animation: none;\r
+ -ms-animation: none;\r
+ -o-animation: none;\r
+ animation: none;\r
+}\r
+\r
+.tape .reel.right,\r
+.tape .spokes.right {\r
+ -moz-animation-duration: 3.5s;\r
+ -webkit-animation-duration: 3.5s;\r
+ -ms-animation-duration: 3.5s;\r
+ -o-animation-duration: 3.5s;\r
+ animation-duration: 3.5s;\r
+}\r
+\r
+.tape.clear,\r
+.tape.clear .rail-left,\r
+.tape.clear .rail-right {\r
+ background: #f0f0f0;\r
+}\r
+\r
+.tape.clear.blue,\r
+.tape.clear.blue .rail-left,\r
+.tape.clear.blue .rail-right {\r
+ background: #3399cc;\r
+}\r
+\r
+.tape.clear.blue .screw-tl,\r
+.tape.clear.blue .screw-tr,\r
+.tape.clear.blue .screw-bl,\r
+.tape.clear.blue .screw-tm,\r
+.tape.clear.blue .screw-bm,\r
+.tape.clear.blue .screw-br {\r
+ border-color: rgba(0,32,96,0.5);\r
+}\r
+\r
+.tape.clear.green,\r
+.tape.clear.green .rail-left,\r
+.tape.clear.green .rail-right {\r
+ background: #33cc33;\r
+}\r
+\r
+.tape.clear.blue .window {\r
+ background: rgba(0,0,0,0.075);\r
+}\r
+\r
+.tape.clear .label {\r
+ background: rgba(255,255,255,0.9);\r
+}\r
+\r
+.tape.texture .rail-middle {\r
+ /* background: transparent url(../image/body-texture-strips.png); */\r
+ background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAACCAYAAAC3zQLZAAAAH0lEQVR42u3DAQ0AAAzCMGzgX+h+H6xJA9T25rza3nwCFS8u8CRhoQAAAABJRU5ErkJggg==);\r
+}\r
+\r
+.tape.clear .reel.right {\r
+ border-width: 0px;\r
+}\r
+\r
+@-moz-keyframes spin {\r
+ from {\r
+ -moz-transform: rotate(360deg);\r
+ }\r
+ to {\r
+ -moz-transform: rotate(0deg);\r
+ }\r
+}\r
+\r
+@-webkit-keyframes spin {\r
+ from {\r
+ -webkit-transform: rotate(360deg);\r
+ }\r
+ to {\r
+ -webkit-transform: rotate(0deg);\r
+ }\r
+}\r
+\r
+@-ms-keyframes spin {\r
+ from {\r
+ -ms-transform: rotate(360deg);\r
+ }\r
+ to {\r
+ -ms-transform: rotate(0deg);\r
+ }\r
+}\r
+\r
+@-o-keyframes spin {\r
+ from {\r
+ -o-transform: rotate(360deg);\r
+ }\r
+ to {\r
+ -o-transform: rotate(0deg);\r
+ }\r
+}\r
+\r
+@keyframes spin {\r
+ from {\r
+ transform: rotate(360deg);\r
+ }\r
+ to {\r
+ transform: rotate(0deg);\r
+ }\r
+}\r
+\r
+.screw-tl,\r
+.screw-tr,\r
+.screw-bl,\r
+.screw-tm,\r
+.screw-bm,\r
+.screw-br {\r
+ position: absolute;\r
+ width: 3.74%;\r
+ height: 5.95%;\r
+ max-width: 32px;\r
+ max-height: 32px;\r
+ /*\r
+ background: rgba(255,255,255,0.5) url(../image/tape-screw.png) no-repeat 50% 50%;\r
+ */\r
+ background: rgba(255,255,255,0.5) url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABAklEQVR42u2QTUvDQBCGPViRgu2lJw9Bb570kE1Dd5OQL/Ml7aE59Me8UPCXx5lSQYaNSUO9OfDAsPPuwzA3fdV13YJwiBfijXg99w7PZP430f23aACHs0OyOfFEPI+Es/M+2Yx4nMjMJlwSK0nbtoef2DL8V8puiQcbdV3vwzD8ZLjvy7FDCu9skGhrtD4aY47c9+XOwuFyXbcOwgAkA/diPE4gSdMUeZbDNhsrxHrtn7bKsgxVVaFpGhRFgTiOoTcaSilcJPR9H1EUIc/fSfaB3W6LsqyQJAm0vlAoKYvytKV8n3xT3orvaBNMEhqjEQTmekLlKXiedyWhvNl//Xl9AUz2aaW7RdRjAAAAAElFTkSuQmCC) no-repeat 50% 50%;\r
+ background-size: 100% 100%;\r
+ border: 2px solid rgba(0,0,0,0.25);\r
+ border-radius: 100%;\r
+ -moz-box-sizing: border-box;\r
+ -webkit-box-sizing: border-box;\r
+ box-sizing: border-box;\r
+/*\r
+ -moz-transform: rotate(22.5deg);\r
+ -webkit-transform: rotate(22.5deg);\r
+ transform: rotate(22.5deg);\r
+*/\r
+}\r
+\r
+.screw-bl,\r
+.screw-bm,\r
+.screw-br {\r
+ border-color: rgba(0,0,0,0.5);\r
+}\r
+\r
+.tape.dark .screw-tl,\r
+.tape.dark .screw-tr,\r
+.tape.dark .screw-bl,\r
+.tape.dark .screw-tm,\r
+.tape.dark .screw-bm,\r
+.tape.dark .screw-br {\r
+/*\r
+ background: transparent url(../image/tape-screw-dark.png) no-repeat 50% 50%;\r
+*/\r
+ background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABfElEQVR42p2UW4uCUBhF5z9FNtnDZBeLytIstZvU2J0uEAT1EtQf38N+qEbOUTRhwYfuvbyfL9m2XC5xOBxwuVxwu93weDxwv9/Bmft4jBmhKBNtt9unKBZmmGUnUrbb7XC9XlPBDruCbLPZ4Hw+fwS7dISEx+MRp9NJwLKsF6ZpyjLsvoUc1us19vu9lHa7jUwmQzhH5uig6ynkZUsxDANqPg9VVTlH5cLCOJrNJirVCnS9yjkuKxWyJNDpdGCZluxYMiGfl6oWoFd18EUMBgOMx2P0+300Gg0Uf4rIZrPphIVCAbVaDd2ujcnERxD8wnU9tIwWNE2DoiiJhQKu4/IqP7tl2QkMo8VPJvlLWSwWCIJACp9ZqaShXC5xjsrR8RauVitMp1Mp9XodSk7Bdy7HOSpHR/hv4Vl83xfgi/mHLMPuSxb6/fhpjEajNLDD7ksoSIfDITzPSwKzgky6jM1mMziOEwczzKZbuefzOXhbtm2j1+tx5r7YlfoPlDTtZXQWxkUAAAAASUVORK5CYII=) no-repeat 50% 50%;\r
+ background-size: 100% 100%;\r
+ border-color: rgba(0,0,0,0.9);\r
+ opacity: 0.9;\r
+}\r
+\r
+.tape.color .screw-tl,\r
+.tape.color .screw-tr,\r
+.tape.color .screw-bl,\r
+.tape.color .screw-tm,\r
+.tape.color .screw-bm,\r
+.tape.color .screw-br {\r
+ border: 2px solid rgba(0,0,0,0.25);\r
+ box-shadow: none;\r
+}\r
+\r
+.screw-tl {\r
+ top: 1.6%;\r
+ left: 1%;\r
+}\r
+\r
+.screw-tr {\r
+ top: 1.6%;\r
+ right: 1%;\r
+}\r
+\r
+.screw-bl {\r
+ bottom: 1.6%;\r
+ left: 1%;\r
+}\r
+\r
+.screw-bm {\r
+ top: 15%;\r
+ left: 50%;\r
+ width: 3.85%;\r
+ height: 30%;\r
+ margin: 0px 0px 0px -1.925%;\r
+}\r
+\r
+.screw-tm {\r
+ top: 7%;\r
+ left: 50%;\r
+ width: 3.85%;\r
+ height: 6%;\r
+ margin: 0px 0px 0px -1.925%;\r
+}\r
+\r
+.screw-br {\r
+ bottom: 1.6%;\r
+ right: 1%;\r
+}\r
+\r
+.rail-left,\r
+.rail-right {\r
+ position: absolute;\r
+ bottom: 9%;\r
+ width: 3px;\r
+ height: 22.5%;\r
+ background: #ccc;\r
+ border-radius: 0px 6px 6px 0px;\r
+ border: 1px solid rgba(255,255,255,0.1);\r
+}\r
+\r
+.rail-left {\r
+ left: 0px;\r
+ margin-left: -5px;\r
+ border-radius: 6px 0px 0px 6px;\r
+ border-left: none;\r
+}\r
+\r
+.rail-right {\r
+ right: 0px;\r
+ margin-right: -5px;\r
+ border-right: none;\r
+}\r
+\r
+.rail-middle {\r
+ position: absolute;\r
+ bottom: 0px;\r
+ width: 100%;\r
+ height: 20%;\r
+}\r
+\r
+.rail-middle-outline {\r
+ position: absolute;\r
+ top: 0px;\r
+ left: 0px;\r
+ width: 66%;\r
+ height: 100%;\r
+ margin-left: 17%;\r
+ border-top: none;\r
+ border-bottom: none;\r
+ -moz-box-sizing: border-box;\r
+ -webkit-box-sizing: border-box;\r
+ box-sizing: border-box;\r
+}\r
+\r
+.tape .rail-middle-outline {\r
+ background: transparent url(../image/rail-middle-outline.png) no-repeat 50% 100%;\r
+ background-size: contain;\r
+ z-index: 2;\r
+}\r
+\r
+.hole-1,\r
+.hole-2,\r
+.hole-3,\r
+.hole-4 {\r
+ position: absolute;\r
+ bottom: 5%;\r
+ background: rgba(0,0,0,0.1);\r
+ background: #fff;\r
+ width: 16px;\r
+ height: 16px;\r
+ margin: -8px 0px 0px -8px;\r
+ -moz-box-sizing: border-box;\r
+ -webkit-box-sizing: border-box;\r
+ box-sizing: border-box;\r
+}\r
+\r
+.hole-1,\r
+.hole-4 {\r
+ /* circles */\r
+ border-radius: 100%;\r
+}\r
+\r
+.hole-2,\r
+.hole-3 {\r
+ width: 18px;\r
+ margin-top: -9px;\r
+ border-radius: 33%;\r
+ bottom: 15%;\r
+}\r
+\r
+.hole-1 {\r
+ left: 15%;\r
+}\r
+\r
+.hole-2 {\r
+ left: 30%;\r
+}\r
+\r
+.hole-3 {\r
+ left: 70%;\r
+}\r
+\r
+.hole-4 {\r
+ left: 85%;\r
+}\r
+\r
+.tape-pad-holder {\r
+ position: absolute;\r
+ bottom: 1px;\r
+ left: 50%;\r
+ width: 15%;\r
+ height: 25%;\r
+ margin: 0px 0px 0px -7.5%;\r
+ background: #fff;\r
+}\r
+\r
+.tape-pad-holder .tape-pad {\r
+ position: absolute;\r
+ bottom: 0px;\r
+ left: 50%;\r
+ width: 35%;\r
+ height: 45%;\r
+ margin: -1px 0px 0px -17.5%;\r
+ background: rgba(0,0,0,0.2);\r
+}\r
+\r
+.tape.dark .tape-pad-holder .tape-pad {\r
+ background: rgba(0,0,0,0.5);\r
+}\r
+\r
+.tape-pad-holder .tape-pad-line {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 50%;\r
+ width: 100%;\r
+ height: 0px;\r
+ margin-top: -2px;\r
+ border-top: 1px solid rgba(0,0,0,0.25);\r
+ /* hide by default */\r
+ display: none;\r
+}\r
+\r
+.progress-notches {\r
+ position: absolute;\r
+ top: 50%;\r
+ left: 50%;\r
+ width: 25%;\r
+ height: 2.5%;\r
+ margin: -18px 0px 0px -12.5%;\r
+ font-size: 11px;\r
+ text-align: center;\r
+ white-space: nowrap;\r
+}\r
+\r
+.progress-notches div {\r
+ display: inline-block;\r
+ background: #666;\r
+ width: 2%;\r
+ margin-left: 4%;\r
+ height: 100%;\r
+ vertical-align: top;\r
+ /* due to rounding errors, this doesn't always work out. */\r
+ width: 2px;\r
+}\r
+\r
+.progress-notches div:first-of-type {\r
+ margin-left: 0px;\r
+}\r
+\r
+.tape .tape-guide {\r
+ position: absolute;\r
+ top: auto;\r
+ bottom: 0px;\r
+ width: 6.875%;\r
+ height: 11%;\r
+ margin: -10.5% 0px 0px -3.4375%;\r
+ background: rgba(0,0,0,0.1) url(../image/tape-guide.png) no-repeat 50% 50%;\r
+ border-radius: 100%;\r
+}\r
+\r
+.tape.color .tape-guide {\r
+ background-color: transparent;\r
+}\r
+\r
+.tape .tape-guide.left {\r
+ left: 11%;\r
+}\r
+\r
+.tape .tape-guide.right {\r
+ left: 89%;\r
+}\r
+\r
+.tape canvas {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 100%;\r
+ height: 100%;\r
+}\r
+\r
+.tape canvas.connecting-tape {\r
+ visibility: hidden;\r
+}\r
+\r
+.tape .tape-guide,\r
+.tape .label {\r
+ /* stacking corrections (so tape goes through bottom holes) */\r
+ z-index: 4;\r
+}\r
+\r
+.skin-overlay {\r
+ position: absolute;\r
+ top: 0px;\r
+ left: 0px;\r
+ width: 100%;\r
+ height: 100%;\r
+ /* potentially ugly */\r
+ background-size: contain;\r
+}\r
+\r
+.tape.black-micro,\r
+.tape.black-micro .rail-left,\r
+.tape.black-micro .rail-right {\r
+ /* background: transparent url(../image/black-micro.png); */\r
+ background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAGAgMAAACdogfbAAAACVBMVEUWFhYbGxsiIiJSQVJ8AAAAGklEQVQIHWMQZWCYsoAhKIDBM4BBlYFBlAEAHbACv0f8IxYAAAAASUVORK5CYII=);\r
+}\r
+\r
+.tape.ma-r90,\r
+.tape.ma-r90 .rail-left,\r
+.tape.ma-r90 .rail-right {\r
+ background: transparent url(../image/ma-r90-body-skin.png) 0px 0px no-repeat;\r
+}\r
+\r
+.tape.ma-r90 .rail-right {\r
+ /* hack? */\r
+ width: 4px;\r
+}\r
+\r
+.tape.ma-r90 .rail-left,\r
+.tape.ma-r90 .rail-right {\r
+ background-position: 0px 75%;\r
+}\r
+\r
+.tape.ma-r90 .rail-middle {\r
+ background: transparent;\r
+}\r
+\r
+.tape.ma-r90 .tab-left,\r
+.tape.ma-r90 .tab-right {\r
+ position: absolute;\r
+ top: 0px;\r
+ width: 3.74%;\r
+ height: 6.1%;\r
+ max-width: 32px;\r
+ max-height: 32px;\r
+ background-color: rgb(34,142,41);\r
+}\r
+\r
+.tape.ma-r90 .tab-left {\r
+ left: 5.65%;\r
+}\r
+\r
+.tape.ma-r90 .tab-right {\r
+ right: 5.65%;\r
+}\r
+\r
+.tape .tab-left .ridge,\r
+.tape .tab-right .ridge {\r
+ position: absolute;\r
+ left: -10%;\r
+ top: 0px;\r
+ width: 120%;\r
+ height: 3px;\r
+ background-color: rgb(34,142,41);\r
+}\r
+\r
+.tape .tab-left .notch,\r
+.tape .tab-right .notch {\r
+ position: absolute;\r
+ left: 50%;\r
+ top: 50%;\r
+ width: 6px;\r
+ height: 7px;\r
+ margin: -3px 0px 0px -5px;\r
+ border: 2px solid rgb(33,169,43);\r
+ border-top: none;\r
+}\r
+\r
+.tape .controls {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: -1px;\r
+ width: 100%;\r
+ height: 20px;\r
+ margin-top: -20px;\r
+ vertical-align: bottom;\r
+ z-index: -1;\r
+ overflow: hidden;\r
+}\r
+\r
+.tape .controls ul {\r
+ position: relative;\r
+ margin-top: 21px;\r
+ -moz-transition: all 0.2s ease-out;\r
+ -moz-transition-property: height, margin;\r
+ -ms-transition: all 0.2s ease-out;\r
+ -ms-transition-property: height, margin;\r
+ -o-transition: all 0.2s ease-out;\r
+ -o-transition-property: height, margin;\r
+ -webkit-transition: all 0.2s ease-out;\r
+ -webkit-transition-property: height, margin;\r
+ transition: all 0.2s ease-out;\r
+ transition-property: height, margin;\r
+}\r
+\r
+.tape:hover .controls ul {\r
+ margin-top: 0px;\r
+}\r
+\r
+.tape .controls .bd {\r
+ margin: 0px auto;\r
+ text-align: center;\r
+}\r
+\r
+.tape .controls ul {\r
+ list-style-type: none;\r
+ padding: 0px;\r
+ font-size: 0px; /* collapse */\r
+ background-color: rgba(255,255,255,0.9);\r
+ border-radius: 2px 2px 0px 0px;\r
+ overflow: hidden;\r
+ /* http://www.colorzilla.com/gradient-editor/ */\r
+ background: rgb(255,255,255); /* Old browsers */\r
+ background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(241,241,241,1) 50%, rgba(225,225,225,1) 51%, rgba(246,246,246,1) 100%); /* FF3.6+ */\r
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(50%,rgba(241,241,241,1)), color-stop(51%,rgba(225,225,225,1)), color-stop(100%,rgba(246,246,246,1))); /* Chrome,Safari4+ */\r
+ background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Chrome10+,Safari5.1+ */\r
+ background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Opera 11.10+ */\r
+ background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* IE10+ */\r
+ background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* W3C */\r
+ box-shadow: 0px 0px 2px rgba(0,0,0,0.1);\r
+}\r
+\r
+#tape1 .controls.aqua ul {\r
+ /* http://www.colorzilla.com/gradient-editor/ */\r
+ background: rgb(255,255,255); /* Old browsers */\r
+ background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(241,241,241,1) 50%, rgba(225,225,225,1) 51%, rgba(246,246,246,1) 100%); /* FF3.6+ */\r
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(50%,rgba(241,241,241,1)), color-stop(51%,rgba(225,225,225,1)), color-stop(100%,rgba(246,246,246,1))); /* Chrome,Safari4+ */\r
+ background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Chrome10+,Safari5.1+ */\r
+ background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Opera 11.10+ */\r
+ background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* IE10+ */\r
+ background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* W3C */\r
+ box-shadow: 0px 1px 2px rgba(0,0,0,0.1);\r
+}\r
+\r
+.tape .controls ul,\r
+.tape .controls ul li a {\r
+ border: 1px solid rgba(255,255,255,0.9);\r
+}\r
+\r
+.tape .controls ul li {\r
+ border: 1px solid rgba(0,0,0,0.1);\r
+ border-right: none;\r
+ border-top: none;\r
+ border-bottom: none;\r
+}\r
+\r
+.tape .controls ul li:first-of-type,\r
+.tape .controls ul li:first-of-type a {\r
+ border-left: none;\r
+}\r
+\r
+.tape .controls ul {\r
+ position: relative;\r
+ border: none;\r
+ display: inline-block;\r
+ height: 20px;\r
+ overflow: hidden;\r
+}\r
+\r
+.tape .controls ul li {\r
+ position: relative;\r
+ display: inline-block;\r
+ text-align: center;\r
+}\r
+\r
+.tape .controls ul li a {\r
+ position: relative;\r
+ display: block;\r
+ text-decoration: none;\r
+ color: #999;\r
+ font-size: 16px;\r
+ line-height: 20px;\r
+ padding: 0px 16px;\r
+ border-left: none;\r
+ border-top: none;\r
+ border-bottom: none;\r
+}\r
+\r
+.tape .controls ul:hover li a {\r
+ color: #999;\r
+ text-shadow: 0px 1px 1px #fff;\r
+}\r
+\r
+.tape .controls ul li a:hover {\r
+ background: #ccc;\r
+ color: #fff;\r
+ border-color: transparent;\r
+ text-shadow: none;\r
+}\r
+\r
+.tape .controls.aqua ul li a:hover {\r
+ background-color: rgba(0,0,0,0.1);\r
+ background: rgb(184,225,252); /* Old browsers */\r
+ background: -moz-linear-gradient(top, rgba(184,225,252,1) 0%, rgba(169,210,243,1) 10%, rgba(144,186,228,1) 25%, rgba(144,188,234,1) 37%, rgba(144,191,240,1) 50%, rgba(107,168,229,1) 51%, rgba(162,218,245,1) 83%, rgba(189,243,253,1) 100%); /* FF3.6+ */\r
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(184,225,252,1)), color-stop(10%,rgba(169,210,243,1)), color-stop(25%,rgba(144,186,228,1)), color-stop(37%,rgba(144,188,234,1)), color-stop(50%,rgba(144,191,240,1)), color-stop(51%,rgba(107,168,229,1)), color-stop(83%,rgba(162,218,245,1)), color-stop(100%,rgba(189,243,253,1))); /* Chrome,Safari4+ */\r
+ background: -webkit-linear-gradient(top, rgba(184,225,252,1) 0%,rgba(169,210,243,1) 10%,rgba(144,186,228,1) 25%,rgba(144,188,234,1) 37%,rgba(144,191,240,1) 50%,rgba(107,168,229,1) 51%,rgba(162,218,245,1) 83%,rgba(189,243,253,1) 100%); /* Chrome10+,Safari5.1+ */\r
+ background: -o-linear-gradient(top, rgba(184,225,252,1) 0%,rgba(169,210,243,1) 10%,rgba(144,186,228,1) 25%,rgba(144,188,234,1) 37%,rgba(144,191,240,1) 50%,rgba(107,168,229,1) 51%,rgba(162,218,245,1) 83%,rgba(189,243,253,1) 100%); /* Opera 11.10+ */\r
+ background: -ms-linear-gradient(top, rgba(184,225,252,1) 0%,rgba(169,210,243,1) 10%,rgba(144,186,228,1) 25%,rgba(144,188,234,1) 37%,rgba(144,191,240,1) 50%,rgba(107,168,229,1) 51%,rgba(162,218,245,1) 83%,rgba(189,243,253,1) 100%); /* IE10+ */\r
+ background: linear-gradient(to bottom, rgba(184,225,252,1) 0%,rgba(169,210,243,1) 10%,rgba(144,186,228,1) 25%,rgba(144,188,234,1) 37%,rgba(144,191,240,1) 50%,rgba(107,168,229,1) 51%,rgba(162,218,245,1) 83%,rgba(189,243,253,1) 100%); /* W3C */\r
+ color: #fff;\r
+}\r
+\r
+\r
+.tape .controls.aqua ul li a:active {\r
+ background: #999;\r
+}\r
+\r
+.tape .controls ul li:first-child a {\r
+ border-left: none;\r
+}\r
+\r
+.tape .controls ul li:last-child a {\r
+ border-right: none;\r
+}
\ No newline at end of file
--- /dev/null
+/**\r
+ * Cassette demo page CSS - you don't need this part.\r
+ */\r
+\r
+body {\r
+ margin: 0px;\r
+ padding: 0px;\r
+ font-size: 100%;\r
+ font-family: "Helvetica Neue", Helvetica, verdana, arial, tahoma, sans-serif;\r
+ color: #fff;\r
+ /* font trickery */\r
+ -moz-osx-font-smoothing: grayscale;\r
+ -webkit-font-smoothing: antialiased;\r
+}\r
+\r
+body#page-more {\r
+ color: #222;\r
+}\r
+\r
+@font-face {\r
+ /**\r
+ * http://www.theleagueofmoveabletype.com/ostrich-sans\r
+ */\r
+ font-family: 'ostrich-sans-roundedmedium';\r
+ src: url('../font/ostrich-rounded-webfont.eot');\r
+ src: url('../font/ostrich-rounded-webfont.eot?#iefix') format('embedded_opentype'),\r
+ url('../font/ostrich-rounded-webfont.woff') format('woff'),\r
+ url('../font/ostrich-rounded-webfont.ttf') format('truetype'),\r
+ url('../font/ostrich-rounded-webfont.svg#ostrich-sans_roundedmedium') format('svg');\r
+ font-weight: normal;\r
+ font-style: normal;\r
+}\r
+\r
+#demo-header-wrapper {\r
+ position: relative;\r
+ background: rgba(0,0,0,0.15);\r
+ opacity: 0;\r
+}\r
+\r
+#demo-header-wrapper.visible {\r
+ opacity: 1;\r
+}\r
+\r
+#demo-header-wrapper.visible {\r
+ -moz-transition: opacity 0.2s ease-in-out;\r
+ -ms-transition: opacity 0.2s ease-in-out;\r
+ -o-transition: opacity 0.2s ease-in-out;\r
+ -webkit-transition: opacity 0.2s ease-in-out;\r
+ transition: opacity 0.2s ease-in-out;\r
+}\r
+\r
+#demo-header {\r
+ position: relative;\r
+ display: inline-block;\r
+ margin: 0.5em;\r
+ border-top: 2px solid #fff;\r
+ border-bottom: 2px solid #fff;\r
+ padding: 0.5em 0px;\r
+ text-shadow: 0px 1px 1px rgba(0,0,0,0.15);\r
+ white-space: nowrap;\r
+}\r
+\r
+#demo-header,\r
+.demo-subheader {\r
+ margin: 0.5em;\r
+}\r
+\r
+#demo-header-wrapper.light #demo-header {\r
+ border-color: #222;\r
+ text-shadow: none;\r
+}\r
+\r
+#demo-header h1,\r
+#demo-header p,\r
+#demo-header h2 {\r
+ font-weight: normal;\r
+ margin: 0px;\r
+ padding: 0px;\r
+}\r
+\r
+#demo-header h1,\r
+#demo-header h2 {\r
+ font-family: ostrich-sans-roundedmedium, verdana, tahoma, arial, sans-serif;\r
+}\r
+\r
+#demo-header h1 {\r
+ font-size: 533%;\r
+}\r
+\r
+#demo-header h2 {\r
+ font-size: 300%;\r
+}\r
+\r
+#demo-header p {\r
+ background: rgba(0,0,0,0.35);\r
+ margin-bottom: 0.5em;\r
+ vertical-align: middle;\r
+ text-indent: 5px;\r
+ font-weight: 400;\r
+}\r
+\r
+#demo-header-wrapper.light,\r
+#demo-header-wrapper.light #demo-header p {\r
+ background: transparent;\r
+}\r
+\r
+#demo-header-wrapper.light p {\r
+ font-size: 131%;\r
+ text-indent: 2px;\r
+}\r
+\r
+#demo-header p:last-of-type {\r
+ margin-bottom: 0px;\r
+}\r
+\r
+#demo-header a {\r
+ display: inline-block;\r
+ color: #fff;\r
+ text-decoration: none;\r
+ text-shadow: none;\r
+ padding: 2px;\r
+ line-height: 20px;\r
+ min-height: 20px;\r
+ background: rgba(0,0,0,0.4);\r
+}\r
+\r
+#demo-header a:hover {\r
+ color: #fff;\r
+ background: rgba(32,128,255,0.5);\r
+}\r
+\r
+.demo-subheader p {\r
+ max-width: 660px;\r
+ font-size: 95%;\r
+ line-height: 1.4em;\r
+}\r
+\r
+.demo-subheader h2 {\r
+ font-weight: 400;\r
+ margin: 1em 0px 0px 0px;\r
+ padding: 0px;\r
+}\r
+\r
+.demo-subheader h2:first-of-type {\r
+ margin-top: 0.5em;\r
+}\r
+\r
+.demo-subheader p {\r
+ margin-top: 0.5em;\r
+ font-weight: 300;\r
+}\r
+\r
+.demo-subheader a {\r
+ display: inline-block;\r
+ color: #222;\r
+ background-color: #f3f3f3;\r
+ text-decoration: none;\r
+ padding: 0px 3px;\r
+ margin: 0px -1px;\r
+ border-radius: 2px;\r
+ text-shadow: 0px 1px 0px #fff;\r
+}\r
+\r
+.demo-subheader a:hover {\r
+ color: #fff;\r
+ background-color: rgba(32, 128, 255, 0.5);\r
+ text-shadow: none;\r
+}\r
+\r
+.demo-subheader a img {\r
+ padding: 3px 0px;\r
+ vertical-align: bottom;\r
+}\r
+\r
+#tape-loader {\r
+ position: absolute;\r
+ top: 50%;\r
+ left: 50%;\r
+ width: 36px;\r
+ height: 36px;\r
+ margin: -42px 0px 0px -28px;\r
+ border: 9px solid rgba(0,0,0,0.66);\r
+ border-radius: 100%;\r
+ opacity: 1;\r
+}\r
+\r
+#tape-loader .spinner-box {\r
+ position: absolute;\r
+ left: -3px;\r
+ top: -3px;\r
+ width: 42px;\r
+ height: 42px;\r
+ -moz-animation-duration: 0.66s;\r
+ -moz-animation-name: spin;\r
+ -moz-animation-iteration-count: infinite;\r
+ -moz-animation-timing-function: linear;\r
+ -ms-animation-duration: 0.66s;\r
+ -ms-animation-name: spin;\r
+ -ms-animation-iteration-count: infinite;\r
+ -ms-animation-timing-function: linear;\r
+ -o-animation-duration: 0.66s;\r
+ -o-animation-name: spin;\r
+ -o-animation-iteration-count: infinite;\r
+ -o-animation-timing-function: linear;\r
+ -webkit-animation-duration: 0.66s;\r
+ -webkit-animation-name: spin;\r
+ -webkit-animation-iteration-count: infinite;\r
+ -webkit-animation-timing-function: linear;\r
+ animation-duration: 0.66s;\r
+ animation-name: spin;\r
+ animation-iteration-count: infinite;\r
+ animation-timing-function: linear;\r
+}\r
+\r
+#tape-loader .spinner {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 10px;\r
+ height: 10px;\r
+ border-radius: 100%;\r
+ background: rgba(255,255,255,0.75);\r
+ background: rgb(109,179,242);\r
+ background: -moz-radial-gradient(center, ellipse cover, rgba(109,179,242,1) 0%, rgba(84,163,238,1) 50%, rgba(54,144,240,1) 51%, rgba(30,105,222,1) 100%); /* FF3.6+ */\r
+ background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(109,179,242,1)), color-stop(50%,rgba(84,163,238,1)), color-stop(51%,rgba(54,144,240,1)), color-stop(100%,rgba(30,105,222,1))); /* Chrome,Safari4+ */\r
+ background: -webkit-radial-gradient(center, ellipse cover, rgba(109,179,242,1) 0%,rgba(84,163,238,1) 50%,rgba(54,144,240,1) 51%,rgba(30,105,222,1) 100%); /* Chrome10+,Safari5.1+ */\r
+ background: -o-radial-gradient(center, ellipse cover, rgba(109,179,242,1) 0%,rgba(84,163,238,1) 50%,rgba(54,144,240,1) 51%,rgba(30,105,222,1) 100%); /* Opera 12+ */\r
+ background: -ms-radial-gradient(center, ellipse cover, rgba(109,179,242,1) 0%,rgba(84,163,238,1) 50%,rgba(54,144,240,1) 51%,rgba(30,105,222,1) 100%); /* IE10+ */\r
+ background: radial-gradient(ellipse at center, rgba(109,179,242,1) 0%,rgba(84,163,238,1) 50%,rgba(54,144,240,1) 51%,rgba(30,105,222,1) 100%); /* W3C */\r
+\r
+}\r
+\r
+@-moz-keyframes tape_loading {\r
+ from {\r
+ background-position: 0px 0px;\r
+ }\r
+ to {\r
+ background-position: -20px 0px;\r
+ }\r
+}\r
+\r
+@-webkit-keyframes tape_loading {\r
+ from {\r
+ background-position: 0px 0px;\r
+ }\r
+ to {\r
+ background-position: -20px 0px;\r
+ }\r
+}\r
+\r
+\r
+#tape-loader,\r
+#tape-loader.hidden {\r
+ -moz-transition: all 0.33s ease-in-out;\r
+ -moz-transition-property: opacity, -moz-transform;\r
+ -ms-transition: all 0.33s ease-in-out;\r
+ -ms-transition-property: opacity, -ms-transform;\r
+ -o-transition: all 0.33s ease-in-out;\r
+ -o-transition-property: opacity, -o-transform;\r
+ -webkit-transition: all 0.33s ease-in-out;\r
+ -webkit-transition-property: opacity, -webkit-transform;\r
+ transition: all 0.33s ease-in-out;\r
+ transition-property: opacity, transform;\r
+}\r
+\r
+#tape-loader,\r
+#tape-loader.hidden,\r
+#tape-loader.visible.hidden {\r
+ -o-transform: scale(0);\r
+ -moz-transform: scale3d(0, 0, 1);\r
+ -webkit-transform: scale3d(0, 0, 1);\r
+ -ms-transform: scale3d(0, 0, 1);\r
+ transform: scale3d(0, 0, 1);\r
+ opacity: 0;\r
+}\r
+\r
+#tape-loader.visible {\r
+ -o-transform: scale(1);\r
+ -moz-transform: scale3d(1, 1, 1);\r
+ -webkit-transform: scale3d(1, 1, 1);\r
+ -ms-transform: scale3d(1, 1, 1);\r
+ transform: scale3d(1, 1, 1);\r
+ opacity: 1;\r
+}\r
+\r
+/* demo loader */\r
+.tape form {\r
+ margin: 0px;\r
+ padding: 0px;\r
+}\r
+\r
+.tape form input {\r
+ margin: 0px;\r
+ padding: 0px;\r
+ border: none;\r
+}\r
+\r
+.tape form input:-moz-placeholder {\r
+ color: #999;\r
+}\r
+\r
+.tape form input {\r
+ -moz-transition: box-shadow 0.2s ease-in-out;\r
+ -ms-transition: box-shadow 0.2s ease-in-out;\r
+ -o-transition: box-shadow 0.2s ease-in-out;\r
+ -webkit-transition: box-shadow 0.2s ease-in-out;\r
+ transition: box-shadow 0.2s ease-in-out;\r
+ box-shadow: none;\r
+}\r
+\r
+.tape form input:hover,\r
+.tape form input:focus {\r
+ box-shadow: 0px 0px 12px rgb(0,192,255);\r
+}\r
+\r
+/**\r
+ * Oh, what a hack! Let some of the background show through, so we don't entirely mask the header + HTML content with the blurred image.\r
+ * to truly blur the content behind the tape window, one would have to clone the entire DOM (including webfonts, etc.)\r
+ * to mix with the canvas content before blurring, and that is a fairly significant challenge at present.\r
+ */\r
+.tape .blur-image-wrapper .blur-image {\r
+ opacity: 0.9;\r
+}\r
+\r
+/* "more" demo page */\r
+\r
+#col1 {\r
+ width: 640px;\r
+ margin-right: 20px;\r
+}\r
+\r
+#col2 {\r
+ width: 500px;\r
+}\r
+\r
+#col1,\r
+#col2 {\r
+ display: inline-block;\r
+ vertical-align: top;\r
+ -moz-box-sizing: border-box;\r
+ -webkit-box-sizing: border-box;\r
+ box-sizing: border-box;\r
+}\r
+\r
+#col2 .tape {\r
+ margin-top: 1em;\r
+}\r
+\r
+.thanks {\r
+ position: fixed;\r
+ bottom: 0px;\r
+ left: 0px;\r
+ margin: 0px;\r
+ width: 100%;\r
+}\r
+\r
+.thanks p {\r
+ display: block;\r
+ margin: 0px;\r
+ padding: 0.75em;\r
+ background: rgba(0,0,0,0.25);\r
+ text-shadow: 0px 1px #000;\r
+ font-weight: normal;\r
+ font-size: 12px;\r
+ color: #ddd;\r
+}\r
+\r
+.thanks a {\r
+ color: #99ccff;\r
+ text-decoration: none;\r
+}
\ No newline at end of file
--- /dev/null
+\r
+ Apache License\r
+ Version 2.0, January 2004\r
+ http://www.apache.org/licenses/\r
+\r
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
+\r
+ 1. Definitions.\r
+\r
+ "License" shall mean the terms and conditions for use, reproduction,\r
+ and distribution as defined by Sections 1 through 9 of this document.\r
+\r
+ "Licensor" shall mean the copyright owner or entity authorized by\r
+ the copyright owner that is granting the License.\r
+\r
+ "Legal Entity" shall mean the union of the acting entity and all\r
+ other entities that control, are controlled by, or are under common\r
+ control with that entity. For the purposes of this definition,\r
+ "control" means (i) the power, direct or indirect, to cause the\r
+ direction or management of such entity, whether by contract or\r
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
+ outstanding shares, or (iii) beneficial ownership of such entity.\r
+\r
+ "You" (or "Your") shall mean an individual or Legal Entity\r
+ exercising permissions granted by this License.\r
+\r
+ "Source" form shall mean the preferred form for making modifications,\r
+ including but not limited to software source code, documentation\r
+ source, and configuration files.\r
+\r
+ "Object" form shall mean any form resulting from mechanical\r
+ transformation or translation of a Source form, including but\r
+ not limited to compiled object code, generated documentation,\r
+ and conversions to other media types.\r
+\r
+ "Work" shall mean the work of authorship, whether in Source or\r
+ Object form, made available under the License, as indicated by a\r
+ copyright notice that is included in or attached to the work\r
+ (an example is provided in the Appendix below).\r
+\r
+ "Derivative Works" shall mean any work, whether in Source or Object\r
+ form, that is based on (or derived from) the Work and for which the\r
+ editorial revisions, annotations, elaborations, or other modifications\r
+ represent, as a whole, an original work of authorship. For the purposes\r
+ of this License, Derivative Works shall not include works that remain\r
+ separable from, or merely link (or bind by name) to the interfaces of,\r
+ the Work and Derivative Works thereof.\r
+\r
+ "Contribution" shall mean any work of authorship, including\r
+ the original version of the Work and any modifications or additions\r
+ to that Work or Derivative Works thereof, that is intentionally\r
+ submitted to Licensor for inclusion in the Work by the copyright owner\r
+ or by an individual or Legal Entity authorized to submit on behalf of\r
+ the copyright owner. For the purposes of this definition, "submitted"\r
+ means any form of electronic, verbal, or written communication sent\r
+ to the Licensor or its representatives, including but not limited to\r
+ communication on electronic mailing lists, source code control systems,\r
+ and issue tracking systems that are managed by, or on behalf of, the\r
+ Licensor for the purpose of discussing and improving the Work, but\r
+ excluding communication that is conspicuously marked or otherwise\r
+ designated in writing by the copyright owner as "Not a Contribution."\r
+\r
+ "Contributor" shall mean Licensor and any individual or Legal Entity\r
+ on behalf of whom a Contribution has been received by Licensor and\r
+ subsequently incorporated within the Work.\r
+\r
+ 2. Grant of Copyright License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ copyright license to reproduce, prepare Derivative Works of,\r
+ publicly display, publicly perform, sublicense, and distribute the\r
+ Work and such Derivative Works in Source or Object form.\r
+\r
+ 3. Grant of Patent License. Subject to the terms and conditions of\r
+ this License, each Contributor hereby grants to You a perpetual,\r
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+ (except as stated in this section) patent license to make, have made,\r
+ use, offer to sell, sell, import, and otherwise transfer the Work,\r
+ where such license applies only to those patent claims licensable\r
+ by such Contributor that are necessarily infringed by their\r
+ Contribution(s) alone or by combination of their Contribution(s)\r
+ with the Work to which such Contribution(s) was submitted. If You\r
+ institute patent litigation against any entity (including a\r
+ cross-claim or counterclaim in a lawsuit) alleging that the Work\r
+ or a Contribution incorporated within the Work constitutes direct\r
+ or contributory patent infringement, then any patent licenses\r
+ granted to You under this License for that Work shall terminate\r
+ as of the date such litigation is filed.\r
+\r
+ 4. Redistribution. You may reproduce and distribute copies of the\r
+ Work or Derivative Works thereof in any medium, with or without\r
+ modifications, and in Source or Object form, provided that You\r
+ meet the following conditions:\r
+\r
+ (a) You must give any other recipients of the Work or\r
+ Derivative Works a copy of this License; and\r
+\r
+ (b) You must cause any modified files to carry prominent notices\r
+ stating that You changed the files; and\r
+\r
+ (c) You must retain, in the Source form of any Derivative Works\r
+ that You distribute, all copyright, patent, trademark, and\r
+ attribution notices from the Source form of the Work,\r
+ excluding those notices that do not pertain to any part of\r
+ the Derivative Works; and\r
+\r
+ (d) If the Work includes a "NOTICE" text file as part of its\r
+ distribution, then any Derivative Works that You distribute must\r
+ include a readable copy of the attribution notices contained\r
+ within such NOTICE file, excluding those notices that do not\r
+ pertain to any part of the Derivative Works, in at least one\r
+ of the following places: within a NOTICE text file distributed\r
+ as part of the Derivative Works; within the Source form or\r
+ documentation, if provided along with the Derivative Works; or,\r
+ within a display generated by the Derivative Works, if and\r
+ wherever such third-party notices normally appear. The contents\r
+ of the NOTICE file are for informational purposes only and\r
+ do not modify the License. You may add Your own attribution\r
+ notices within Derivative Works that You distribute, alongside\r
+ or as an addendum to the NOTICE text from the Work, provided\r
+ that such additional attribution notices cannot be construed\r
+ as modifying the License.\r
+\r
+ You may add Your own copyright statement to Your modifications and\r
+ may provide additional or different license terms and conditions\r
+ for use, reproduction, or distribution of Your modifications, or\r
+ for any such Derivative Works as a whole, provided Your use,\r
+ reproduction, and distribution of the Work otherwise complies with\r
+ the conditions stated in this License.\r
+\r
+ 5. Submission of Contributions. Unless You explicitly state otherwise,\r
+ any Contribution intentionally submitted for inclusion in the Work\r
+ by You to the Licensor shall be under the terms and conditions of\r
+ this License, without any additional terms or conditions.\r
+ Notwithstanding the above, nothing herein shall supersede or modify\r
+ the terms of any separate license agreement you may have executed\r
+ with Licensor regarding such Contributions.\r
+\r
+ 6. Trademarks. This License does not grant permission to use the trade\r
+ names, trademarks, service marks, or product names of the Licensor,\r
+ except as required for reasonable and customary use in describing the\r
+ origin of the Work and reproducing the content of the NOTICE file.\r
+\r
+ 7. Disclaimer of Warranty. Unless required by applicable law or\r
+ agreed to in writing, Licensor provides the Work (and each\r
+ Contributor provides its Contributions) on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+ implied, including, without limitation, any warranties or conditions\r
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
+ PARTICULAR PURPOSE. You are solely responsible for determining the\r
+ appropriateness of using or redistributing the Work and assume any\r
+ risks associated with Your exercise of permissions under this License.\r
+\r
+ 8. Limitation of Liability. In no event and under no legal theory,\r
+ whether in tort (including negligence), contract, or otherwise,\r
+ unless required by applicable law (such as deliberate and grossly\r
+ negligent acts) or agreed to in writing, shall any Contributor be\r
+ liable to You for damages, including any direct, indirect, special,\r
+ incidental, or consequential damages of any character arising as a\r
+ result of this License or out of the use or inability to use the\r
+ Work (including but not limited to damages for loss of goodwill,\r
+ work stoppage, computer failure or malfunction, or any and all\r
+ other commercial damages or losses), even if such Contributor\r
+ has been advised of the possibility of such damages.\r
+\r
+ 9. Accepting Warranty or Additional Liability. While redistributing\r
+ the Work or Derivative Works thereof, You may choose to offer,\r
+ and charge a fee for, acceptance of support, warranty, indemnity,\r
+ or other liability obligations and/or rights consistent with this\r
+ License. However, in accepting such obligations, You may act only\r
+ on Your own behalf and on Your sole responsibility, not on behalf\r
+ of any other Contributor, and only if You agree to indemnify,\r
+ defend, and hold each Contributor harmless for any liability\r
+ incurred by, or claims asserted against, such Contributor by reason\r
+ of your accepting any such warranty or additional liability.\r
+\r
+ END OF TERMS AND CONDITIONS\r
+\r
+ APPENDIX: How to apply the Apache License to your work.\r
+\r
+ To apply the Apache License to your work, attach the following\r
+ boilerplate notice, with the fields enclosed by brackets "[]"\r
+ replaced with your own identifying information. (Don't include\r
+ the brackets!) The text should be enclosed in the appropriate\r
+ comment syntax for the file format. We also recommend that a\r
+ file or class name and description of purpose be included on the\r
+ same "printed page" as the copyright notice for easier\r
+ identification within third-party archives.\r
+\r
+ Copyright [yyyy] [name of copyright owner]\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
--- /dev/null
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>
+This is a custom SVG webfont generated by Font Squirrel.
+Copyright : Copyright c 2011 by Tyler Finck All rights reserved
+Designer : Tyler Finck
+Foundry : Tyler Finck
+Foundry URL : httpwwwsurslycom
+</metadata>
+<defs>
+<font id="OstrichSansRoundedMedium" horiz-adv-x="1705" >
+<font-face units-per-em="2048" ascent="1536" descent="-512" />
+<missing-glyph horiz-adv-x="430" />
+<glyph unicode=" " horiz-adv-x="430" />
+<glyph unicode="	" horiz-adv-x="430" />
+<glyph unicode=" " horiz-adv-x="430" />
+<glyph unicode="!" horiz-adv-x="190" d="M20 33v24q0 12 9.5 21.5t24 9.5t23.5 -9t9 -22v-24q0 -33 -33 -33t-33 33zM20 233v1117q0 12 9.5 21t24 9t23.5 -9t9 -21v-1117q0 -33 -33 -33t-33 33z" />
+<glyph unicode=""" horiz-adv-x="331" d="M23 1233v117q0 14 9 23t21 9q33 0 33 -32v-117q0 -12 -9 -21.5t-24 -9.5q-12 0 -21 9.5t-9 21.5zM143 1233v117q0 33 33 32.5t33 -32.5v-117q0 -12 -9.5 -21.5t-23.5 -9.5t-23.5 9.5t-9.5 21.5z" />
+<glyph unicode="#" horiz-adv-x="1110" d="M-41 496q0 14 9 23t22 9h268l64 324h-267q-14 0 -23 9t-9 22q0 33 32 32h279l86 441q4 12 14 20q7 5 15 6q4 0 8 -2q14 -4 22 -14t4 -23l-84 -428h289l86 441q4 12 14 20q7 5 16 6q4 0 9 -2q12 -4 20.5 -14t4.5 -23l-84 -428h215q33 0 32 -32q0 -12 -9 -21.5t-23 -9.5 h-228l-63 -324h227q12 0 21.5 -9t9.5 -23q0 -12 -9 -22.5t-22 -10.5h-239l-86 -436q-4 -27 -31 -27h-6q-31 6 -27 39l84 424h-289l-86 -436q-6 -27 -32 -27h-7q-12 4 -20 14.5t-4 24.5l84 424h-256q-12 0 -21.5 10.5t-9.5 22.5zM324 528h288l64 324h-289z" />
+<glyph unicode="$" horiz-adv-x="655" d="M27 965q0 133 63 219q59 84 160 94v72q0 12 9 21t23.5 9t23.5 -9t9 -21v-70q41 -4 81 -20.5t72 -52.5t51.5 -95t19.5 -147q0 -33 -33 -33t-33 33q0 74 -14.5 121t-37 74.5t-50 38.5t-56.5 15v-514q4 -2 7.5 -3t7.5 -3q27 -12 63.5 -32.5t68.5 -53.5t54.5 -82t22.5 -120 q0 -133 -64 -216q-59 -78 -160 -90v-67q0 -33 -32.5 -33t-32.5 33v67q-41 4 -81 20.5t-71.5 51.5t-51 93.5t-19.5 148.5q0 33 32.5 32.5t32.5 -32.5q0 -74 14.5 -121t37 -75t50 -40t56.5 -14v498q-4 2 -7 4t-7 4l-63 35q-36 20 -68.5 54t-55 84t-22.5 122zM92 965 q0 -53 14.5 -91t38 -64t51 -44t54.5 -31v479q-43 -6 -73 -30.5t-49 -59t-27.5 -75.5t-8.5 -84zM315 166q76 10 117 72.5t41 167.5q0 53 -15.5 89.5t-38 62.5t-51 42l-53.5 29v-463z" />
+<glyph unicode="%" horiz-adv-x="919" d="M0 922v176q0 84 47 136t121 52t121 -52t47 -136v-176q0 -84 -47 -136.5t-121 -52.5t-121 52.5t-47 136.5zM63 922q0 -43 24 -83t81 -40t79.5 40t22.5 83v176q0 43 -22.5 83t-79.5 40t-81 -40t-24 -83v-176zM95 20q-2 6 -2 12q0 7 3 13l590 1317q10 19 28 19q7 0 15 -3 q27 -14 16 -43l-589 -1317q-10 -18 -31 -18q-8 0 -12 2q-13 6 -18 18zM502 281v176q0 84 46 135t122 51q74 0 120 -51t46 -135v-176q0 -84 -46.5 -136.5t-119.5 -52.5q-76 0 -122 52.5t-46 136.5zM565 281q0 -43 22.5 -84t82.5 -41q57 0 79.5 41t22.5 84v176q0 20 -5 41.5 t-17.5 40t-32 30t-48 11.5t-49 -11.5t-33 -30t-17.5 -40t-5 -41.5v-176z" />
+<glyph unicode="&" horiz-adv-x="878" d="M-2 340q0 68 16.5 119t44 92t63.5 74l73 63l35 32l36 32q-14 20 -36.5 59t-43 86t-36 99.5t-15.5 103.5q0 137 35 200q43 80 137 80q106 0 148 -94q18 -41 22 -92t4 -94q0 -74 -14 -133.5t-35.5 -104.5t-44 -74.5t-39.5 -46.5l270 -460q27 78 34 160.5t7 148.5 q0 14 9.5 23.5t21.5 9.5q33 0 33 -33q0 -78 -10.5 -180.5t-53.5 -194.5q0 -2 -2 -4l97 -162q4 -8 4 -17q0 -4 -1 -8q-3 -13 -16 -20q-8 -4 -16 -4q-16 0 -27 16l-77 131q-104 -147 -314 -147q-139 0 -227 100q-82 95 -82 240zM63 340q0 -51 14.5 -101.5t44.5 -89t76 -62.5 t109 -24q193 0 277 146l-283 485l-32 -27l-31 -28l-69 -59q-32 -29 -55.5 -63t-37 -77t-13.5 -100zM199 1100q0 -41 12 -85t30.5 -85t38 -76t33.5 -57q8 10 18.5 24.5t20.5 30.5q66 109 66 248q0 68 -8.5 109.5t-22.5 66t-34.5 33t-45.5 8.5q-20 0 -39.5 -7t-35 -30 t-24.5 -65.5t-9 -114.5z" />
+<glyph unicode="'" horiz-adv-x="165" d="M23 1233v117q0 14 9 23t21 9q33 0 33 -32v-117q0 -12 -9 -21.5t-24 -9.5q-12 0 -21 9.5t-9 21.5z" />
+<glyph unicode="(" horiz-adv-x="339" d="M18 690q0 209 30 341t66 209t66 107l33 31q6 4 14 6q3 1 7 1t8 -1q8 -2 14 -12q6 -12 6 -21q0 -6 -2 -12q-4 -8 -10 -14q-12 -10 -27 -27q-12 -14 -26.5 -36.5t-30.5 -57.5q-29 -66 -56.5 -188.5t-27.5 -325.5t27.5 -324.5t56.5 -185.5q31 -66 55 -94q12 -16 27 -25 q8 -4 12 -12q4 -7 4 -14q0 -9 -6 -19t-14 -13q-5 -2 -9 -2q-3 0 -6 1q-8 2 -14 6q-4 2 -36 31t-66 104q-95 195 -95 547z" />
+<glyph unicode=")" horiz-adv-x="323" d="M23 49q4 8 12 12q10 8 24 25l26 37q15 23 32 57q14 31 28.5 77t26.5 108.5t20.5 142.5t8.5 182q0 203 -28 326t-56 188q-31 68 -56.5 94.5t-27.5 26.5h2q-6 6 -10 14q-4 6 -5.5 14.5t7.5 18.5q6 10 14 12q4 1 7.5 1t6.5 -1q8 -2 15 -6q2 -2 33.5 -31.5t66.5 -106.5 t64.5 -209t29.5 -341q0 -350 -92 -547q-37 -76 -68.5 -104.5t-35.5 -30.5q-8 -4 -17 -6q-3 -1 -6 -1q-12 0 -20 15q-7 9 -8 17q1 8 6 16z" />
+<glyph unicode="*" horiz-adv-x="604" d="M25 1212q4 12 16 18.5t25 0.5l167 -62v179q0 33 33 32.5t33 -32.5v-179l168 62q12 6 24.5 0t16.5 -19q2 -5 2 -11q0 -7 -3 -13q-5 -12 -18 -17l-167 -63l127 -143q10 -10 8 -22.5t-13 -22.5q-8 -8 -20 -9q-14 0 -25 11l-133 151l-133 -151q-10 -10 -24.5 -10.5t-22.5 8.5 q-10 10 -11 22t9 23l127 143l-168 63q-12 4 -17 17q-3 7 -3 13t2 11z" />
+<glyph unicode="+" horiz-adv-x="786" d="M12 686q0 33 33 33h266v266q0 33 33 33t33 -33v-266h266q33 0 33 -33t-33 -33h-266v-266q0 -33 -33 -33t-33 33v266h-266q-33 0 -33 33z" />
+<glyph unicode="," horiz-adv-x="174" d="M23 -47v104q0 33 32.5 33t32.5 -33v-104q0 -33 -32.5 -33t-32.5 33z" />
+<glyph unicode="-" horiz-adv-x="612" d="M14 692q0 33 33 33h436q12 0 21.5 -9t9.5 -23.5t-9 -24t-22 -9.5h-436q-33 0 -33 33z" />
+<glyph unicode="." horiz-adv-x="165" d="M29 33v24q0 12 9 21.5t23.5 9.5t23.5 -9t9 -22v-24q0 -33 -32.5 -33t-32.5 33z" />
+<glyph unicode="/" horiz-adv-x="786" d="M61 43l484 1317q8 21 27 21q7 0 16 -3q12 -4 17 -16q3 -7 3 -14q0 -5 -2 -11l-483 -1317q-10 -20 -31 -20q-8 0 -12 2q-12 4 -18 16q-3 7 -2 14q-1 6 1 11z" />
+<glyph unicode="0" horiz-adv-x="729" d="M20 367v649q0 176 72 270q76 94 221 94q147 0 222 -94q74 -92 73 -270v-649q0 -115 -26.5 -185.5t-69.5 -111.5t-95 -55.5t-104 -14.5q-49 0 -101 14.5t-95 55.5t-70 111.5t-27 185.5zM84 367q0 -156 59 -232q55 -72 170 -72q113 0 172 72q57 72 58 232v649 q0 158 -57.5 229.5t-172.5 71.5q-117 0 -170 -72q-59 -76 -59 -229v-649z" />
+<glyph unicode="1" horiz-adv-x="397" d="M10 1115q0 11 8 20l195 235q9 12 22 12q7 0 15 -4q20 -6 20 -28v-1317q0 -33 -32.5 -33t-32.5 33v1227l-137 -168q-10 -10 -22.5 -11.5t-22.5 6.5q-13 13 -13 28z" />
+<glyph unicode="2" horiz-adv-x="655" d="M37 33q0 182 47 309q29 78 75 144.5t111 125.5q213 190 213 439q0 125 -51 194q-49 72 -139 72q-96 0 -141 -64q-51 -70 -52 -211q0 -14 -9 -23t-21 -9q-33 0 -33 32q0 164 61 250q68 88 195 88q125 0 192 -98q63 -88 64 -231q0 -276 -236 -488q-106 -96 -156.5 -215 t-54.5 -285h191h223q12 0 22.5 -9t10.5 -21q0 -14 -10.5 -23.5t-22.5 -9.5h-223h-223q-33 0 -33 33z" />
+<glyph unicode="3" horiz-adv-x="620" d="M18 365q0 33 33 32q12 0 21.5 -9t9.5 -23q0 -154 51 -230q49 -72 141 -72q88 0 139.5 80t51.5 213q0 92 -29.5 147.5t-58.5 84.5q-41 39 -84 54t-72 15h-2h-59q-12 0 -21.5 9.5t-9.5 21.5q0 14 9 23.5t22 9.5h61q37 0 80 18.5t79 55t60.5 93t24.5 134.5q0 131 -51 215 q-49 80 -140 80q-193 0 -192 -303q0 -14 -9.5 -23.5t-21.5 -9.5q-33 0 -33 33q0 174 62 266q63 100 194 100q123 0 195 -110q61 -96 61 -248q0 -106 -35.5 -174t-72.5 -103q-41 -37 -78 -57q43 -23 78 -55q37 -35 72.5 -101.5t35.5 -175.5q0 -164 -69.5 -260t-186.5 -96 q-131 0 -194 98q-62 93 -62 267z" />
+<glyph unicode="4" horiz-adv-x="663" d="M12 436q-5 8 -5 16.5t5 16.5l494 895q10 18 27 18q5 0 10 -2q25 -6 24 -30v-1317q0 -14 -10 -23.5t-22 -9.5q-33 0 -33 33v389h-461q-19 0 -29 14zM94 485h408v738z" />
+<glyph unicode="5" horiz-adv-x="634" d="M23 504v846q0 12 9 21t23 9h447q12 0 22.5 -9t10.5 -21q0 -14 -10.5 -23.5t-22.5 -9.5h-416v-561q74 104 193 104q127 0 192 -94q63 -88 64 -260v-146q0 -72 -16.5 -136t-45.5 -111q-72 -113 -194 -113q-127 0 -195 96q-61 92 -61 264q0 33 32 33q12 0 21.5 -9t9.5 -24 q0 -152 51 -227q49 -70 142 -70q86 0 139 84q51 84 51 213v146q0 154 -51 223q-45 66 -139 66q-88 0 -142 -78q-51 -80 -51 -211v-2q0 -14 -9 -23.5t-22 -9.5q-32 0 -32 33z" />
+<glyph unicode="6" horiz-adv-x="638" d="M16 324v194v2v408q0 147 27 237t65.5 137.5t84 62.5t79.5 15q127 0 193 -90q63 -82 63 -225q0 -12 -9 -21.5t-23 -9.5q-12 0 -22.5 9.5t-10.5 21.5q0 121 -49 186.5t-142 65.5q-61 0 -99 -40t-58.5 -99.5t-26.5 -127t-6 -122.5v-154q70 104 190 105q131 0 195 -95 q61 -92 61 -266v-149q0 -74 -16 -139.5t-45 -114.5q-68 -115 -195 -115q-121 0 -188.5 85t-67.5 239zM82 324q0 -37 6 -82t26.5 -85t58.5 -67t99 -27q90 0 140 87q27 41 39 97t12 122v149q0 156 -49 230q-47 68 -142 67q-90 0 -139 -82q-51 -80 -51 -213v-196z" />
+<glyph unicode="7" horiz-adv-x="770" d="M8 1350q0 12 9.5 21t21.5 9h629q18 0 26 -14q6 -9 7 -19q0 -6 -3 -12l-548 -1315q-10 -20 -31 -20q-8 0 -13 2q-12 6 -17 18.5t1 24.5l531 1272h-582q-12 0 -21.5 9.5t-9.5 23.5z" />
+<glyph unicode="8" horiz-adv-x="679" d="M20 360.5q0 178.5 66 268.5q29 41 70 61q-41 23 -70 62q-66 90 -66 268t66 268q68 92 213 92q143 0 211 -92q66 -86 65.5 -268t-65.5 -268q-29 -37 -68 -62q39 -23 68 -61q66 -86 65.5 -268.5t-65.5 -268.5q-68 -92 -211 -92q-145 0 -213 92q-66 90 -66 268.5zM86 360.5 q0 -159.5 51 -229.5q51 -68 162 -68t160 68q51 70 51 229.5t-51 231.5q-49 68 -160 67.5t-162 -67.5q-51 -72 -51 -231.5zM86 1020q0 -160 51 -229q51 -68 162 -68t160 68q51 70 51 229.5t-51 228.5q-49 68 -160 68t-162 -68q-51 -69 -51 -229z" />
+<glyph unicode="9" horiz-adv-x="630" d="M12 334q0 33 33 33t33 -33q0 -133 49 -203q49 -68 141 -68q59 0 96 36t58.5 92.5t29 125t7.5 134.5v155q-33 -51 -81 -78.5t-110 -27.5q-127 0 -192 96q-63 90 -64 268v152q0 166 70 265t186 99q127 0 193 -88q63 -82 63 -231v-197v-2v-411q0 -211 -59 -326 q-66 -125 -197 -125q-127 0 -192 94q-64 88 -64 240zM78 864q0 -160 51 -231q45 -68 139 -68q90 0 140 82q25 39 38 94.5t13 120.5v199q0 127 -49 192q-47 63 -142 64q-88 0 -139 -82q-51 -84 -51 -219v-152z" />
+<glyph unicode=":" horiz-adv-x="231" d="M27 367v90q0 33 32 32q12 0 21.5 -9t9.5 -23v-90q0 -14 -9 -23.5t-22 -9.5q-32 0 -32 33zM27 930v92q0 12 9 21.5t23 9.5q12 0 21.5 -9.5t9.5 -21.5v-92q0 -14 -9 -23.5t-22 -9.5q-32 0 -32 33z" />
+<glyph unicode=";" horiz-adv-x="198" d="M25 293v164q0 33 32.5 32.5t32.5 -32.5v-164q0 -33 -32.5 -33t-32.5 33zM25 930v92q0 12 9 21.5t23.5 9.5t23.5 -9.5t9 -21.5v-92q0 -33 -32.5 -33t-32.5 33z" />
+<glyph unicode="<" />
+<glyph unicode="=" horiz-adv-x="638" d="M14 487.5q0 32.5 33 32.5h436q12 0 21.5 -9t9.5 -23.5t-9 -23.5t-22 -9h-436q-33 0 -33 32.5zM14 897q0 33 33 33h436q12 0 21.5 -9.5t9.5 -23.5t-9 -23.5t-22 -9.5h-436q-33 0 -33 33z" />
+<glyph unicode=">" />
+<glyph unicode="?" horiz-adv-x="620" d="M27 1028q0 166 63 258q63 96 193 96q125 0 194 -104q31 -47 46.5 -107.5t15.5 -132.5q0 -74 -17.5 -128t-42 -94t-52.5 -66.5t-50 -44.5l-18 -15q-7 -6 -13 -12q-41 -47 -63.5 -159.5t-22.5 -274.5v-6q0 -14 -9 -23.5t-22 -9.5q-33 0 -32 33v6q0 61 3 130.5t14 134 t31.5 121t53.5 91.5q12 16 37 33l45 41q25 23 45 56.5t33.5 78.5t13.5 108q0 61 -12 113.5t-37 89.5q-53 78 -141 78q-94 0 -140 -70q-51 -70 -51 -221q0 -12 -9 -21.5t-23.5 -9.5t-23.5 9.5t-9 21.5zM195 35v24q0 12 9 21.5t23.5 9.5t23.5 -9t9 -22v-24q0 -33 -32.5 -33 t-32.5 33z" />
+<glyph unicode="@" horiz-adv-x="1325" d="M31 719q37 233 190 389q68 70 152 115t180 65q66 14 131 14q22 0 44 -2q87 -6 164 -34.5t141.5 -78.5t109.5 -120q33 -51 51 -115.5t24 -133.5q2 -25 1 -49q0 -44 -6 -89q-9 -70 -33 -131q-23 -55 -69 -99t-102.5 -74t-113.5 -40q-26 -5 -50 -5q-28 0 -52 7 q-45 10 -67 43q-17 25 -17 60q0 10 2 20q-33 -23 -71 -28t-85 -5q-113 0 -164 57q-42 50 -42 142q0 25 3 53q16 127 76 190q63 70 178 70q29 0 76 -6t82 -31q6 -4 16 -14q2 8 2 16q4 12 14.5 20.5t22.5 4.5q14 -2 22.5 -12.5t4.5 -24.5l-4 -29q-4 -29 -12 -71l-16 -96 l-17 -100l-15 -86q-6 -38 -8 -54q-1 -6 -1 -12q0 -35 36 -46q8 -2 15 -3t18 -1q33 0 74.5 12.5t81.5 36t73 56t49 73.5q20 53 30 115q6 39 6 80q0 22 -2 44q-5 62 -21.5 119.5t-45.5 100.5q-39 61 -95 105.5t-124.5 69t-145.5 29.5q-18 1 -37 1q-59 0 -120 -12 q-74 -16 -148.5 -53t-140 -100.5t-114.5 -154t-68 -208.5q-10 -61 -9 -117q0 -112 38 -207q57 -141 192 -225q86 -53 192 -76q83 -18 167 -18q23 0 46 2q108 6 211 38.5t187 94.5q10 8 23.5 6t21.5 -12q16 -27 -6 -48q-90 -63 -200.5 -101t-233.5 -44h-45q-111 0 -211 25.5 t-184 76.5q-154 96 -220 253q-44 104 -43 231q0 63 11 131zM418 672q-4 -29 -4 -53q0 -61 26 -91q29 -35 115 -34q51 0 80 5t47 23q23 23 40 74t32 139q5 29 5 49t-5 32q-10 24 -27 34q-16 12 -48 18t-73 6q-86 0 -131 -47q-45 -51 -57 -155z" />
+<glyph unicode="A" horiz-adv-x="802" d="M27 39l305 1317q6 25 30 24q27 0 33 -24l305 -1317l2 -8q0 -8 -6 -16q-8 -11 -20 -15h-8q-25 0 -31 25l-92 397h-363l-92 -397q-4 -12 -15 -21q-8 -5 -16 -5q-4 0 -8 1q-14 4 -21 15q-5 7 -5 15q1 5 2 9zM197 485h333l-168 721z" />
+<glyph unicode="B" horiz-adv-x="688" d="M29 33v1317q0 12 9 21t23 9h195q158 0 233 -90q72 -90 72 -270q0 -178 -72 -268q-16 -20 -34.5 -35t-40.5 -27q45 -23 75 -59q72 -90 72 -270.5t-72 -270.5q-76 -90 -233 -90h-195q-32 0 -32 33zM94 63h162q129 0 184.5 69t55.5 228.5t-58 229.5q-55 70 -182 69h-162 v-596zM94 723h162q127 0 182 70q57 70 58 227q0 160 -55.5 228.5t-184.5 68.5h-162v-594z" />
+<glyph unicode="C" horiz-adv-x="704" d="M20 367v649q0 113 27 184.5t70 111.5t95 54t101 14q51 0 103.5 -14t95.5 -54t69.5 -112t26.5 -184q0 -33 -32.5 -33t-32.5 33q0 154 -60 229q-53 72 -170 72q-113 0 -170 -72q-59 -76 -59 -229v-649q0 -154 59 -232q59 -72 170 -72q115 0 170 72q59 78 60 232 q0 33 32.5 32.5t32.5 -32.5q0 -115 -26.5 -185.5t-69.5 -111.5t-95 -55.5t-104 -14.5q-49 0 -101 14.5t-95 55.5t-70 111.5t-27 185.5z" />
+<glyph unicode="D" horiz-adv-x="712" d="M25 33v1317q0 12 9 21t23 9h203q164 0 244 -98q76 -90 76 -274v-635q0 -184 -76 -275q-80 -98 -244 -98h-203q-32 0 -32 33zM88 63h172q133 0 193.5 75t60.5 235v635q0 160 -60.5 234.5t-193.5 74.5h-172v-1254z" />
+<glyph unicode="E" horiz-adv-x="638" d="M23 33v1317q0 12 9 21t23 9h430q14 0 23.5 -9t9.5 -21q0 -33 -33 -33h-399v-594h399q33 0 33 -33q0 -12 -9 -21.5t-24 -9.5h-399v-596h399q14 0 23.5 -9t9.5 -21q0 -33 -33 -33h-430q-32 0 -32 33z" />
+<glyph unicode="F" horiz-adv-x="630" d="M31 33v1317q0 12 9 21t23 9h431q14 0 23 -9t9 -21q0 -33 -32 -33h-400v-594h400q33 0 32 -33q0 -12 -9 -21.5t-23 -9.5h-400v-626q0 -14 -9 -23.5t-22 -9.5q-32 0 -32 33z" />
+<glyph unicode="G" horiz-adv-x="720" d="M14 365v653q0 178 74 270t221.5 92t221 -92t73.5 -270q0 -33 -32.5 -33t-32.5 33q0 100 -22.5 159.5t-56.5 90t-74 40t-77 9.5t-78 -9.5t-74.5 -40t-56 -90t-22.5 -159.5v-653q0 -154 59 -230q59 -72 172 -72t172 72q57 72 58 230v180h-267q-33 0 -32.5 32.5t32.5 32.5 h299q33 0 33 -32v-213q0 -178 -74 -271q-76 -94 -221 -94t-221 94q-74 93 -74 271z" />
+<glyph unicode="H" horiz-adv-x="704" d="M25 33v1317q0 12 9 21t23.5 9t23.5 -9t9 -21v-627h418v627q0 12 9 21t23.5 9t23.5 -9t9 -21v-1317q0 -33 -32.5 -33t-32.5 33v624h-418v-624q0 -33 -32.5 -33t-32.5 33z" />
+<glyph unicode="I" horiz-adv-x="215" d="M37 33v1317q0 12 9 21t23.5 9t23.5 -9t9 -21v-1317q0 -33 -32.5 -33t-32.5 33z" />
+<glyph unicode="J" horiz-adv-x="663" d="M0 338q0 12 9 22.5t24 10.5q12 0 21 -10.5t9 -22.5q0 -92 20.5 -146.5t51.5 -83t68 -37t71 -8.5q102 0 156 64q53 70 53 211v1012q0 12 9.5 21t23.5 9q12 0 21.5 -9t9.5 -21v-1012q0 -168 -68 -250q-68 -88 -205 -88t-206 88q-68 82 -68 250z" />
+<glyph unicode="K" horiz-adv-x="737" d="M16 33v1317q0 12 9.5 21t23.5 9q12 0 21.5 -9t9.5 -21v-754l516 770q8 12 21 14q3 1 7 1q9 0 17 -5q14 -11 14 -28q0 -9 -6 -17l-389 -586l391 -698q4 -6 4 -13q0 -5 -2 -10q-4 -13 -14 -20q-12 -4 -16 -4q-18 0 -29 16l-375 670l-139 -209v-444q0 -14 -9.5 -23.5 t-21.5 -9.5q-33 0 -33 33z" />
+<glyph unicode="L" horiz-adv-x="604" d="M10 33v1317q0 12 9.5 21t23.5 9q12 0 21.5 -9t9.5 -21v-1287h432q14 0 23.5 -9t9.5 -21q0 -33 -33 -33h-463q-33 0 -33 33z" />
+<glyph unicode="M" horiz-adv-x="968" d="M14 33v1317q0 27 29 30q4 1 7 1q21 0 28 -23l346 -1208l348 1208q7 23 28 23q3 0 7 -1q29 -4 29 -30v-1317q0 -14 -10.5 -23.5t-22.5 -9.5q-33 0 -33 33v1085l-313 -1095q-8 -23 -33 -23q-23 0 -31 23l-313 1095v-1085q0 -33 -33 -33t-33 33z" />
+<glyph unicode="N" horiz-adv-x="737" d="M20 33v1317q0 27 27 30q4 1 7 1q21 0 30 -21l467 -1161v1151q0 12 9 21t23.5 9t23.5 -9t9 -21v-1317q0 -27 -26 -33h-6q-23 0 -29 20l-469 1162v-1149q0 -33 -33 -33t-33 33z" />
+<glyph unicode="O" horiz-adv-x="712" d="M20 367v649q0 176 72 270q76 94 221 94q147 0 222 -94q74 -92 73 -270v-649q0 -115 -26.5 -185.5t-69.5 -111.5t-95 -55.5t-104 -14.5q-49 0 -101 14.5t-95 55.5t-70 111.5t-27 185.5zM84 367q0 -156 59 -232q55 -72 170 -72q113 0 172 72q57 72 58 232v649 q0 158 -57.5 229.5t-172.5 71.5q-117 0 -170 -72q-59 -76 -59 -229v-649z" />
+<glyph unicode="P" horiz-adv-x="696" d="M20 33v1317q0 12 9.5 21t23.5 9h217q166 0 244 -90q76 -88 76 -270t-76 -270q-78 -90 -244 -91h-184v-626q0 -33 -33 -33t-33 33zM86 723h184q133 0 195 70q59 68 59 227.5t-59 228t-195 68.5h-184v-594z" />
+<glyph unicode="Q" horiz-adv-x="712" d="M14 373v649q0 176 74 266q74 92 219 92q147 0 221 -92q72 -86 72 -266v-649q0 -180 -72 -273q0 -2 -1 -2t-1 -2l78 -94q7 -8 7 -18q0 -17 -13 -27q-6 -8 -18 -8q-18 0 -27 12l-74 90q-66 -51 -172 -51q-145 0 -221 100q-72 97 -72 273zM78 373q0 -156 59 -234 q57 -76 170 -76q78 0 131 37l-69 88q-10 10 -8.5 22.5t12.5 22.5q25 16 45 -4l65 -82q53 78 54 226v649q0 152 -60 227q-55 68 -169.5 68t-170.5 -68q-59 -76 -59 -227v-649z" />
+<glyph unicode="R" horiz-adv-x="712" d="M27 35v1317q0 12 9 21t21 9h217q164 0 242 -88t78 -276q0 -186 -76 -277q-33 -39 -84 -61q20 -10 37.5 -22.5t34.5 -28.5q90 -86 90 -244v-350q0 -33 -33 -33q-12 0 -21.5 9t-9.5 24v350q0 127 -67.5 195.5t-190.5 68.5h-184v-614q0 -33 -33 -33q-12 0 -21 9.5t-9 23.5z M90 713h184q133 0 195 71q59 68 59 234q0 160 -59 230.5t-195 70.5h-184v-606z" />
+<glyph unicode="S" horiz-adv-x="720" d="M29 1016q0 156 71 256q80 111 224 110q147 0 223 -94q74 -92 74 -272q0 -12 -9.5 -22.5t-24 -10.5t-23.5 10.5t-9 22.5q0 156 -59 231q-55 72 -172 72q-109 0 -170 -86q-61 -84 -62 -217q0 -74 24.5 -125t60.5 -85t75 -54.5t70 -32.5l32 -14l72 -35q45 -23 88 -63 t75 -100.5t32 -150.5q0 -76 -19.5 -139t-54.5 -111q-80 -104 -223 -104q-147 0 -222 94q-74 92 -73 271q0 33 32 32q12 0 21.5 -9t9.5 -23q0 -100 22.5 -160t56.5 -91.5t75 -40.5t78 -9q111 0 171 76.5t60 213.5q0 74 -25.5 124t-61.5 82t-75 50l-63 31l-35 16 q-31 12 -76 36t-87 66t-72.5 103.5t-30.5 151.5z" />
+<glyph unicode="T" horiz-adv-x="778" d="M-29 1352q0 12 9.5 21t21.5 9h662q14 0 23 -9t9 -21q0 -33 -32 -33h-297v-1284q0 -14 -10.5 -23.5t-22.5 -9.5q-33 0 -33 33v1284h-299q-12 0 -21.5 9.5t-9.5 23.5z" />
+<glyph unicode="U" horiz-adv-x="712" d="M18 340v1012q0 12 9.5 21t23.5 9q12 0 21.5 -9t9.5 -21v-1012q0 -92 20.5 -146.5t51 -83t67.5 -36.5t72 -8q33 0 69.5 8t67.5 36.5t51.5 83t20.5 146.5v1012q0 12 9 21t21 9q14 0 23.5 -9t9.5 -21v-1012q0 -104 -24.5 -170t-64.5 -103.5t-88 -51t-95 -13.5t-95 13.5 t-88 51t-66 103.5t-26 170z" />
+<glyph unicode="V" horiz-adv-x="821" d="M12 1343q-1 4 -1 9q0 8 4 15q7 11 22 15q4 1 9 2q8 0 14 -5q11 -7 16 -21l297 -1190l299 1190q4 14 15 21q7 5 15 5q4 0 9 -2q12 -4 19 -15q5 -7 5 -15q0 -4 -2 -9l-327 -1316q-6 -25 -33 -25q-25 0 -31 25z" />
+<glyph unicode="W" horiz-adv-x="1333" d="M10 1343q-1 4 -1 9q0 8 5 15q8 11 21 15q4 1 8 1q26 0 31 -25l258 -1174l260 1174q4 25 30.5 24.5t32.5 -24.5l258 -1174l258 1174q4 12 16 19q9 6 18 6q3 0 5 -1q14 -4 22 -15q5 -7 4 -15q0 -4 -1 -9l-291 -1316q-4 -25 -30.5 -25t-30.5 25l-260 1173l-258 -1173 q-6 -25 -33 -25q-25 0 -31 25z" />
+<glyph unicode="X" horiz-adv-x="802" d="M18 47l306 645l-306 643q-2 6 -2 12.5t2 13.5q4 13 17 17q10 5 17 5q16 0 26 -19l280 -596l281 596q6 12 19 16q5 2 11 2q7 0 13 -4q12 -4 17 -17q2 -6 3 -12q0 -7 -4 -14l-303 -643l303 -645q3 -7 4 -13q0 -6 -3 -11q-5 -12 -17 -19q-4 -2 -12 -2q-23 0 -31 18l-281 596 l-280 -596q-10 -18 -29 -18q-10 0 -14 2q-19 10 -19 28q-1 7 2 15z" />
+<glyph unicode="Y" horiz-adv-x="854" d="M7 1359q3 13 16 19q7 4 14 4l10 -2q12 -4 21 -14l331 -606l334 606q6 10 20 14q5 2 10 2q7 0 13 -4q12 -6 17 -19q1 -4 1 -9q0 -8 -6 -15l-356 -651v-651q0 -12 -9 -21.5t-23.5 -9.5t-23.5 9t-9 22v651l-357 651q-4 7 -4 15q0 5 1 9z" />
+<glyph unicode="Z" horiz-adv-x="837" d="M6 1349.5q0 32.5 33 32.5h616q18 0 27 -14q10 -18 2 -33l-596 -1269h567q33 0 33 -33q0 -12 -9 -21.5t-24 -9.5h-616q-20 0 -29 14q-5 9 -4 18q0 7 2 13l596 1270h-565q-33 0 -33 32.5z" />
+<glyph unicode="[" />
+<glyph unicode="\" horiz-adv-x="778" d="M66 1337q-2 5 -2 11q0 7 3 14q5 12 17 16q9 3 16 3q20 0 27 -21l483 -1317q2 -5 2 -11q0 -7 -3 -14q-5 -12 -17 -16q-4 -2 -12 -2q-20 0 -31 20z" />
+<glyph unicode="]" />
+<glyph unicode="^" />
+<glyph unicode="_" horiz-adv-x="944" d="M20 -33q0 12 9.5 21.5t23.5 9.5h762q14 0 23.5 -9t9.5 -22q0 -33 -33 -33h-762q-33 0 -33 33z" />
+<glyph unicode="`" horiz-adv-x="165" d="M23 1233v117q0 14 9 23t21 9q33 0 33 -32v-117q0 -12 -9 -21.5t-24 -9.5q-12 0 -21 9.5t-9 21.5z" />
+<glyph unicode="a" horiz-adv-x="802" d="M27 39l305 1317q6 25 30 24q27 0 33 -24l305 -1317l2 -8q0 -8 -6 -16q-8 -11 -20 -15h-8q-25 0 -31 25l-92 397h-363l-92 -397q-4 -12 -15 -21q-8 -5 -16 -5q-4 0 -8 1q-14 4 -21 15q-5 7 -5 15q1 5 2 9zM197 485h333l-168 721z" />
+<glyph unicode="b" horiz-adv-x="688" d="M29 33v1317q0 12 9 21t23 9h195q158 0 233 -90q72 -90 72 -270q0 -178 -72 -268q-16 -20 -34.5 -35t-40.5 -27q45 -23 75 -59q72 -90 72 -270.5t-72 -270.5q-76 -90 -233 -90h-195q-32 0 -32 33zM94 63h162q129 0 184.5 69t55.5 228.5t-58 229.5q-55 70 -182 69h-162 v-596zM94 723h162q127 0 182 70q57 70 58 227q0 160 -55.5 228.5t-184.5 68.5h-162v-594z" />
+<glyph unicode="c" horiz-adv-x="704" d="M20 367v649q0 113 27 184.5t70 111.5t95 54t101 14q51 0 103.5 -14t95.5 -54t69.5 -112t26.5 -184q0 -33 -32.5 -33t-32.5 33q0 154 -60 229q-53 72 -170 72q-113 0 -170 -72q-59 -76 -59 -229v-649q0 -154 59 -232q59 -72 170 -72q115 0 170 72q59 78 60 232 q0 33 32.5 32.5t32.5 -32.5q0 -115 -26.5 -185.5t-69.5 -111.5t-95 -55.5t-104 -14.5q-49 0 -101 14.5t-95 55.5t-70 111.5t-27 185.5z" />
+<glyph unicode="d" horiz-adv-x="712" d="M25 33v1317q0 12 9 21t23 9h203q164 0 244 -98q76 -90 76 -274v-635q0 -184 -76 -275q-80 -98 -244 -98h-203q-32 0 -32 33zM88 63h172q133 0 193.5 75t60.5 235v635q0 160 -60.5 234.5t-193.5 74.5h-172v-1254z" />
+<glyph unicode="e" horiz-adv-x="638" d="M23 33v1317q0 12 9 21t23 9h430q14 0 23.5 -9t9.5 -21q0 -33 -33 -33h-399v-594h399q33 0 33 -33q0 -12 -9 -21.5t-24 -9.5h-399v-596h399q14 0 23.5 -9t9.5 -21q0 -33 -33 -33h-430q-32 0 -32 33z" />
+<glyph unicode="f" horiz-adv-x="630" d="M31 33v1317q0 12 9 21t23 9h431q14 0 23 -9t9 -21q0 -33 -32 -33h-400v-594h400q33 0 32 -33q0 -12 -9 -21.5t-23 -9.5h-400v-626q0 -14 -9 -23.5t-22 -9.5q-32 0 -32 33z" />
+<glyph unicode="g" horiz-adv-x="720" d="M14 365v653q0 178 74 270t221.5 92t221 -92t73.5 -270q0 -33 -32.5 -33t-32.5 33q0 100 -22.5 159.5t-56.5 90t-74 40t-77 9.5t-78 -9.5t-74.5 -40t-56 -90t-22.5 -159.5v-653q0 -154 59 -230q59 -72 172 -72t172 72q57 72 58 230v180h-267q-33 0 -32.5 32.5t32.5 32.5 h299q33 0 33 -32v-213q0 -178 -74 -271q-76 -94 -221 -94t-221 94q-74 93 -74 271z" />
+<glyph unicode="h" horiz-adv-x="704" d="M25 33v1317q0 12 9 21t23.5 9t23.5 -9t9 -21v-627h418v627q0 12 9 21t23.5 9t23.5 -9t9 -21v-1317q0 -33 -32.5 -33t-32.5 33v624h-418v-624q0 -33 -32.5 -33t-32.5 33z" />
+<glyph unicode="i" horiz-adv-x="215" d="M37 33v1317q0 12 9 21t23.5 9t23.5 -9t9 -21v-1317q0 -33 -32.5 -33t-32.5 33z" />
+<glyph unicode="j" horiz-adv-x="663" d="M0 338q0 12 9 22.5t24 10.5q12 0 21 -10.5t9 -22.5q0 -92 20.5 -146.5t51.5 -83t68 -37t71 -8.5q102 0 156 64q53 70 53 211v1012q0 12 9.5 21t23.5 9q12 0 21.5 -9t9.5 -21v-1012q0 -168 -68 -250q-68 -88 -205 -88t-206 88q-68 82 -68 250z" />
+<glyph unicode="k" horiz-adv-x="737" d="M16 33v1317q0 12 9.5 21t23.5 9q12 0 21.5 -9t9.5 -21v-754l516 770q8 12 21 14q3 1 7 1q9 0 17 -5q14 -11 14 -28q0 -9 -6 -17l-389 -586l391 -698q4 -6 4 -13q0 -5 -2 -10q-4 -13 -14 -20q-12 -4 -16 -4q-18 0 -29 16l-375 670l-139 -209v-444q0 -14 -9.5 -23.5 t-21.5 -9.5q-33 0 -33 33z" />
+<glyph unicode="l" horiz-adv-x="604" d="M10 33v1317q0 12 9.5 21t23.5 9q12 0 21.5 -9t9.5 -21v-1287h432q14 0 23.5 -9t9.5 -21q0 -33 -33 -33h-463q-33 0 -33 33z" />
+<glyph unicode="m" horiz-adv-x="968" d="M14 33v1317q0 27 29 30q4 1 7 1q21 0 28 -23l346 -1208l348 1208q7 23 28 23q3 0 7 -1q29 -4 29 -30v-1317q0 -14 -10.5 -23.5t-22.5 -9.5q-33 0 -33 33v1085l-313 -1095q-8 -23 -33 -23q-23 0 -31 23l-313 1095v-1085q0 -33 -33 -33t-33 33z" />
+<glyph unicode="n" horiz-adv-x="737" d="M20 33v1317q0 27 27 30q4 1 7 1q21 0 30 -21l467 -1161v1151q0 12 9 21t23.5 9t23.5 -9t9 -21v-1317q0 -27 -26 -33h-6q-23 0 -29 20l-469 1162v-1149q0 -33 -33 -33t-33 33z" />
+<glyph unicode="o" horiz-adv-x="712" d="M20 367v649q0 176 72 270q76 94 221 94q147 0 222 -94q74 -92 73 -270v-649q0 -115 -26.5 -185.5t-69.5 -111.5t-95 -55.5t-104 -14.5q-49 0 -101 14.5t-95 55.5t-70 111.5t-27 185.5zM84 367q0 -156 59 -232q55 -72 170 -72q113 0 172 72q57 72 58 232v649 q0 158 -57.5 229.5t-172.5 71.5q-117 0 -170 -72q-59 -76 -59 -229v-649z" />
+<glyph unicode="p" horiz-adv-x="696" d="M20 33v1317q0 12 9.5 21t23.5 9h217q166 0 244 -90q76 -88 76 -270t-76 -270q-78 -90 -244 -91h-184v-626q0 -33 -33 -33t-33 33zM86 723h184q133 0 195 70q59 68 59 227.5t-59 228t-195 68.5h-184v-594z" />
+<glyph unicode="q" horiz-adv-x="712" d="M14 373v649q0 176 74 266q74 92 219 92q147 0 221 -92q72 -86 72 -266v-649q0 -180 -72 -273q0 -2 -1 -2t-1 -2l78 -94q7 -8 7 -18q0 -17 -13 -27q-6 -8 -18 -8q-18 0 -27 12l-74 90q-66 -51 -172 -51q-145 0 -221 100q-72 97 -72 273zM78 373q0 -156 59 -234 q57 -76 170 -76q78 0 131 37l-69 88q-10 10 -8.5 22.5t12.5 22.5q25 16 45 -4l65 -82q53 78 54 226v649q0 152 -60 227q-55 68 -169.5 68t-170.5 -68q-59 -76 -59 -227v-649z" />
+<glyph unicode="r" horiz-adv-x="712" d="M27 35v1317q0 12 9 21t21 9h217q164 0 242 -88t78 -276q0 -186 -76 -277q-33 -39 -84 -61q20 -10 37.5 -22.5t34.5 -28.5q90 -86 90 -244v-350q0 -33 -33 -33q-12 0 -21.5 9t-9.5 24v350q0 127 -67.5 195.5t-190.5 68.5h-184v-614q0 -33 -33 -33q-12 0 -21 9.5t-9 23.5z M90 713h184q133 0 195 71q59 68 59 234q0 160 -59 230.5t-195 70.5h-184v-606z" />
+<glyph unicode="s" horiz-adv-x="720" d="M29 1016q0 156 71 256q80 111 224 110q147 0 223 -94q74 -92 74 -272q0 -12 -9.5 -22.5t-24 -10.5t-23.5 10.5t-9 22.5q0 156 -59 231q-55 72 -172 72q-109 0 -170 -86q-61 -84 -62 -217q0 -74 24.5 -125t60.5 -85t75 -54.5t70 -32.5l32 -14l72 -35q45 -23 88 -63 t75 -100.5t32 -150.5q0 -76 -19.5 -139t-54.5 -111q-80 -104 -223 -104q-147 0 -222 94q-74 92 -73 271q0 33 32 32q12 0 21.5 -9t9.5 -23q0 -100 22.5 -160t56.5 -91.5t75 -40.5t78 -9q111 0 171 76.5t60 213.5q0 74 -25.5 124t-61.5 82t-75 50l-63 31l-35 16 q-31 12 -76 36t-87 66t-72.5 103.5t-30.5 151.5z" />
+<glyph unicode="t" horiz-adv-x="778" d="M-29 1352q0 12 9.5 21t21.5 9h662q14 0 23 -9t9 -21q0 -33 -32 -33h-297v-1284q0 -14 -10.5 -23.5t-22.5 -9.5q-33 0 -33 33v1284h-299q-12 0 -21.5 9.5t-9.5 23.5z" />
+<glyph unicode="u" horiz-adv-x="712" d="M18 340v1012q0 12 9.5 21t23.5 9q12 0 21.5 -9t9.5 -21v-1012q0 -92 20.5 -146.5t51 -83t67.5 -36.5t72 -8q33 0 69.5 8t67.5 36.5t51.5 83t20.5 146.5v1012q0 12 9 21t21 9q14 0 23.5 -9t9.5 -21v-1012q0 -104 -24.5 -170t-64.5 -103.5t-88 -51t-95 -13.5t-95 13.5 t-88 51t-66 103.5t-26 170z" />
+<glyph unicode="v" horiz-adv-x="821" d="M12 1343q-1 4 -1 9q0 8 4 15q7 11 22 15q4 1 9 2q8 0 14 -5q11 -7 16 -21l297 -1190l299 1190q4 14 15 21q7 5 15 5q4 0 9 -2q12 -4 19 -15q5 -7 5 -15q0 -4 -2 -9l-327 -1316q-6 -25 -33 -25q-25 0 -31 25z" />
+<glyph unicode="w" horiz-adv-x="1333" d="M10 1343q-1 4 -1 9q0 8 5 15q8 11 21 15q4 1 8 1q26 0 31 -25l258 -1174l260 1174q4 25 30.5 24.5t32.5 -24.5l258 -1174l258 1174q4 12 16 19q9 6 18 6q3 0 5 -1q14 -4 22 -15q5 -7 4 -15q0 -4 -1 -9l-291 -1316q-4 -25 -30.5 -25t-30.5 25l-260 1173l-258 -1173 q-6 -25 -33 -25q-25 0 -31 25z" />
+<glyph unicode="x" horiz-adv-x="802" d="M18 47l306 645l-306 643q-2 6 -2 12.5t2 13.5q4 13 17 17q10 5 17 5q16 0 26 -19l280 -596l281 596q6 12 19 16q5 2 11 2q7 0 13 -4q12 -4 17 -17q2 -6 3 -12q0 -7 -4 -14l-303 -643l303 -645q3 -7 4 -13q0 -6 -3 -11q-5 -12 -17 -19q-4 -2 -12 -2q-23 0 -31 18l-281 596 l-280 -596q-10 -18 -29 -18q-10 0 -14 2q-19 10 -19 28q-1 7 2 15z" />
+<glyph unicode="y" horiz-adv-x="854" d="M7 1359q3 13 16 19q7 4 14 4l10 -2q12 -4 21 -14l331 -606l334 606q6 10 20 14q5 2 10 2q7 0 13 -4q12 -6 17 -19q1 -4 1 -9q0 -8 -6 -15l-356 -651v-651q0 -12 -9 -21.5t-23.5 -9.5t-23.5 9t-9 22v651l-357 651q-4 7 -4 15q0 5 1 9z" />
+<glyph unicode="z" horiz-adv-x="837" d="M6 1349.5q0 32.5 33 32.5h616q18 0 27 -14q10 -18 2 -33l-596 -1269h567q33 0 33 -33q0 -12 -9 -21.5t-24 -9.5h-616q-20 0 -29 14q-5 9 -4 18q0 7 2 13l596 1270h-565q-33 0 -33 32.5z" />
+<glyph unicode="{" />
+<glyph unicode="|" horiz-adv-x="182" d="M16 33v1317q0 12 9.5 21t23.5 9t23.5 -9t9.5 -21v-1317q0 -33 -33 -33t-33 33z" />
+<glyph unicode="}" />
+<glyph unicode="~" />
+<glyph unicode="©" />
+<glyph unicode="­" horiz-adv-x="612" d="M14 692q0 33 33 33h436q12 0 21.5 -9t9.5 -23.5t-9 -24t-22 -9.5h-436q-33 0 -33 33z" />
+<glyph unicode="®" />
+<glyph unicode=" " horiz-adv-x="692" />
+<glyph unicode=" " horiz-adv-x="1384" />
+<glyph unicode=" " horiz-adv-x="692" />
+<glyph unicode=" " horiz-adv-x="1384" />
+<glyph unicode=" " horiz-adv-x="460" />
+<glyph unicode=" " horiz-adv-x="346" />
+<glyph unicode=" " horiz-adv-x="229" />
+<glyph unicode=" " horiz-adv-x="229" />
+<glyph unicode=" " horiz-adv-x="172" />
+<glyph unicode=" " horiz-adv-x="276" />
+<glyph unicode=" " horiz-adv-x="75" />
+<glyph unicode="‐" horiz-adv-x="612" d="M14 692q0 33 33 33h436q12 0 21.5 -9t9.5 -23.5t-9 -24t-22 -9.5h-436q-33 0 -33 33z" />
+<glyph unicode="‑" horiz-adv-x="612" d="M14 692q0 33 33 33h436q12 0 21.5 -9t9.5 -23.5t-9 -24t-22 -9.5h-436q-33 0 -33 33z" />
+<glyph unicode="‒" horiz-adv-x="612" d="M14 692q0 33 33 33h436q12 0 21.5 -9t9.5 -23.5t-9 -24t-22 -9.5h-436q-33 0 -33 33z" />
+<glyph unicode="–" horiz-adv-x="612" d="M27 657v64h499v-64h-499z" />
+<glyph unicode="—" horiz-adv-x="612" d="M27 657v64h499v-64h-499z" />
+<glyph unicode="‘" horiz-adv-x="165" d="M23 1233v117q0 14 9 23t21 9q33 0 33 -32v-117q0 -12 -9 -21.5t-24 -9.5q-12 0 -21 9.5t-9 21.5z" />
+<glyph unicode="’" horiz-adv-x="165" d="M23 1233v117q0 14 9 23t21 9q33 0 33 -32v-117q0 -12 -9 -21.5t-24 -9.5q-12 0 -21 9.5t-9 21.5z" />
+<glyph unicode="“" horiz-adv-x="331" d="M23 1233v117q0 14 9 23t21 9q33 0 33 -32v-117q0 -12 -9 -21.5t-24 -9.5q-12 0 -21 9.5t-9 21.5zM143 1233v117q0 33 33 32.5t33 -32.5v-117q0 -12 -9.5 -21.5t-23.5 -9.5t-23.5 9.5t-9.5 21.5z" />
+<glyph unicode="”" horiz-adv-x="331" d="M23 1233v117q0 14 9 23t21 9q33 0 33 -32v-117q0 -12 -9 -21.5t-24 -9.5q-12 0 -21 9.5t-9 21.5zM143 1233v117q0 33 33 32.5t33 -32.5v-117q0 -12 -9.5 -21.5t-23.5 -9.5t-23.5 9.5t-9.5 21.5z" />
+<glyph unicode="•" />
+<glyph unicode="…" horiz-adv-x="497" d="M29 33v24q0 12 9 21.5t23.5 9.5t23.5 -9t9 -22v-24q0 -33 -32.5 -33t-32.5 33zM195 33v24q0 12 9 21.5t23.5 9.5t23.5 -9t9 -22v-24q0 -33 -32.5 -33t-32.5 33zM360 33v24q0 12 9.5 21.5t24 9.5t23.5 -9t9 -22v-24q0 -33 -33 -33t-33 33z" />
+<glyph unicode=" " horiz-adv-x="276" />
+<glyph unicode=" " horiz-adv-x="346" />
+<glyph unicode="" horiz-adv-x="1385" d="M0 1385h1385v-1385h-1385v1385z" />
+</font>
+</defs></svg>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>\r
+<!--\r
+/**\r
+ * Cassette Tape UI Prototype (09/2012)\r
+ * ALPHA build / experimental state, unsupported; use at own risk\r
+ * Requires CSS3 border-radius + <canvas> support\r
+ * http://www.schillmania.com/projects/soundmanager2/\r
+ */\r
+-->\r
+<html>\r
+<head>\r
+<title>Cassette Tape Prototype: Canvas mask + blur effects version (MA-R90-style design)</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="An experimental web audio player UI based on the TDK MA-R90 cassette tape, a classic metal-alloy cassette model from 1982. Includes slight translucency and blurring effects." />\r
+<meta name="keywords" content="javascript sound, html5 audio, css3, cassette tape, tdk, mar, ma-r, mar90, html5 sound, javascript audio, schill, schillmania, soundmanager, soundmanager2" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="css/cassette-tape-ui.css" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="css/cassette-tape-ui-blur.css" />\r
+<noscript>\r
+ <!-- Legal? Probably not - but, works. -->\r
+ <link rel="stylesheet" type="text/css" media="screen" href="css/cassette-tape-ui-blur-nojs.css" />\r
+</noscript>\r
+<link rel="stylesheet" type="text/css" media="screen" href="css/demo.css" />\r
+<script src="../../script/soundmanager2.js"></script>\r
+<script src="script/cassette-tape-ui.js"></script>\r
+<script src="script/demo.js"></script>\r
+</head>\r
+\r
+<body>\r
+\r
+<div id="demo-header-wrapper">\r
+ <div id="demo-header">\r
+ <h1>Cassette Tape UI</h1>\r
+ <p>An exercise in skeuomorphic excess. <a id="nextBackground" href="#next" title="Change background">✭ </a> <a href="more.html" title="More cassette tape prototype designs">more ↬</a> <a href="../../" title="SoundManager 2 homepage">home ↬</a></p>\r
+ </div>\r
+</div>\r
+\r
+<div id="tape-loader">\r
+ <div class="spinner-box">\r
+ <div class="spinner"></div>\r
+ </div>\r
+</div>\r
+\r
+<!-- \r
+/**\r
+ * DIV-tastic! Indeed, tons of elements in this version - but this allows for easy customization.\r
+ * The basic version (no canvas + blur effects) uses more images for skinning and has a few less elements.\r
+ */\r
+-->\r
+\r
+<div class="draggable clear ma-r90 cutout tape">\r
+ <div class="blur-image-wrapper">\r
+ <canvas class="blur-image"></canvas>\r
+ </div>\r
+ <div class="transparency-sheet"></div>\r
+ <div class="tape-shell image-mask" data-image-repeat="true" data-mask-url="image/ma-r90-mask.png"></div>\r
+ <div class="tape-gradient image-mask" data-mask-url="image/ma-r90-mask.png"></div>\r
+ <div class="tab-left">\r
+ <div class="notch"></div>\r
+ <div class="ridge"></div>\r
+ </div>\r
+ <div class="tab-right">\r
+ <div class="notch"></div>\r
+ <div class="ridge"></div>\r
+ </div>\r
+ <div class="rail-left"></div>\r
+ <div class="rail-right"></div>\r
+ <div class="rail-middle">\r
+ <div class="rail-middle-outline">\r
+ <div class="tape-pad-holder">\r
+ <div class="tape-pad"></div>\r
+ <div class="tape-pad-line"></div>\r
+ </div>\r
+ </div>\r
+ <div class="screw-bm"></div>\r
+ </div>\r
+ <div class="screw-tl"></div>\r
+ <div class="screw-tr"></div>\r
+ <div class="screw-bl"></div>\r
+ <div class="screw-br"></div>\r
+ <div class="screw-tm"></div>\r
+ <div class="left reel-mask"></div>\r
+ <div class="right reel-mask"></div>\r
+ <canvas class="connecting-tape"></canvas>\r
+ <div class="left reel"></div>\r
+ <div class="left spokes"></div>\r
+ <div class="right reel"></div>\r
+ <div class="right spokes"></div>\r
+ <div class="progress-notches">\r
+ <div class="n1"></div>\r
+ <div class="n2"></div>\r
+ <div class="n3"></div>\r
+ <div class="n4"></div>\r
+ <div class="n5"></div>\r
+ <div class="n6"></div>\r
+ <div class="n7"></div>\r
+ <div class="n8"></div>\r
+ <div class="n9"></div>\r
+ </div>\r
+\r
+ <!-- static label version -->\r
+ <!--\r
+ <div class="label">Chill With Schill: Mixtape Demo</div>\r
+ -->\r
+\r
+ <!-- editable URL-based label for the demo, you don't need to use this -->\r
+ <form id="tape-form" action="." method="get" onsubmit="return false">\r
+ <input class="label" name="tape_url" placeholder="Type an MP3 URL here ..." title="Click to edit and provide your own MP3 URL" value="Chill With Schill: Mixtape Demo" data-default-value="Chill With Schill: Mixtape Demo" />\r
+ </form>\r
+\r
+ <div class="aqua controls">\r
+ <div class="bd">\r
+ <ul>\r
+ <li><a href="#" title="play/pause" class="play">◄</a></li>\r
+ <li><a href="#" title="rewind" class="rew">«</a></li>\r
+ <li><a href="#" title="fast-forward" class="ffwd">»</a></li>\r
+ <li><a href="#" title="stop" class="stop">■</a></li>\r
+ </ul>\r
+ </div>\r
+ </div>\r
+</div>\r
+\r
+<div class="thanks">\r
+ <p>Mixtape demo includes "Render Your Heart" by <a href="http://sonreal.ca/" title="SonReal (official website)">SonReal</a>. For the complete mix, see <a href="http://www.mixcrate.com/schill/chill-with-schill-summer-idj-live-session-169722" title="Chill With Schill: Summer iDJ Live Session (mixcrate)">Chill With Schill: Summer iDJ Live Session</a> on Mixcrate.</p>\r
+</div>\r
+\r
+<script>\r
+(function() {\r
+ window.setTimeout(function() {\r
+ // transition hack\r
+ document.getElementById('tape-loader').className = 'visible';\r
+ }, 1);\r
+ // oh, what a hack! (demo only: no high-end unicode characters on WinXP)\r
+ var char = '∞';\r
+ if (navigator.userAgent.indexOf('Windows NT 5.1') !== -1) {\r
+ document.getElementById('nextBackground').innerHTML = char + ' ';\r
+ }\r
+}());\r
+</script>\r
+\r
+</body>\r
+</html>
--- /dev/null
+<!DOCTYPE html>\r
+<!--\r
+/**\r
+ * Cassette Tape UI Prototype (09/2012)\r
+ * ALPHA build / experimental state, unsupported; use at own risk\r
+ * Requires CSS3 border-radius + <canvas> support\r
+ * http://www.schillmania.com/projects/soundmanager2/\r
+ */\r
+-->\r
+<html>\r
+<head>\r
+<title>SoundManager 2: Cassette Tape Prototype</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="An experimental HTML and CSS-based web audio player featuring designs based on the TDK MA-R90 cassette tape, a classic metal-alloy cassette model from 1982, and others" />\r
+<meta name="keywords" content="javascript sound, html5 audio, css3, cassette tape, tdk, mar, ma-r, mar90, html5 sound, javascript audio, schill, schillmania, soundmanager, soundmanager2" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="css/cassette-tape-ui.css" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="css/demo.css" />\r
+<script src="../../script/soundmanager2.js"></script>\r
+<script src="script/cassette-tape-ui.js"></script>\r
+</head>\r
+<body id="page-more">\r
+\r
+<div id="content">\r
+\r
+ <div id="demo-header-wrapper" class="visible light">\r
+\r
+ <div id="demo-header">\r
+ <h1>Cassette Tape UI</h1>\r
+ <p>An exercise in skeuomorphic excess. <a href="./" title="More cassette tape prototype designs">main ↬</a></p>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="col1" class="demo-subheader">\r
+\r
+ <h2 id="about">About</h2>\r
+ <p>The Cassette Tape UI began as a silly web design idea which spawned a <a href="#lamp-project" title="Tangential: The Cassette Tape Lamp Project">Tape Lamp Project</a> and some <a href="http://www.flickr.com/photos/schill/sets/72157630538617822/" title="Cassette Tape Miscellany by Schill (on Flickr)">eBay finds</a> along the way. This page documents some analog history, and the "making-of".</p>\r
+\r
+ <h2 id="purpose">Purpose</h2>\r
+ <p>Following up on the <a href="http://www.schillmania.com/content/entries/2011/wheels-of-steel/" title="The Wheels Of Steel: An Ode To Turntables (in HTML)">Wheels Of Steel</a>, The Cassette Tape UI is another experiment in skeuomorphic design - a term that in the context of computers, involves digital recreations of analog design elements and functionality that serve little to no practical purpose in the digital world.</p>\r
+ <p>In other words: <em>"You know what never gets old? ... Nostalgia."</em></p>\r
+\r
+ <h2 id="technology">Technology</h2>\r
+ <p>This experimental UI demo uses <a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2: JavaScript Sound For The Web">SoundManager 2</a> for audio playback and control. HTML5 and/or Flash can be used by SM2 under the hood, depending on support.</p>\r
+ <p>The UI is driven mostly by the <code>whileplaying()</code> event, which results in the spooling of cassette tape between the reels as playback progresses. The tape "connecting" the two reels is drawn dynamically on a <code><canvas></code> element, as applicable.</p>\r
+ <p>CSS animations are used to make the reels spin at different speeds, and <code><canvas></code> is also used to apply some masking and blurring effects on the home page demo.</p>\r
+\r
+ <h2 id="credits">Credits</h2>\r
+ <p>Thanks go out to <a href="http://www.sxates.com/" title="Brian Scates, design-centric entrepreneur">Brian Scates</a>, who designed graphic elements for the tape spokes, reels and textures. Kudos are also due to design + tech friends who played with early pre-release versions, found bugs and gave feedback.</p>\r
+ <p>Web fonts used: <a href="http://www.google.com/webfonts/specimen/Just+Another+Hand" title="Just Another Hand (Google Web Fonts)">Just Another Hand</a> (mixtape "label"), <a href="http://www.theleagueofmoveabletype.com/ostrich-sans" title="Ostrich Sans (League Of Moveable Type)">Ostrich Sans</a> (Demo page headers).</p>\r
+\r
+ <h2 id="inspiration">Inspiration</h2>\r
+ <p>\r
+ <a href="http://www.flickr.com/photos/schill/7586864728/" title="Heavy Metal: TDK MA-R90 Cassette Tape by Schill, on Flickr" style="margin-bottom:1em"><img src="http://farm8.staticflickr.com/7274/7586864728_a4466d7703_z.jpg" width="640" height="427" alt="Heavy Metal: TDK MA-R90 Cassette Tape"></a>\r
+ <a href="http://www.flickr.com/photos/schill/7990633818/" title="TDK MAR-90 Cassette Tape (Back) by Schill, on Flickr"><img src="http://farm9.staticflickr.com/8038/7990633818_8c5c5f7aa8_z.jpg" width="640" height="427" alt="TDK MAR-90 Cassette Tape (Back)"></a>\r
+ </p>\r
+ <p>The <b>TDK MA-R</b> (Metal-Alloy Reference) cassette series debuted in 1979 with a stunning design. Housed in a metal shell, the MA-R was a pretty serious piece of hardware weighing several times more than its counterparts. It was also innovative: Unlike other tapes with one-use tabs designed to be snapped and broken off, the MA-R series' tabs could be rotated in-place to prevent re-recording.</p>\r
+ <p>It turns out that cassette tapes, like many other things, are collectible. Rare and still-new, sealed models can go for hundreds of dollars online.</p>\r
+ <p>There were also some creative blends of functionality and design. It's inspiring to note that someone thought to make this tape head degausser tool transparent, exposing its unique inner circuitry.</p>\r
+ <p>\r
+ <a href="http://www.flickr.com/photos/schill/7992502552/" title="TDK HD-01 Head Demagnetizer by Schill, on Flickr"><img src="http://farm9.staticflickr.com/8035/7992502552_14c0c33689_z.jpg" width="640" height="427" alt="TDK HD-01 Head Demagnetizer"></a>\r
+ </p>\r
+\r
+ <h2 id="lamp-project">Tangential: The Lamp Project</h2>\r
+\r
+ <p>When searching for transparent tape designs online, I found photos of a "lamp" made by a San Francisco-based architecture firm and couldn't resist a shot at making my own. While they used larger scales and incandescent lighting, my approach was to build 1x5 and 2x5 stacks using transparent Maxell DUP-120 tapes in jewel boxes, and to light the stack with a special LED panel.</p>\r
+\r
+ <p>\r
+ <a href="http://www.flickr.com/photos/schill/7992891165/" title="Cassette Tape Lamps: 1x5, 2x5 by Schill, on Flickr"><img src="http://farm9.staticflickr.com/8039/7992891165_d2c44fb063_z.jpg" width="640" height="427" alt="Cassette Tape Lamps: 1x5, 2x5"></a>\r
+ </p>\r
+\r
+ <p>Incandescent flood lighting was tested, and turned out to be impractical (and perhaps, fire-prone).</p>\r
+\r
+ <p>\r
+ <a href="http://www.flickr.com/photos/schill/7635098808/" title="Cassette Tape Lamp: Test Build 1 (Desaturated) by Schill, on Flickr"><img src="http://farm9.staticflickr.com/8427/7635098808_3b9683286a_z.jpg" width="640" height="427" alt="Cassette Tape Lamp: Test Build 1 (Desaturated)"></a>\r
+ </p>\r
+\r
+ <p>Things improved greatly with a dimmable RGB LED panel which offered consistent illumination.</p>\r
+\r
+ <p>\r
+ <a href="http://www.flickr.com/photos/schill/7786579946/" title="Cassette Tape Lamp, LED Panel lighting by Schill, on Flickr"><img src="http://farm8.staticflickr.com/7256/7786579946_407c942bb9_z.jpg" width="640" height="427" alt="Cassette Tape Lamp, LED Panel lighting"></a>\r
+ </p>\r
+\r
+ <p>After making three 2x5 lamps (120 tapes in total), it was too tempting not to stack them.</p>\r
+\r
+ <p>\r
+ <a href="http://www.flickr.com/photos/schill/7821156750/" title="Cassette Tape Tower + RGB LED Panel Lighting by Schill, on Flickr"><img src="http://farm9.staticflickr.com/8445/7821156750_2384af6d10_z.jpg" width="640" height="240" alt="Cassette Tape Tower + RGB LED Panel Lighting"></a>\r
+ </p>\r
+\r
+ <p>Following up on the larger builds, I started making smaller 1x5-sized lamps for friends.</p>\r
+\r
+ <p>\r
+ <a href="http://www.flickr.com/photos/schill/8077249383/" title="Tape Lamp @ FlickrHQ (1x1x5), HDR by Schill, on Flickr"><img src="http://farm9.staticflickr.com/8325/8077249383_45b95de864_c.jpg" width="600" height="800" alt="Tape Lamp @ FlickrHQ (1x1x5), HDR"></a>\r
+ <a href="http://www.flickr.com/photos/schill/8078733596/" title="Accidental Minecraft-style lighting by Schill, on Flickr"><img src="http://farm9.staticflickr.com/8323/8078733596_89b79d174a_c.jpg" width="600" height="800" alt="Accidental Minecraft-style lighting"></a>\r
+ </p>\r
+\r
+ <p>See the <a href="http://www.flickr.com/photos/schill/sets/72157630659892600/" title="Cassette Tape Lamp Project by Schill (on Flickr)">Cassette Tape Lamp Project</a> set for more photos.</p>\r
+\r
+ </div>\r
+\r
+ <div id="col2" class="demo-subheader">\r
+\r
+ <h2 id="demo">Live Demo</h2>\r
+\r
+ <p>Here are some cassette tape UI skin/theme variants; the styling is a mix of HTML elements and class names.</p>\r
+\r
+ <p style="font-size:small"><b style="font-weight:bold">Disclaimer</b>: This UI is a prototype, experimental and subject to change. It is not officially "supported" as a demo, and requires a fairly-modern browser that supports CSS3 and <canvas>. It does not degrade gracefully in older browsers. Use at your own risk.</p>\r
+\r
+ <div class="cutout clear texture ma-r90 tape">\r
+ <div class="rail-left"></div>\r
+ <div class="rail-right"></div>\r
+ <div class="rail-middle">\r
+ <div class="rail-middle-outline"></div>\r
+ </div>\r
+ <div class="left reel-mask"></div>\r
+ <div class="right reel-mask"></div>\r
+ <canvas class="connecting-tape"></canvas>\r
+ <div class="left reel"></div>\r
+ <div class="left spokes"></div>\r
+ <div class="right reel"></div>\r
+ <div class="right spokes"></div>\r
+ <div class="progress-notches">\r
+ <div class="n1"></div>\r
+ <div class="n2"></div>\r
+ <div class="n3"></div>\r
+ <div class="n4"></div>\r
+ <div class="n5"></div>\r
+ <div class="n6"></div>\r
+ <div class="n7"></div>\r
+ <div class="n8"></div>\r
+ <div class="n9"></div>\r
+ </div>\r
+ <div class="label">Mixtape Demo</div>\r
+ <div class="aqua controls">\r
+ <div class="bd">\r
+ <ul>\r
+ <li><a href="#" title="play/pause" class="play">◄</a></li>\r
+ <li><a href="#" title="rewind" class="rew">«</a></li>\r
+ <li><a href="#" title="fast-forward" class="ffwd">»</a></li>\r
+ <li><a href="#" title="stop" class="stop">■</a></li>\r
+ </ul>\r
+ </div>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="clear black-micro dark cutout texture tape">\r
+ <div class="rail-left"></div>\r
+ <div class="rail-right"></div>\r
+ <div class="rail-middle">\r
+ <div class="rail-middle-outline" style="border:none;background-color:transparent">\r
+ <div class="hole-1"></div>\r
+ <div class="hole-2"></div>\r
+ <div class="hole-3"></div>\r
+ <div class="hole-4"></div>\r
+ <div class="tape-pad-holder">\r
+ <div class="tape-pad"></div>\r
+ <div class="tape-pad-line"></div>\r
+ </div>\r
+ </div>\r
+ <div class="screw-bm"></div>\r
+ </div>\r
+ <div class="screw-tl"></div>\r
+ <div class="screw-tr"></div>\r
+ <div class="screw-bl"></div>\r
+ <div class="screw-br"></div>\r
+ <div class="screw-tm"></div>\r
+ <div class="left reel-mask"></div>\r
+ <div class="right reel-mask"></div>\r
+ <canvas class="connecting-tape"></canvas>\r
+ <div class="left reel"></div>\r
+ <div class="left spokes"></div>\r
+ <div class="right reel"></div>\r
+ <div class="right spokes"></div>\r
+ <div class="progress-notches">\r
+ <div class="n1"></div>\r
+ <div class="n2"></div>\r
+ <div class="n3"></div>\r
+ <div class="n4"></div>\r
+ <div class="n5"></div>\r
+ <div class="n6"></div>\r
+ <div class="n7"></div>\r
+ <div class="n8"></div>\r
+ <div class="n9"></div>\r
+ </div>\r
+ <div class="label">Mixtape Demo</div>\r
+ <div class="controls">\r
+ <div class="bd">\r
+ <ul>\r
+ <li><a href="#" title="play/pause" class="play">◄</a></li>\r
+ <li><a href="#" title="rewind" class="rew">«</a></li>\r
+ <li><a href="#" title="fast-forward" class="ffwd">»</a></li>\r
+ <li><a href="#" title="stop" class="stop">■</a></li>\r
+ </ul>\r
+ </div>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="clear texture cutout tape">\r
+ <div class="rail-left"></div>\r
+ <div class="rail-right"></div>\r
+ <div class="rail-middle">\r
+ <div class="rail-middle-outline">\r
+ <div class="hole-1"></div>\r
+ <div class="hole-2"></div>\r
+ <div class="hole-3"></div>\r
+ <div class="hole-4"></div>\r
+ <div class="tape-pad-holder">\r
+ <div class="tape-pad"></div>\r
+ <div class="tape-pad-line"></div>\r
+ </div>\r
+ </div>\r
+ <div class="screw-bm"></div>\r
+ </div>\r
+ <div class="screw-tl"></div>\r
+ <div class="screw-tr"></div>\r
+ <div class="screw-bl"></div>\r
+ <div class="screw-br"></div>\r
+ <div class="screw-tm"></div>\r
+ <div class="left reel-mask"></div>\r
+ <div class="right reel-mask"></div>\r
+ <canvas class="connecting-tape"></canvas>\r
+ <div class="left reel"></div>\r
+ <div class="left spokes"></div>\r
+ <div class="right reel"></div>\r
+ <div class="right spokes"></div>\r
+ <div class="progress-notches">\r
+ <div class="n1"></div>\r
+ <div class="n2"></div>\r
+ <div class="n3"></div>\r
+ <div class="n4"></div>\r
+ <div class="n5"></div>\r
+ <div class="n6"></div>\r
+ <div class="n7"></div>\r
+ <div class="n8"></div>\r
+ <div class="n9"></div>\r
+ </div>\r
+ <div class="label">Mixtape Demo</div>\r
+ <div class="controls">\r
+ <div class="bd">\r
+ <ul>\r
+ <li><a href="#" title="play/pause" class="play">◄</a></li>\r
+ <li><a href="#" title="rewind" class="rew">«</a></li>\r
+ <li><a href="#" title="fast-forward" class="ffwd">»</a></li>\r
+ <li><a href="#" title="stop" class="stop">■</a></li>\r
+ </ul>\r
+ </div>\r
+ </div>\r
+ </div>\r
+\r
+ <div id="tape1-x" class="clear tape">\r
+ <div class="window"></div>\r
+ <div class="rail-left"></div>\r
+ <div class="rail-right"></div>\r
+ <div class="rail-middle">\r
+ <div class="rail-middle-outline">\r
+ <div class="hole-1"></div>\r
+ <div class="hole-2"></div>\r
+ <div class="hole-3"></div>\r
+ <div class="hole-4"></div>\r
+ <div class="tape-pad-holder">\r
+ <div class="tape-pad"></div>\r
+ <div class="tape-pad-line"></div>\r
+ </div>\r
+ </div>\r
+ <div class="screw-bm"></div>\r
+ </div>\r
+ <div class="screw-tl"></div>\r
+ <div class="screw-tr"></div>\r
+ <div class="screw-bl"></div>\r
+ <div class="screw-br"></div>\r
+ <div class="left reel"></div>\r
+ <div class="left spokes"></div>\r
+ <div class="right reel"></div>\r
+ <div class="right spokes">\r
+ </div>\r
+ <canvas class="connecting-tape"></canvas>\r
+ <div class="left tape-guide"></div>\r
+ <div class="right tape-guide"></div>\r
+ <div class="progress-notches">\r
+ <div class="n1"></div>\r
+ <div class="n2"></div>\r
+ <div class="n3"></div>\r
+ <div class="n4"></div>\r
+ <div class="n5"></div>\r
+ <div class="n6"></div>\r
+ <div class="n7"></div>\r
+ <div class="n8"></div>\r
+ <div class="n9"></div>\r
+ </div>\r
+ <div class="label">Mixtape Demo</div>\r
+ <div class="controls">\r
+ <div class="bd">\r
+ <ul>\r
+ <li><a href="#" title="play/pause" class="play">◄</a></li>\r
+ <li><a href="#" title="rewind" class="rew">«</a></li>\r
+ <li><a href="#" title="fast-forward" class="ffwd">»</a></li>\r
+ <li><a href="#" title="stop" class="stop">■</a></li>\r
+ </ul>\r
+ </div>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="clear blue color texture tape">\r
+ <div class="window"></div>\r
+ <div class="rail-left"></div>\r
+ <div class="rail-right"></div>\r
+ <div class="rail-middle">\r
+ <div class="rail-middle-outline">\r
+ <div class="hole-1"></div>\r
+ <div class="hole-2"></div>\r
+ <div class="hole-3"></div>\r
+ <div class="hole-4"></div>\r
+ <div class="tape-pad-holder">\r
+ <div class="tape-pad"></div>\r
+ <div class="tape-pad-line"></div>\r
+ </div>\r
+ </div>\r
+ <div class="screw-bm"></div>\r
+ </div>\r
+ <div class="screw-tl"></div>\r
+ <div class="screw-tr"></div>\r
+ <div class="screw-bl"></div>\r
+ <div class="screw-br"></div>\r
+ <div class="left reel"></div>\r
+ <div class="left spokes">\r
+ </div>\r
+ <div class="right reel"></div>\r
+ <div class="right spokes">\r
+ </div>\r
+ <canvas class="connecting-tape"></canvas>\r
+ <div class="left tape-guide"></div>\r
+ <div class="right tape-guide"></div>\r
+ <div class="progress-notches">\r
+ <div class="n1"></div>\r
+ <div class="n2"></div>\r
+ <div class="n3"></div>\r
+ <div class="n4"></div>\r
+ <div class="n5"></div>\r
+ <div class="n6"></div>\r
+ <div class="n7"></div>\r
+ <div class="n8"></div>\r
+ <div class="n9"></div>\r
+ </div>\r
+ <div class="label">Mixtape Demo</div>\r
+ <div class="controls">\r
+ <div class="bd">\r
+ <ul>\r
+ <li><a href="#" title="play/pause" class="play">◄</a></li>\r
+ <li><a href="#" title="rewind" class="rew">«</a></li>\r
+ <li><a href="#" title="fast-forward" class="ffwd">»</a></li>\r
+ <li><a href="#" title="stop" class="stop">■</a></li>\r
+ </ul>\r
+ </div>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="black-micro dark clear texture tape">\r
+ <div class="rail-left"></div>\r
+ <div class="rail-right"></div>\r
+ <div class="rail-middle">\r
+ <div class="rail-middle-outline" style="border:none;background-color:transparent">\r
+ <div class="hole-1"></div>\r
+ <div class="hole-2"></div>\r
+ <div class="hole-3"></div>\r
+ <div class="hole-4"></div>\r
+ <div class="tape-pad-holder">\r
+ <div class="tape-pad"></div>\r
+ <div class="tape-pad-line"></div>\r
+ </div>\r
+ </div>\r
+ <div class="screw-bm"></div>\r
+ </div>\r
+ <div class="screw-tl"></div>\r
+ <div class="screw-tr"></div>\r
+ <div class="screw-bl"></div>\r
+ <div class="screw-br"></div>\r
+ <div class="screw-tm"></div>\r
+ <div class="left reel"></div>\r
+ <div class="left spokes"></div>\r
+ <div class="right reel"></div>\r
+ <div class="right spokes"></div>\r
+ <div class="progress-notches">\r
+ <div class="n1"></div>\r
+ <div class="n2"></div>\r
+ <div class="n3"></div>\r
+ <div class="n4"></div>\r
+ <div class="n5"></div>\r
+ <div class="n6"></div>\r
+ <div class="n7"></div>\r
+ <div class="n8"></div>\r
+ <div class="n9"></div>\r
+ </div>\r
+ <!--\r
+ <div class="label"></div>\r
+ -->\r
+ <div class="controls">\r
+ <div class="bd">\r
+ <ul>\r
+ <li><a href="#" title="play/pause" class="play">◄</a></li>\r
+ <li><a href="#" title="rewind" class="rew">«</a></li>\r
+ <li><a href="#" title="fast-forward" class="ffwd">»</a></li>\r
+ <li><a href="#" title="stop" class="stop">■</a></li>\r
+ </ul>\r
+ </div>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+</body>
--- /dev/null
+/**\r
+ * Cassette Tape UI Prototype (09/2012)\r
+ * ALPHA build / experimental state, unsupported; use at own risk\r
+ * Requires CSS3 border-radius + <canvas> support\r
+ * --------------------------------------------------\r
+ * http://www.schillmania.com/projects/soundmanager2/\r
+ */\r
+\r
+(function(window) {\r
+\r
+var caughtError = false;\r
+\r
+var CanvasImage = function(canvas, image) {\r
+\r
+ /**\r
+ * https://github.com/ceramedia/examples/tree/gh-pages/canvas-blur/v5\r
+ * original: http://www.flother.com/blog/2010/image-blur-html5-canvas/\r
+ *\r
+ * Light layer on top of a canvas element to represent an image displayed\r
+ * within. Pass in a canvas element and an Image object and you'll see the\r
+ * image within the canvas element. Use the provided methods (e.g. blur) to\r
+ * manipulate it.\r
+ *\r
+ * @constructor\r
+ * @param {HTMLElement} element HTML canvas element.\r
+ * @param {Image} image Image object.\r
+ */\r
+\r
+ var width, height;\r
+\r
+ this.image = image;\r
+\r
+ width = this.image.width;\r
+ height = this.image.height;\r
+\r
+ this.element = canvas || document.createElement('canvas');\r
+ // IE 10 complains if 'auto' is used for style.width|height.\r
+\r
+ this.element.style.width = width+'px';\r
+ this.element.style.height = height+'px';\r
+ this.element.width = width;\r
+ this.element.height = height;\r
+ this.context = this.element.getContext('2d');\r
+ this.context.drawImage(this.image, 0, 0);\r
+\r
+};\r
+\r
+CanvasImage.prototype = {\r
+ /**\r
+ * Runs a blur filter over the image.\r
+ * @param {int} strength Strength of the blur.\r
+ */\r
+ blur: function (strength) {\r
+ this.context.globalAlpha = 0.5; // Higher alpha made it more smooth\r
+ // Add blur layers by strength to x and y\r
+ // 2 made it a bit faster without noticeable quality loss\r
+ for (var y = -strength; y <= strength; y += 2) {\r
+ for (var x = -strength; x <= strength; x += 2) {\r
+ // Apply layers\r
+ this.context.drawImage(this.element, x, y);\r
+ // Add an extra layer, prevents it from rendering lines\r
+ // on top of the images (does makes it slower though)\r
+ if (x>=0 && y>=0) {\r
+ this.context.drawImage(this.element, -(x-1), -(y-1));\r
+ }\r
+ }\r
+ }\r
+ this.context.globalAlpha = 1.0;\r
+ }\r
+};\r
+\r
+function imageMask(imageSrc, maskSrc, canvasWidth, canvasHeight, useRepeat, oncomplete) {\r
+\r
+ /**\r
+ * quick-and-dirty "load an image and apply a mask to it" function\r
+ * parameters:\r
+ * @imageSrc {URL} string Source image URL\r
+ * @maskSrc {URL} string Mask image URL\r
+ * @oncomplete {Function} function Callback with data: URI of masked image result\r
+ */\r
+\r
+ var images = [\r
+ new Image(),\r
+ new Image()\r
+ ];\r
+\r
+ // CORS option?\r
+ // images[0].crossOrigin = 'anonymous';\r
+ // images[1].crossOrigin = 'anonymous';\r
+\r
+ var canvas = [\r
+ document.createElement('canvas'),\r
+ document.createElement('canvas')\r
+ ];\r
+\r
+ var loadCount = 0;\r
+\r
+ var loadTarget = images.length;\r
+\r
+ function applyMask() {\r
+\r
+ // draw and mask image\r
+\r
+ var srcWidth = canvasWidth;\r
+ var srcHeight = canvasHeight;\r
+\r
+ var targetWidth = canvasWidth;\r
+ var targetHeight = canvasHeight;\r
+\r
+ var ctx;\r
+\r
+ var repeatPattern;\r
+\r
+ canvas[0].width = srcWidth;\r
+ canvas[0].height = srcHeight;\r
+\r
+ canvas[1].width = targetWidth;\r
+ canvas[1].height = targetHeight;\r
+\r
+ ctx = [\r
+ canvas[0].getContext('2d'),\r
+ canvas[1].getContext('2d')\r
+ ];\r
+\r
+ if (!useRepeat) {\r
+\r
+ // simple 1:1 case\r
+\r
+ ctx[0].drawImage(images[0], 0, 0);\r
+\r
+ } else {\r
+\r
+ // tile the image across the canvas\r
+\r
+ repeatPattern = ctx[0].createPattern(images[0], 'repeat');\r
+\r
+ ctx[0].fillStyle = repeatPattern;\r
+\r
+ ctx[0].fillRect(0, 0, targetWidth, targetHeight);\r
+\r
+ ctx[0].fillStyle = '';\r
+\r
+ }\r
+\r
+ // draw mask on target canvas\r
+\r
+ ctx[1].drawImage(images[1], 0, 0);\r
+\r
+ // apply the mask\r
+\r
+ ctx[0].globalCompositeOperation = 'destination-in';\r
+\r
+ ctx[0].drawImage(canvas[1], 0, 0);\r
+\r
+ ctx[0].globalCompositeOperation = null;\r
+\r
+ // the resulting masked image\r
+\r
+ return canvas[0];\r
+\r
+ }\r
+\r
+ function imageLoaded() {\r
+\r
+ // load handler\r
+\r
+ this.onload = this.onerror = null;\r
+\r
+ loadCount++;\r
+\r
+ if (loadCount >= loadTarget) {\r
+\r
+ // apply the mask, providing the resulting data URI to the handler\r
+ // TODO: Don't use data URL, just modify canvas directly; likely much faster.\r
+\r
+ try {\r
+\r
+ oncomplete(applyMask().toDataURL('image/png'));\r
+\r
+ } catch(e) {\r
+\r
+ // may fail with DOM exception 18 under Chrome when offline eg., file:// instead of over HTTP.\r
+\r
+ if (typeof console !== 'undefined' && typeof console.warn !== 'undefined') {\r
+ console.warn('Unable to apply image mask, likely a security exception from offline (file://) use.', e);\r
+ if (!caughtError && typeof console.info !== 'undefined') {\r
+ console.info('Using static skin image as a workaround.');\r
+ }\r
+ }\r
+\r
+ // hack: try applying the body skin instead, without masking. HTML-based screw elements will overlay the skin, but, eh. this is an edge case anyway.\r
+\r
+ if (!caughtError) {\r
+\r
+ oncomplete('image/ma-r90-body-skin.png');\r
+ caughtError = true;\r
+\r
+ } else {\r
+\r
+ oncomplete();\r
+\r
+ }\r
+\r
+ }\r
+\r
+ // cleanup?\r
+ canvas = null;\r
+ images = null;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ function init() {\r
+\r
+ // preload source / target images\r
+\r
+ images[0].onload = images[0].onerror = imageLoaded;\r
+ images[1].onload = images[1].onerror = imageLoaded;\r
+\r
+ images[0].src = imageSrc;\r
+ images[1].src = maskSrc;\r
+\r
+ // TODO: check .complete (cached) case?\r
+\r
+ }\r
+\r
+ init();\r
+\r
+}\r
+\r
+function TapeUI(oOptions) {\r
+\r
+ var css = {\r
+\r
+ playing: 'playing',\r
+ stopped: 'stopped',\r
+ ready: 'ready',\r
+ dropin: 'dropin'\r
+\r
+ };\r
+\r
+ var data = {\r
+\r
+ progress: 0\r
+\r
+ };\r
+\r
+ var controlHandler;\r
+\r
+ var sound;\r
+\r
+ var dom = {};\r
+\r
+ var spoolWidth = 91;\r
+\r
+ var borderMaxWidth = 76;\r
+\r
+ var reelBoxWidth = 234;\r
+\r
+ var tapeWidth = 480;\r
+ var tapeHeight = parseInt(tapeWidth/1.6, 10);\r
+\r
+ var blurCanvas;\r
+\r
+ var maskCanvas;\r
+ var maskCanvasLoaded;\r
+ var maskContext;\r
+ var maskImage;\r
+ var maskVisible;\r
+\r
+ var context;\r
+\r
+ function getBackgroundURL(node) {\r
+\r
+ var url;\r
+ var cssprop = 'backgroundImage';\r
+\r
+ if (node.currentStyle) {\r
+\r
+ // IE\r
+ url = node.currentStyle[cssprop];\r
+\r
+ } else if (document.defaultView && document.defaultView.getComputedStyle) {\r
+\r
+ // Firefox\r
+ url = document.defaultView.getComputedStyle(node, '')[cssprop];\r
+\r
+ } else {\r
+\r
+ // inline style?\r
+ url = node.style[cssprop];\r
+\r
+ }\r
+\r
+ // HACK: strip url() and/or quotes from string\r
+\r
+ url = url.replace('url(', '').replace(')', '');\r
+\r
+ url = url.replace(/\'/g, '').replace(/\"/g, '');\r
+\r
+ return url;\r
+\r
+ }\r
+\r
+ function maskedImageReady(node, uri) {\r
+\r
+ // callback with data: URI of masked image\r
+\r
+ if (node && uri) {\r
+ node.style.backgroundImage = uri;\r
+ }\r
+\r
+ }\r
+\r
+ function createMaskedImage(node) {\r
+\r
+ // get background image (or if <img>, src?) and data-mask-image attributes\r
+\r
+ var imageSrc = getBackgroundURL(node),\r
+ elementWidth = node.offsetWidth,\r
+ elementHeight = node.offsetHeight,\r
+ useRepeat = !!node.getAttribute('data-image-repeat'),\r
+ maskSrc = node.getAttribute('data-mask-url');\r
+\r
+ return imageMask(imageSrc, maskSrc, elementWidth, elementHeight, useRepeat, function(maskURI) {\r
+ var uri = (maskURI ? 'url(' + maskURI + ')' : null);\r
+ maskedImageReady(node, uri);\r
+ });\r
+\r
+ }\r
+\r
+ // canvas stuffs\r
+\r
+ function scaleWidth(w) {\r
+ return (w * tapeWidth);\r
+ }\r
+\r
+ function scaleHeight(h) {\r
+ return (h * tapeHeight);\r
+ }\r
+\r
+ function initMask(callback) {\r
+\r
+ if (!dom.node.className.match(/cutout/i)) {\r
+ return false;\r
+ }\r
+\r
+ // draw our tape cut-outs\r
+\r
+ maskCanvas = document.createElement('canvas');\r
+\r
+ maskImage = new Image();\r
+\r
+ // Ensure same dimensions\r
+ maskCanvas.width = tapeWidth;\r
+ maskCanvas.height = tapeHeight;\r
+\r
+/*\r
+ maskContext = maskCanvas.getContext('2d');\r
+\r
+ var spoolBoxRadius = 134;\r
+\r
+ var spoolCoords = [\r
+ // left\r
+ tapeWidth * 0.29,\r
+ tapeHeight * 0.45,\r
+ // right\r
+ tapeWidth * 0.71,\r
+ tapeHeight * 0.45\r
+ ];\r
+\r
+ // filled shape color\r
+ maskContext.fillStyle = "black";\r
+\r
+ maskContext.arc(spoolCoords[0], spoolCoords[1], spoolBoxRadius, 0, 4 * Math.PI);\r
+\r
+ maskContext.arc(spoolCoords[2], spoolCoords[3], spoolBoxRadius, 0, 4 * Math.PI);\r
+\r
+ maskContext.fill();\r
+*/\r
+\r
+ maskImage.onload = function() {\r
+ var ctx = maskCanvas.getContext('2d');\r
+ ctx.drawImage(this, 0, 0);\r
+ this.onload = null;\r
+ maskCanvasLoaded = true;\r
+ callback();\r
+ };\r
+\r
+ // load the mask to apply\r
+ maskImage.src = 'image/ma-r90-mask.png';\r
+\r
+ }\r
+\r
+ function createBlurImage(callback) {\r
+\r
+ var url = getBackgroundURL(document.getElementsByTagName('html')[0]);\r
+\r
+ var image = new Image();\r
+\r
+ // CORS option?\r
+ // image.crossOrigin = 'anonymous';\r
+\r
+ image.onload = image.onerror = function() {\r
+\r
+ // in error state, w/h will be empty.\r
+\r
+ if (this.width || this.height) {\r
+\r
+ // make + blur\r
+\r
+ var canvasImage = new CanvasImage(dom.blurNode, this);\r
+\r
+ // var uri = canvasImage.element.toDataURL('image/png');\r
+\r
+ // + assign to DOM\r
+\r
+ dom.blurNode.style.backgroundImage = '';\r
+\r
+ canvasImage.blur(2);\r
+\r
+ }\r
+\r
+ this.onload = this.onerror = null;\r
+\r
+ if (callback) {\r
+ callback();\r
+ }\r
+\r
+ }\r
+\r
+ image.src = url;\r
+\r
+ }\r
+\r
+ function center() {\r
+\r
+ // given screen x/y, position at center.\r
+\r
+ // don't center unless draggable.\r
+ if (!dragHandler.data.dragTarget.node) {\r
+ return false;\r
+ }\r
+\r
+ var screenX = window.innerWidth,\r
+ screenX2 = parseInt(screenX/2, 10),\r
+ screenY = window.innerHeight,\r
+ screenY2 = parseInt(screenY/2, 10),\r
+ x, y,\r
+ node = dom.node,\r
+ blurNode = dom.blurNode;\r
+\r
+ if (node) {\r
+ x = parseInt(screenX2 - (tapeWidth/2), 10);\r
+ y = parseInt(screenY2 - (tapeHeight/2), 10);\r
+ node.style.left = x + 'px';\r
+ node.style.top = y + 'px';\r
+ if (blurNode) {\r
+ blurNode.style.marginLeft = -x + 'px';\r
+ blurNode.style.marginTop = -y + 'px';\r
+ }\r
+ }\r
+ \r
+ }\r
+\r
+ var readyCompleteTimer = null;\r
+\r
+ function readyComplete(loader) {\r
+\r
+ utils.css.add(dom.node, css.ready);\r
+ utils.css.add(dom.node, css.dropin);\r
+\r
+ if (readyCompleteTimer) {\r
+ window.clearTimeout(readyCompleteTimer);\r
+ }\r
+\r
+ readyCompleteTimer = window.setTimeout(function() {\r
+ utils.css.remove(dom.node, css.dropin);\r
+ // demo hack: remove the loader, too\r
+ /*\r
+ if (loader) {\r
+ document.body.removeChild(loader);\r
+ loader = null;\r
+ }\r
+ */\r
+ }, 1000);\r
+\r
+ }\r
+\r
+ function ready() {\r
+\r
+ // demo hack: hide the loading element, if present\r
+ var loader = document.getElementById('tape-loader'),\r
+ wrapper = document.getElementById('demo-header-wrapper');\r
+\r
+ if (loader) {\r
+ utils.css.remove(loader, 'visible');\r
+ utils.css.add(loader, 'hidden');\r
+ if (wrapper) {\r
+ utils.css.add(wrapper, 'visible');\r
+ }\r
+ }\r
+\r
+ // trigger animations after slight yield (depending on loader element)\r
+ window.setTimeout(function() {\r
+ // reposition\r
+ center();\r
+ readyComplete(loader);\r
+ }, loader ? 300 : 1);\r
+\r
+ }\r
+\r
+ function init() {\r
+\r
+ var i, j;\r
+\r
+ sound = oOptions.sound;\r
+\r
+ dom = {\r
+ node: oOptions.node,\r
+ canvas: oOptions.node.querySelectorAll('.connecting-tape'),\r
+ reels: oOptions.node.querySelectorAll('div.reel'),\r
+ spokes: oOptions.node.querySelectorAll('div.spokes'),\r
+ label: oOptions.node.querySelectorAll('div.label'),\r
+ maskImages: oOptions.node.querySelectorAll('.image-mask'),\r
+ blurNode: oOptions.node.querySelectorAll('.blur-image')\r
+ }\r
+\r
+ if (dom.canvas && dom.canvas.length) {\r
+ dom.canvas = dom.canvas[0];\r
+ initMask(function() {\r
+ // force redraw\r
+ setProgress(0, true);\r
+ });\r
+ } else {\r
+ dom.canvas = null;\r
+ }\r
+\r
+ // images needing masking?\r
+ if (dom.maskImages) {\r
+ for (i=0, j=dom.maskImages.length; i<j; i++) {\r
+ createMaskedImage(dom.maskImages[i]);\r
+ }\r
+ }\r
+\r
+ // blur image?\r
+ if (dom.blurNode && dom.blurNode.length) {\r
+ dom.blurNode = dom.blurNode[0];\r
+ createBlurImage(ready);\r
+ } else {\r
+ dom.blurNode = null;\r
+ ready();\r
+ }\r
+\r
+ // controls\r
+ controlHandler = new ControlHandler(dom, sound);\r
+\r
+ }\r
+\r
+ var reelStatus = [{\r
+ borderWidth: null\r
+ }, {\r
+ borderWidth: null\r
+ }];\r
+\r
+ function setReelSize(reelCount, reel, size) {\r
+\r
+ // return value: was an update applied?\r
+ var newFrame = 0;\r
+\r
+ // limit to between 0 and 1\r
+ size = Math.min(1, Math.max(0, size));\r
+\r
+ var borderWidth = Math.floor(borderMaxWidth*size);\r
+\r
+ var margin;\r
+\r
+ if (reelStatus[reelCount].borderWidth !== borderWidth) {\r
+\r
+ reelStatus[reelCount].borderWidth = borderWidth;\r
+\r
+ reel.style.borderWidth = borderWidth + 'px';\r
+\r
+ margin = -(Math.floor(spoolWidth/2) + borderWidth) + 'px';\r
+\r
+ reel.style.marginLeft = margin;\r
+\r
+ reel.style.marginTop = margin;\r
+\r
+ newFrame = 1;\r
+\r
+ }\r
+\r
+ return newFrame;\r
+\r
+ }\r
+\r
+ function deg2rad(degrees) {\r
+\r
+ return (Math.PI/180)*degrees;\r
+\r
+ }\r
+\r
+ var tapeCache = {\r
+ leftReel: {\r
+ left: null\r
+ },\r
+ rightReel: {\r
+ left: null\r
+ }\r
+ };\r
+\r
+ function drawConnectingTape(canvas, progress, forceUpdate) {\r
+\r
+ // draw a line of tape between the two reels, at angles relative to the amount of tape on each reel.\r
+\r
+ var leftReelRadius = borderMaxWidth - (borderMaxWidth * progress);\r
+\r
+ var rightReelRadius = (borderMaxWidth * progress);\r
+\r
+ var bottomTapeOffset = scaleHeight(0.998);\r
+\r
+ var leftReel = {\r
+ left: Math.floor(scaleWidth(0.29) - (spoolWidth/2) - leftReelRadius) + 4,\r
+ top: scaleHeight(0.42)\r
+ };\r
+\r
+ var guideRadius = 16;\r
+\r
+ var rightReel = {\r
+ left: Math.floor(scaleWidth(0.71) + (spoolWidth/2) + rightReelRadius) - 3,\r
+ top: scaleHeight(0.42)\r
+ };\r
+\r
+ var leftGuide = {\r
+ left: scaleWidth(0.11) - guideRadius,\r
+ top: bottomTapeOffset - guideRadius*2\r
+ };\r
+\r
+ var rightGuide = {\r
+ left: scaleWidth(0.89) - guideRadius,\r
+ top: bottomTapeOffset\r
+ };\r
+\r
+ var bottomLeftPoint = {\r
+ from: [leftGuide.left, leftGuide.top],\r
+ to: [leftReel.left, leftReel.top]\r
+ };\r
+\r
+ var bottomRightPoint = {\r
+ from: [rightGuide.left, rightGuide.top],\r
+ to: [rightReel.left, rightReel.top]\r
+ };\r
+\r
+ var bottomMidPoint = {\r
+ left: tapeWidth * 0.5,\r
+ top: bottomTapeOffset\r
+ };\r
+\r
+ if (!forceUpdate && tapeCache.leftReel.left === leftReel.left && tapeCache.rightReel.left === rightReel.left) {\r
+ // no change since last time.\r
+ return false;\r
+ }\r
+\r
+ // otherwise, update everything.\r
+ tapeCache.leftReel.left = leftReel.left;\r
+ tapeCache.rightReel.left = rightReel.left;\r
+\r
+ var context = canvas.getContext('2d');\r
+\r
+ canvas.width = tapeWidth;\r
+ canvas.height = tapeHeight;\r
+\r
+ // context.lineWidth = 1;\r
+\r
+ context.beginPath();\r
+\r
+ // move to bottom middle\r
+ context.moveTo(bottomMidPoint.left, bottomMidPoint.top);\r
+\r
+ // -> left guide\r
+ context.lineTo(bottomLeftPoint.from[0] + guideRadius, bottomLeftPoint.from[1] + guideRadius*2);\r
+\r
+ // arc\r
+ context.arc(bottomLeftPoint.from[0] + guideRadius, bottomLeftPoint.from[1] + guideRadius, guideRadius, deg2rad(90), deg2rad(180), false);\r
+\r
+ // -> left reel\r
+ context.lineTo(leftReel.left, leftReel.top);\r
+\r
+ context.lineWidth = 0.5;\r
+\r
+ // move to bottom middle\r
+ context.moveTo(bottomMidPoint.left, bottomMidPoint.top);\r
+\r
+ // -> right guide\r
+ context.lineTo(bottomRightPoint.from[0] + guideRadius, bottomRightPoint.from[1]);\r
+\r
+ // right side\r
+ context.arc(bottomRightPoint.from[0] + guideRadius, bottomRightPoint.from[1] - guideRadius, guideRadius, deg2rad(90), deg2rad(0), true); // -30 on last for curve effect\r
+\r
+ // -> right reel\r
+ context.lineTo(rightReel.left, rightReel.top);\r
+\r
+ context.lineWidth = 1;\r
+\r
+ context.stroke();\r
+\r
+ // apply the mask (only the circular areas around the tape)\r
+\r
+ if (maskCanvas) {\r
+\r
+ // set composite operation\r
+\r
+ context.globalCompositeOperation = 'destination-out';\r
+\r
+ context.drawImage(maskCanvas, 0, 0);\r
+\r
+ context.globalCompositeOperation = null;\r
+\r
+ // visibility check\r
+\r
+ if (maskCanvasLoaded && !maskVisible) {\r
+\r
+ maskVisible = true;\r
+\r
+ canvas.style.visibility = 'visible';\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ function setReelSpeed(reel, speed) {\r
+\r
+ // base speed plus a given amount based on speed (multiplier?)\r
+\r
+ }\r
+\r
+ function applyProgress(progress) {\r
+\r
+ var newFrames = 0;\r
+\r
+ setReelSpeed(dom.reels[0], progress);\r
+ newFrames += setReelSize(0, dom.reels[0], 1-progress);\r
+ newFrames += setReelSize(1, dom.reels[1], progress);\r
+\r
+ return newFrames;\r
+\r
+ }\r
+\r
+ function setProgress(progress, forceUpdate) {\r
+\r
+ var newFrames = 0;\r
+\r
+ forceUpdate = forceUpdate || false;\r
+\r
+ data.progress = progress;\r
+\r
+ newFrames = applyProgress(progress);\r
+\r
+ if ((newFrames || forceUpdate) && dom.canvas) {\r
+\r
+ drawConnectingTape(dom.canvas, progress, forceUpdate);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ function start() {\r
+\r
+ utils.css.remove(dom.node, css.stopped);\r
+ utils.css.add(dom.node, css.playing);\r
+\r
+ }\r
+\r
+ function stop() {\r
+\r
+ utils.css.remove(dom.node, css.playing);\r
+ utils.css.add(dom.node, css.stopped);\r
+\r
+ }\r
+\r
+ return {\r
+\r
+ refreshBlurImage: function(callback) {\r
+ utils.css.remove(dom.node, css.dropin);\r
+ utils.css.remove(dom.node, css.ready);\r
+ return createBlurImage(function() {\r
+ utils.css.add(dom.node, css.dropin);\r
+ utils.css.add(dom.node, css.ready);\r
+ readyComplete();\r
+ if (callback) {\r
+ callback(this);\r
+ }\r
+ });\r
+ },\r
+ dom: dom,\r
+ init: init,\r
+ setProgress: setProgress,\r
+ start: start,\r
+ stop: stop\r
+ \r
+ };\r
+\r
+}\r
+\r
+var tapeUIs = [];\r
+\r
+function resetTapeUIs() {\r
+\r
+ for (var i=tapeUIs.length; i--;) {\r
+ tapeUIs[i].setProgress(0);\r
+ }\r
+\r
+}\r
+\r
+var ignoreNextClick = false;\r
+\r
+var dragHandler = (function() {\r
+\r
+ var css,\r
+ data,\r
+ dom,\r
+ events;\r
+\r
+ function findPos(obj) {\r
+ var curleft = curtop = 0;\r
+ if (obj.offsetParent) {\r
+ do {\r
+ curleft += obj.offsetLeft;\r
+ curtop += obj.offsetTop;\r
+ } while (obj = obj.offsetParent);\r
+ }\r
+ return [curleft, curtop];\r
+ }\r
+\r
+ css = {\r
+ dragActive: 'dragging',\r
+ dropActive: 'dropping'\r
+ };\r
+\r
+ data = {\r
+ dragTarget: {\r
+ node: null,\r
+ blurNode: null,\r
+ blurNodeContainer: null,\r
+ x: null,\r
+ y: null,\r
+ lastX: null,\r
+ lastY: null\r
+ },\r
+ mousedown: {\r
+ x: null,\r
+ y: null\r
+ },\r
+ drag: {\r
+ xOffset: null,\r
+ yOffset: null\r
+ },\r
+ background: {\r
+ xOffset: -151,\r
+ yOffset: -119\r
+ }\r
+ };\r
+\r
+ events = {\r
+ mousedown: function(e) {\r
+ var target = data.dragTarget.node,\r
+ clickTarget = e.target;\r
+ if (!data.dragTarget.node) {\r
+ return true;\r
+ }\r
+ // additional safety check\r
+ if (clickTarget && clickTarget.tagName == 'INPUT') {\r
+ ignoreNextClick = true;\r
+ return true;\r
+ }\r
+ ignoreNextClick = false;\r
+ var xy = findPos(target);\r
+ data.dragTarget.x = xy[0];\r
+ data.dragTarget.y = xy[1];\r
+ data.mousedown.x = e.clientX;\r
+ data.mousedown.y = e.clientY;\r
+ data.drag.xOffset = data.mousedown.x - data.dragTarget.x;\r
+ data.drag.yOffset = data.mousedown.y - data.dragTarget.y;\r
+ utils.events.add(document, 'mousemove', events.mousemove);\r
+ utils.events.add(document, 'mouseup', events.mouseup);\r
+ e.preventDefault();\r
+ return false;\r
+ },\r
+ mousemove: function(e) {\r
+ var x, y,\r
+ node = data.dragTarget.node,\r
+ blurNode = data.dragTarget.blurNode;\r
+ if (node) {\r
+ x = (e.clientX - data.drag.xOffset);\r
+ y = (e.clientY - data.drag.yOffset);\r
+ node.style.left = x + 'px';\r
+ node.style.top = y + 'px';\r
+ if (blurNode) {\r
+ blurNode.style.marginLeft = -x + 'px';\r
+ blurNode.style.marginTop = -y + 'px';\r
+ }\r
+ if (!ignoreNextClick) {\r
+ ignoreNextClick = true;\r
+ utils.css.add(data.dragTarget.node, css.dragActive);\r
+ }\r
+ }\r
+ },\r
+ mouseup: function(e) {\r
+ utils.css.remove(data.dragTarget.node, css.dragActive);\r
+ if (ignoreNextClick) {\r
+ // remove drag work\r
+ utils.css.add(data.dragTarget.node, css.dropActive);\r
+ window.setTimeout(function() {\r
+ utils.css.remove(data.dragTarget.node, css.dropActive);\r
+ }, 500);\r
+ }\r
+ utils.events.remove(document, 'mousemove', events.mousemove);\r
+ utils.events.remove(document, 'mouseup', events.mouseup);\r
+ e.preventDefault();\r
+ return false;\r
+ }\r
+ \r
+ };\r
+\r
+ function updateLastXY() {\r
+ var target = data.dragTarget.node;\r
+ var xy = findPos(target);\r
+ data.dragTarget.lastX = xy[0];\r
+ data.dragTarget.lastY = xy[1];\r
+ }\r
+\r
+ function addEvents() {\r
+ if (data.dragTarget && data.dragTarget.node) {\r
+ utils.events.add(data.dragTarget.node, 'mousedown', events.mousedown);\r
+ }\r
+ }\r
+\r
+ function init() {\r
+ data.dragTarget.node = document.querySelector('.tape.draggable');\r
+ data.dragTarget.blurNode = document.querySelector('.tape.draggable .blur-image');\r
+ addEvents();\r
+ }\r
+\r
+ return {\r
+ data: data,\r
+ init: init\r
+ }\r
+\r
+}());\r
+\r
+var utils = (function() {\r
+\r
+ var addEventHandler = (typeof window.addEventListener !== 'undefined' ? function(o, evtName, evtHandler) {\r
+ return o.addEventListener(evtName,evtHandler,false);\r
+ } : function(o, evtName, evtHandler) {\r
+ o.attachEvent('on'+evtName,evtHandler);\r
+ });\r
+\r
+ var removeEventHandler = (typeof window.removeEventListener !== 'undefined' ? function(o, evtName, evtHandler) {\r
+ return o.removeEventListener(evtName,evtHandler,false);\r
+ } : function(o, evtName, evtHandler) {\r
+ return o.detachEvent('on'+evtName,evtHandler);\r
+ });\r
+\r
+ var classContains = function(o,cStr) {\r
+ return (typeof(o.className)!=='undefined'?o.className.match(new RegExp('(\s|^)'+cStr+'(\s|$)')):false);\r
+ };\r
+\r
+ var addClass = function(o,cStr) {\r
+ if (!o || !cStr || classContains(o,cStr)) {\r
+ return false;\r
+ }\r
+ o.className = (o.className?o.className+' ':'')+cStr;\r
+ };\r
+\r
+ var removeClass = function(o,cStr) {\r
+ if (!o || !cStr || classContains(o,cStr)) {\r
+ return false;\r
+ }\r
+ o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');\r
+ };\r
+\r
+/*\r
+ var isChildOfNode = function(o,sNodeName) {\r
+ if (!o || !o.parentNode) {\r
+ return false;\r
+ }\r
+ sNodeName = sNodeName.toLowerCase();\r
+ do {\r
+ o = o.parentNode;\r
+ } while (o && o.parentNode && o.nodeName.toLowerCase() !== sNodeName);\r
+ return (o.nodeName.toLowerCase() === sNodeName ? o : null);\r
+ };\r
+*/\r
+\r
+ return {\r
+ css: {\r
+ has: classContains,\r
+ add: addClass,\r
+ remove: removeClass\r
+ },\r
+/*\r
+ dom: {\r
+ isChildOfNode: this.isChildOfNode\r
+ },\r
+*/\r
+ events: {\r
+ add: addEventHandler,\r
+ remove: removeEventHandler\r
+ }\r
+ }\r
+\r
+}());\r
+\r
+function ControlHandler(tapeUIDOM, soundObject) {\r
+\r
+ var soundObject;\r
+\r
+ var css, dom, events, eventMap, soundOK;\r
+\r
+ // percentage to jump with each click of the rewind / fast-forward buttons\r
+ var rewind_ffwd_offset = 0.033;\r
+\r
+ dom = {\r
+ oControls: null,\r
+ play: null,\r
+ rew: null,\r
+ ffwd: null,\r
+ stop: null\r
+ };\r
+\r
+ events = {\r
+ mousedown: function(e) {\r
+ // need <a>\r
+ var target = e.target,\r
+ className = e.target.className;\r
+ if (soundOK && typeof eventMap[className] !== 'undefined') {\r
+ eventMap[className](e);\r
+ return events.stopEvent(e);\r
+ }\r
+ },\r
+ stopEvent: function(e) {\r
+ e.preventDefault();\r
+ return false;\r
+ },\r
+ click: function(e) {\r
+ // simple/dumb: just toggle the playstate of the tape.\r
+ if (ignoreNextClick) {\r
+ ignoreNextClick = false;\r
+ return events.stopEvent(e);\r
+ }\r
+ var target = e.target,\r
+ className = e.target.className;\r
+ if (typeof eventMap[className] == 'undefined') {\r
+ soundObject.togglePause();\r
+ } else {\r
+ return events.mousedown(e);\r
+ }\r
+ }\r
+ };\r
+\r
+ eventMap = {\r
+ 'play': function(e) {\r
+ soundObject.play();\r
+ },\r
+ 'rew': function() {\r
+ // rewind\r
+ var newPosition = Math.max(0, soundObject.position - soundObject.duration * rewind_ffwd_offset);\r
+ if (soundObject.duration) {\r
+ soundObject.setPosition(newPosition);\r
+ // if not playing, force update?\r
+ tapeUIs[0].setProgress(newPosition/soundObject.duration);\r
+ }\r
+ },\r
+ 'ffwd': function() {\r
+ // fast-forward\r
+ var newPosition;\r
+ if (soundObject.duration) {\r
+ newPosition = Math.min(soundObject.duration, soundObject.position + soundObject.duration * rewind_ffwd_offset);\r
+ soundObject.setPosition(newPosition);\r
+ }\r
+ },\r
+ 'stop': function() {\r
+ // equivalent to digital pause\r
+ soundObject.pause();\r
+ }\r
+ };\r
+\r
+ function addEvents() {\r
+ utils.events.add(dom.o, 'mousedown', events.mousedown);\r
+ utils.events.add(tapeUIDOM.node, 'click', events.click);\r
+ }\r
+\r
+ function init() {\r
+ soundOK = soundManager.ok();\r
+ dom.o = tapeUIDOM.node.querySelector('.controls');\r
+ dom.play = dom.o.querySelector('.play');\r
+ dom.rewind = dom.o.querySelector('.rew');\r
+ dom.ffwd = dom.o.querySelector('.ffwd');\r
+ dom.stop = dom.o.querySelector('.stop');\r
+ addEvents();\r
+ }\r
+\r
+ init();\r
+\r
+}\r
+\r
+function init() {\r
+\r
+ var hasCanvas = (typeof document.createElement('canvas').getContext !== 'undefined');\r
+\r
+ if (!hasCanvas) {\r
+ // assume a crap browser (e.g., IE 8.)\r
+ return false;\r
+ }\r
+\r
+ var tapes,\r
+ i, s;\r
+\r
+ dragHandler.init();\r
+\r
+ function genericStart() {\r
+ for (var i=tapeUIs.length; i--;) {\r
+ tapeUIs[i].start();\r
+ }\r
+ }\r
+\r
+ function genericStop() {\r
+ for (var i=tapeUIs.length; i--;) {\r
+ tapeUIs[i].stop();\r
+ }\r
+ }\r
+\r
+ if (soundManager.ok()) {\r
+\r
+ s = soundManager.createSound({\r
+ id: 'tapeSound',\r
+ url: 'http://freshly-ground.com/data/audio/sm2/Chill With Schill (Summer 2012 Session Excerpt).mp3',\r
+ multiShot: false,\r
+ whileplaying: function() {\r
+ for (var i=tapeUIs.length; i--;) {\r
+ // console.log(this.position, this.durationEstimate);\r
+ tapeUIs[i].setProgress(this.position/this.durationEstimate);\r
+ }\r
+ },\r
+ onplay: genericStart,\r
+ onfinish: genericStop,\r
+ onpause: genericStop,\r
+ onresume: genericStart\r
+ });\r
+\r
+ }\r
+\r
+ tapes = document.querySelectorAll('div.tape');\r
+\r
+ for (i=tapes.length; i--;) {\r
+ tapeUIs.push(new TapeUI({\r
+ node: tapes[i],\r
+ sound: s\r
+ }));\r
+ tapeUIs[tapeUIs.length-1].init();\r
+ }\r
+\r
+ resetTapeUIs();\r
+\r
+}\r
+\r
+function delayInit() {\r
+\r
+ var loader = document.getElementById('tape-loader');\r
+\r
+ if (loader) {\r
+ loader.className = 'visible';\r
+ }\r
+\r
+ window.setTimeout(function() {\r
+ init();\r
+ }, 20);\r
+}\r
+\r
+soundManager.setup({\r
+ url: '../../swf/',\r
+ flashVersion: 9,\r
+ useHighPerformance: true,\r
+ preferFlash: false,\r
+ html5PollingInterval: 50,\r
+ onready: delayInit,\r
+ ontimeout: delayInit\r
+});\r
+\r
+// interface\r
+window.tapeUIs = tapeUIs;\r
+\r
+}(window));
\ No newline at end of file
--- /dev/null
+/**\r
+ * Cassette Demo page JS - you don't need this part.\r
+ */\r
+\r
+(function() {\r
+\r
+function init() {\r
+\r
+ // Demo-specific things: background-switching, etc.\r
+\r
+ var bgIndex = 1,\r
+ backgrounds;\r
+\r
+ // note: remote servers will need to serve a CORS response header for cross-domain canvas access.\r
+ backgrounds = [\r
+ 'image/demo_backgrounds/sfatnight_1600.jpg',\r
+ 'http://freshly-ground.com/data/image/sm2/lake_1600.jpg',\r
+ 'http://freshly-ground.com/data/image/sm2/wall_of_hard_drives.jpg',\r
+ 'http://freshly-ground.com/data/image/sm2/attack_of_the_jellyfish.jpg',\r
+ 'http://freshly-ground.com/data/image/sm2/cassette_tape_lamp.jpg'\r
+ ];\r
+\r
+ document.getElementById('nextBackground').onclick = function(e) {\r
+\r
+ var i, j, refreshed,\r
+ loader = document.getElementById('tape-loader');\r
+\r
+ function refreshDone() {\r
+ // re-hide the loader\r
+ refreshed++;\r
+ if (refreshed == tapeUIs.length) {\r
+ if (loader) {\r
+ loader.className = 'hidden';\r
+ }\r
+ }\r
+ }\r
+\r
+ // hack: make the loader visible again\r
+ if (loader) {\r
+ loader.className = 'visible';\r
+ }\r
+\r
+ document.getElementsByTagName('html')[0].style.backgroundImage = 'url(' + backgrounds[bgIndex] + ')';\r
+\r
+ refreshed = 0;\r
+\r
+ for (i=0, j=tapeUIs.length; i<j; i++) {\r
+ tapeUIs[i].refreshBlurImage(refreshDone);\r
+ }\r
+\r
+ if (++bgIndex >= backgrounds.length) {\r
+ bgIndex = 0;\r
+ }\r
+\r
+ e.preventDefault();\r
+ return false;\r
+\r
+ }\r
+\r
+ // form helpers\r
+\r
+ var form = document.getElementById('tape-form'),\r
+ defaultValue,\r
+ input;\r
+\r
+ if (form) {\r
+\r
+ input = form.getElementsByTagName('input')[0];\r
+\r
+ function submitHandler(e) {\r
+\r
+ var inputURL = input.value,\r
+ s = soundManager.getSoundById('tapeSound'),\r
+ lastValue,\r
+ caughtSubmit;\r
+\r
+ // URL should at least have two slashes in it, to be considered valid.\r
+ if (s && inputURL.match(/\/\//) && s.url !== inputURL) {\r
+\r
+ s.load({\r
+ url: inputURL\r
+ }).play();\r
+\r
+ }\r
+\r
+ if (e) {\r
+ e.preventDefault();\r
+ }\r
+\r
+ // is the form focused? blur if so.\r
+ if (document.activeElement && document.activeElement == input) {\r
+ try {\r
+ caughtSubmit = true;\r
+ input.blur();\r
+ } catch(ee) {\r
+ // oh well\r
+ }\r
+ }\r
+\r
+ return false;\r
+\r
+ }\r
+\r
+ form.onsubmit = submitHandler;\r
+\r
+ // reset form on load\r
+ defaultValue = input.getAttribute('data-default-value');\r
+\r
+ input.value = defaultValue;\r
+\r
+ input.onfocus = function() {\r
+\r
+ caughtSubmit = false;\r
+\r
+ lastValue = this.value;\r
+\r
+ this.value = '';\r
+\r
+ }\r
+\r
+ input.onblur = function() {\r
+\r
+ if (!this.value) {\r
+\r
+ this.value = (lastValue || defaultValue);\r
+\r
+ }\r
+\r
+ if (!caughtSubmit) {\r
+ // user tabbed out, etc.? we may load a new URL now.\r
+ submitHandler();\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+}\r
+\r
+soundManager.setup({\r
+ onready: init,\r
+ ontimeout: init\r
+});\r
+\r
+}());\r
--- /dev/null
+/* XLSF 2007 */\r
+\r
+body {\r
+ font-family:"Helvetica Neue",helvetica,georgia,"times new roman","Arial Rounded MT Bold",helvetica,verdana,tahoma,arial,"sans serif";\r
+ font-size:75%;\r
+ color:#666;\r
+ *background:#333 url(image/bg-strip-dark.png) 0px 0px; /* IE */\r
+}\r
+\r
+#explosion-box {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:100%;\r
+ height:100%;\r
+ overflow:hidden;\r
+ background:#333 url(image/bg-strip-dark.png) 0px 0px;\r
+ background: -webkit-gradient(\r
+ linear,\r
+ left bottom,\r
+ left top,\r
+ color-stop(0, rgb(16,16,32)),\r
+ color-stop(1, rgb(32,132,202))\r
+ );\r
+ background: -moz-linear-gradient(\r
+ center bottom,\r
+ rgb(16,16,32) 0%,\r
+ rgb(32,132,202) 100%\r
+ );\r
+}\r
+\r
+#explosion-box-texture {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:100%;\r
+ height:100%;\r
+ background: transparent url(image/noise-pattern.png);\r
+ opacity: 0.035;\r
+}\r
+\r
+h1, h1 a {\r
+ color:#999;\r
+ text-decoration:none;\r
+}\r
+\r
+h1 {\r
+ color:#999;\r
+ margin-bottom:0;\r
+ margin-left:-5px;\r
+ margin-top:0;\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+}\r
+\r
+h1, h2, h3 {\r
+ clear:both;\r
+ float:left;\r
+ font-family:"Helvetica Neue",georgia,"times new roman","Arial Rounded MT Bold",helvetica,verdana,tahoma,arial,"sans serif";\r
+ font-size:3em;\r
+ font-size-adjust:none;\r
+ margin-bottom:0.25em;\r
+ padding-bottom:1px;\r
+}\r
+\r
+h1, h2 {\r
+ letter-spacing:-1px;\r
+ margin-bottom:0;\r
+ margin-left:-5px;\r
+ margin-top:0;\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+}\r
+\r
+a {\r
+ color:#6699cc;\r
+ padding:0px 2px;\r
+ text-decoration:none;\r
+}\r
+\r
+a:hover {\r
+ background:#6699cc;\r
+ color:#fff;\r
+}\r
+\r
+#lights {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:100%;\r
+ height:100%;\r
+ overflow:hidden;\r
+ z-index:2;\r
+ pointer-events: none; /* https://developer.mozilla.org/en/CSS/pointer-events */\r
+}\r
+\r
+.xlsf-light {\r
+ position:absolute;\r
+ z-index:2;\r
+}\r
+\r
+.xlsf-angled {\r
+ -webkit-transform: rotate(45deg);\r
+ -moz-transform:rotate(45deg);\r
+ -o-transform:rotate(45deg);\r
+ transform:rotate(45deg);\r
+}\r
+\r
+body.fast .xlsf-light {\r
+ opacity:0.9;\r
+}\r
+\r
+.xlsf-fragment,\r
+.xlsf-fragment-box {\r
+ pointer-events: none; /* https://developer.mozilla.org/en/CSS/pointer-events */\r
+}\r
+\r
+.xlsf-fragment {\r
+ position:absolute;\r
+ background:transparent url(image/bulbs-50x50-fragments.png) no-repeat 0px 0px;\r
+ width:50px;\r
+ height:50px;\r
+}\r
+\r
+.xlsf-fragment-box {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:50px;\r
+ height:50px;\r
+ *width:100%;\r
+ *height:100%;\r
+ z-index:2;\r
+ display:none;\r
+}\r
+\r
+/*\r
+.xlsf-light.bottom {\r
+ height:49px;\r
+ border-bottom:1px solid #006600;\r
+}\r
+\r
+.xlsf-light.top {\r
+ height:49px;\r
+ border-top:1px solid #009900;\r
+}\r
+*/\r
--- /dev/null
+/**\r
+ * Christmas Light Smashfest\r
+ *\r
+ * Adapted from XLSF 2007 as originally used on http://schillmania.com/?theme=2007&christmas=1\r
+ * Requires YUI3 library - http://yuilibrary.com/projects/yui3/\r
+ */\r
+\r
+(function() {\r
+\r
+ var YUI_SEED_URL = 'http://yui.yahooapis.com/3.8.0/build/yui/yui-min.js';\r
+\r
+ function initChristmasLights() {\r
+\r
+ YUI().use('anim', function(Y) {\r
+\r
+ function XLSF(oTarget) {\r
+ var writeDebug = soundManager._wD;\r
+ writeDebug('XLSF()');\r
+ var IS_MOON_COMPUTER = false;\r
+ var isIE = navigator.userAgent.match(/msie/i);\r
+ var isTouchDevice = navigator.userAgent.match(/ipad|ipod|iphone|android/i);\r
+ var self = this;\r
+ var xlsf = self;\r
+ var useAngle = window.location.href.match(/angle/i);\r
+ var useFollow = window.location.toString().match(/follow/i);\r
+ var classBase = 'xlsf-light' + (useAngle ? ' xlsf-angled' : '');\r
+ var animDuration = 1;\r
+ var lastMouseX = 0;\r
+ var lastMouseY = 0;\r
+ var mmhTimer = null;\r
+ var activeLights = [];\r
+ var testDiv = document.createElement('div');\r
+ var offset = 0;\r
+ var transforms = {\r
+ ie: (typeof testDiv.style['-ms-transform'] !== 'undefined' ? '-ms-transform' : null),\r
+ moz: (typeof testDiv.style.MozTransform !== 'undefined' ? 'MozTransform' : null),\r
+ opera: (typeof testDiv.style['OTransform'] !== 'undefined' ? 'OTransform' : null),\r
+ webkit: (typeof testDiv.style.webkitTransform !== 'undefined' ? 'webkitTransform' : null),\r
+ prop: null\r
+ }\r
+ transforms.prop = (transforms.moz || transforms.webkit || transforms.ie || transforms.opera);\r
+ this.oFrag = document.createDocumentFragment();\r
+ this.oExplosionTarget = document.getElementById('explosion-box');\r
+ if (!this.oExplosionTarget) {\r
+ this.oExplosionTarget = document.createElement('div');\r
+ this.oExplosionTarget.id = 'explosion-box';\r
+ document.body.appendChild(this.oExplosionTarget);\r
+ }\r
+ this.oTarget = (oTarget ? oTarget : document.documentElement);\r
+ this.oExplosionBox = document.createElement('div');\r
+ this.oExplosionBox.className = 'xlsf-fragment-box';\r
+ this.oExplosionFrag = document.createElement('div');\r
+ this.oExplosionFrag.className = 'xlsf-fragment';\r
+ this.lights = [];\r
+ this.lightClasses = {\r
+ pico: 32,\r
+ tiny: 50,\r
+ small: 64,\r
+ medium: 72,\r
+ large: 96\r
+ }\r
+\r
+ this.lightClass = (window.XLSF_LIGHT_CLASS || 'tiny'); // kind of light to show (32px to 96px square)\r
+ if (window.location.href.match(/size=/i)) {\r
+ this.lightClass = window.location.href.substr(window.location.href.indexOf('size=') + 5);\r
+ if (this.lightClass.indexOf('#') !== -1) {\r
+ this.lightClass = this.lightClass.substr(0, this.lightClass.indexOf('#'));\r
+ }\r
+ }\r
+\r
+ this.lightXY = this.lightClasses[this.lightClass]; // shortcut to w/h\r
+\r
+ function rnd(n) {\r
+ return parseInt(Math.random() * n);\r
+ }\r
+\r
+ function plusMinus(n) {\r
+ return (parseInt(rnd(2), 10) === 1 ? n * -1 : n);\r
+ }\r
+\r
+ this.lightGroups = {\r
+ left: [],\r
+ top: [],\r
+ right: [],\r
+ bottom: []\r
+ }\r
+ this.lightSmashCounter = 0;\r
+ this.lightIndex = 0;\r
+ this.lightInterval = 500;\r
+ this.timer = null;\r
+ this.bgBaseX = 0;\r
+ this.bgBaseY = 0;\r
+ this.soundIDs = 0;\r
+ this.soundPan = {\r
+ panValue: 75,\r
+ left: 0,\r
+ mid: 481,\r
+ right: 962\r
+ }\r
+\r
+ this.initSounds = function() {\r
+ if (!soundManager.supported()) {\r
+ return false;\r
+ }\r
+ for (var i = 0; i < 6; i++) {\r
+ soundManager.createSound({\r
+ id: 'smash' + i,\r
+ url: (window.XLSF_URL_BASE || '') + 'sound/glass' + i + '.mp3',\r
+ autoLoad: true,\r
+ multiShot: true,\r
+ volume: 25\r
+ });\r
+ }\r
+ self.initSounds = function() {} // safety net\r
+ }\r
+\r
+ this.appendLights = function() {\r
+ writeDebug('xlsf.appendLights()');\r
+ self.oTarget.appendChild(self.oFrag);\r
+ // self.oFrag = document.createDocumentFragment();\r
+ }\r
+\r
+ function ExplosionFragment(nType, sClass, x, y, vX, vY) {\r
+ var self = this;\r
+ this.o = xlsf.oExplosionFrag.cloneNode(true);\r
+ this.nType = nType;\r
+ this.sClass = sClass;\r
+ this.x = x;\r
+ this.y = y;\r
+ this.w = 50;\r
+ this.h = 50;\r
+ this.bgBaseX = 0;\r
+ this.bgBaseY = this.h * this.nType;\r
+ this.vX = vX * (1.5 + Math.random());\r
+ this.vY = vY * (1.5 + Math.random());\r
+ this.oA = null;\r
+ this.oA2 = null;\r
+ this.burstPhase = 1; // starting background offset point\r
+ this.burstPhases = 4; // 1+offset (ignore large size)\r
+ this.animDuration = 1; // how long the animations run for\r
+ this.o.style.backgroundPosition = ((this.w * -this.burstPhase) + 'px ' + (this.h * -nType) + 'px');\r
+\r
+ // boundary checks\r
+ if (self.sClass == 'left') {\r
+ this.vX = Math.abs(this.vX);\r
+ } else if (self.sClass == 'right') {\r
+ this.vX = Math.abs(this.vX) * -1;\r
+ }\r
+\r
+ this.burstTween = function() {\r
+ // determine frame to show based on animation's progress vs. its total time (and don't allow overflow, in the event animation runs long.)\r
+ var phase = 1 + (Math.floor(Math.min(self.animDuration, (this.get('elapsedTime') / 1000)) * self.burstPhases));\r
+ if (phase != self.burstPhase) {\r
+ self.burstPhase = phase;\r
+ self.o.style.backgroundPosition = ((self.w * -self.burstPhase) + 'px ' + (self.h * -nType) + 'px');\r
+ }\r
+ }\r
+\r
+\r
+ this.burst = function() {\r
+ self.oA = new Y.Anim({\r
+ node: Y.one(self.o),\r
+ to: {\r
+ marginLeft: (self.vX * (5 + Math.random() * 10)),\r
+ marginTop: (self.vY * (5 + Math.random() * 10))\r
+ },\r
+ duration: animDuration,\r
+ easing: Y.Easing.easeOutStrong\r
+ });\r
+ self.oA.on('tween', self.burstTween);\r
+ self.oA.on('end', self.hide);\r
+ self.oA.run();\r
+ }\r
+\r
+ this.hide = function() {\r
+ if (!isIE) self.o.style.opacity = 0;\r
+ }\r
+\r
+ this.reset = function() {\r
+ self.o.style.left = '0px';\r
+ self.o.style.top = '0px';\r
+ self.o.style.marginLeft = '0px';\r
+ self.o.style.marginTop = '0px';\r
+ if (!isIE) self.o.style.opacity = 1;\r
+ }\r
+\r
+ this.animate = function() {\r
+ self.reset();\r
+ self.burst();\r
+ }\r
+\r
+ }\r
+\r
+ function Explosion(nType, sClass, x, y) {\r
+ var oParent = this;\r
+ var self = this;\r
+ this.o = null;\r
+ this.nType = nType;\r
+ this.sClass = sClass;\r
+ this.x = x;\r
+ this.y = y;\r
+ this.boxVX = 0;\r
+ this.boxVY = 0;\r
+ this.o = xlsf.oExplosionBox.cloneNode(true);\r
+ this.o.style.left = x + 'px';\r
+ this.o.style.top = y + 'px';\r
+ // this.oFrag = document.createDocumentFragment();\r
+ this.fragments = [];\r
+\r
+ var mX = x;\r
+ var mY = y;\r
+ var type = typeMap[nType + sClass];\r
+ var scale = 5 + Math.random() * 10;\r
+ var shift = 2;\r
+\r
+ this.fragments.push(new ExplosionFragment(type, sClass, mX, mY, -rnd(scale), -rnd(scale)));\r
+ this.fragments.push(new ExplosionFragment(type, sClass, mX, mY, plusMinus(rnd(shift)), -rnd(scale)));\r
+ this.fragments.push(new ExplosionFragment(type, sClass, mX, mY, rnd(scale), -rnd(scale)));\r
+\r
+ this.fragments.push(new ExplosionFragment(type, sClass, mX, mY, -rnd(scale), plusMinus(rnd(shift))));\r
+ this.fragments.push(new ExplosionFragment(type, sClass, mX, mY, plusMinus(rnd(shift)), plusMinus(rnd(shift))));\r
+ this.fragments.push(new ExplosionFragment(type, sClass, mX, mY, rnd(scale), plusMinus(rnd(shift))));\r
+\r
+ this.fragments.push(new ExplosionFragment(type, sClass, mX, mY, rnd(scale), -rnd(scale)));\r
+ this.fragments.push(new ExplosionFragment(type, sClass, mX, mY, rnd(scale), plusMinus(rnd(shift))));\r
+ this.fragments.push(new ExplosionFragment(type, sClass, mX, mY, rnd(scale), rnd(scale)));\r
+\r
+ this.init = function() {\r
+ for (var i = self.fragments.length; i--;) {\r
+ self.o.appendChild(self.fragments[i].o);\r
+ }\r
+ if (!IS_MOON_COMPUTER) {\r
+ // faster rendering, particles get cropped\r
+ xlsf.oExplosionTarget.appendChild(self.o);\r
+ } else {\r
+ // slower rendering, can overlay body\r
+ xlsf.oExplosionTarget.appendChild(self.o);\r
+ }\r
+ }\r
+\r
+ this.reset = function() {\r
+ // clean-up\r
+ // self.o.parentNode.removeChild(self.o);\r
+ self.o.style.display = 'none';\r
+ self.o.style.marginLeft = '0px';\r
+ self.o.style.marginTop = '0px';\r
+ self.o.style.left = self.x + 'px';\r
+ self.o.style.top = self.y + 'px';\r
+ if (!isIE) self.o.style.opacity = 1;\r
+ for (var i = self.fragments.length; i--;) {\r
+ self.fragments[i].reset();\r
+ }\r
+ }\r
+\r
+ this.trigger = function(boxVX, boxVY) {\r
+ self.o.style.display = 'block';\r
+ self.boxVX = boxVX;\r
+ self.boxVY = boxVY;\r
+ // boundary checks\r
+ if (self.sClass == 'right') {\r
+ self.boxVX = Math.abs(self.boxVX) * -1;\r
+ } else if (self.sClass == 'left') {\r
+ self.boxVX = Math.abs(self.boxVX);\r
+ }\r
+ for (var i = self.fragments.length; i--;) {\r
+ self.fragments[i].animate();\r
+ }\r
+ if (!isIE && (IS_MOON_COMPUTER)) {\r
+ var oAExplode = new Y.Anim({\r
+ node: Y.one(o),\r
+ to: {\r
+ marginLeft: 100 * self.boxVX,\r
+ marginTop: 150 * self.boxVY,\r
+ opacity: 0.01\r
+ },\r
+ duration: animDuration,\r
+ easing: Y.Easing.easeInStrong\r
+ });\r
+ } else {\r
+ // even IE 7 sucks w/alpha-transparent PNG + CSS opacity. Boourns.\r
+ var oAExplode = new Y.Anim({\r
+ node: Y.one(self.o),\r
+ to: {\r
+ marginLeft: 100 * self.boxVX,\r
+ marginTop: 150 * self.boxVY\r
+ },\r
+ duration: animDuration,\r
+ easing: Y.Easing.easeInStrong\r
+ });\r
+ }\r
+ oAExplode.on('end', self.reset);\r
+ oAExplode.run();\r
+ // setTimeout(self.reset,animDuration*1000*1.5);\r
+ }\r
+\r
+ this.init();\r
+\r
+ }\r
+\r
+ function Light(sSizeClass, sClass, nType, x, y, row, col) {\r
+ var self = this;\r
+ this.o = document.createElement('div');\r
+ this.sClass = sClass;\r
+ this.sSizeClass = sSizeClass;\r
+ this.nType = (nType || 0);\r
+ this.useY = (sClass == 'left' || sClass == 'right');\r
+ this.state = null;\r
+ this.broken = 0;\r
+ this.w = xlsf.lightClasses[sSizeClass];\r
+ this.h = xlsf.lightClasses[sSizeClass];\r
+ this.x = x;\r
+ this.y = y;\r
+ this.row = row;\r
+ this.col = col;\r
+ this.bg = (window.XLSF_URL_BASE || '') + 'image/bulbs-' + this.w + 'x' + this.h + '-' + this.sClass + '.png';\r
+ this.o.style.width = this.w + 'px';\r
+ this.o.style.height = this.h + 'px';\r
+ this.o.style.background = 'url(' + this.bg + ') no-repeat 0px 0px';\r
+ this.bgBaseX = (self.useY ? -self.w * this.nType : 0);\r
+ this.bgBaseY = (!self.useY ? -self.h * this.nType : 0);\r
+ this.glassType = parseInt(Math.random() * 6);\r
+ // this.bonusSounds = ['griffin-laugh','bblaff','bblaff2'];\r
+ // this.bonusSound = null;\r
+ this.oExplosion = null;\r
+ this.soundID = 'smash' + this.glassType;\r
+ var panValue = xlsf.soundPan.panValue; // eg. +/- 80%\r
+ this.pan = parseInt(this.x <= xlsf.soundPan.mid ? -panValue + ((this.x / xlsf.soundPan.mid) * panValue) : (this.x - xlsf.soundPan.mid) / (xlsf.soundPan.right - xlsf.soundPan.mid) * panValue);\r
+\r
+ this.setBGPos = function(x, y) {\r
+ self.o.style.backgroundPosition = ((self.bgBaseX + x) + 'px ' + (self.bgBaseY + y) + 'px');\r
+ }\r
+\r
+ this.setLight = function(bOn) {\r
+ if (self.broken || self.state == bOn) return false;\r
+ if (!self.w || !self.h) self.getDimensions();\r
+ self.state = bOn;\r
+ if (self.useY) {\r
+ self.setBGPos(0, -this.h * (bOn ? 0 : 1));\r
+ } else {\r
+ self.setBGPos(-this.w * (bOn ? 0 : 1), 0);\r
+ }\r
+ }\r
+\r
+ this.getDimensions = function() {\r
+ self.w = self.o.offsetWidth;\r
+ self.h = self.o.offsetHeight;\r
+ self.bgBaseX = (self.useY ? -self.w * self.nType : 0);\r
+ self.bgBaseY = (!self.useY ? -self.h * self.nType : 0);\r
+ }\r
+\r
+ this.on = function() {\r
+ self.setLight(1);\r
+ }\r
+\r
+ this.off = function() {\r
+ self.setLight(0);\r
+ }\r
+\r
+ this.flickr = function() {\r
+ self.setLight(Math.random() >= 0.5 ? 1 : 0);\r
+ }\r
+\r
+ this.toggle = function() {\r
+ self.setLight(!self.state ? 1 : 0);\r
+ }\r
+\r
+ this.explode = function(e) {\r
+ self.oExplosion.trigger(0, 1); // boooom!\r
+ }\r
+\r
+ this.smash = function(e) {\r
+ if (self.broken) return false;\r
+ self.broken = true;\r
+ if (soundManager && soundManager.supported()) {\r
+ soundManager.play(self.soundID, {\r
+ pan: self.pan\r
+ });\r
+ // soundManager.sounds[self.soundID].play({pan:self.pan});\r
+ // if (self.bonusSound != null) window.setTimeout(self.smashBonus,1000);\r
+ }\r
+ self.explode(e);\r
+ var rndFrame = 2; // +parseInt(Math.random()*3);\r
+ if (self.useY) {\r
+ self.setBGPos(0, self.h * -rndFrame);\r
+ } else {\r
+ self.setBGPos(self.w * -rndFrame, 0);\r
+ }\r
+ if (!useFollow && !useAngle && transforms.prop) {\r
+ self.o.style[transforms.prop] = 'rotate(' + Math.random() * plusMinus(20) + 'deg)';\r
+ }\r
+ xlsf.lightSmashCounter++;\r
+ for (var i = activeLights.length; i--;) {\r
+ // find this in the active array, and take it out\r
+ if (activeLights[i] === self) {\r
+ activeLights.splice(i, 1);\r
+ break;\r
+ }\r
+ }\r
+ // xlsf.doNukeCheck();\r
+ // window.setTimeout(self.reset,3000); // respawn\r
+ }\r
+\r
+ this.smashBonus = function() {\r
+ // soundManager.play(self.bonusSounds[self.bonusSound],urlBase+'sound/'+self.bonusSounds[self.bonusSound]+'.mp3');\r
+ }\r
+\r
+ this.reset = function() {\r
+ if (!self.broken) return false;\r
+ self.broken = false;\r
+ self.state = null;\r
+ xlsf.lightSmashCounter--;\r
+ // self.oExplosion.reset(); // may not be necessary\r
+ self.flickr();\r
+ }\r
+\r
+ this.init = function() {\r
+ self.o.className = classBase + ' ' + this.sizeClass + ' ' + this.sClass;\r
+ self.o.style.left = self.x + 'px';\r
+ self.o.style.top = self.y + 'px';\r
+ self.o.style.width = self.w + 'px';\r
+ self.o.style.height = self.h + 'px';\r
+ self.flickr();\r
+ xlsf.oFrag.appendChild(self.o);\r
+ self.oExplosion = new Explosion(self.nType, self.sClass, self.x, self.y);\r
+ }\r
+\r
+ this.init();\r
+\r
+ } // Light()\r
+ this.createLight = function(sClass, nType, x, y, row, col) {\r
+ var oLight = new Light(self.lightClass, sClass, nType, x, y, row, col);\r
+ activeLights.push(oLight);\r
+ self.lightGroups[sClass].push(oLight);\r
+ self.lights.push(oLight);\r
+ return oLight;\r
+ }\r
+\r
+ this.rotateLights = function() {\r
+ self.lights[self.lightIndex == self.lights.length ? self.lights.length - 1 : self.lightIndex].off();\r
+ self.lightIndex++;\r
+ if (self.lightIndex == self.lights.length) {\r
+ self.lightIndex = 0;\r
+ }\r
+ self.lights[self.lightIndex].on();\r
+ }\r
+\r
+ this.randomLights = function() {\r
+ self.lights[parseInt(Math.random() * self.lights.length)].toggle();\r
+ }\r
+\r
+ this.destroyLights = function() {\r
+ // reset counter\r
+ self.lightSmashCounter = 0;\r
+ self.startSequence(Math.random() > 0.75 ? self.destroyLight : self.destroyRandom, 33);\r
+ }\r
+\r
+ this.destroyRandom = function() {\r
+ for (var i = 2; i--;) {\r
+ if (activeLights.length) {\r
+ activeLights[parseInt(Math.random() * activeLights.length)].smash();\r
+ }\r
+ }\r
+ }\r
+\r
+ this.destroyLight = function() {\r
+ var groupSize = 2; // # to smash at a time\r
+ if (self.lightSmashCounter < self.lights.length) {\r
+ var limit = Math.min(self.lightSmashCounter + groupSize, self.lights.length);\r
+ var reverseLimit = Math.max(0, self.lights.length - self.lightSmashCounter - groupSize);\r
+ for (var i = self.lightSmashCounter; i < limit; i++) {\r
+ if (self.lights[self.lightSmashCounter]) {\r
+ self.lights[self.lightSmashCounter].smash();\r
+ }\r
+ self.lights[self.lights.length - self.lightSmashCounter].smash();\r
+ }\r
+ } else {\r
+ self.stopSequence();\r
+ }\r
+ }\r
+\r
+ this.uberSmash = function() {\r
+ // make everything explode - including your CPU.\r
+ self.stopSequence();\r
+ var ebCN = Y.D.getElementsByClassName;\r
+ /*\r
+ window.setTimeout(function(){self.smashGroup(self.lightGroups.left)},500);\r
+ window.setTimeout(function(){self.smashGroup(self.lightGroups.right)},2000);\r
+ window.setTimeout(function(){self.smashGroup(self.lightGroups.bottom)},4000);\r
+ window.setTimeout(function(){self.smashGroup(self.lightGroups.top)},6000); \r
+ */\r
+ window.setTimeout(function() {\r
+ self.smashGroup(self.lightGroups.bottom)\r
+ }, 500);\r
+ window.setTimeout(function() {\r
+ self.smashGroup(self.lightGroups.top)\r
+ }, 3500);\r
+\r
+ }\r
+\r
+ this.smashGroup = function(oGroup) {\r
+ for (var i = oGroup.length; i--;) {\r
+ oGroup[i].smash();\r
+ }\r
+ }\r
+\r
+ this.startSequence = function(fSequence, nInterval) {\r
+ if (self.timer) self.stopSequence();\r
+ self.timer = window.setInterval(fSequence, (typeof nInterval != 'undefined' ? nInterval : self.lightInterval));\r
+ }\r
+\r
+ this.stopSequence = function() {\r
+ if (self.timer) {\r
+ window.clearInterval(self.timer);\r
+ self.timer = null;\r
+ }\r
+ }\r
+\r
+ var typeMaps = {\r
+ 'tiny': {\r
+ '0bottom': 0,\r
+ '0top': 3,\r
+ '1bottom': 1,\r
+ '1top': 2,\r
+ '2bottom': 2,\r
+ '2top': 1,\r
+ '3bottom': 3,\r
+ '3top': 0\r
+ },\r
+ 'other': {\r
+ '0bottom': 3,\r
+ '0top': 3,\r
+ '1bottom': 2,\r
+ '1top': 2,\r
+ '2bottom': 1,\r
+ '2top': 1,\r
+ '3bottom': 0,\r
+ '3top': 0\r
+ }\r
+ }\r
+\r
+ var typeMap = typeMaps[(this.lightClass === 'tiny' ? 'tiny' : 'other')];\r
+\r
+ var i = 0;\r
+\r
+ /*\r
+ for (i=0; i<6; i++) {\r
+ this.createLight('left',parseInt(Math.random()*4),-2,50+i*(self.lightXY*0.7));\r
+ this.createLight('right',parseInt(Math.random()*4),962,50+i*(self.lightXY*0.7));\r
+ }\r
+\r
+ for (i=0; i<27; i++) {\r
+ this.createLight('top',parseInt(Math.random()*4),20+i*(self.lightXY*0.7),23);\r
+ this.createLight('bottom',parseInt(Math.random()*4),20+i*(self.lightXY*0.7),253);\r
+ }\r
+ */\r
+\r
+ var j = 0;\r
+\r
+ if (window.innerWidth || window.innerHeight) {\r
+ var screenX = window.innerWidth; // -(!isIE?24:2);\r
+ var screenY = window.innerHeight;\r
+ } else {\r
+ var screenX = (document.documentElement.clientWidth || document.body.clientWidth || document.body.scrollWidth); // -(!isIE?8:0);\r
+ var screenY = (document.documentElement.clientHeight || document.body.clientHeight || document.body.scrollHeight);\r
+ }\r
+\r
+ // hack for SM2 homepage\r
+ if (document.body && document.body.className && document.body.className.match(/home/i)) {\r
+\r
+ _id('lights').style.display = 'block';\r
+\r
+ // start lights to the right of <h1>\r
+ // offset = parseInt(document.getElementsByTagName('h1')[0].offsetWidth)+16;\r
+ var jMax = Math.floor((screenX - offset - 16) / self.lightXY);\r
+ var iMax = Math.floor((screenY - offset - 16) / self.lightXY);\r
+\r
+ for (j = 0; j < jMax; j++) {\r
+ this.createLight('top', j % 3, offset + j * self.lightXY, 0);\r
+ // this.createLight('bottom',j%3,offset+j*self.lightXY,screenY-offset-offset+1);\r
+ }\r
+\r
+ if (typeof isFun != 'undefined') {\r
+ for (i = 0; i < iMax; i++) {\r
+ this.createLight('left', i % 3, 0, offset + i * self.lightXY);\r
+ // this.createLight('right',i%3,screenX-offset-offset,offset+i*self.lightXY);\r
+ }\r
+ }\r
+\r
+\r
+ } else {\r
+\r
+ var jMax = Math.floor((screenX) / self.lightXY);\r
+ var iMax = Math.floor((screenY - 12) / self.lightXY);\r
+\r
+ for (i = 0; i < iMax; i++) {\r
+ for (j = 0; j < jMax; j++) {\r
+ this.createLight((i + 1) % 2 == 0 ? 'bottom' : 'top', i % 4, j * self.lightXY, i * self.lightXY, j, i);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ /*\r
+ var bsCounter = 0;\r
+ for (i=0; i<8; i++) {\r
+ // plant a few random seeds.. er, sounds.\r
+ self.lights[parseInt(Math.random()*self.lights.length)].bonusSound = bsCounter++;\r
+ if (bsCounter>2) bsCounter = 0; // hack - loop through sounds\r
+ }\r
+ */\r
+\r
+ this.appendLights();\r
+\r
+ function followMouseMove(e) {\r
+ if (!self.lights.length) {\r
+ return false;\r
+ }\r
+ var x = lastMouseX;\r
+ var y = lastMouseY;\r
+ var x2 = null;\r
+ var y2 = null;\r
+ var angle = 0;\r
+ var light = null;\r
+ for (var i = self.lights.length; i--;) {\r
+ light = self.lights[i];\r
+ if (light && !light.broken) {\r
+ x2 = light.x;\r
+ y2 = light.y;\r
+ angle = Math.atan2((y - y2), (x - x2)) * (180 / Math.PI);\r
+ if (light.col % 2 === 0) {\r
+ angle += (270 * 180 / Math.PI);\r
+ }\r
+ if (transforms.prop) {\r
+ light.o.style[transforms.prop] = 'rotate(' + angle + 'deg)';\r
+ }\r
+ }\r
+ }\r
+ mmhTimer = null;\r
+ }\r
+\r
+ function mouseOrTouchMove(e) {\r
+ // coordinate -> row/col check, smashy smash\r
+ var x, y, lightIndex;\r
+ if (e.targetTouches) {\r
+ if (e.targetTouches.length === 1) {\r
+ x = e.targetTouches[0].clientX - offset;\r
+ y = e.targetTouches[0].clientY;\r
+ }\r
+ } else {\r
+ x = e.clientX - offset;\r
+ y = e.clientY;\r
+ }\r
+ if (x < 0) {\r
+ // ignore off-screen values.\r
+ return;\r
+ }\r
+ lightCol = Math.floor((x / (self.lightClasses[self.lightClass] * jMax) * jMax)), lightRow = Math.floor((y / (self.lightClasses[self.lightClass] * iMax) * iMax))\r
+ lightIndex = (jMax * lightRow) + lightCol;\r
+ if (self.lights[lightIndex]) {\r
+ self.lights[lightIndex].smash();\r
+ }\r
+ if (useFollow) {\r
+ lastMouseX = x;\r
+ lastMouseY = y;\r
+ if (!mmhTimer) {\r
+ mmhTimer = window.setTimeout(followMouseMove, 33); // try to be nice and throttle this call, which may be expensive\r
+ }\r
+ }\r
+ }\r
+\r
+ if (isTouchDevice) {\r
+\r
+ document.addEventListener('touchstart', function(e) {\r
+\r
+ // ignore pinch-to-zoom, links and so forth.\r
+\r
+ if (e.touches && e.touches.length === 1 && e.target && e.target.nodeName !== 'A') {\r
+\r
+ document.addEventListener('touchmove', mouseOrTouchMove, false);\r
+ document.addEventListener('touchend', function(e) {\r
+ document.removeEventListener('touchMove', mouseOrTouchMove);\r
+ });\r
+\r
+ mouseOrTouchMove(e); // initial touch might be a smashy one, too\r
+ e.preventDefault();\r
+ return false;\r
+\r
+ }\r
+\r
+ }, false);\r
+\r
+ } else {\r
+\r
+ // generic event handler\r
+\r
+ if (document.addEventListener) {\r
+ document.addEventListener('mousemove', mouseOrTouchMove, false);\r
+ } else if (document.attachEvent) {\r
+ document.attachEvent('onmousemove', mouseOrTouchMove);\r
+ }\r
+\r
+ }\r
+\r
+ this.startSequence(self.randomLights);\r
+\r
+ } // --- XLSF2007()\r
+\r
+ var xlsf = null;\r
+\r
+ function smashInit() {\r
+ var loading = document.getElementById('loading');\r
+ xlsf = new XLSF(document.getElementById('lights'));\r
+ window.xlsf = xlsf; // expose to global\r
+ xlsf.initSounds();\r
+ if (loading) {\r
+ loading.style.display = 'none';\r
+ }\r
+ }\r
+\r
+ window.smashInit = smashInit;\r
+\r
+ soundManager.setup({\r
+ url: '../../swf/',\r
+ // preferFlash: true,\r
+ flashVersion: 9,\r
+ useHighPerformance: true,\r
+ wmode: 'transparent',\r
+ debugMode: false,\r
+ onready: smashInit,\r
+ ontimeout: smashInit\r
+ });\r
+\r
+ });\r
+\r
+ }\r
+\r
+ (function() {\r
+\r
+ // script loader helper for YUI library\r
+ // http://yui.yahooapis.com/3.4.1/build/yui/yui-min.js\r
+\r
+ function loadScript(sURL, onLoad) {\r
+ try {\r
+ var loadScriptHandler = function() {\r
+ var rs = this.readyState;\r
+ if (rs == 'loaded' || rs == 'complete') {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ if (onLoad) {\r
+ window.setTimeout(onLoad, 20);\r
+ }\r
+ }\r
+ }\r
+ function scriptOnload() {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ window.setTimeout(onLoad, 20);\r
+ }\r
+ var oS = document.createElement('script');\r
+ oS.type = 'text/javascript';\r
+ oS.setAttribute('async', true);\r
+ if (onLoad) {\r
+ oS.onreadystatechange = loadScriptHandler;\r
+ oS.onload = scriptOnload;\r
+ }\r
+ oS.src = sURL;\r
+ document.getElementsByTagName('head')[0].appendChild(oS);\r
+ } catch (e) {\r
+ // oh well\r
+ }\r
+ }\r
+\r
+ if (typeof window.YUI === 'undefined') {\r
+\r
+ loadScript(YUI_SEED_URL, function() {\r
+\r
+ initChristmasLights();\r
+\r
+ });\r
+\r
+ }\r
+\r
+ }());\r
+\r
+}());
\ No newline at end of file
--- /dev/null
+<html>\r
+<head>\r
+<title>Smashable Christmas Lights</title>
+<meta name="robots" content="noindex" />\r
+<link rel="stylesheet" media="screen" href="christmaslights.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="christmaslights.js"></script>\r
+</head>\r
+\r
+<body>\r
+\r
+<div>\r
+\r
+ <div id="loading">\r
+ <h1>Christmas Light Smashfest 2008: Prototype</h1>\r
+ <h2>Rendering...</h2>\r
+ </div>\r
+\r
+ <div id="lights">\r
+ <div id="explosion-box-texture"></div>\r
+ <!-- lights go here -->\r
+ </div>\r
+\r
+ <div style="position:absolute;bottom:5px;left:8px;z-index:10" class="allow-touch">\r
+ <a href="?size=pico">pico</a> | <a href="?size=tiny">tiny</a> | <a href="?size=small">small</a> | <a href="?size=medium">medium</a> | <a href="?size=large">large</a> <span style="*display:none">| <a href="#angle=1" onclick="window.location.href=this.href;window.location.reload()">+angle</a> | <a href="#follow=1" onclick="window.location.href=this.href;window.location.reload()">+follow</a></span> / <a href="#" onclick="xlsf.destroyLights()">AutoSmash!</a>\r
+ </div>\r
+\r
+ <div style="position:absolute;bottom:5px;right:8px;z-index:10" class="allow-touch">\r
+ a goofy <a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2</a> experiment.\r
+ </div>\r
+\r
+</div>\r
+\r
+\r
+\r
+</body>\r
+</html>
--- /dev/null
+#soundmanager-debug {\r
+ position:fixed;\r
+ _position:absolute; /* IE <7 */\r
+ bottom:1em;\r
+ right:1em;\r
+ width:38em;\r
+ height:30em;\r
+ overflow:auto;\r
+ padding:0px;\r
+ margin:1em;\r
+ font-family:monaco,"VT-100","lucida console",courier,system;\r
+ opacity:0.9;\r
+ color:#333;\r
+ border:1px solid #ccddee;\r
+ border-radius:3px;\r
+ background:#f3f9ff;\r
+}\r
+\r
+#soundmanager-debug div {\r
+ font-size:x-small;\r
+ padding:0.2em;\r
+ margin:0px;\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Flash blocker handling - basic example</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Demo of SoundManager 2 handling flashblock / "click to flash" blockers gracefully" />\r
+<meta name="keywords" content="javascript sound, javascript audio, DHTML sound, flashblock, flash blocker, handling flashblock, click to flash, click2flash" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />\r
+\r
+<!-- actual flashblock demo stuff, this is for you -->\r
+<link rel="stylesheet" type="text/css" href="flashblock.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ // enable flash block handling\r
+ useFlashBlock: true,\r
+ // custom demo options, not for your needs\r
+ debugMode: true,\r
+ url: '../../swf/'\r
+});\r
+</script>\r
+</head>\r
+<body>\r
+\r
+<div>\r
+ \r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2</a>: Flashblock / "click to flash" handling: Basic Demo</h1>\r
+\r
+ <div id="sm2-container">\r
+ <!-- flash movie will be placed here -->\r
+ </div>\r
+\r
+ <p>See <a href="flashblock.css">flashblock.css</a> as a template for making your own SM2 + flash block implementations.</p>\r
+\r
+</div>\r
--- /dev/null
+/**\r
+ * SoundManager 2 + useFlashBlock\r
+ * ------------------------------\r
+ * Flash positioning and flashblock / clicktoflash handling\r
+ */\r
+\r
+#sm2-container {\r
+ /**\r
+ * where the SM2 flash movie goes. by default, relative container.\r
+ * set relative or absolute here, and don't touch it later or bad things will happen (see below comments.)\r
+ */\r
+ position: absolute;\r
+ width: 1px;\r
+ height: 1px;\r
+ overflow: hidden;\r
+ /* screw IE 6, just make it display nice */\r
+ _overflow: hidden;\r
+}\r
+\r
+#sm2-container object,\r
+#sm2-container embed {\r
+ /**\r
+ * the actual SWF movie bit.\r
+ * important: The SWF needs to be able to be moved off-screen without display: or position: changes.\r
+ * changing display: or position: or overflow: here or on parent can cause SWF reload or other weird issues after unblock\r
+ * e.g., SM2 starts but strange errors, no whileplaying() etc.\r
+ */\r
+ width: 48px;\r
+ height: 48px;\r
+ /* some flash blockers may also respect this rule */\r
+ max-width: 48px;\r
+ max-height: 48px;\r
+}\r
+\r
+#sm2-container.swf_timedout {\r
+ /* expand to show the timed-out SWF content */\r
+ position: relative;\r
+ width: 48px;\r
+ height: 48px;\r
+}\r
+\r
+#sm2-container.swf_timedout,\r
+#sm2-container.swf_timedout object,\r
+#sm2-container.swf_timedout embed {\r
+ /**\r
+ * when SM2 didn't start normally, time-out case. flash blocked, missing SWF, no flash?\r
+ * 48px square flash placeholder is typically used by blockers.\r
+ */\r
+ min-width: 48px;\r
+ min-height: 48px;\r
+}\r
+\r
+#sm2-container.swf_unblocked {\r
+ /* SWF unblocked, or was never blocked to begin with; try to collapse container as much as possible. */\r
+ width: 1px;\r
+ height: 1px;\r
+}\r
+\r
+#sm2-container.swf_loaded object,\r
+#sm2-container.swf_loaded embed,\r
+#sm2-container.swf_unblocked object,\r
+#sm2-container.swf_unblocked embed {\r
+ /* hide flash off-screen (relative to container) when it has loaded OK */\r
+ left: -9999em;\r
+ top: -9999em;\r
+}\r
+\r
+#sm2-container.swf_error {\r
+ /* when there is a fatal error (flash loaded, but SM2 failed) */\r
+ display: none;\r
+}\r
+\r
+#sm2-container.high_performance,\r
+#sm2-container.high_performance.swf_timeout {\r
+ /* "high performance" case: keep on-screen at all times */\r
+ position: absolute;\r
+ position: fixed;\r
+}\r
+\r
+#sm2-container.high_performance {\r
+ overflow: hidden;\r
+ _top: -9999px; /* IE 6 hax, no position:fixed */\r
+ _left: -9999px;\r
+ bottom: 0px;\r
+ left: 0px;\r
+ /**\r
+ * special case: show at first with w/h, hide when unblocked.\r
+ * might be bad/annoying.\r
+ * try to stay within ClickToFlash "invisible" limits (so it won't be blocked.)\r
+ */\r
+ z-index: 99; /* try to stay on top */\r
+}\r
+\r
+#sm2-container.high_performance.swf_loaded,\r
+#sm2-container.high_performance.swf_unblocked {\r
+ z-index: auto;\r
+}\r
+\r
+#sm2-container.high_performance.swf_loaded,\r
+#sm2-container.high_performance.swf_unblocked,\r
+#sm2-container.high_performance.swf_unblocked object,\r
+#sm2-container.high_performance.swf_unblocked embed {\r
+ /**\r
+ * 8x8px is required minimum to load in fx/win32 in some cases(?)\r
+ * 6x6+ good for fast performance, even better when on-screen via position:fixed\r
+ * also, clickToFlash (Safari <5.1) may auto-load "invisible" SWFs at this size\r
+ */\r
+ height: 8px;\r
+ width: 8px;\r
+}\r
+\r
+#sm2-container.high_performance.swf_loaded {\r
+ /* stay bottom/left */\r
+ top: auto;\r
+ bottom: 0px;\r
+ left: 0px;\r
+}\r
+\r
+#sm2-container.high_performance.swf_loaded object,\r
+#sm2-container.high_performance.swf_loaded embed,\r
+#sm2-container.high_performance.swf_unblocked object,\r
+#sm2-container.high_performance.swf_unblocked embed {\r
+ /* high-performance case must stay on-screen */\r
+ left: auto;\r
+ top: auto;\r
+}\r
+\r
+#sm2-container.high_performance.swf_timedout {\r
+ z-index: 99; /* try to stay on top */\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Flash Block handling examples</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Demo of SoundManager 2 handling flashblock / "click to flash" blockers gracefully" />\r
+<meta name="keywords" content="javascript sound, javascript audio, DHTML sound, flashblock, flash blocker, handling flashblock, click to flash, click2flash" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />\r
+<!-- design template, you don't need this -->\r
+<link rel="stylesheet" type="text/css" href="../index.css" />\r
+<link rel="stylesheet" type="text/css" href="../debug.css" />\r
+\r
+<!-- actual flashblock demo stuff, this is for you -->\r
+<link rel="stylesheet" type="text/css" href="flashblock.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ // enable flash block handling\r
+ useFlashBlock: true,\r
+ // making sure this demo uses flash, of course...\r
+ preferFlash: true,\r
+ // custom demo options, not for your needs\r
+ debugMode: true,\r
+ url: '../../swf/'\r
+});\r
+\r
+var winLoc = window.location.toString();\r
+if (winLoc.match(/flash9/i)) {\r
+ soundManager.setup({\r
+ flashVersion: 9\r
+ });\r
+ if (winLoc.match(/highperformance/i)) {\r
+ soundManager.setup({\r
+ useHighPerformance: true\r
+ });\r
+ }\r
+} else if (winLoc.match(/flash8/i)) {\r
+ soundManager.setup({\r
+ flashVersion: 8\r
+ });\r
+}\r
+\r
+soundManager.ontimeout(function(){\r
+ var loaded = soundManager.getMoviePercent();\r
+ document.getElementById('sm2-status').innerHTML = 'No response (yet), flash movie '+(loaded?'loaded OK (likely security/error case)':'has not loaded (likely flash-blocked.)')+' Waiting indefinitely ...';\r
+});\r
+\r
+soundManager.onready(function(){\r
+ var loaded = soundManager.getMoviePercent();\r
+ document.getElementById('sm2-status').innerHTML = 'SoundManager load OK';\r
+});\r
+\r
+</script>\r
+</head>\r
+<body>\r
+\r
+<div style="margin:1em;max-width:60em">\r
+ \r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2</a>: Flashblock / "click to flash" handling demos</h1>\r
+\r
+ <h3>Show SWF inline, wait indefinitely for load (click-to-run or whitelist)</h3>\r
+\r
+ <p class="note">You can run this demo with <a href="#flash8" onclick="window.location.replace(this.href);window.location.reload()">Flash 8</a> (default), <a href="#flash9" onclick="window.location.replace(this.href);window.location.reload()">Flash 9</a> (normal mode) or <a href="#flash9-highperformance" onclick="window.location.replace(this.href);window.location.reload()">Flash 9 + highPerformance mode</a> (higher JS callback frequency).</p>\r
+\r
+ <h4>Where (and when) to show the SWF</h4>\r
+\r
+ <p>To handle potential flash block cases, put <code><div id="sm2-container"></div></code> in your markup where you'd like the SWF to appear in those cases. If not specified, SM2 will create and append the <code>#sm2-container</code> node to the document when it starts.</p>\r
+\r
+ <p>When <code>soundManager.useFlashBlock</code> is true, SM2 will not apply styles (eg. <code>style.position.left</code>) directly to the flash; rather, it will assign CSS classes and you can handle it as you choose. Take a look at <a href="#flashblock-css">the related CSS</a> file you will also need if you turn this feature on.</p>\r
+\r
+ <h4>Handling failed start-up cases</h4>\r
+\r
+ <p>In the blocked/failed start-up case, <code>#sm2-container</code> will have a class name of <code>swf_timedout</code> applied to it.</p>\r
+\r
+ <p>SM2 will start its init process, and will fire <code>onready()</code>, <code>onload()</code> and <code>onerror()</code> handlers accordingly. Keep in mind that while <code>onerror()</code> may fire at first, it may be preceded by a successful <code>onload()</code> if the user first loads the page and then later unblocks the flash movie.</p>\r
+\r
+ <p>Note that flash blockers may not run when viewing offline (via <code>file://</code>) content, so try viewing this demo online. For FlashBlock (under Firefox), you can also go to <code>about:config</code> using your address bar and change the value of <code>flashblock.blockLocal</code> to test while offline.</p>\r
+\r
+ <h3>Flash Block Example</h3>\r
+\r
+ <p>Here, Flash is appended by SM2 to the <code>#sm2-container</code> DIV and after a failed start attempt (if you have a blocker active), will have a <code>swf_timedout</code> class appended.</p>\r
+\r
+ <p>The SWF uses <code>position:absolute</code> and negative left/top values so as not to affect the normal page layout, but shifts to <code>left:auto;top:auto</code> (effectively left/top:0) in the blocked case, and becomes visible to the user. On a successful unblock, the movie goes back to left/top:-9999em and is hidden from view.</p>\r
+\r
+ <p>SoundManager 2 load status: <b id="sm2-status">Loading...</b></p>\r
+\r
+ <!-- here is where the SWF is shown in the blocked / failed start-up case. -->\r
+\r
+ <div id="sm2-container">\r
+ <!-- flash is appended here -->\r
+ </div>\r
+ \r
+ <h3 id="flashblock-css">Flash Block-related CSS</h3>\r
+ \r
+ <p>When <code>soundManager.useFlashBlock</code> is enabled, CSS is applied to <code>#sm2-container</code> depending on the progress of SM2's start-up.</p>\r
+ <p>This page + demos use the rules below, fully-defined and commented in <a href="flashblock.css">flashblock.css</a>. Use it as a base for your own SM2 + flash block implementations.</p>\r
+\r
+<pre class="block"><code>#sm2-container {\r
+ <span><span>/* Initial state: position:absolute/off-screen, or left/top:0 */</span></span>\r
+}\r
+#sm2-container.swf_timedout {\r
+ <span><span>/* Didn't load before time-out, show to user.\r
+ Maybe highlight on-screen, red border, etc..? */</span></span>\r
+}\r
+#sm2-container.swf_unblocked {\r
+ <span><span>/* Applied if movie loads successfully after\r
+ an unblock (flash started, so move off-screen etc.) */</span></span>\r
+}\r
+#sm2-container.swf_loaded {\r
+ <span><span>/* Applied if movie loads, regardless of whether\r
+ it was initially blocked */</span></span>\r
+}\r
+#sm2-container.swf_error {\r
+ <span><span>/* "Fatal" error case: SWF loaded,\r
+ but SM2 was unable to start for some reason.\r
+ (Flash security or other error case.) */</span></span>\r
+}\r
+#sm2-container.high_performance {\r
+ <span><span>/* Additional modifier for "high performance" mode\r
+ should apply position:fixed and left/bottom 0 to stay on-screen\r
+ at all times (better flash performance) */</span></span>\r
+}\r
+#sm2-container.flash_debug {\r
+ <span><span>/* Additional modifier for flash debug output mode\r
+ should use width/height 100% so you can read debug messages */</span></span>\r
+}</code></pre>\r
+\r
+ <h3>Basic Demo</h3>\r
+ \r
+ <p>For a more minimal example, see the <a href="basic.html" title="SoundManager 2: Basic Flashblock handling demo">basic flashblock demo</a>.</p>\r
+ \r
+</div>
--- /dev/null
+#sm2-container {\r
+ /* where the SM2 flash movie goes. */\r
+ position:relative;\r
+}\r
+\r
+#sm2-container,\r
+#sm2-container embed,\r
+#sm2-container.swf_timedout {\r
+ /* 48px square flash placeholder is typically used by blockers */\r
+ width:48px;\r
+ height:48px;\r
+}\r
+\r
+#sm2-container.swf_timedout {\r
+ /* likely a flash block situation. Maybe make it more bold, red, show descriptive nested elements? */\r
+ border:1px solid red;\r
+}\r
+\r
+#sm2-container object,\r
+#sm2-container embed {\r
+ /* hide flash off-screen by default */\r
+ position:absolute;\r
+ left:-9999em;\r
+ top:-9999em;\r
+}\r
+\r
+#sm2-container.swf_timedout object,\r
+#sm2-container.swf_timedout embed {\r
+ /* when blocked, make visible inside container */\r
+ left:auto;\r
+ top:auto;\r
+}\r
+\r
+#sm2-container object,\r
+#sm2-container embed {\r
+ /* 6x6 is small enough to be "invisible" and not blocked by click2flash if allowed, also enough to be really fast/performant on-screen */\r
+ width:48px;\r
+ height:48px;\r
+}\r
+\r
+#sm2-container.swf_unblocked,\r
+#sm2-container.swf_unblocked object,\r
+#sm2-container.swf_unblocked embed {\r
+ width:6px;\r
+ height:6px;\r
+}\r
+\r
+#sm2-container.high_performance {\r
+ position:absolute;\r
+ position:fixed;\r
+ _top:0px; /* IE 6 hax */\r
+ bottom:0px;\r
+ left:0px;\r
+}\r
+\r
+#sm2-container.high_performance object,\r
+#sm2-container.high_performance embed {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+}
\ No newline at end of file
--- /dev/null
+/*\r
+\r
+ FlashBlock handler for SoundManager 2\r
+ -------------------------------------------------------------------\r
+ Attempt to handle and gracefully recover from flashblock conditions\r
+ Requires SoundManger v2.95a.20090717+\r
+\r
+ http://schillmania.com/projects/soundmanager2/\r
+\r
+*/\r
+soundManager._flashBlock = new function() {\r
+\r
+ var _s = this;\r
+ this.name = 'soundManager._flashblock';\r
+ this.didTimeout = false; // did initial attempt fail?\r
+ this.timer = null; // for setTimeout call\r
+\r
+ this.startTimer = function(nMsec) {\r
+ // soundManager._wD(_s.name+'_.starttimer()');\r
+ _s.timer = window.setTimeout(_s.checkFlashStatus,nMsec);\r
+ };\r
+\r
+ this.stopTimer = function() {\r
+ // soundManager._wD(_s.name+'.stoptimer()');\r
+ if (_s.timer) {\r
+ window.clearTimeout(_s.timer);\r
+ _s.timer = null;\r
+ }\r
+ };\r
+\r
+ this.checkFlashStatus = function() {\r
+ // soundManager._wD(_s.name+'.checkflashstatus()');\r
+ var _sm = soundManager;\r
+ var oMC = _sm.oMC; // DIV (default: #sm2-container) for .SWF\r
+ var oStatus = document.getElementById('sm2-status'); // demo-only\r
+\r
+ if (!_sm.ok()) {\r
+ // make the movie more visible, so user can fix\r
+ oMC.className = 'swf-timedout';\r
+ _s.didTimeout = true;\r
+ var msg = 'No flash response, applying .swf-timedout CSS..';\r
+ _sm._wD(_s.name+': '+msg);\r
+ if (oStatus) {\r
+ oStatus.innerHTML = '<span style="color:#996633">'+msg+'</span>';\r
+ }\r
+ } else {\r
+ // SM2 loaded OK\r
+ // move the movie container to its proper place\r
+ oMC.className = 'swf-loaded';\r
+ if (!_s.didTimeout) {\r
+ // SM2 didn't previously fail, no blocker active\r
+ var msg = 'SM2 loaded OK (before timeout), fast unblock or no blocker.';\r
+ _sm._writeDebug(_s.name+'.checkFlashStatus: '+msg,1);\r
+ if (oStatus) {\r
+ oStatus.innerHTML = '<span style="color:green">'+msg+'</span>';\r
+ }\r
+ } else {\r
+ var msg = 'SM2 recovered after block (or timeout), loaded OK.';\r
+ _sm._wD(_s.name+': '+msg);\r
+ if (oStatus) {\r
+ oStatus.innerHTML = '<span style="color:#996633">'+msg+'</span>';\r
+ }\r
+ }\r
+ // stop timer, if applicable\r
+ _s.stopTimer();\r
+ return false;\r
+ }\r
+ };\r
+\r
+ soundManager.flashLoadTimeout = 0; // wait forever for flash to load - we'll set our own timeout via oninitmovie()\r
+\r
+ soundManager.oninitmovie = function() {\r
+ // when SWF is written (or ready to start), wait and make SWF visible (time-out case)\r
+ soundManager._flashBlock.startTimer(750);\r
+ };\r
+\r
+ soundManager.onready(function() {\r
+ // SM2 has now initialized, either no blocking OR blocked movie was allowed/whitelisted\r
+ var fb = soundManager._flashBlock;\r
+ // Yay! recovered OK.\r
+ fb.checkFlashStatus();\r
+ });\r
+\r
+ soundManager.ontimeout(function() {\r
+ // Blocking was passed (or no blocking), but then something *else* went wrong.\r
+ // stop timer, if applicable\r
+ fb.stopTimer();\r
+ });\r
+\r
+}();\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Flash blocker handling examples</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Demo of SoundManager 2 handling flashblock / "click to flash" blockers gracefully" />\r
+<meta name="keywords" content="javascript sound, javascript audio, DHTML sound, flashblock, flash blocker, handling flashblock, click to flash" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />\r
+<!-- design template, you don't need this -->\r
+<link rel="stylesheet" type="text/css" href="../../index.css" />\r
+<link rel="stylesheet" type="text/css" href="../../debug.css" />\r
+\r
+<!-- actual flashblock demo stuff, this is for you -->\r
+<link rel="stylesheet" type="text/css" href="flashblock.css" />\r
+<script type="text/javascript" src="../../../script/soundmanager2.js"></script>\r
+\r
+<script type="text/javascript">\r
+\r
+soundManager.setup({\r
+ // custom demo options, not for your needs\r
+ debugMode: true,\r
+ url: '../../../swf/'\r
+});\r
+\r
+var winLoc = window.location.toString();\r
+\r
+if (winLoc.match(/flash9/i)) {\r
+ soundManager.setup({\r
+ flashVersion: 9\r
+ });\r
+ if (winLoc.match(/highperformance/i)) {\r
+ soundManager.setup({\r
+ useHighPerformance: true\r
+ });\r
+ }\r
+} else if (winLoc.match(/flash8/i)) {\r
+ soundManager.setup({\r
+ flashVersion: 8\r
+ });\r
+}\r
+\r
+soundManager.onready(function(){\r
+ var loaded = soundManager.getMoviePercent();\r
+ document.getElementById('sm2-status').innerHTML = 'SoundManager load OK';\r
+});\r
+\r
+soundManager.ontimeout(function(){\r
+ var loaded = soundManager.getMoviePercent();\r
+ document.getElementById('sm2-status').innerHTML = 'No response (yet), flash movie '+(loaded?'loaded OK (likely security/error case)':'has not loaded (likely flash-blocked.)')+' Waiting indefinitely ...';\r
+});\r
+\r
+</script>\r
+</head>\r
+<body>\r
+\r
+<div style="margin:1em;max-width:60em;font-size:110%">\r
+ \r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2</a>: Flashblock / "click to flash" handling demos</h1>\r
+\r
+ <h3>Show SWF inline, wait indefinitely for load</h3>\r
+\r
+ <p class="note">You can run this demo with <a href="#flash8" onclick="window.location.replace(this.href);window.location.reload()">Flash 8</a> (default), <a href="#flash9" onclick="window.location.replace(this.href);window.location.reload()">Flash 9</a> (normal mode) or <a href="#flash9-highperformance" onclick="window.location.replace(this.href);window.location.reload()">Flash 9 + highPerformance mode</a> (higher JS callback frequency).</p>\r
+\r
+ <p>Typically SM2 appends a DIV and hides the SWF off-screen. To handle potential flash block cases, a flash container DIV with an ID of "sm2-container" is placed in the HTML. SM2 will find and append the flash movie to this element. In this case, the SWF can be targeted with CSS and is not positioned off-screen as it normally would be.</p>\r
+ <p>SM2 will start its init process, and will fire <code>onready()</code>, <code>onload()</code> and <code>onerror()</code> handlers accordingly. Keep in mind that while <code>onerror()</code> may fire at first, it may be preceded by a successful <code>onload()</code> if the user first loads the page and then later unblocks the flash movie.</p>\r
+ <p>Note that flash blockers may not run when viewing offline (via <code>file://</code>) content, so try viewing this demo online. For FlashBlock (under Firefox), you can also adjust <code>flashblock.blockLocal</code> under <code>about:config</code> in the address bar to test while offline.</p>\r
+\r
+ <p>CSS applied to <code>#sm2-container</code>, depending on state:</p>\r
+<pre class="block"><code>#sm2-container.movieContainer {<span><span>/* Initial state: position:absolute/off-screen, or inline/relative */</span></span>}\r
+#sm2-container.swf_timedout {<span><span>/* Didn't load before time-out, show to user: On-screen, red border, etc..? */</span></span>}\r
+#sm2-container.swf_unblocked {<span><span>/* Applied if a timeout followed by an unblock (flash started.) Move off-screen. */</span></span>}\r
+#sm2-container.high_performance {<span><span>/* Additional modifier for "high performance" mode, should apply position:fixed and left/bottom 0 to stay on-screen at all times (better flash performance) */</span></span>}\r
+#sm2-container.flash_debug {<span><span>/* Additional modifier for flash debug output mode, should use width/height 100% so you can read debug messages */</span></span>}\r
+#sm2-container.swf_error {<span><span>/* Additional modifier, "something really broke" (fatal: security, missing SWF etc.) */</span></span>}</code></pre>\r
+ \r
+ <p>SoundManager 2 load status: <b id="sm2-status">Loading...</b></p>\r
+ \r
+ <p>Take a look at <a href="flashblock.css">flashblock.css</a> for implementation details.</p>\r
+\r
+ <div id="sm2-container">\r
+ <!-- flash is appended here -->\r
+ </div>\r
+ \r
+</div>
--- /dev/null
+/**
+ * SoundManager 2 homepage demo CSS
+ * --------------------------------
+ * Numerous demo CSS minified + combined
+ * for optimal performance.
+ * For raw source, see individual demo pages.
+ * --------------------------------
+ * Source files:
+ * demo/play-mp3-links/css/inlineplayer.css
+ * demo/page-player/css/page-player.css
+ * demo/bar-ui/css/bar-ui.css
+ * demo/360-player/360player.css
+ * demo/360-player/360player-visualization.css
+ * demo/mp3-player-button/css/mp3-player-button.css
+ * demo/turntable/css/turntable.css
+ * demo/flashblock/flashblock.css
+ * demo/index/index.css
+ */
+
+@font-face {
+ /*
+ * 'Chunk' font by Meredith Mandel - http://work.meredithmandel.com/#379252/Typeface-Chunk-Five
+ * http://www.theleagueofmoveabletype.com/fonts/4-chunk
+ * Provided under the SIL Open Font License (OFL)
+ * http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL&_sc=1
+ */
+ font-family: 'ChunkFiveRegular';
+ src: url('_image/chunk-webfont.woff') format('woff'),
+ url('_image/chunk-webfont.ttf') format('truetype'),
+ url('_image/chunk-webfont.svg#ChunkFiveRegular') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+ul.flat{list-style-type:none;padding-left:0}ul.flat li,ul.graphic li{padding-bottom:1px}ul.flat li a{display:inline-block;padding:2px 4px 2px 4px}ul.graphic{list-style-type:none;padding-left:0;margin-left:0}ul.graphic{list-style-type:none;margin:0;padding:0}ul.graphic li{margin-bottom:2px}ul.graphic li a,ul.graphic li a.sm2_link{display:inline-block;padding-left:22px;min-height:16px;vertical-align:middle;background-color:#369;border-radius:3px;padding:3px 3px 3px 25px;min-width:19em;_width:19em;text-decoration:none;font-weight:normal;color:#f6f9ff}ul.graphic li a.sm2_link{-webkit-transition-property:hover;-webkit-transition:background-color .15s linear;-moz-transition:background-color .15s linear 0;-o-transition-property:background-color;-o-transition-duration:.15s}ul.graphic li a,ul.graphic li a.sm2_paused:hover,ul.graphic li a.sm2_link:hover{background-image:url(play-mp3-links/image/icon_play.png);background-position:3px 50%;background-repeat:no-repeat;_background-image:url(play-mp3-links/image/icon_play.gif)}ul.graphic li a.sm2_link:hover{background-color:#036;color:#fff}ul.graphic li a.sm2_paused{background-color:#999}ul.graphic li a.sm2_paused:hover{background:#036 url(play-mp3-links/image/icon_play.png) no-repeat 3px 50%;_background-image:url(play-mp3-links/image/icon_play.gif)}ul.graphic li a.sm2_playing,ul.graphic li a.sm2_playing:hover{background:#036 url(play-mp3-links/image/icon_pause.png) no-repeat 3px 50%;_background-image:url(play-mp3-links/image/icon_pause.gif);text-decoration:none}body #sm2-container object,body #sm2-container embed{left:-9999em;top:-9999em}ul.flat a.sm2_link{border-left:6px solid #999;padding-left:4px;padding-right:4px}ul.flat a.sm2_link:hover{border-left-color:#333}ul.flat a.sm2_playing{border-left-color:#66f;background-color:#000;color:#fff;text-decoration:none}ul.flat a.sm2_playing:hover{border-left-color:#c33}ul.flat a.sm2_paused{background-color:#666;color:#fff;text-decoration:none}ul.flat a.sm2_paused:hover{border-left-color:#3c3}.spectrum-container{display:none}ul.use-spectrum li.sm2_playing .spectrum-container{position:absolute;left:0;top:0;margin-left:-266px;margin-top:-1px;display:block;background-color:#58b;border:1px solid #9cf;border-radius:4px}ul.use-spectrum .spectrum-box{position:relative;width:255px;font-size:1em;padding:2px 0;height:1.2em;overflow:hidden}ul.use-spectrum .spectrum-box .spectrum{position:absolute;left:0;top:-2px;margin-top:20px;display:block;font-size:1px;width:1px;height:1px;overflow:hidden;background-color:#fff}ul.playlist{list-style-type:none;margin:0;padding:0;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}ul.playlist li{position:relative;display:block;width:auto;font-size:2em;color:#666;padding:.25em .5em .25em .5em;border:0;letter-spacing:-1px;background-color:#f9f9f9;-webkit-transition-property:hover;-webkit-transition:background-color .15s ease-in-out;-moz-transition:background-color .15s linear 0;-o-transition-property:background-color;-o-transition-duration:.15s}ul.playlist li a{display:block;text-decoration:none;font-weight:normal;color:#000;font-size:120%;outline:0;position:relative;z-index:2}ul.playlist li.sm2_playing,ul.playlist li.sm2_paused,ul.playlist li.sm2_playing a{color:#fff;border-radius:3px}ul.playlist li:hover{background-color:#eee}ul.playlist li:hover a{color:#333}ul.playlist li.sm2_playing,ul.playlist li.sm2_playing:hover{background-color:#69c}ul.playlist li.sm2_paused{background-color:#999}ul.playlist li.sm2_playing:hover a,ul.playlist li.sm2_paused a{color:#fff}ul.playlist li .controls{display:none}ul.playlist li .peak,ul.playlist.use-peak li .peak{display:none;position:absolute;top:.55em;right:.5em}ul.playlist li.sm2_playing .controls,ul.playlist li.sm2_paused .controls{position:relative;display:block}ul.playlist.use-peak li.sm2_playing .peak,ul.playlist.use-peak li.sm2_paused .peak{display:inline;display:inline-block}ul.playlist.use-peak li .peak{display:none}ul.playlist li.sm2_paused .controls{background-color:#666}ul.playlist li:hover .controls .statusbar{position:relative;cursor:-moz-grab;cursor:-webkit-grab;cursor:grab}ul.playlist li.sm2_paused .controls .statusbar{background-color:#ccc}ul.playlist li .controls{position:relative;margin-top:.25em;margin-bottom:.25em;background-color:#9cf}ul.playlist li .controls .statusbar{position:relative;height:.5em;background-color:#cdf;border:2px solid #fff;border-radius:2px;overflow:hidden;cursor:-moz-grab;cursor:-webkit-grab;cursor:grab}ul.playlist li .controls.dragging .statusbar{cursor:-moz-grabbing;cursor:-webkit-grabbing;cursor:grabbing}ul.playlist li .controls .statusbar .position,ul.playlist li .controls .statusbar .loading,ul.playlist li .controls .statusbar .annotation{position:absolute;left:0;top:0;height:.5em}ul.playlist li .controls .statusbar .position{background-color:#369;border-right:3px solid #369;border-radius:3px}ul.playlist li.sm2_paused .controls .statusbar .position{background-color:#666;border-color:#666}ul.playlist li .controls .statusbar .loading{background-color:#eee}ul.playlist li .controls .statusbar .position,ul.playlist li .controls .statusbar .loading{width:0}ul.playlist li.sm2_playing a.sm2_link,ul.playlist li.sm2_paused a.sm2_link{margin-right:4.5em}ul.playlist li .timing{position:absolute;display:none;text-align:right;right:1em;top:1em;width:auto;height:1em;padding:3px 5px;background-color:#58b;border:1px solid #9cf;border-radius:4px;letter-spacing:0;font:44% monaco,"VT-100","lucida console",courier,system;line-height:1em;vertical-align:middle}ul.playlist.use-peak li .timing{right:4.25em}ul.playlist li:hover .timing{z-index:2}ul.playlist li .timing div.sm2_timing{margin:0;padding:0;margin-top:-1em}ul.playlist li.sm2_playing .timing,ul.playlist li.sm2_paused .timing{display:block}ul.playlist li.sm2_paused .timing .sm2_position{text-decoration:blink}ul.playlist li.sm2_paused .timing,ul.playlist.use-peak li.sm2_paused .peak{background-color:#888;border-color:#ccc}ul.playlist.use-peak li .peak{display:none;zoom:1;border:1px solid #9cf;padding:2px;height:.55em;border-radius:4px;background-color:#58b;width:.8em;height:.55em;margin-top:-3px}ul.playlist.use-peak li .peak-box{position:relative;width:100%;height:.55em;overflow:hidden}ul.playlist li .peak .l,ul.playlist li .peak .r{position:absolute;left:0;top:0;width:7px;height:50px;background:#fff;border:1px solid #fff;border-radius:1px;margin-top:1em}ul.playlist li .peak .l{margin-right:1px}ul.playlist li .peak .r{left:10px}#control-template{display:none} .sm2-bar-ui{position:relative;display:inline-block;width:100%;font-family:helvetica,arial,verdana,sans-serif;font-weight:normal;-webkit-background-clip:padding-box;background-clip:padding-box;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-smoothing:antialiased;text-rendering:optimizeLegibility;min-width:20em;max-width:30em;border-radius:2px;overflow:hidden;transition:max-width .2s ease-in-out}.sm2-bar-ui .sm2-playlist li{text-align:center;margin-top:-2px;font-size:95%;line-height:1em}.sm2-bar-ui.compact{min-width:1em;max-width:15em}.sm2-bar-ui ul{line-height:1em}.sm2-bar-ui.left .sm2-playlist li{text-align:left}.sm2-bar-ui .sm2-playlist li .load-error{cursor:help}.sm2-bar-ui.full-width{max-width:100%;z-index:5}.sm2-bar-ui.fixed{position:fixed;top:auto;bottom:0;left:0;border-radius:0;overflow:visible;z-index:999}.sm2-bar-ui.fixed .bd,.sm2-bar-ui.bottom .bd{border-radius:0;border-bottom:0}.sm2-bar-ui.bottom{top:auto;bottom:0;left:0;border-radius:0;overflow:visible}.sm2-bar-ui.playlist-open .bd{border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-color:transparent}.sm2-bar-ui .bd,.sm2-bar-ui .sm2-extra-controls{position:relative;background-color:#28c}.sm2-bar-ui .sm2-inline-gradient{position:absolute;left:0;top:0;width:100%;height:100%;background-image:-moz-linear-gradient(to bottom,rgba(255,255,255,0.125) 5%,rgba(255,255,255,0.125) 45%,rgba(255,255,255,0.15) 52%,rgba(0,0,0,0.01) 51%,rgba(0,0,0,0.1) 95%);background-image:linear-gradient(to bottom,rgba(255,255,255,0.125) 5%,rgba(255,255,255,0.125) 45%,rgba(255,255,255,0.15) 50%,rgba(0,0,0,0.1) 51%,rgba(0,0,0,0.1) 95%)}
+.sm2-bar-ui.flat .sm2-inline-gradient{background-image:none}.sm2-bar-ui.flat .sm2-box-shadow{display:none;box-shadow:none}.sm2-bar-ui.no-volume .sm2-volume{display:none}.sm2-bar-ui.textured .sm2-inline-texture{position:absolute;top:0;left:0;width:100%;height:100%;opacity:.75}.sm2-bar-ui.textured.dark-text .sm2-playlist-wrapper{background-color:transparent}.sm2-bar-ui.textured.dark-text .sm2-playlist-wrapper ul li:hover a,.sm2-bar-ui.textured.dark-text .sm2-playlist-wrapper ul li.selected a{background-color:rgba(0,0,0,0.1);background-image:url(bar-ui/image/black-10.png);background-image:none,none}.sm2-bar-ui .bd{display:table;border-bottom:0}.sm2-bar-ui .sm2-playlist-wrapper{background-color:rgba(0,0,0,0.1)}.sm2-bar-ui .sm2-extra-controls .bd{background-color:rgba(0,0,0,0.2)}.sm2-bar-ui.textured .sm2-extra-controls .bd{background-color:rgba(0,0,0,0.05)}.sm2-bar-ui .sm2-extra-controls{background-color:transparent;border:0}.sm2-bar-ui .sm2-extra-controls .bd{display:block;border:0}.sm2-bar-ui .sm2-extra-controls .sm2-inline-element{display:inline-block}.sm2-bar-ui,.sm2-bar-ui .bd a{color:#fff}.sm2-bar-ui.dark-text,.sm2-bar-ui.dark-text .bd a{color:#000}.sm2-bar-ui.dark-text .sm2-inline-button{-webkit-filter:invert(1);filter:url("data:image/svg+xml;utf8,<svgxmlns=\'http://www.w3.org/2000/svg\'><filterid=\'invert\'><feColorMatrixin='SourceGraphic'type='matrix'values='-100010-100100-10100010'/></filter></svg>#invert");filter:invert(1);filter:none\9}.sm2-bar-ui .bd a{text-decoration:none}.sm2-bar-ui .bd .sm2-button-element:hover{background-color:rgba(0,0,0,0.1);background-image:url(bar-ui/image/black-10.png);background-image:none,none}.sm2-bar-ui .bd .sm2-button-element:active{background-color:rgba(0,0,0,0.25);background-image:url(bar-ui/image/black-25.png);background-image:none,none}.sm2-bar-ui .bd .sm2-extra-controls .sm2-button-element:active .sm2-inline-button,.sm2-bar-ui .bd .active .sm2-inline-button{-ms-transform:scale(0.9);-webkit-transform:scale(0.9);-webkit-transform-origin:50% 50%;transform:scale(0.9);transform-origin:50% 50%;-moz-transform:none}.sm2-bar-ui .bd .sm2-extra-controls .sm2-button-element:hover,.sm2-bar-ui .bd .sm2-extra-controls .sm2-button-element:active,.sm2-bar-ui .bd .active{background-color:rgba(0,0,0,0.1);background-image:url(bar-ui/image/black-10.png);background-image:none,none}.sm2-bar-ui .bd .sm2-extra-controls .sm2-button-element:active{box-shadow:none}.sm2-bar-ui{font-size:15px;text-shadow:none}.sm2-bar-ui .sm2-inline-element{position:relative;display:inline-block;vertical-align:middle;padding:0;overflow:hidden}.sm2-bar-ui .sm2-inline-element,.sm2-bar-ui .sm2-button-element .sm2-button-bd{position:relative}.sm2-bar-ui .sm2-inline-element,.sm2-bar-ui .sm2-button-element .sm2-button-bd{min-width:2.8em;min-height:2.8em}.sm2-bar-ui .sm2-inline-button{position:absolute;top:0;left:0;width:100%;height:100%}.sm2-bar-ui .sm2-extra-controls .bd{background-image:none;background-color:rgba(0,0,0,0.15)}.sm2-bar-ui .sm2-extra-controls .sm2-inline-element{width:25px;min-height:1.75em;min-width:2.5em}.sm2-bar-ui .sm2-inline-status{line-height:100%;display:inline-block;min-width:200px;max-width:20em;padding-left:.75em;padding-right:.75em}.sm2-bar-ui .sm2-inline-element{border-right:.075em dotted #666;border-right:.075em solid rgba(0,0,0,0.1)}.sm2-bar-ui .sm2-inline-element.noborder{border-right:0}.sm2-bar-ui .sm2-inline-element.compact{min-width:2em;padding:0 .25em}.sm2-bar-ui .sm2-inline-element:first-of-type{border-top-left-radius:3px;border-bottom-left-radius:3px;overflow:hidden}.sm2-bar-ui .sm2-inline-element:last-of-type{border-right:0;border-top-right-radius:3px;border-bottom-right-radius:3px}.sm2-bar-ui .sm2-inline-status a:hover{background-color:transparent;text-decoration:underline}.sm2-inline-time,.sm2-inline-duration{display:table-cell;width:1%;font-size:75%;line-height:.9em;min-width:2em;vertical-align:middle}.sm2-bar-ui .sm2-playlist{position:relative;height:1.45em}.sm2-bar-ui .sm2-playlist-target{position:relative;min-height:1em}.sm2-bar-ui .sm2-playlist ul{position:absolute;left:0;top:0;width:100%;list-style-type:none;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.sm2-bar-ui p,.sm2-bar-ui .sm2-playlist ul,.sm2-bar-ui .sm2-playlist ul li{margin:0;padding:0}.sm2-bar-ui .sm2-playlist ul li{position:relative}.sm2-bar-ui .sm2-playlist ul li,.sm2-bar-ui .sm2-playlist ul li a{position:relative;display:block;height:1.5em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center}.sm2-row{position:relative;display:table-row}.sm2-progress-bd{padding:0 .8em}.sm2-progress .sm2-progress-track,.sm2-progress .sm2-progress-ball,.sm2-progress .sm2-progress-bar{position:relative;width:100%;height:.65em;border-radius:.65em}.sm2-progress .sm2-progress-bar{position:absolute;left:0;top:0;width:0;background-color:rgba(0,0,0,0.33);background-image:url(bar-ui/image/black-33.png);background-image:none,none}.volume-shade,.playing .sm2-progress .sm2-progress-track,.paused .sm2-progress .sm2-progress-track{cursor:pointer}.playing .sm2-progress .sm2-progress-ball{cursor:-moz-grab;cursor:-webkit-grab;cursor:grab}.sm2-progress .sm2-progress-ball{position:absolute;top:0;left:0;width:1em;height:1em;margin:-0.2em 0 0 -0.5em;width:14px;height:14px;margin:-2px 0 0 -7px;width:.9333em;height:.9333em;margin:-0.175em 0 0 -0.466em;background-color:#fff;padding:0;-webkit-transition:-webkit-transform .15s ease-in-out;transition:transform .15s ease-in-out}.sm2-progress .sm2-progress-track{background-color:rgba(0,0,0,0.4);background-image:url(bar-ui/image/black-33.png);background-image:none,none}.sm2-playlist-wrapper ul::-webkit-scrollbar-track{background-color:rgba(0,0,0,0.4)}.playing.grabbing .sm2-progress .sm2-progress-track,.playing.grabbing .sm2-progress .sm2-progress-ball{cursor:-moz-grabbing;cursor:-webkit-grabbing;cursor:grabbing}.sm2-bar-ui.grabbing .sm2-progress .sm2-progress-ball{-webkit-transform:scale(1.15);transform:scale(1.15)}.sm2-inline-button{background-position:50% 50%;background-repeat:no-repeat;line-height:10em;image-rendering:-moz-crisp-edges;image-rendering:-webkit-optimize-contrast;image-rendering:crisp-edges;-ms-interpolation-mode:nearest-neighbor;-ms-interpolation-mode:bicubic}.play-pause,.play-pause:hover,.paused .play-pause:hover{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/play.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/play.svg);background-size:67.5%;background-position:40% 53%}.playing .play-pause{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/pause.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/pause.svg);background-size:57.6%;background-position:50% 53%}.sm2-volume-control{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/volume.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/volume.svg)}.sm2-volume-control,.sm2-volume-shade{background-position:42% 50%;background-size:56%}.volume-shade{filter:alpha(opacity=33);opacity:.33;background-image:url(bar-ui/image/icomoon/entypo-25px-000000/PNG/volume.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-000000/SVG/volume.svg)}.menu{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/list2.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/list2.svg);background-size:58%;background-position:54% 51%}.previous{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/first.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/first.svg)}.next{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/last.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/last.svg)}.previous,.next{background-size:49.5%;background-position:50% 50%}.sm2-extra-controls .previous,.sm2-extra-controls .next{backgound-size:53%}.shuffle{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/shuffle.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/shuffle.svg);background-size:45%;background-position:50% 50%}.repeat{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/loop.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/loop.svg);background-position:50% 43%;background-size:54%}
+.sm2-extra-controls .repeat{background-position:50% 45%}.sm2-playlist-wrapper ul li .sm2-row{display:table;width:100%}.sm2-playlist-wrapper ul li .sm2-col{display:table-cell;vertical-align:top;width:0}.sm2-playlist-wrapper ul li .sm2-col.sm2-wide{width:100%}.sm2-playlist-wrapper ul li .sm2-icon{display:inline-block;overflow:hidden;width:2em;color:transparent !important;white-space:nowrap;padding-left:0;padding-right:0;text-indent:2em}.sm2-playlist-wrapper ul li .sm2-icon,.sm2-playlist-wrapper ul li:hover .sm2-icon,.sm2-playlist-wrapper ul li.selected .sm2-icon{background-size:55%;background-position:50% 50%;background-repeat:no-repeat}.sm2-playlist-wrapper ul li .sm2-col{border-right:1px solid rgba(0,0,0,0.075)}.sm2-playlist-wrapper ul li.selected .sm2-col{border-color:rgba(255,255,255,0.075)}.sm2-playlist-wrapper ul li .sm2-col:last-of-type{border-right:0}.sm2-playlist-wrapper ul li .sm2-cart,.sm2-playlist-wrapper ul li:hover .sm2-cart,.sm2-playlist-wrapper ul li.selected .sm2-cart{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/cart.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/cart.svg);background-position:48% 50%}.sm2-playlist-wrapper ul li .sm2-music,.sm2-playlist-wrapper ul li:hover .sm2-music,.sm2-playlist-wrapper ul li.selected .sm2-music{background-image:url(bar-ui/image/icomoon/entypo-25px-ffffff/PNG/music.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-ffffff/SVG/music.svg)}.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li .sm2-cart,.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li:hover .sm2-cart,.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li.selected .sm2-cart{background-image:url(bar-ui/image/icomoon/entypo-25px-000000/PNG/cart.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-000000/SVG/cart.svg)}.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li .sm2-music,.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li:hover .sm2-music,.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li.selected .sm2-music{background-image:url(bar-ui/image/icomoon/entypo-25px-000000/PNG/music.png);background-image:none,url(bar-ui/image/icomoon/entypo-25px-000000/SVG/music.svg)}.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li .sm2-col{border-left-color:rgba(0,0,0,0.15)}.sm2-playlist-wrapper ul li .sm2-icon:hover{background-color:rgba(0,0,0,0.33)}.sm2-bar-ui .sm2-playlist-wrapper ul li .sm2-icon:hover{background-color:rgba(0,0,0,0.45)}.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li.selected .sm2-icon:hover{background-color:rgba(255,255,255,0.25);border-color:rgba(0,0,0,0.125)}.sm2-progress-ball .icon-overlay{position:absolute;width:100%;height:100%;top:0;left:0;background:none,url(bar-ui/image/icomoon/free-25px-000000/SVG/spinner.svg);background-size:72%;background-position:50%;background-repeat:no-repeat;display:none}.playing.buffering .sm2-progress-ball .icon-overlay{display:block;-webkit-animation:spin .6s linear infinite;animation:spin .6s linear infinite}@-webkit-keyframes spin{0{-webkit-transform:rotate(0)}100%{-webkit-transform:rotate(360deg)}}@-moz-keyframes spin{0{transform:rotate(0)}100%{transform:rotate(360deg)}}@keyframes spin{0{transform:rotate(0)}100%{transform:rotate(360deg)}}.sm2-element ul{font-size:95%;list-style-type:none}.sm2-element ul,.sm2-element ul li{margin:0;padding:0}.bd.sm2-playlist-drawer{z-index:3;border-radius:0;width:100%;height:0;border:0;background-image:none;display:block;overflow:hidden;transition:height .2s ease-in-out}.sm2-bar-ui.fixed .bd.sm2-playlist-drawer,.sm2-bar-ui.bottom .bd.sm2-playlist-drawer{position:absolute}.sm2-bar-ui.fixed .sm2-playlist-wrapper,.sm2-bar-ui.bottom .sm2-playlist-wrapper{padding-bottom:0}.sm2-bar-ui.fixed .bd.sm2-playlist-drawer,.sm2-bar-ui.bottom .bd.sm2-playlist-drawer{bottom:2.8em}.sm2-bar-ui .bd.sm2-playlist-drawer{opacity:.5;transform:translateZ(0)}.sm2-bar-ui.playlist-open .bd.sm2-playlist-drawer{height:auto;opacity:1}.sm2-bar-ui.playlist-open .bd.sm2-playlist-drawer a{-webkit-filter:none}.sm2-bar-ui.fixed.playlist-open .bd.sm2-playlist-drawer .sm2-playlist-wrapper,.sm2-bar-ui.bottom.playlist-open .bd.sm2-playlist-drawer .sm2-playlist-wrapper{padding-bottom:.5em;box-shadow:none}.sm2-bar-ui .bd.sm2-playlist-drawer{transition:all .2s ease-in-out;transition-property:transform,height,opacity,background-color,-webkit-filter}.sm2-bar-ui .bd.sm2-playlist-drawer a{transition:-webkit-filter .2s ease-in-out}.sm2-bar-ui .bd.sm2-playlist-drawer .sm2-inline-texture{background-position:0 -2.8em}.sm2-box-shadow{position:absolute;left:0;top:0;width:100%;height:100%;box-shadow:inset 0 1px 6px rgba(0,0,0,0.15)}.sm2-playlist-wrapper{position:relative;padding:.5em .5em .5em .25em;background-image:none,none}.sm2-playlist-wrapper ul{max-height:9.25em;overflow:auto}.sm2-playlist-wrapper ul li{border-bottom:1px solid rgba(0,0,0,0.05)}.sm2-playlist-wrapper ul li:nth-child(odd){background-color:rgba(255,255,255,0.03)}.sm2-playlist-wrapper ul li a{display:block;padding:.5em .25em .5em .75em;margin-right:0;font-size:90%;vertical-align:middle}.sm2-playlist-wrapper ul li a.sm2-exclude{display:inline-block}.sm2-playlist-wrapper ul li a.sm2-exclude .label{font-size:95%;line-height:1em;margin-left:0;padding:2px 4px}.sm2-playlist-wrapper ul li:hover a{background-color:rgba(0,0,0,0.20);background-image:url(bar-ui/image/black-20.png);background-image:none,none}.sm2-bar-ui.dark-text .sm2-playlist-wrapper ul li:hover a{background-color:rgba(255,255,255,0.1);background-image:url(bar-ui/image/black-10.png);background-image:none,none}.sm2-playlist-wrapper ul li.selected a{background-color:rgba(0,0,0,0.25);background-image:url(bar-ui/image/black-20.png);background-image:none,none}.sm2-bar-ui.dark-text ul li.selected a{background-color:rgba(255,255,255,0.1);background-image:url(bar-ui/image/black-10.png);background-image:none,none}.sm2-bar-ui .disabled{filter:alpha(opacity=33);opacity:.33}.sm2-bar-ui .bd .sm2-button-element.disabled:hover{background-color:transparent}.sm2-bar-ui .active,.sm2-bar-ui.playlist-open .sm2-menu:hover{box-shadow:inset 0 0 2px rgba(0,0,0,0.1);background-image:none}.firefox-fix{position:relative;display:inline-block;width:100%;height:100%}.sm2-playlist-wrapper ul::-webkit-scrollbar{width:10px}.sm2-playlist-wrapper ul::-webkit-scrollbar-track{background:rgba(0,0,0,0.33);border-radius:10px}.sm2-playlist-wrapper ul::-webkit-scrollbar-thumb{border-radius:10px;background:#fff}.sm2-extra-controls{font-size:0;text-align:center}.sm2-bar-ui .label{position:relative;display:inline-block;font-size:.7em;margin-left:.25em;vertical-align:top;background-color:rgba(0,0,0,0.25);border-radius:3px;padding:0 3px;box-sizing:padding-box}.sm2-bar-ui.dark-text .label{background-color:rgba(0,0,0,0.1);background-image:url(bar-ui/image/black-10.png);background-image:none,none}.sm2-bar-ui .sm2-playlist-drawer .label{font-size:.8em;padding:0 3px}.sm2-bar-ui .sm2-inline-element{display:table-cell}.sm2-bar-ui .sm2-inline-element{width:1%}.sm2-bar-ui .sm2-inline-status{width:100%;min-width:100%;max-width:100%}.sm2-bar-ui>.bd{width:100%}.sm2-bar-ui .sm2-playlist-drawer{display:block;overflow:hidden}.ui360,.sm2-360ui{position:relative}.ui360{margin-bottom:5px;margin-right:5px}.ui360,.sm2-360ui{min-width:50px;min-height:50px}.sm2-360ui{width:50px;height:50px}.sm2-360ui{background-color:#f9f9f9;background-color:rgba(0,0,0,0.025);box-shadow:inset 0 0 8px rgba(0,0,0,0.15);border-radius:100%;-webkit-transition:all .1s ease-in-out;-moz-transition:all .1s ease-in-out;transition:all .1s ease-in-out;-moz-transition-property:background,border,box-shadow;-webkit-transition-property:background,border,box-shadow;transition-property:background,border,box-shadow}.sm2-360ui:hover{background-color:rgba(0,0,0,0.1);border-color:rgba(0,0,0,0.15);box-shadow:inset 0 0 5px rgba(0,0,0,0.15)}.ui360,.ui360 *{vertical-align:middle}.sm2-360ui{position:relative;display:inline-block;float:left;*display:inline;clear:left}.sm2-360ui.sm2_playing,.sm2-360ui.sm2_paused{z-index:10}.ui360 a{float:left;display:inline;position:relative;color:#000;text-decoration:none;left:3px;top:18px;text-indent:50px}
+.ui360 a.sm2_link{text-indent:0}.ui360 a,.ui360 a:hover,.ui360 a:focus{padding:2px;margin-left:-2px;margin-top:-2px}.ui360 a:hover,.ui360 a:focus{background:#eee;border-radius:3px;outline:0}.ui360 .sm2-canvas{position:absolute;left:0;top:0}.ui360 .sm2-canvas.hi-dpi{top:-50%;left:-50%;-moz-transform:scale(0.5);-ms-transform:scale(0.5);-webkit-transform:scale(0.5);transform:scale(0.5)}.ui360 .sm2-timing{position:absolute;display:block;left:0;top:0;width:100%;height:100%;margin:0;font:11px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;color:#666;text-align:center;line-height:50px}.ui360 .sm2-cover{position:absolute;left:0;top:0;width:100%;height:100%;z-index:2;display:none;background-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}.ui360 .sm2-360btn{position:absolute;display:block;top:50%;left:50%;width:50px;height:50px;margin-left:-25px;margin-top:-25px;border-radius:25px;cursor:pointer;z-index:3}.ui360 .sm2-360data{display:inline-block;font-family:helvetica}.sm2-inline-block .ui360 .sm2-360btn,.ui360 .sm2-360ui.sm2_playing .sm2-360btn,.ui360 .sm2-360ui.sm2_paused .sm2-360btn{width:22px;height:22px;margin-left:-11px;margin-top:-11px}.ui360 .sm2-360ui.sm2_playing .sm2-cover,.ui360 .sm2-360ui.sm2_paused .sm2-cover{display:block}.ui360,.ui360 .sm2-360btn-default,.ui360 .sm2-360ui.sm2_paused .sm2-360btn{background:transparent url(360-player/360-button-play.png) no-repeat;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAABoUlEQVR42sWVu2oCQRhGU/s8gpVYJeQJNkZSbiH4QNuLlQZS21sJayGYaOEFVFDxNiremj9zig2uzk5YQpKFg8PMd75ZZle9E5Ff4e+Ll8tlQuNoPI2vUcCYOdbIxCmm9F5T0YgNMmS/LebSwWdNa7VayXq9ls1mI9vtVna7nQBj5lgjQxYHN7KY3QkiUbDf7+V4PMrpdArBHGtkyOJc3/n1mVaUUl+F5/PZSrABDi4dpmKH3QkixQEHlw5TsccZmsRCoSD1et1ajkuHqdg/HA5GKZPJCOTzeanVasYMLh2mYsXDIGAoDuG6rlSr1WCdBxrcsTIWazgrQiHS6bSRYJ3XDzeq2O/3+9Ltdm9IpVIhstmslEqlUAY36ii8ZrMpjUbjhmQyKeA4jhSLRWMGN+rhOZ1Oh8ANuVxOyuUy40hwo163RK/XeyPQbrdjgYNr/ILAYDB41Gf1wZnFAQfX+iM0HA5fxuPx+2g0Ej22QoYsDq61mGsymTxMp9NX/Sk2yJDFsRZfXpzXbDZ7WiwW3nw+9zUKGDPHGpkL5V//mn7OJyJZApyzeUS5AAAAAElFTkSuQmCC);background-image:none,url(360-player/360-button-play-2x.png);background-size:22px 22px;*background-image:url(360-player/360-button-play.png);background-repeat:no-repeat}.ui360{background-position:14px 50%;_background:transparent url(360-player/360-button-play.gif) no-repeat 14px 50%}.ui360 .sm2-360btn-default,.ui360 .sm2-360ui.sm2_paused .sm2-360btn{background-position:50% 50%;_background:transparent url(360-player/360-button-play.gif) no-repeat 50% 50%}.ui360 .sm2-360btn-default,.ui360 .sm2-360ui.sm2_paused .sm2-360btn{cursor:pointer}.ui360 .sm2-360btn-default:hover,.ui360 .sm2-360ui.sm2_paused .sm2-360btn:hover{background:transparent url(360-player/360-button-play-light.png) no-repeat 50% 50%;background-image:none,url(360-player/360-button-play-light-2x.png);background-size:22px 22px;_background:transparent url(360-player/360-button-play.gif) no-repeat 50% 50%;cursor:pointer}.ui360 .sm2-360ui.sm2_playing .sm2-360btn:hover,.ui360 .sm2-360btn-playing:hover{background:transparent url(360-player/360-button-pause-light.png) no-repeat 50% 50%;background-image:none,url(360-player/360-button-pause-light-2x.png);background-size:22px 22px;_background:transparent url(360-player/360-button-pause-light.gif) no-repeat 50% 50%;cursor:pointer}.ui360 .sm2-360ui.sm2_playing .sm2-timing{visibility:visible}.ui360 .sm2-360ui.sm2_buffering .sm2-timing{visibility:hidden}.ui360 .sm2-360ui .sm2-timing,.ui360 .sm2-360ui .sm2-360btn:hover+.sm2-timing,.ui360 .sm2-360ui.sm2_paused .sm2-timing{visibility:hidden}.ui360 .sm2-360ui.sm2_dragging .sm2-timing,.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover+.sm2-timing{visibility:visible}.ui360 .sm2-360ui.sm2_playing .sm2-360btn,.ui360 .sm2-360ui.sm2_dragging .sm2-360btn,.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover,.ui360 .sm2-360ui.sm2_dragging .sm2-360btn-playing:hover{background:transparent;cursor:auto}.ui360 .sm2-360ui.sm2_buffering .sm2-360btn,.ui360 .sm2-360ui.sm2_buffering .sm2-360btn:hover{background:transparent url(360-player/icon_loading_spinner.gif) no-repeat 50% 50%;opacity:.5;visibility:visible}.sm2-inline-list .ui360,.sm2-inline-block .ui360{position:relative;display:inline-block;float:left;_display:inline}.sm2-inline-block .ui360{margin-right:8px}.sm2-inline-list .ui360 a{display:none}ul.ui360playlist{list-style-type:none}ul.ui360playlist,ul.ui360playlist li{margin:0;padding:0}div.ui360 div.metadata{display:none}div.ui360 a span.metadata,div.ui360 a span.metadata *{vertical-align:baseline}.ui360-vis,.ui360-vis .sm2-360ui,.sm2-inline-list .ui360-vis{width:256px;height:256px}.ui360-vis{position:relative;padding-top:1px;padding-bottom:1px;padding-left:248px;margin-left:0;background-position:22.6% 50%}.sm2-inline-list .ui360-vis{cursor:pointer}.ui360-vis a{font:14px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;white-space:nowrap;text-indent:0;top:46%}.sm2-inline-list .ui360-vis a{line-height:256px;top:auto}.ui360-vis .sm2-360ui{margin-left:-256px}.ui360-vis .sm2-timing{font:bold 24px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;color:#333;text-align:center;line-height:256px;text-indent:0}.sm2-inline-list .ui360-vis,.sm2-inline-list .ui360-vis .sm2-360ui{margin-left:0}.sm2-inline-list .ui360-vis{margin:8px 13px 7px 0;padding-left:0;background-position:50% 50%}.sm2-inline-list .ui360-vis .sm2-360ui{border:1px solid #eee;margin-left:-1px;margin-top:-1px}.sm2-inline-list .ui360-vis a{position:absolute;display:inline;left:0;bottom:0;top:1px;width:100%;height:99%;*height:256px;overflow:hidden;font-size:small;font-weight:300;color:#333;margin:0;padding:0;line-height:488px;*line-height:480px;text-align:center;border-radius:0}.sm2-inline-list .ui360 a:hover{background-color:transparent}.sm2-inline-list .ui360-vis:hover .sm2-360ui,.sm2-inline-list .ui360-vis a.sm2_link:hover,.sm2-inline-list .ui360-vis a.sm2_link:active,.sm2-inline-list .ui360-vis a.sm2_link:focus{background-color:transparent}.ui360-vis .sm2-360btn,.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn,.ui360-vis .sm2-360ui.sm2_playing .sm2-360btn{width:48px;height:48px;margin-left:-24px;margin-top:-24px;border-radius:none}.ui360-vis,.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn,.ui360-vis .sm2-360btn-default{background:transparent url(360-player/360-button-vis-play.png) no-repeat 50% 50%;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAABuVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7++lpaXr6+uAgIDk5OQzMzPt7e1tbW3n5+dgYGDW1tZNTU10dHQ5OTnw8PCvr6/e3t6JiYlAQEDb29vo6OgrKyuqqqrq6uq4uLjf399AQEDGxsbq6uqAgIDY2Nje3t61tbXp6enU1NTu7u7r6+vl5eXt7e2fn5/n5+fDw8Ph4eHv7+/t7e3CwsLW1tbu7u7b29vw8PDm5uYgICDp6enY2Nji4uLo6Ojm5uakpKTS0tLPz8/h4eHw8PDs7Ozj4+Pa2trg4ODx8fHT09Pk5OTPz8/S0tLBwcGmpqawsLCOjo7h4eHn5+fo6OgAAADY2NjNzc3n5+cAAADd3d3Gxsbu7u7t7e0AAADX19fl5eXi4uLf39/Hx8fn5+fs7Ozg4ODR0dHX19e4uLjv7+/z8/P09PTy8vL19fXv7+/n5+fx8fH29vbs7Ozq6urm5ubo6Ojw8PDu7u7p6enr6+sAAAB/f3/Z2dn39/fh4eGOjo4ODg7t7e3l5eWWlpba2tqjo6NVVVXk5OTe3t65ubnMzMzExMTf39/GxsampqZiYmJNcTiZAAAAbXRSTlMAAQIEAwcFCAb5EdAImAXpB6oIUAoLCfsgZQ0EVrsGEr4ZYQgbsgpUYxikNd/aatQQli+R7rlUUdas6+8I+VaFruoOOV/S8Nq5sWL8UqmKUFsuHyTcrtsJm0z7C49V3NMKkdKXuk7S7oVeVSv7tAAEVwAAAu5JREFUeF6llmVz3DwURmNLsr1pmJmZmZmxzMwsybS8gXJfhl9cKXbHEK+TmZ4P/nDnOXN1NbalHD8CQ7QRGDmhnIQhBDYQnkhheRECSVIQQrLMHookAciUkHhBw1zVwuLShcJIpPDC0uJC1VxDQTaFx1srSvM3DUxU1TRVlWBjM7+0opUrQaupLSnrLK7ELIepwaCYmbiyuLOspJY38eeLykdGxzDhYQfKCmOjI+VFPkMQYF7NZD0l2DgFJrR+siYPegxBzBvqeoQxpgGw8qOuoTz3HGw9udUPCaFZIORhdS5blZOHjXWDBIdABusanb0S4MpqEw4XcNPqCrQFQQTN+XwPQ8CY5jcDUbB3KLdlg6hnQDZacqEgWA3a2rF6Jri9zWohwI6dXXK2QHZ3OqBw0qC7B6vnAPd0sxZMkHr7VNPD34YZgNrXK3EBSgPU9HJ4eIQDDDogQS4ow4QJxy4+MmKs4oYJZFhhggjQuMoKHoHzn3bsQx1HQOTClOkXLP6lviZTtjCjmn7B5g/izqszliBHTB+HDhl3PSJbwnxSS3n45HDkVLXkvCWg5Uws7eHgJ98/uKqxzLI9w3o6oXuwhd+OPNVEet0WtnU9/sWNJfz1u6cY1/VtLghQuRgk/PmBmT7hogJPXo3L8YQed3Nw8PWfuB89Eb8scUGUrl33DfH/N93BGeH6NUnkArh1O5FOuNETp2GR27cAE/iaJu6mz8HdCQnan+i96XQmdgaZ9PQ9+xMVoPJgNhrNhBKNzj5Q+E/AavH4SSz6OZRo7Mlj3oDDp7jyPJoKJfr8CpvAOUrQi6eppJaVZOrpCwTdP1cgr93UjKxoN9dka2KX8ealZtBADO3lG2+e7xRAd7Y0igOg2tYdBKD/CBIBenf/lYGJD2y8uv8OgaBDDkry3v57SlQXhL7f35OlwJOXGUBBl571JykmzCIE02T/s0tIASyf/R6Arr59fcM62G+8fnsVhdwFwq4Ov345Of/15wd0RYY81HHUTQAAAABJRU5ErkJggg==);*background-image:url(360-player/360-button-vis-play.png);_background:transparent url(360-player/360-button-vis-play.gif) no-repeat 50% 50%;cursor:pointer}.ui360-vis:hover .sm2-360btn,.ui360-vis .sm2-360btn-default:hover,.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn:hover{background:transparent url(360-player/360-button-vis-play-light.png) no-repeat 50% 50%;_background:transparent url(360-player/360-button-vis-play.gif) no-repeat 50% 50%;cursor:pointer}.ui360-vis .sm2-360ui.sm2_playing .sm2-360btn:hover,.ui360-vis .sm2-360btn-playing:hover{background:transparent url(360-player/360-button-vis-pause-light.png) no-repeat 50% 50%;_background:transparent url(360-player/360-button-vis-pause-light.gif) no-repeat 50% 50%;cursor:pointer}.ui360-vis{background-position:21% 50%;_background:transparent url(360-player/360-button-vis-play.gif) no-repeat 21% 50%}.ui360-vis .sm2-360btn-default{_background:transparent url(360-player/360-button-vis-play.gif) no-repeat 50% 50%}.ui360-vis .sm2-360ui.sm2_dragging .sm2-360btn{visibility:hidden}a.sm2_button{position:relative;display:inline-block;width:18px;height:18px;text-indent:-9999px;overflow:hidden;vertical-align:middle;border-radius:2px;margin-top:-1px;-webkit-transition-property:hover;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out 0;-o-transition-property:background-color;-o-transition-duration:.15s;*text-indent:0;*line-height:99em;*vertical-align:top}a.sm2_button:focus{outline:0}a.sm2_button,a.sm2_button.sm2_paused:hover{background-color:#39c;background-image:url(mp3-player-button/image/arrow-right-white.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAKCAYAAABmBXS+AAAAbklEQVQY02NgQAL//v1jZMAF/v//vwuIs9HEUBUBTbj4HwIeA3EGVsVAxtn/qOAVUGM8uknIiv4hsV8A5ZKxKfoLVvnvHwifAzLtMKwDSQLBVSBti27dJajkcSD2RJODO3wtkOOMz/tMSJJYAxMA5dmsL0IfubQAAAAASUVORK5CYII=);background-image:none,url(mp3-player-button/image/arrow-right-white-2x.png);background-size:9px 10px;*background-image:url(mp3-player-button/image/arrow-right-white.gif);background-repeat:no-repeat;background-position:5px 50%;*background-position:5px 4px}a.sm2_button:hover,a.sm2_button.sm2_playing,a.sm2_button.sm2_playing:hover{background-color:#c33}a.sm2_button.sm2_playing,a.sm2_button.sm2_playing:hover{-moz-transform:rotate(90deg);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg)}a.sm2_button.sm2_paused,a.sm2_button.sm2_paused:hover{background-color:#666}
+.turntable{position:relative}.turntable,.turntable img.stub{width:100%;max-width:1256px}.turntable .table-bg{position:absolute;top:0;left:0;width:100%;height:100%;background:transparent url(turntable/image/tt_table.png) no-repeat 0 0;background-size:contain}.turntable .frame,.turntable .bd{position:absolute;top:9.7%;left:5.4936%;height:82.25%;width:88.15%;padding:.054936% 0 0 .099%;border-radius:5px;-webkit-background-clip:padding-box;background-clip:padding-box;overflow:hidden}.turntable .frame{background:#262626;padding:1px;margin-left:-1px}.turntable .platter{position:absolute;top:.33%;left:5.025%;width:72.75%;height:100%;background:transparent url(turntable/image/platter.png) no-repeat 50% 50%;background-size:contain;border-radius:100%;overflow:hidden}.turntable .slipmat,.turntable .record,.turntable .record-grooves{position:absolute;top:6.3%;left:8.35%;width:66.2%;height:87.994%;border-radius:100%;overflow:hidden}.turntable .label{position:absolute;top:37.25%;left:31.45%;width:20%;height:26.5%;background:#fff;border-radius:100%}.turntable.has-artwork.hide-label-with-artwork .label{display:none}.turntable .slipmat{background:transparent url(turntable/image/slipmat.jpg) no-repeat 50% 50%;background-size:contain}.turntable.power-on.motor-on .platter,.turntable.power-on.motor-on .spindle,.turntable.power-on.motor-on .record-grooves,.turntable.power-on.motor-on.has-artwork .record,.turntable.power-on.motor-on .slipmat{-webkit-transition-property:-webkit-transform;-webkit-transform-origin:50% 50%;transition-property:transform;transform-origin:50% 50%;-webkit-animation:spin 2.33s linear infinite;animation:spin 2.33s linear infinite}.turntable.power-on.motor-on .slipmat{-webkit-animation-duration:1.75s;animation-duration:1.75s}.turntable .record-holder,.turntable .slipmat-holder{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;-webkit-transition:all .35s;transition:all .35s;transform:scale3d(1.15,1.15,1.15);transform-origin:42% 50%}.turntable.has-record .record-holder,.turntable.has-slipmat .slipmat-holder{opacity:1;transform:scale3d(1,1,1);-webkit-filter:none;filter:none}.turntable .record{background-color:#000;background-size:cover;background-position:50% 50%;background-repeat:no-repeat}.turntable .record-grooves{background:transparent url(turntable/image/record-grooves-1440x1440-white.png) no-repeat 50% 50%;background-size:contain;opacity:.15}.turntable .spindle{position:absolute;left:40.78%;top:49.45%;width:1.17%;height:1.55%;background-color:rgba(0,0,0,0.65);border-radius:100%;border:1px solid rgba(0,0,0,0.15);background-image:-webkit-radial-gradient(center,ellipse cover,rgba(255,255,255,1) 0,rgba(128,128,128,0) 100%);background-image:-o-radial-gradient(center,ellipse cover,rgba(255,255,255,1) 0,rgba(128,128,128,0) 100%);background-image:-ms-radial-gradient(center,ellipse cover,rgba(255,255,255,1) 0,rgba(128,128,128,0) 100%);background-image:radial-gradient(ellipse at center,rgba(255,255,255,1) 0,rgba(128,128,128,0) 100%);-webkit-background-clip:padding-box;background-clip:padding-box}.turntable .tonearm-holder,.turntable .tonearm{-webkit-transform-origin:54% 27%;transform-origin:54% 27%}.turntable .tonearm-holder{position:absolute;right:0;top:0;margin-top:-4%;margin-right:2.75%;width:28.55%;height:99.75%}.turntable .tonearm{position:absolute;right:0;top:0;width:100%;height:100%;background:transparent url(turntable/image/tt_arm.png) no-repeat 0 0;background-size:contain;-webkit-transition:-webkit-transform .1s;transition:transform .1s}.turntable.motor-on.has-record .tonearm-holder{-webkit-animation:wobble 1s ease-in-out alternate infinite;animation:wobble 1s ease-in-out alternate infinite}.turntable .button:active{transform-origin:50% 50%;transform:scale(0.975);opacity:.9}.turntable .start-stop{position:absolute;top:85.85%;left:2%;width:10.58983%;height:10.65%;background:transparent url(turntable/image/tt_startstop.png) no-repeat 0 0;background-size:contain;margin:.175% 0 0 -0.175%;border-radius:5px}.turntable .power-light{position:absolute;bottom:18.5%;left:5.75%;width:15.95%;height:17.9%;background:transparent url(turntable/image/power-light.png) no-repeat 0 0;background-size:contain;-webkit-transform:rotate(12.5deg);transform:rotate(12.5deg);-webkit-transform-origin:50% 50%;transform-origin:50% 50%;-webkit-transition:opacity .25s;transition:opacity .25s;opacity:0}.turntable.power-on .power-light{opacity:1}.turntable.power-on.motor-on .power-light{-webkit-animation:flicker .08s linear infinite;animation:flicker .08s linear infinite}.turntable .power-dial{position:absolute;bottom:17.5%;left:2.75%;width:5.95%;height:7.9%;-webkit-transform:rotate(0);-webkit-transform-origin:50% 50%;-webkit-transition:transform .2s ease-out;transform:rotate(0);transform-origin:50% 50%;-webkit-transition:-webkit-transform .2s ease-out;transition:transform .2s ease-out;background:transparent url(turntable/image/tt_powerdial.png) no-repeat 0 0;background-size:contain}.turntable.power-on .power-dial{-webkit-transform:rotate(22.5deg);transform:rotate(22.5deg)}.turntable .speed-33{position:absolute;bottom:4%;left:13.4%;width:5.12%;height:1.85%;background:transparent url(turntable/image/tt_33.png) no-repeat 0 0;background-size:contain}.turntable.power-on .speed-33.on{background-image:url(turntable/image/tt_33_on.png)}.turntable .speed-45{position:absolute;bottom:4%;left:19.05%;width:5.12%;height:1.85%;background:transparent url(turntable/image/tt_45.png) no-repeat 0 0;background-size:contain}.turntable.power-on .speed-45.on{background-image:url(turntable/image/tt_45_on.png)}.turntable .light{position:absolute;bottom:2%;left:48.25%;width:21.7%;height:24.9%;background:transparent url(turntable/image/tt_lightoff.png) no-repeat 0 0;background-size:contain}.turntable .light-on{position:absolute;bottom:3.15%;left:52.25%;width:18.7%;height:19.9%;background:transparent url(turntable/image/tt_lighton.png) no-repeat 0 0;background-size:contain;transform:rotate(12deg);opacity:0;-webkit-transition:opacity .2s;transition:opacity .2s}.turntable.power-on .light-on{opacity:1}@-webkit-keyframes flicker{from{opacity:.85}to{opacity:1}}@keyframes flicker{from{opacity:.85}to{opacity:1}}@-webkit-keyframes spin{from{-webkit-transform:rotate(180deg)}to{-webkit-transform:rotate(540deg)}}@keyframes spin{from{transform:rotate(180deg)}to{transform:rotate(540deg)}}@-webkit-keyframes wobble{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(0.33deg)}}@keyframes wobble{from{transform:rotate(0)}to{transform:rotate(0.33deg)}}#sm2-container{position:absolute;width:1px;height:1px;overflow:hidden;_overflow:hidden}#sm2-container object,#sm2-container embed{width:48px;height:48px;max-width:48px;max-height:48px}#sm2-container.swf_timedout{position:relative;width:48px;height:48px}#sm2-container.swf_timedout,#sm2-container.swf_timedout object,#sm2-container.swf_timedout embed{min-width:48px;min-height:48px}#sm2-container.swf_unblocked{width:1px;height:1px}#sm2-container.swf_loaded object,#sm2-container.swf_loaded embed,#sm2-container.swf_unblocked object,#sm2-container.swf_unblocked embed{left:-9999em;top:-9999em}#sm2-container.swf_error{display:none}#sm2-container.high_performance,#sm2-container.high_performance.swf_timeout{position:absolute;position:fixed}#sm2-container.high_performance{overflow:hidden;_top:-9999px;_left:-9999px;bottom:0;left:0;z-index:99}#sm2-container.high_performance.swf_loaded,#sm2-container.high_performance.swf_unblocked{z-index:auto}#sm2-container.high_performance.swf_loaded,#sm2-container.high_performance.swf_unblocked,#sm2-container.high_performance.swf_unblocked object,#sm2-container.high_performance.swf_unblocked embed{height:8px;width:8px}#sm2-container.high_performance.swf_loaded{top:auto;bottom:0;left:0}#sm2-container.high_performance.swf_loaded object,#sm2-container.high_performance.swf_loaded embed,#sm2-container.high_performance.swf_unblocked object,#sm2-container.high_performance.swf_unblocked embed{left:auto;top:auto}#sm2-container.high_performance.swf_timedout{z-index:99}
+body{background:#fff;color:#333;margin:0;padding:0;font:76% "helvetica neue",helvetica,arial,verdana,tahoma,"sans serif";_width:99.5%;-moz-transition:font-size .1s;-webkit-transition:font-size .1s;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}@media all and (min-width:1280px){body{font-size:85%}}@media all and (min-width:1600px){body{font-size:90%}#nav>ul>li>strong>a{padding-bottom:.5em !important}}@media all and (min-width:1800px){body{font-size:105%}}body.home{min-width:80em}body,#main-wrapper,#nav ul li strong a{background:#fff url(../demo/_image/noise.png)}body,#main-wrapper,#nav ul li strong a{background:#fff url(../demo/_image/tiny_grid.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaAgMAAADUJKRdAAAADFBMVEX8/Pz19fX09PT29vY9qbYoAAAAaElEQVR4Xk2MoREDMRADrzSDBQcEQj71GBw4kBbSQKp4YBBw9PsJyLxtsR2tZNfx/LyPhzX7R1Ue2SfjKlicDKBNdpBXsz790Nj8kUlo+WR47PvEPfY+gb7+kMhm5801EBsLvq/z3v8Apg8pkRmgbrsAAAAASUVORK5CYII=);*background:#fff url(../demo/_image/tiny_grid.png)}#nav ul li strong a{background-position:0 5px}@font-face{font-family:'DejaVuSansMonoBook';src:url('../demo/_image/dejavusansmono-webfont.eot');src:url('../demo/_image/dejavusansmono-webfont.eot?#iefix') format('embedded-opentype'),url('../demo/_image/dejavusansmono-webfont.woff') format('woff'),url('../demo/_image/dejavusansmono-webfont.ttf') format('truetype');font-weight:normal;font-style:normal}h2.special{font-family:"ChunkFive","ChunkFiveRegular","helvetica neue",helvetica,arial,verdana,tahoma,"sans serif";font-weight:normal;display:inline}h1,h2,h3,h4{font-size:1em;margin:0;padding:0;vertical-align:middle;font-weight:500}h4.new,h4.recent,h4.flash9{min-height:24px}h1{font-size:2em;font-weight:500}h2{font-size:1.5em}h3{font-size:1.17em;font-weight:bold;border-top:.25em solid #333;border-bottom:1px dotted #999;padding-top:.25em;padding-bottom:.25em;_margin-top:1.5em}body.home h3{border-top:.25em solid #444;margin-top:1.25em}#doc .c2 h3{position:relative;background:#333;color:#fff;padding:.25em .75em;border:0;line-height:1.4em}h3,.likeh3,.home .columnar .c2 #about-sm2 h3:first-child{margin-top:1.5em}h4{margin:1.5em 0 .5em 0;font-size:1.15em;font-weight:500}h5{font-size:1.2em;font-weight:500;color:#333}.c2 h5{border-bottom:1px solid #ccc;padding-bottom:.25em}.sub-heading{color:#666;font-weight:400}h2.special a{top:-0.65em}#turntable-video{width:100%;max-width:1920px;max-height:500px;overflow:hidden}body.home #about-header{position:relative;background-size:contain;padding-left:18%;margin-right:19em;min-height:175px;padding-top:1.75em}body.home .sm2-speaker{position:absolute;left:0;top:0;width:20%;height:120%;background:transparent url(../demo/_image/soundmanager2-speaker.png) no-repeat 50% 50%;max-width:256px;max-height:250px;background-size:contain}body.home #about-header .feature{position:relative;vertical-align:middle;font-size:1.2em}body.home #about-sm2 h2.special,body.home #about-sm2 h3,body.home #about-sm2 h4{font-weight:500;font-size:2em;border-bottom:0;padding-bottom:0}body.home #about-sm2 h2.special{font-size:3.5em;color:#333;margin-top:.1em}body.home #about-sm2 h3{font-size:2.25em}body.home #about-sm2 b{font-weight:500}body.home #about-sm2 ul b{font-weight:600}body.home #about-sm2 strong{font-weight:500;color:#333}#col3 a.button,a.feature-hot,a.feature{display:inline-block;-moz-transition:all .25s ease-in-out;-webkit-transition:all .25s ease-in-out;transition:all .25s ease-in-out;text-shadow:0 1px 0 rgba(0,0,0,0.33)}@-moz-keyframes highlight{from{box-shadow:0 0 0 rgba(255,64,64,0)}to{box-shadow:0 0 16px rgba(255,64,64,0.75)}}@-webkit-keyframes highlight{from{box-shadow:0 0 0 rgba(255,64,64,0)}to{box-shadow:0 0 16px rgba(255,64,64,0.75)}}#col3 a.feature{margin-top:0}a.feature-hot:hover,a.feature:hover,#col3 a.button:hover{-moz-animation-duration:.5s;-moz-animation-name:highlight;-moz-animation-iteration-count:infinite;-moz-animation-direction:alternate;-webkit-animation-duration:.5s;-webkit-animation-name:highlight;-webkit-animation-iteration-count:infinite;-webkit-animation-direction:alternate}body.home #about-sm2 h3{color:#444;font-weight:bold;padding-bottom:0;margin-bottom:0;font-weight:300}body.home h4{border-bottom:1px solid #e9e9e9;padding-bottom:.33em;margin-bottom:.75em}body.home #about-sm2 h4{font-weight:600;color:#777;font-size:1.3em;margin-bottom:1.25em;margin-top:.15em}body.home #about-sm2 h4 b{color:#777}body.home #about-sm2 h3+h4{color:#666;font-size:1.25em;font-weight:400;margin-bottom:2em;border-bottom:1px dotted #b0b0b0;padding-bottom:.75em}body.home .demo-more,body.home .demo-more-abs{text-align:right;font-size:100%;margin-right:.25em;white-space:nowrap}body.home .demo-more-abs{position:absolute;right:0;bottom:0}body.home #about-sm2 h4.home-shopping-network{font-style:italic}em em{color:#036;background:#e9f3ff;font-weight:bold;margin-top:-0.3em;padding:.2em .25em}pre{border-left:2px solid #f3f3f3;padding-left:.5em}dl pre{border-color:#e9f3ff}dl.alt pre{border-color:#f3f3f3}pre,code,pre code,.code,.code-block,dt,#soundmanager-debug,.c3 ul li ul li{font-family:Menlo,"DejaVu Sans Mono","DejaVuSansMonoBook",monaco,"Andale Mono","VT-100","Lucida Console","Courier New",monospace,courier,system,sans-serif}pre,code,.code,dt,#soundmanager-debug{font-weight:normal;line-height:auto;color:#069;background:#f6fcff}.no-code-highlight pre,.no-code-highlight code,.no-code-highlight .code .no-code-highlight{background:transparent}pre,#soundmanager-debug{font-size:100%}body.home p code{font-size:91%}pre code{font-size:100%}pre{line-height:1.75em}pre.specialcommentblock span span{*line-height:1.75em}.block.small{font-size:92%}p pre,p.in pre{font-size:.97em}#soundmanager-debug{background:#fff;padding-left:.75em;border:2px solid #def;font-size:85%;line-height:1.7em}body.home #soundmanager-debug{position:fixed;_position:absolute;bottom:1em;right:1em;height:12em;width:auto;overflow:auto;padding:0;margin:1em 6px 6px 1em;opacity:.95;color:#333;border:1px solid #cde;border-radius:3px;background:#f3f9ff;z-index:10;font-size:85%;line-height:1.2em}body.home #soundmanager-debug div{padding-left:.5em}#soundmanager-debug div{margin:0;padding:.25em 0;font-size:100%;color:#333}#soundmanager-debug div{background-color:#fff}#soundmanager-debug div.sm2-alt{background-color:#f3f9ff;color:#369}#live-debug{display:table;*display:block}dd pre,dd code{background:transparent}pre code{font-size:1em}pre{white-space:-moz-pre-wrap;white-space:pre-wrap;word-wrap:break-word}ul.code-block em,pre span,code span,dt span{color:#393}ul.code-block em{font-style:normal}ul.code-block span,pre span span,code span span,dt span span{color:#567}pre.block,pre.block code,div.block div.code,ul.code-block{position:relative;display:table;*display:block;border:1px solid #ccc;border-radius:3px}div.block,pre.block{background:#e9f3ff;border-color:#eee;padding:3px}pre.block code,.block .code{background:#fff;border:1px solid #cde;padding:.5em;font-size:100%;line-height:1.75em;background-image:-webkit-linear-gradient(#fcfcfc 50%,#fff 50%);background-image:-o-linear-gradient(#fcfcfc 50%,#fff 50%);background-image:linear-gradient(#fcfcfc 50%,#fff 50%);background-size:100% 3.5em;background-origin:content-box}#sm2-properties .code{background-image:none}pre.block code{padding:1em}h2 code{background:0;font-size:93%}dl{background:#f9fcff;padding-bottom:1px;border:1px solid #cde;border-radius:3px;margin-top:1em}dd{margin:1em 0;padding:0 1em;line-height:1.75em}dt{padding:0;margin:0;border-bottom:1px solid #def;padding:.5em .5em .5em .75em;background:#eef6ff;font-size:1.15em}dt.alt{background:#f3f3f3;border-bottom-color:#e6e6e6}dl:nth-child(2n+1),dl.alt{background:#fcfcfc;padding:0 0 1px 0;border-color:#ddd}dl.tight dt.alt{background:#fcfcfc}#smsound-methods dl a{font-weight:normal}#smsound-methods dt:last-of-type{border-bottom:0}h2{padding-top:.5em}#top{position:relative;padding:1em 1em 0 1.5em;max-width:95.5em;color:#fff;z-index:3;margin:0 auto}
+#content{background:#222 url(../demo/_image/noise-dark.png)}#top,#top div{*zoom:1}#top h1{display:inline}#top h2{font-size:1.25em;font-weight:300;padding-top:2px}#top h1,#top h2,#version{text-shadow:0 1px 0 rgba(0,0,0,0.5)}#main-wrapper{position:relative;box-shadow:inset 0 0 16px #fff}#main{position:relative;padding:0 0 2em 0;padding-top:1px;margin:0 auto;*padding:0 1em 2em 1em;zoom:1}#main{max-width:98em}body.home #main{box-shadow:none;max-width:104em}.columnar{position:relative;margin:0;padding:0;margin:1.9em .5em .5em 1em}.columnar .c1{position:absolute;left:0;top:0;width:20em;height:30px;_position:relative;_height:auto}#doc .columnar .c1{left:auto;right:1em;_right:auto}.columnar .c1 h2{position:relative;font-size:1.2em;padding:.37em .5em;vertical-align:middle;background:#333;color:#fff;text-indent:.25em}.columnar .c1 p{margin:.5em 0 1em 0;padding-left:.5em;padding-right:.5em;font-size:.95em;line-height:1.35em;color:#666}.columnar .c1 p code{color:#369}.columnar .c2{position:relative;margin-top:0;margin-left:22em;margin-bottom:1.5em}.triple .columnar .c2{margin-right:21.25em;min-width:20em}#doc .triple .columnar .c2{margin-left:21.5em;margin-right:23em;_margin-right:0}#doc.special .triple .columnar .c2{margin-right:.75em;max-width:70em}#doc .triple .columnar .c1{margin-right:0;margin-left:21.25em}.columnar .c2 p:first-child{margin-top:.2em}.columnar .c2>.f-block:first-child>h4{margin-top:.5em}.columnar .c2 strong strong{display:block;padding:.5em;border-bottom:1px solid #999;background:#f0f6ff;color:#369}.columnar .c2 p{line-height:1.75em;padding-top:.25em;padding-bottom:.25em}p code,.columnar .c2 p code{font-size:97%}.three .columnar{position:relative}.three .columnar .c1{position:relative;width:20em}.three .columnar .c2{position:relative;margin-right:16em}.c3{position:absolute;right:1em;margin-right:16px;top:2em;width:16em;margin-top:-0.5em}#doc .c3{right:auto;margin-right:0;margin-left:16px;left:1.25em;z-index:1}#nav{position:relative;margin-top:.75em;margin-left:-0.5em}ul{line-height:1.75em}ul li{margin-bottom:.75em}#nav ul{margin:0;padding:0;line-height:1em;list-style-type:none}#nav ul li{position:relative;margin:0;padding:0;float:left;display:inline;padding-right:1px}#nav ul li ul{position:absolute;z-index:1;display:none;min-width:19em;max-width:21em;background:#39c;background:-moz-linear-gradient(top,rgba(51,153,204,0.99) 0,rgba(35,96,127,0.96) 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,rgba(51,153,204,0.99)),color-stop(100%,rgba(35,96,127,0.96)));background:-webkit-linear-gradient(top,rgba(51,153,204,0.99) 0,rgba(35,96,127,0.96) 100%);background:-o-linear-gradient(top,rgba(51,153,204,0.99) 0,rgba(35,96,127,0.96) 100%);background:-ms-linear-gradient(top,rgba(51,153,204,0.99) 0,rgba(35,96,127,0.96) 100%);background:linear-gradient(top,rgba(51,153,204,0.99) 0,rgba(35,96,127,0.96) 100%);text-shadow:0 1px 0 rgba(0,0,0,0.25);_width:19em;*top:2.3em;*left:0}#nav ul li:last-child ul{right:1px}#nav ul li:hover ul,#nav ul li ul:hover{display:block}#nav ul li ul li{float:none;display:block;width:100%}#nav ul li ul li a{display:block;width:auto;border:0;padding:.5em 0 .5em 1em;font-size:1.1em;line-height:1.1em;color:#fff;font-weight:400;color:rgba(255,255,255,0.9);border-bottom:1px dotted rgba(0,0,0,0.2);border-top:1px dotted rgba(255,255,255,0.2)}#nav ul li ul li:first-of-type a{border-top:0}#nav ul li a{display:inline-block;padding:.5em 1em;text-decoration:none;font-weight:bold;color:#fff}#nav ul li ul li a:hover{background-color:#369;background-color:rgba(0,0,0,0.45)}#nav>ul>li>a,#nav>ul>li>strong>a{color:#ddd;font-size:1.25em;font-weight:400;vertical-align:bottom}#nav ul li strong a{color:#333}#nav>ul>li>strong>a{padding-bottom:9px}#nav ul li a:hover,#nav>ul>li:hover>a{background:#39c;color:#fff;text-shadow:0 1px 0 rgba(0,0,0,0.25)}#version{position:relative;float:right;display:inline;margin-left:1em;font-size:90%;margin-bottom:0;bottom:-0.9em;color:#ccc}div.clear{clear:both;font-size:1px;line-height:1px}.note{margin-top:.5em;font-size:.95em;color:#999}.note a{color:#666;padding:1px;margin:-1px}.note a:hover{color:#fff;background:#666}.medium-note{padding-top:1.5em;font-size:1em}ul.standard{line-height:1.5em;padding-left:1.2em;*padding-left:0;color:#333;margin-top:1em;margin-bottom:1em;list-style-type:square}ul.standard li{margin-bottom:.5em}ul.standard ul{margin-top:.5em;margin-bottom:1.5em;padding-left:1.2em}.c3 ul{list-style-type:none}.c3 ul,.c3 ul li{margin:0;padding:0}.c3 h2{font-size:1.1em;text-indent:.4em}.c3 ul li a{display:block;text-decoration:none}.c3 ul li,.c3 ul li a,.c3 ul li a:hover,.c3 ul li a:focus{color:#333;_color:#333;outline:0}.c3 ul li.active{box-shadow:0 0 6px #036 inset;border-radius:1px}.c3 ul li.active a{border-radius:2px;text-shadow:0 1px 0 rgba(0,0,0,0.25)}.c3 ul li.active,.c3 ul li.active a,.c3 ul li ul li:hover,.c3 ul li ul li:hover a{color:#fff}.c3 ul li.active a:hover{_color:#fff}.c3 .box{margin-top:6px}.wedge,.c3 h2{position:relative;background:#333;color:#fff;margin:0;padding:0;height:2.101em;line-height:1.65em}.c3 h2{height:2em;line-height:2em}.c3 h2,#doc .c2 h3{text-shadow:0 1px 0 #000}.wedge{background-color:#39c}.wedge-dark{background:#333}.wedge .l,.wedge .r{border-top:1.75em solid #333}.c3 h2 .l,.c3 h2 .r{border-top:2em solid #333;border-top:2.1em solid #333\9}.wedge .l,.c3 h2 .l,.wedge .r,.wedge-dark .r,.c3 h2 .r{background:transparent url(../demo/_image/wedge.png) no-repeat;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAAEABAMAAACJ12OUAAAAGFBMVEUREREAZpkYGBgAZpkiIiIAZpkREREAZpkArR2CAAAABnRSTlMAAOvrEhJBIv9yAAAC0UlEQVR42u3ZuW0cQRCF4cIPhrG2MhDkLZgDM5ChBGQoKBlMgdgElAQ9gVACNMTZ2WOO7rraI2rcna33cdjTTTzyQ7++fzFuQPTrdDBuMAa8H04vQwNOL++HkQHTtw0CBmAekh0wf1cnYAEsAibAIGACDAI2QCdgA3QCDoBKwAFQCXgAGgEPQCPgAigEXACFgA/QJ+AD9Ak4AV0CTkCXgBfQI+C/tT0W952dubgBncH4Ae3J+AHt0QQAzdkEAM3hRACt6UQArfGEAI35hACNAGKAfQIxwD6CIGCXQRCwCyEK2KYQBWxjCAM2OYQBmyDigHUSccA6igRglUUCsAojA1imkQEs40gBFnmkAItAcoB7IjnAPZIk4JZJEnALJQu4ppIFXGNJAy65pAGXYPKAOZk8YI5mAHDOZgBwJjACmAiMACYCT7/U6+c3/fOv1R9Uf1D9QfUH1R9Uf1D9QfUH1R9Uf1D9QfUH1R9Uf1D9wefvD/4NXhwfRwQPrzy8jgw4PiIjhI90ZITwEY4MEKZsZIAwRSN5wjkZyRPOwUiaMOciacIci2QJl1QkS7iEIknCNRNJEq6RSI5wS0RyhFsgkiLc85AU4R6HZAiLNCRDWIQhCcIyC0kQllFInLBKQuKEVRASJqxzkDBhHYNECZsUJErYhCBBwjYDCRK2EUiMsEtAYoRdABIi7OcjIcJ+PBIhNKYjEUJjOBIgtGYjAUJrNOInNCcjfkJzMO47O3Px39oeixvb+cFwP67Oo8X7vHpPFu9vrPe7xblmuqsL56rtrm98y7a/vPG9OP0XDNerq7ziuDYPZZPBs3toewye/Uvb5XDsoOo+i2MPV3d67E1c3+ixjxH9qME8yIzDDvMoNY5brLPUOm2xTnPrvLf++3+0/uLgz2/1ev6rf/5W/UH1B9UfVH9Q/UH1B9UfVH9Q/UH1B9UfVH9Q/UH1B9UffPr+4D+tsZObsTO2qgAAAABJRU5ErkJggg==);*background-image:url(../demo/_image/wedge.png)}.wedge .l,.c3 h2 .l{background-position:-64px 0;position:absolute;left:0;top:0;width:16px;height:100%;margin-left:-16px}.wedge .r,.wedge-dark .r,.c3 h2 .r{background-position:-48px 0;position:absolute;right:0;top:0;width:16px;height:100%;margin-right:-16px}.wedge .l,.wedge .r{border-color:#39c}.wedge .l{background-position:-64px -64px;border-top:2em solid #39c}.wedge .r{margin-top:-15px;border-top:0;height:16px;border-bottom:2em solid #39c;background-position:0 -192px}.wedge-dark .l,.wedge-dark .r{border-color:#333}.wedge-dark .l{background-position:-64px 0}.wedge-dark .r{background-position:0 -128px}.c3 h2 .r.up{margin-top:-16px;border-top:0;height:16px;border-bottom:1.66em solid #333;background-position:0 -128px}.c3 h2 .l.flat,.wedge .l.flat,.c3 h2 .r.flat,.wedge .r.flat{background-image:none}.c3 ul{margin:0;padding:0;list-style-type:none}.c3 ul li{border:1px solid #f3f3f3;border-top:0;border-bottom:0}.c3 ul ul li{border:0}.c3 ul li{margin:0;padding:0}.c3 ul li ul li{background-color:#fcfcfc;background-color:rgba(255,255,255,0.5);font-size:97%;line-height:2.4em;text-indent:.5em;padding:0 .25em;cursor:hand;border-bottom:1px dotted #eee}.c3 ul li ul li:hover{background-color:#999;cursor:pointer;cursor:hand}.c3 ul li ul li.active{background-color:#39c;color:#fff}.c3 h3{position:relative;margin:0;padding:0;height:auto;min-height:25px;background:#39c;border:0;color:#fff;text-indent:.5em;font-size:1em;line-height:2em;text-shadow:0 1px 0 rgba(0,0,0,0.25)}.c3 h4{font-size:1em;margin:0;padding:.4em .2em .4em .75em;vertical-align:middle;color:#333;background-color:#f3f3f3;background-color:rgba(0,0,0,0.05);border-top:1px dotted #d6d6d6;border-bottom:1px dashed #e9e9e9;text-shadow:0 1px 0 #fff}.c3 h4:first-of-type{border-top-color:transparent}#get-satisfaction h2 a{color:#fff}#get-satisfaction a{color:#444}#get-satisfaction a:hover{color:#fff}.c3 h2 a{color:#fff}.c3 h2 a:hover{color:#fff;text-decoration:underline}.flash9{background-image:url(../demo/_image/flash9.png);background-repeat:no-repeat;background-position:bottom right;_background-image:none}li.flash9{background-position:bottom right}.flash9:hover,.flash9.active{background-image:url(../demo/_image/flash9-dark.png);_background-image:none}.new{background-image:url(../demo/_image/new.png);background-repeat:no-repeat;background-position:bottom right;_background-image:none}.recent{background-image:url(../demo/_image/new-bw.png);background-repeat:no-repeat;background-position:bottom right;_background-image:none}
+.new:hover,.new.active,.recent:hover,.recent.active{background-image:url(../demo/_image/new-dark.png);background-repeat:no-repeat;background-position:bottom right;_background-image:none}.deprecated{font-style:italic;color:#333 !important}span.nevermind,.removed{text-decoration:line-through;opacity:.33}strong.removed{font-weight:normal;opacity:.5}.padded{padding:.5em}dd.deprecation-note{color:#933;background-color:#fff6f6}.c3 p{font-size:.9em;padding-left:.75em;padding-right:.5em}.c1 pre code{margin-top:0;color:#369;margin-left:0}.c1 pre{margin-top:0;padding-top:0;margin-left:.5em}#reset-filter{position:relative;font-family:"Helvetica Neue","Helvetica",helvetica,arial,verdana,sans-serif;font-weight:300;font-size:2.5em}.c2 .option{font-size:85%;float:right;display:inline;margin-left:1em;margin-right:.5em;margin-top:3px;line-height:1em;white-space:nowrap}.c2 .option a{padding:.1em .35em .1em .35em;color:#39c}#filter-box{position:relative;display:none}#get-satisfaction{position:relative}#support-wrapper{position:relative;background:#fff;border:1px solid rgba(0,0,0,0.03);box-shadow:0 0 1px rgba(0,0,0,0.075)}body.home #support-wrapper{position:absolute;width:100%}#gsfn_content{position:relative;padding:.5em 0 .5em 0}#gsfn_content ul{position:relative;overflow:hidden;height:0;margin:0;-webkit-transition:height .5s ease-in-out;-moz-transition:height .5s ease-in-out;transition:height .5s ease-in-out}#gsfn_content ul li{border:0}div#gsfn_list_widget img{border:0}div#gsfn_list_widget a{text-decoration:none}div#gsfn_list_widget a.widget_title{display:block;margin-bottom:10px;font-weight:bold}div#gsfn_list_widget .powered_by{font-family:verdana,arial;margin:-0.25em 1em 0 1em;padding:.25em 0 .5em 0;border-top:1px dotted #ddd;font-size:75%}body.home div#gsfn_list_widget .powered_by{padding-bottom:0}div#gsfn_list_widget .powered_by a{font-style:italic;color:#999}div#gsfn_list_widget .powered_by a:hover{color:#333}div#gsfn_list_widget div#gsfn_content{font-size:.88em;padding-left:.5em;padding-right:.5em}div#gsfn_list_widget div#gsfn_content li{text-align:left;position:relative;clear:right;*zoom:1}div#gsfn_list_widget div#gsfn_content li:hover,div#gsfn_list_widget div#gsfn_content li:hover a{background:#39c;color:#fff}div#gsfn_list_widget div#gsfn_content a.gsfn_link{display:block;line-height:1.2em;padding:5px 0 5px 5px}div#gsfn_list_widget div#gsfn_content a.gsfn_link:hover{_color:#fff;_background-color:#39c}div#gsfn_list_widget div#gsfn_content span.time{font-size:85%;color:#999;padding-left:3px;padding-right:3px;text-align:right;float:right;display:inline;margin-top:1px}div#gsfn_list_widget div#gsfn_content li:hover span.time{color:#fff}div#gsfn_list_widget div#gsfn_content p.gsfn_summary{margin-top:2px;position:relative;z-index:2}.tight{margin-top:0}.compact{margin-bottom:.25em !important}.smaller{margin-top:0 !important;margin-bottom:.25em !important;line-height:1.2em !important}.c2 a,a.cta{margin-top:-0.3em;padding:.2em .25em;margin-left:-0.25em;margin-right:-0.25em;*margin:0;*padding:0 2px;*margin:0 -2px 0 -2px;text-decoration:none;color:#39c;font-weight:500;border-radius:.25em;zoom:1}body.home .c2 a:hover,body.home a.cta:hover{text-shadow:none}pre code a,.c2 pre code a{color:#39c;font-weight:400;text-decoration:none;text-shadow:none}pre code a:hover,.c2 pre code a:hover{background-color:#39c;color:#fff;font-weight:400}.c2 a.sm2_button{border-radius:6px}.c2 a.sm2_button.type-2{border-radius:9px}.c2 a{color:#39c;font-weight:500;text-decoration:none}.c2 a.cta{text-decoration:none}a.cta span{font-size:1.5em;line-height:1em}a.cta:hover,.c2 a:hover,#sm2-options a:hover{position:relative;z-index:1;background-color:#39c;border-color:#39c;color:#fff;text-decoration:none}.c2 a.sm2_button:hover{background-color:#c33}dt a:hover span{color:#fff}a.cta-more{color:#def;font-size:.8em;position:absolute;right:0;margin:0;padding:1px;bottom:.9em;line-height:1em}a.cta-more:hover{background:#fff;color:#39c}div.html5support{clear:both;padding-top:2em}div.html5support span{padding:0 5px;display:inline-block;text-align:center;font-weight:400;background:#ccc;color:#fff;margin-bottom:.25em;border-right:1px dotted #fff;border-radius:0;margin-right:none}div.html5support em{font-weight:bold}div.html5support span.true{background:#696}div.html5support span.partial{background:#933}div.html5support em.partial{color:#933}div.html5support em.true{color:#696}#nav ul li ul{box-shadow:2px 2px 2px rgba(51,153,204,0.2)}.newer{vertical-align:middle;margin-top:1em;margin-bottom:1em}.newer a,a.feature,.feature-hot{position:relative;display:inline-block;background:#39f;font-size:1.1em;line-height:1.75em;padding:0 .5em;margin:0 .125em;color:#fff;font-weight:bold;border:3px solid #cce6ff;border:3px solid rgba(255,255,255,0.66);border-radius:8px;text-decoration:none}a.feature{margin-left:0}.newer a,.feature-hot{background:red;border-color:#f66;color:#fff}.newer a:hover,.c2 .feature-hot:hover{background:#900;border-color:#c00}a.feature:focus,a.feature:hover{background:red;border-color:#f66;color:#fff}# a.warning,span.warning{font-weight:bold}a.warning,span.warning,a.warning code,span.warning code{color:#930}a.warning:hover{color:#fff;background:#930}.newer p{margin:0;padding:0}.scratched-out{display:inline-block;text-decoration:line-through;color:#999;font-size:.9em;margin-top:-0.75em;-webkit-transform:rotate(-15deg);-moz-transform:rotate(-15deg);transform:rotate(-15deg)}div.inthewild{position:relative;margin-top:1em}ul.inthewild{display:inline;margin:0 auto;list-style-type:none}ul.inthewild,ul.inthewild li{position:relative;margin:0;padding:0}ul.inthewild{margin-bottom:2em}ul.inthewild li{display:inline-block;*float:left;*display:inline;width:128px;width:24%;min-width:64px;height:64px;vertical-align:middle;text-align:center;margin:2px 0;background-color:#fcfcfc;background-color:rgba(255,255,255,0.5);border-radius:2px;border:1px solid #eee;border-color:rgba(0,0,0,0.05)}ul.inthewild a,ul.inthewild a img{border:0;vertical-align:middle}ul.inthewild a{position:absolute;left:50%;top:50%;overflow:hidden;margin:0;padding:0;border-radius:0;background:transparent url(../demo/_image/logo-sprite.png) no-repeat 0 0;line-height:96px;vertical-align:middle}ul.inthewild a:hover{background-color:transparent}ul.inthewild a span{position:absolute;text-indent:-9999em}#tidal{background:transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMCIgeT0iMCIgdmlld0JveD0iMCAwIDMzMC4yIDQzLjciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDMzMC4yIDQzLjciIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwYXRoIGZpbGw9IiMwMDAwMDAiIGQ9Ik0xMjAuMSA0Mi44aC04LjVWMTIuN2gtMTFWNS41aDMwLjR2Ny4zaC0xMUwxMjAuMSA0Mi44ek0xNjUgNDIuOGgtOC41VjUuNWg4LjVWNDIuOHpNMzE1LjQgMzUuNGgxNC43djcuNGgtMjMuM1Y1LjVoOC41VjM1LjR6Ii8+PHBhdGggZmlsbD0iIzAwMDAwMCIgZD0iTTE5My40IDUuNWgxMy44YzEwLjIgMCAyMC4zIDUuNCAyMC4zIDE4LjYgMCAxMi40LTkuOSAxOC44LTE5LjggMTguOGwtMTQuMyAwTDE5My40IDUuNXpNMjAxLjYgMzUuNWg1LjNjNy4xIDAgMTEuOS00LjQgMTEuOS0xMS41IDAtNi43LTQuOC0xMS4yLTExLjctMTEuMmgtNS41VjM1LjV6TTI3NC44IDQyLjhoOS40TDI2OC44IDUuNUgyNjBsLTE1LjUgMzcuM2g5LjFsMi44LTcuNGgxNS43TDI3NC44IDQyLjh6TTI1OC42IDI4LjhsNS42LTE0LjYgNS42IDE0LjZIMjU4LjZ6Ii8+PHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgcG9pbnRzPSI0My43IDEwLjkgMzIuOCAyMS44IDIxLjkgMTAuOSAzMi44IDAgIi8+PHJlY3QgeD0iMjUiIHk9IjI1LjEiIHRyYW5zZm9ybT0ibWF0cml4KC0wLjcwNzEgMC43MDcxIC0wLjcwNzEgLTAuNzA3MSA3OS4xMjA0IDMyLjc4MTMpIiBmaWxsPSIjMDAwMDAwIiB3aWR0aD0iMTUuNCIgaGVpZ2h0PSIxNS41Ii8+PHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgcG9pbnRzPSIyMS45IDEwLjkgMTAuOSAyMS44IDAgMTAuOSAxMC45IDAgIi8+PHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgcG9pbnRzPSI2NS41IDEwLjkgNTQuNiAyMS44IDQzLjcgMTAuOSA1NC42IDAgIi8+PC9zdmc+) 50% 50% no-repeat;color:#000;width:85%;height:85%;left:0;color:#fff;top:0;margin:3.5% 0 5% 7%}#eight-tracks{background-position:0 0;width:64px;height:20px;margin:-10px 0 0 -32px}#audiogalaxy{width:100px;height:22px;background-position:0 -37px;margin:-11px 0 0 -50px}#discogs{background-position:0 -72px;width:55px;height:20px;margin:-10px 0 0 -27px}#hypem{background-position:0 -111px;width:80px;height:38px;margin:-19px 0 0 -40px}#lastfm{background-position:0 -176px;width:80px;height:28px;margin:-14px 0 0 -40px}#pitchfork{background-position:0 -688px;width:100px;height:20px;margin:-10px 0 0 -50px}#nyancat{background-position:0 -312px;width:64px;height:40px;margin:-20px 0 0 -32px}#earbits{background-position:0 -471px;width:100px;height:58px;margin:-29px 0 0 -50px}#songza{background-position:0 -424px;width:100px;height:58px;margin:-29px 0 0 -50px}#beats-music{background-position:0 -230px;width:100px;height:64px;margin:-34px 0 0 -48px}#baroque-me{background-position:0 -541px;width:88px;height:47px;margin:-23px 0 0 -42px}#freesound{background-position:0 -635px;width:100px;height:27px;margin:-15px 0 0 -50px}div.inthewild.active li:hover{background-color:rgba(255,255,255,0.9);border-color:#ccc;box-shadow:0 0 3px rgba(0,0,0,0.075)}.sidenote{font-size:85%;opacity:.75}ul.playlist{font-size:85%}ul.playlist li{margin-bottom:.2em}ul.playlist li a{font-size:1em;color:#333}ul.playlist li a,ul.playlist li a:hover{background:transparent;border-radius:0;line-height:1em}ul.playlist li .timing{margin-right:.1em;font-size:50%;top:.5em}ul.playlist.use-peak li .peak{height:.61em;margin-top:-5px;width:.92em}
+html.isSafari ul.playlist.use-peak li .peak{margin-top:-4px}ul.playlist.use-peak li .timing{right:4em}ul.playlist.use-peak li .peak-box{height:.66em}ul.playlist li .peak .l{margin-right:0}ul.playlist li .peak .l,ul.playlist li .peak .r{width:6px}ul.playlist li .peak .r{left:9px}a.not-supported{text-decoration:line-through;color:#666;opacity:.25}ul.graphic li{line-height:1.5em}ul.graphic li a,ul.graphic li a.sm2_link{min-width:17.75em;width:auto}ul.graphic li a,ul.graphic li a.sm2_link{background-color:#ddd;border-color:#ddd;color:#333;vertical-align:middle}ul.graphic li a{background:#ddd url(../demo/play-mp3-links/image/icon_play.png) no-repeat 3px 50%;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAA6ElEQVR42q2UvQqDMBRGC47dAj6rgygIDg5OfQlHF30GX0JFURddnEQU+eoNLaSJFRUvnPzA/c4QkjwA3AIf1tJWnitsRT8I+2Q0UfTM8/yFk0UZyooiNk0ThmE4BWUoK4r0cRxxBcr+iMh+AVW0LAtkoihCURS0/ocqwkaZpgnbtrmwrmts1DGR67owDIPjeR7iOEbXdfuisiwh4zgOSb5wcZIkYo8qapoGMpZlkYALwzBElmWoqkrsUUVt20LG930EQUAHTvstVFHf95BJ05TmPVQR3dQLKCI2zzOuQNnbHu3t38gtvAF1L6rpAc8MDwAAAABJRU5ErkJggg==);*background-image:url(../demo/play-mp3-links/image/icon_play.png);_background-image:url(../demo/play-mp3-links/image/icon_play.gif)}ul.graphic li a:hover,ul.graphic li a.sm2_paused:hover,ul.graphic li a.sm2_link:hover,ul.graphic li a.sm2_playing,ul.graphic li a.sm2_playing:hover{background-color:#369;border-color:#369;color:#fff}ul.graphic li a.sm2_link{-webkit-transition-property:none;-webkit-transition:none}.c2 ul.playlist li a{margin:0;padding:0;letter-spacing:-0.02em}ul.inline-playlist{min-height:49px;min-width:512px;margin-top:4em}ul.inline-playlist li{float:left;display:inline;width:45%;margin-right:.25%}body.home .sm2-inline-list .ui360-vis{margin-right:0}body.home #special-demo-left .ui360:last-child{margin-right:0}body.home .columnar .c2 p{font-size:1.1em;line-height:1.6em;color:#333}body.home .c2 ul.playlist li a{_color:#000}body.home .c2 ul.playlist li.sm2_paused a,body.home .c2 ul.playlist li.sm2_playing a{_color:#fff}body.home .c2 ul.standard{_margin-left:1.5em}body.home .ie6sucks{_background:transparent !important;_display:none !important}body.home .ie7sucks{*display:none !important}body.home #sm2-container{position:fixed;bottom:0;left:0;width:48px;height:48px;_margin:-8px 0 0 0}@-moz-keyframes flashblock{from{border-color:#f33}to{border-color:#fff}}@-webkit-keyframes flashblock{from{border-color:#f33}to{border-color:#fff}}body.home #sm2-container.swf_timedout{border:1px solid #f33;-moz-animation-duration:1s;-moz-animation-name:flashblock;-moz-animation-iteration-count:5;-webkit-animation-duration:1s;-webkit-animation-name:flashblock;-webkit-animation-iteration-count:5;width:48px;height:48px}body.home #sm2-container.swf_unblocked,body.home #sm2-container.swf_loaded{top:auto;left:0;bottom:0;margin:0;width:6px;height:6px}#sm2-support-warning{display:none;border:1px solid #f99;padding:.5em;margin-top:1.5em;font-weight:bold}#sm2-support{display:none;font-size:.9em !important;margin-top:1.5em}#sm2-support-warning,#sm2-support{background:#fff6f0;border:1px solid #f33}body.home #about-sm2 #sm2-support h3{border-color:#f99;margin-top:.25em}body.home #special-demo-left{min-height:70px;position:relative;float:left;display:inline;margin-right:14px;padding-right:.9em;border-right:1px dotted #e0e0e0;*border-right:0;_width:210px}body.home #special-demo-right{min-height:51px;position:relative;float:left;display:inline;margin-top:18px;*width:90px;_display:none}body.home #inline-playlist{clear:both;float:right;display:inline;width:256px;min-height:49px;margin-top:2em;padding-bottom:0}#demo-box{position:relative;float:right;display:inline;margin-top:-4px;background:#fff;padding-left:3em;width:256px;z-index:1}hr{visibility:hidden;margin:0;padding:0}.demo-block{position:relative;background:#f9f9f9;border:1px solid #e6e6e6;padding:4px;padding-top:.5em;margin-top:-0.55em;border-top:0}#demo-header{color:#333;background:#f9f9f9;border:1px solid #e6e6e6;border-bottom:0;margin-bottom:0;padding:.5em}#demos h3{padding-bottom:0;text-indent:.5em;font-weight:normal}#demos h3 a{font-weight:normal}#revision-list>li{margin-top:3em;margin-bottom:2em}#revision-list>li:first-child{margin-top:2em}body.home.has-lights{overflow-x:hidden}body.home #lights{position:absolute;border-top:1px solid #060;left:0;top:0;width:100%;z-index:4;display:none}.xlsf-light{position:absolute;margin-top:-1px}body.fast .xlsf-light{opacity:.9}.xlsf-light{opacity:.9}#explosion-box{position:absolute;left:0;top:0;width:100%;z-index:10}.xlsf-fragment{position:absolute;background:transparent url(christmas-lights/image/bulbs-50x50-fragments.png) no-repeat 0 0;width:50px;height:50px}.xlsf-fragment-box{position:absolute;left:0;top:0;width:50px;height:50px;*width:100%;*height:100%;display:none}.figure{display:inline;display:inline-block;border:1px solid #def;padding:.5em;margin:.5em 0 .5em 0}.figure .code span{padding:.25em;border:1px solid #f0f9ff;background:#fff}.figure .code span.mid{color:#666}#sm2-container.flash_debug{position:relative;width:auto;height:300px;width:100%;background:#f6f6f6;border:1px solid #ccc}#sm2-container.flash_debug object,#sm2-container.flash_debug embed{width:100%;height:100%;left:auto;top:auto}ul.file-structure ul{padding-left:1.5em}ul.file-structure li{list-style-type:square;margin-top:.25em;margin-left:0}ul.file-structure li span{color:#999}#sm2-filesizes{border:1px solid #ddd;background:#fff}#sm2-filesizes tr:nth-child(2n+1){background:#f9f9f9}#sm2-filesizes th{background:#eee;font-weight:bold;text-align:left}#sm2-filesizes th{padding:4px 6px}#sm2-filesizes td{padding:0 6px;border:1px solid #eee}#sm2-filesizes p{margin-top:.5em;margin-bottom:0}#sm2-filesizes pre{border-left:0;margin-top:.5em;margin-bottom:.5em}#sm2-filesizes .nw{white-space:nowrap}#sm2-filesizes .booyaa{background:#fff9f9;color:#900}#history li.in>p.compact{font-weight:bold}#sm2-options{position:relative;clear:both;color:#666;margin:.33em .75em 0 .75em;border-top:1px dotted #ddd}#sm2-options .options-divider{font-size:85%;color:#ccc}#sm2-options p{font-size:85%;padding-left:0;padding-bottom:0;margin-bottom:.75em}#sm2-options p:first-child{margin-top:.75em}#sm2-options a{color:#39c;text-decoration:none;padding:1px;margin-top:-2px 0 0 -2px}#without-html5{display:none}body.home #about-sm2 #inline-demo-header{margin-top:1.5em;border-bottom:1px solid #eee;padding-bottom:.5em}body.home #about-sm2 #inline-demo-header,body.home #about-sm2 .home-shopping-network{display:block}#about-sm2 a img{border:0}ul.code-block{list-style-type:none;position:relative;padding:3px;font-size:85%}ul.code-block,ul.code-block li{position:relative;margin:0;padding:0;line-height:1.5em}ul.code-block li{padding:.75em .5em}ul.code-block li:nth-child(2n+1){background-color:#fcfcfc}ul.code-block li:last-child{padding-bottom:0}ul.code-block li div{position:absolute;left:.5em;top:.75em;width:22em;z-index:2}ul.code-block li span{position:relative;display:block;padding-left:22.5em;text-indent:-2em}#soundmanager-properties ul.code-block{min-width:43em}div.oneup,div.twoup,div.threeup{position:relative;clear:both;padding:2em 1em 2.5em 1em;*zoom:1}div.oneup .column{position:relative;width:100%}div.twoup .column,div.threeup .column{position:relative;float:left;display:inline;width:33.3%;_width:32%}div.twoup .column{width:50%;_width:49%}div.oneup .column,div.twoup .column,div.threeup .column{padding-bottom:.5em}div.oneup .column-wrapper,div.twoup .column-wrapper,div.threeup .column-wrapper{margin:0 2.5em}div.oneup .column-wrapper.spaced-out,div.twoup .column-wrapper.spaced-out,div.threeup .column-wrapper.spaced-out{padding-top:6.25em}div.threeup.first{padding-top:.75em}div.threeup.first .column-wrapper{border-top:0}body.home #main .oneup p,body.home #main .twoup p,body.home #main .threeup p{font-size:1.1em;line-height:1.5em;margin-bottom:1.5em}body.home #main p.sidenote{font-size:92%;color:#666}body.home h2{margin-top:0}body.home div.c3{position:relative;float:right;display:inline;margin-left:30px;margin-top:-6px;z-index:2;margin-bottom:2.5em}body.home #inline-playlist{float:none;display:block;width:auto}body.home .sm2-inline-list .ui360-vis{margin:0 auto}body.home ul.playlist{font-size:85%}body.home ul.playlist li{font-size:1.75em;letter-spacing:-0.02em}body.home ul.playlist .sidenote{font-size:85%}body.home ul.graphic{margin-top:1em}body.home ul.graphic{position:relative}
+body.home ul.graphic li{float:left;display:inline;width:50%;margin-bottom:0}body.home ul.graphic li a,body.home ul.graphic li a.sm2_link{display:block;width:auto;min-width:8em;margin-right:.5em;margin-bottom:.5em}body.home ul li a:hover,body.home ul.graphic a.sm2_playing,body.home #inline-playlist li.sm2_paused a,body.home #inline-playlist li.sm2_playing a,body.home ul.playlist li div.timing,body.home .feature-hot,body.home #html5-support-li span{text-shadow:none}body.home .feature-hot{font-size:13px}body.home ul.graphic li a,ul.playlist li a{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;*overflow:auto;*white-space:wrap}body.home ul.playlist li a,body.home ul.playlist li a:hover{line-height:1.2em}body.home .demo-more a span,body.home .demo-more-abs a span{font-size:1.5em;line-height:1em;vertical-align:bottom}body.home #sm2-visualization{clear:both;margin-top:2em}body.home #sm2-visualization .ui360{float:none;display:block}body.home #sm2-visualization .ui360 .sm2-360ui{border-color:rgba(0,0,0,0.05);background-color:rgba(255,255,255,0.5);box-shadow:inset 0 0 32px rgba(0,0,0,0.075)}body.home #sm2-visualization .ui360 canvas,body.home #sm2-visualization .ui360 .sm2-360ui,body.home #sm2-visualization .ui360 a{border-radius:100%}body.home #sm2-visualization .ui360 a{line-height:340px;*line-height:480px;line-height:480px\9;color:#666 !important;text-shadow:0 1px 0 #fff}:root body.home #sm2-visualization .ui360 a{line-height:340px\0/IE9}body.home #sm2-visualization .ui360 a,body.home #sm2-visualization .ui360 canvas{-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out;-moz-transition-property:background-color,border,box-shadow;-webkit-transition-property:background-color,border,box-shadow;transition-property:background-color,border,box-shadow}body.home #sm2-visualization .ui360:hover{background-color:rgba(0,0,0,0)}body.home #sm2-visualization .ui360:hover a{background-color:rgba(0,0,0,0.01);border-color:rgba(0,0,0,0.1);box-shadow:inset 0 0 32px rgba(0,0,0,0.05)}body.home #sm2-visualization .ui360 .sm2_playing canvas,body.home #sm2-visualization .ui360 .sm2_paused canvas{background-color:#fafafa;*background-color:transparent;background-color:transparent\9}body.home #sm2-visualization .ui360 .sm2_playing canvas,body.home #sm2-visualization .ui360 .sm2_paused canvas{background-color:#fafafa;box-shadow:inset 0 0 32px rgba(0,0,0,0.066)}body.home #sm2-visualization .ui360:hover .sm2_playing canvas,body.home #sm2-visualization .ui360:hover .sm2_paused canvas{background-color:#fafafa;box-shadow:inset 0 0 32px rgba(0,0,0,0.1)}body.home .gsfn_topic_list li{display:none}body.home .gsfn_topic_list .gsfn-item-1,body.home .gsfn_topic_list .gsfn-item-2,body.home .gsfn_topic_list .gsfn-item-3{display:block}div.clearfix{font-size:0;height:0;overflow:hidden}div.icons ul{list-style-type:none}div.icons ul,div.icons ul li{margin:0;padding:0}div.icons ul li,.icon{position:relative;display:inline-block;vertical-align:middle;*display:none;background:transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYAAAAAwCAYAAAAYeq1+AAAHLklEQVR42uydT4jcVBzHH6LbLV11wGIVL6OClFbL1P3zEtvDFCsIKqyn0tseFBFKXTwpIu7B017mLBSymwwevBSsiCdjdzOpW5DVg3izXsSbsf5Z3aWd+M1M3jTENpvJTEzS/X7hy0szL+l0d/r95P2SeU9QFEVRFEVRFEVRFEVRFEVRFEVRFEVRFEVRFEVRFEVRFEVRVAFqX5m91+rIMyKFLEf7QFAURVF3jwCAV3ft4849AgAcERRFUXlpenraj7rE77MG27A/pG24VioArOsHTEcum472vtXR/Nv4HLzcducOCIqqqk6fPl2Dbdgfk224Jqg9BwAV/hlti5JoZWN2H8J/E+F/sx/2euBu29W7wZ/R9iHgyC2zI9cERVVVKvzHbFtQuUCgIqCKuxXp01L7ywg2BPtjKOtcR+vDN8LA77Y7OloYreVqPRCYHW2730/+iHZSUEMFzxLs5+wlQSUqr5+9oAiAIS1KINORvyDkEe7yc9OVhwGDLSsI/ltG+MsADt9ZjjyM9mvYx3FfCKr44Im7gNJJpUopsb+zOaJ95ZKWupqhF+EluAXbob0yvXcEYhM24GvxoAz3GXAjVn/fhA0CIHP4XwhLPl0E/0Vs1+E/wqt/WJWC0MfRrqJE9Djay+jThYN9rwgqnTKETqYwqljpJG6bABheYcDHgj29Cw7++pC1dBtuwG9G9hlFAWCkYwvU6rp8AIH+s4Vw7wU6DCD80ysBYTsyAoiUgORfaPv9cdwqoLCycfIeVlBKBAC+/6oBoHg4Fxj+87AXu9Jvwc2YW7GRQdybBMDQtf9HEfh/9gIeRuhHr/r/ux1reyAIjnfmHmYFhQAgAKpVXrwW/XOB4e+H9uDFFMcsKmBE/AZcIwCGLv88CL+F8s7bWWx1YEeeN525/QQAAUAAlAcANrwUej7yXmt3Oqagso8XCf9G2pvAQd8oBNSxBECyrCDwO/I1BPcLpisncCU/ZblyBu1sFltB6+jTpqMH3yKexPnPAihn8HfsJwAIAAIgf2UP8+IBYMfDPxEAyRCwCYA0ANA+UV/qQkifRYhPY3sb5ZybWQ0IeOYV7X6c+yN1bmy/QwAQAAQAASASwtsPvZj1MdDg2Mh5mgRAsqLP92P7M9ORR9DuYJ+fxZYbhL3urX51YgLbv+MeQm8f2nVBEQAEAAFwh+Az1A3fUb8HEJyDTwGlBwDcDW/gfgoAHO0BAPszQ8DRvBVbm8B5foPVDeJcAJDnVT5HAAQAAZC/4qHdGgMAWgomBECyVGgrAKA92nbkjpUt/NV5PNPVJgCTPgBcAoAAIAAIgASlKdvgtZci/V5M6NdU/QiA4QFgAQAjhL8PeHjGBkpAjhYBgEYAEAAEAAEwEgD8qAmA8QNAlYCsEUtApv1caUYAYhcRAAQAAUAAEABqBKBuAmc0gt+7YE/HRwAEAAFAABAAIwHgVKTfKQJgXADQxgaAMPA9c+MkRwAEAAFQYgDEJ4dr8Cbw3gNA/xFNXT0FdAkeCQDh+TzD0SNPAWk4N28CF/JFBgKAALjDh7uZMFdQmR8DbQbmY6Bjewz0V8sdfFlrBe3T4ygBrXwpJ3GenxD86tyXqgAAtEZgAoAAqBIA1JX8ImzAF+OzJMb6LhT1mUlTtkkz/0/KL4I1CIBkmR3t9cE3gR35DK7WJba3RwUA/BDO83L/3DLY93wF8tOIbhMAnA66CgBQge6l+f1ju57Ut+xTQShxKojxadWdO77izh4MRwS6AoDl6t0hw78bziDqmR39UHiP4anVdf0J5icXhOGCMPm87/lhfv/hKMFPYa8Mk8FlCf+wrRMAmWYDPYEA37EGyz9qcHRaaOxXrZr6IVr/x/7eY6Dr8hBnA+WSkGMTAXB7qSmcd3OGz9tShaeDnueSkJknhwtmB/0Bo4C/UbrZAgRuIPzVQvBdbG9hewvbcAABuF9C2u69huNMR9tsX9GnCICc/7Fc0pIAGPbnp97fLjYEVMEFYTx4nmsCj6a2Iw8i0J9FkNfRfm91+iEflneOAQoN7JsZ7OuvDLbcduUxtMexqtgU82fvAMCA/ZxtEAAj/QdoxY5pJSwIMwjQCi4JWS/7ovCp+pRICPerquSDkcHgvZmXZ+4zw/CHgxHAeRETl4TMGwDU2FThkUsry4cX+xvwknKxwZ9c20+xKHxT9ScAxv6Y6FW1/KPpRgCwNhsCAFYAoHK7yeol3ayDa4L6vwCwELpoAMSvgrzYZ8KA64ISRT3NlNF2qQCgRgAhBNT+NgAwePKnQwBQ1QeAnQMAbEHtRQDUMkLAhmslGwF8M1gzAK3a//GaNmHduvoHBOQ5QVF5q0KPs9ocmVFVl+Vo70aWjPw2tp7w9f4KYHjNlWcFRVEUdfcIoT9lOvK86WjvwbXYa08CDB/i9QXAYJ+gKIqiqH/bgwMSAAAAAEH/X7cjUAEAAAAAAAAAAAAAAA4CNogIgRLqd00AAAAASUVORK5CYII=) no-repeat;width:32px;height:24px;padding-right:4px;text-indent:-999em;overflow:hidden;cursor:help;opacity:.75}div.icons ul li:hover,.icon:hover{opacity:1}.icon{display:inline-block;*display:none;width:32px;height:30px;margin-left:16px;margin-top:5px;opacity:.85;cursor:default}div.icons ul li.desktop{background-position:-11px -12px;height:24px}div.icons ul li.laptop{background-position:-59px -13px;height:22px}div.icons ul li.ipad{background-position:-109px -10px;width:28px;height:28px}div.icons ul li.iphone{background-position:-256px -9px;width:22px;height:28px}div.icons ul li.android{background-position:-299px -7px;width:28px;height:32px}.icon.performance,div.icons ul li.performance{background-position:-205px -9px}.icon.performance{width:18px;height:28px;margin-top:-7px}.icon.music-note,div.icons ul li.music-note{background-position:-155px -13px}.icon.music-note{width:19px;height:23px;margin-top:-4px}.icon.package,div.icons ul li.package{background-position:-347px -7px;height:28px}.icon.package{width:22px;margin-top:-8px}.bonus-demos{position:relative;list-style-type:none}.bonus-demos,.bonus-demos li{margin:0;padding:0}.bonus-demos li{float:left;display:inline;width:24%;margin-right:1%;text-align:center}.bonus-demos li img{border-radius:4px}#client-requests ul.flat{list-style-type:none;padding-left:.5em;margin-top:.5em}#client-requests ul.flat li{margin-bottom:0}#inline-video{position:relative;margin-top:4.25em;margin-right:.5em}#bar-ui-1{position:relative;top:-45px}#bar-ui-1 .bd,#bar-ui-1 .sm2-bar-ui .sm2-extra-controls,#bar-ui-1 .sm2-bar-ui .sm2-playlist-drawer{background-color:#29c;background-color:rgba(0,128,224,0.65)}#about-sm2 .sm2-bar-ui .sm2-playlist-drawer{transform:scale3d(1,1,1)}
\ No newline at end of file
--- /dev/null
+/**
+ * SoundManager 2 homepage demo JS
+ * -------------------------------
+ * Numerous demo CSS minified + combined
+ * for optimal performance.
+ * For raw source, see individual demo pages.
+ * --------------------------------
+ * Source files:
+ * demo/play-mp3-links/script/inlineplayer.js
+ * demo/page-player/script/page-player.js
+ * demo/mp3-player-button/script/mp3-player-button.js
+ * demo/360-player/script/berniecode-animator.js
+ * demo/360-player/script/360player.js
+ * demo/index.js
+ */
+
+/*
+
+ Animator.js 1.1.9
+
+ This library is released under the BSD license:
+
+ Copyright (c) 2006, Bernard Sumption. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer. Redistributions in binary
+ form must reproduce the above copyright notice, this list of conditions and
+ the following disclaimer in the documentation and/or other materials
+ provided with the distribution. Neither the name BernieCode nor
+ the names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
+
+
+ SoundManager 2: "Turntable UI": Base and API
+ Copyright (c) 2015, Scott Schiller. All rights reserved.
+ http://www.schillmania.com/projects/soundmanager2/
+ Code provided under BSD license.
+ http://schillmania.com/projects/soundmanager2/license.txt
+
+ SoundManager 2: "Turntable UI": Demo application
+ Copyright (c) 2015, Scott Schiller. All rights reserved.
+ http://www.schillmania.com/projects/soundmanager2/
+ Code provided under BSD license.
+ http://schillmania.com/projects/soundmanager2/license.txt
+*/
+function InlinePlayer(){var a=this,c=this,b=soundManager,d=navigator.userAgent.match(/msie/i);this.playableClass="inline-playable";this.excludeClass="inline-exclude";this.links=[];this.sounds=[];this.soundsByURL=[];this.indexByURL=[];this.lastSound=null;this.soundCount=0;this.config={playNext:!1,autoPlay:!1};this.css={sDefault:"sm2_link",sLoading:"sm2_loading",sPlaying:"sm2_playing",sPaused:"sm2_paused"};this.addEventHandler="undefined"!==typeof window.addEventListener?function(a,b,c){return a.addEventListener(b,
+c,!1)}:function(a,b,c){a.attachEvent("on"+b,c)};this.removeEventHandler="undefined"!==typeof window.removeEventListener?function(a,b,c){return a.removeEventListener(b,c,!1)}:function(a,b,c){return a.detachEvent("on"+b,c)};this.classContains=function(a,b){return"undefined"!=typeof a.className?a.className.match(new RegExp("(\\s|^)"+b+"(\\s|$)")):!1};this.addClass=function(b,c){if(!b||!c||a.classContains(b,c))return!1;b.className=(b.className?b.className+" ":"")+c};this.removeClass=function(b,c){if(!b||
+!c||!a.classContains(b,c))return!1;b.className=b.className.replace(new RegExp("( "+c+")|("+c+")","g"),"")};this.getSoundByURL=function(b){return"undefined"!=typeof a.soundsByURL[b]?a.soundsByURL[b]:null};this.isChildOfNode=function(a,b){if(!a||!a.parentNode)return!1;b=b.toLowerCase();do a=a.parentNode;while(a&&a.parentNode&&a.nodeName.toLowerCase()!=b);return a.nodeName.toLowerCase()==b?a:null};this.events={play:function(){c.removeClass(this._data.oLink,this._data.className);this._data.className=
+c.css.sPlaying;c.addClass(this._data.oLink,this._data.className)},stop:function(){c.removeClass(this._data.oLink,this._data.className);this._data.className=""},pause:function(){c.removeClass(this._data.oLink,this._data.className);this._data.className=c.css.sPaused;c.addClass(this._data.oLink,this._data.className)},resume:function(){c.removeClass(this._data.oLink,this._data.className);this._data.className=c.css.sPlaying;c.addClass(this._data.oLink,this._data.className)},finish:function(){c.removeClass(this._data.oLink,
+this._data.className);this._data.className="";if(c.config.playNext){var a=c.indexByURL[this._data.oLink.href]+1;a<c.links.length&&c.handleClick({target:c.links[a]})}}};this.stopEvent=function(a){"undefined"!=typeof a&&"undefined"!=typeof a.preventDefault?a.preventDefault():"undefined"!=typeof event&&"undefined"!=typeof event.returnValue&&(event.returnValue=!1);return!1};this.getTheDamnLink=d?function(a){return a&&a.target?a.target:window.event.srcElement}:function(a){return a.target};this.handleClick=
+function(c){if("undefined"!=typeof c.button&&1<c.button)return!0;var f=a.getTheDamnLink(c);if("a"!=f.nodeName.toLowerCase()&&(f=a.isChildOfNode(f,"a"),!f))return!0;f.getAttribute("href");if(!f.href||!b.canPlayLink(f)&&!a.classContains(f,a.playableClass)||a.classContains(f,a.excludeClass))return!0;var d=f.href,e=a.getSoundByURL(d);e?(e!=a.lastSound&&(b._writeDebug("sound different than last sound: "+a.lastSound.id),a.lastSound&&a.stopSound(a.lastSound)),e.togglePause()):(a.lastSound&&a.stopSound(a.lastSound),
+e=b.createSound({id:"inlineMP3Sound"+a.soundCount++,url:d,onplay:a.events.play,onstop:a.events.stop,onpause:a.events.pause,onresume:a.events.resume,onfinish:a.events.finish,type:f.type||null}),e._data={oLink:f,className:a.css.sPlaying},a.soundsByURL[d]=e,a.sounds.push(e),e.play());a.lastSound=e;"undefined"!=typeof c&&"undefined"!=typeof c.preventDefault?c.preventDefault():event.returnValue=!1;return!1};this.stopSound=function(a){soundManager.stop(a.id);soundManager.unload(a.id)};this.init=function(){b._writeDebug("inlinePlayer.init()");
+for(var c=document.getElementsByTagName("a"),f=0,d=0,e=c.length;d<e;d++)!b.canPlayLink(c[d])&&!a.classContains(c[d],a.playableClass)||a.classContains(c[d],a.excludeClass)||(a.addClass(c[d],a.css.sDefault),a.links[f]=c[d],a.indexByURL[c[d].href]=f,f++);0<f&&(a.addEventHandler(document,"click",a.handleClick),a.config.autoPlay&&a.handleClick({target:a.links[0],preventDefault:function(){}}));b._writeDebug("inlinePlayer.init(): Found "+f+" relevant items.")};this.init()}var inlinePlayer=null;
+soundManager.setup({debugMode:!0,preferFlash:!1,useFlashBlock:!0,url:"../../swf/",flashVersion:9});soundManager.onready(function(){inlinePlayer=new InlinePlayer});var pagePlayer=null;
+function PagePlayer(){var a=this,c=this,b=soundManager,d,g=null,f=null,h=document.getElementsByTagName("head")[0],e=null,k=navigator.userAgent,m=k.match(/(opera|firefox)/i),q=k.match(/ipad|ipod|iphone/i),r;this.config={usePeakData:!1,useWaveformData:!1,useEQData:!1,fillGraph:!1,allowRightClick:!0,useThrottling:!0,autoStart:!1,playNext:!0,updatePageTitle:!0,emptyTime:"-:--",useFavIcon:!1};this.css={sDefault:"sm2_link",sLoading:"sm2_loading",sPlaying:"sm2_playing",sPaused:"sm2_paused"};this.sounds=
+[];this.soundsByObject=[];this.lastSound=null;this.soundCount=0;this.strings=[];this.dragActive=!1;this.dragExec=new Date;this.dragTimer=null;this.pageTitle=document.title;this.lastWPExec=new Date;this.lastWLExec=new Date;this.vuMeterData=[];this.oControls=null;this._mergeObjects=function(a,b){var l={},c,e;for(c in a)a.hasOwnProperty(c)&&(l[c]=a[c]);c="undefined"===typeof b?{}:b;for(e in c)"undefined"===typeof l[e]&&(l[e]=c[e]);return l};d=function(){function a(b){b=p.call(b);var n=b.length;c?(b[1]=
+"on"+b[1],3<n&&b.pop()):3===n&&b.push(!1);return b}function b(a,n){var p=a.shift(),t=[e[n]];if(c)p[t](a[0],a[1]);else p[t].apply(p,a)}var c=window.attachEvent&&!window.addEventListener,p=Array.prototype.slice,e={add:c?"attachEvent":"addEventListener",remove:c?"detachEvent":"removeEventListener"};return{add:function(){b(a(arguments),"add")},remove:function(){b(a(arguments),"remove")}}}();this.hasClass=function(a,b){return"undefined"!==typeof a.className?(new RegExp("(^|\\s)"+b+"(\\s|$)")).test(a.className):
+!1};this.addClass=function(b,c){if(!b||!c||a.hasClass(b,c))return!1;b.className=(b.className?b.className+" ":"")+c};this.removeClass=function(b,c){if(!b||!c||!a.hasClass(b,c))return!1;b.className=b.className.replace(new RegExp("( "+c+")|("+c+")","g"),"")};this.select=function(b,c){var l=a.getByClassName(b,"div",c||null);return l?l[0]:null};this.getByClassName=document.querySelectorAll?function(a,b,c){a="."+a;b&&(b=b.split(" "));b=1<b.length?b.join(a+", "):b[0]+a;return(c?c:document).querySelectorAll(b)}:
+function(b,c,l){var p=l?l:document;l=[];var e,d=[];c&&(c=c.split(" "));if(c instanceof Array){for(e=c.length;e--;)d&&d[c[e]]||(d[c[e]]=p.getElementsByTagName(c[e]));for(e=c.length;e--;)for(p=d[c[e]].length;p--;)a.hasClass(d[c[e]][p],b)&&l.push(d[c[e]][p])}else for(d=p.all||p.getElementsByTagName("*"),e=0,p=d.length;e<p;e++)a.hasClass(d[e],b)&&l.push(d[e]);return l};this.isChildOfClass=function(b,c){if(!b||!c)return!1;for(;b.parentNode&&!a.hasClass(b,c);)b=b.parentNode;return a.hasClass(b,c)};this.getParentByNodeName=
+function(a,b){if(!a||!b)return!1;for(b=b.toLowerCase();a.parentNode&&b!==a.parentNode.nodeName.toLowerCase();)a=a.parentNode;return a.parentNode&&b===a.parentNode.nodeName.toLowerCase()?a.parentNode:null};this.getOffX=function(a){var b=0;if(a.offsetParent)for(;a.offsetParent;)b+=a.offsetLeft,a=a.offsetParent;else a.x&&(b+=a.x);return b};this.getTime=function(a,b){var c=Math.floor(a/1E3),p=Math.floor(c/60),c=c-60*p;return b?p+":"+(10>c?"0"+c:c):{min:p,sec:c}};this.getSoundByObject=function(b){return"undefined"!==
+typeof a.soundsByObject[b.id]?a.soundsByObject[b.id]:null};this.getPreviousItem=function(a){if(a.previousElementSibling)a=a.previousElementSibling;else for(a=a.previousSibling;a&&a.previousSibling&&1!==a.previousSibling.nodeType;)a=a.previousSibling;return"li"!==a.nodeName.toLowerCase()?null:a.getElementsByTagName("a")[0]};this.playPrevious=function(b){b||(b=a.lastSound);if(!b)return!1;(b=a.getPreviousItem(b._data.oLI))&&c.handleClick({target:b});return b};this.getNextItem=function(a){if(a.nextElementSibling)a=
+a.nextElementSibling;else for(a=a.nextSibling;a&&a.nextSibling&&1!==a.nextSibling.nodeType;)a=a.nextSibling;return"li"!==a.nodeName.toLowerCase()?null:a.getElementsByTagName("a")[0]};this.playNext=function(b){b||(b=a.lastSound);if(!b)return!1;(b=a.getNextItem(b._data.oLI))&&c.handleClick({target:b});return b};this.setPageTitle=function(b){if(!a.config.updatePageTitle)return!1;try{document.title=(b?b+" - ":"")+a.pageTitle}catch(c){a.setPageTitle=function(){return!1}}};this.events={play:function(){c.removeClass(this._data.oLI,
+this._data.className);this._data.className=c.css.sPlaying;c.addClass(this._data.oLI,this._data.className);a.setPageTitle(this._data.originalTitle)},stop:function(){c.removeClass(this._data.oLI,this._data.className);this._data.className="";this._data.oPosition.style.width="0px";a.setPageTitle();a.resetPageIcon()},pause:function(){if(c.dragActive)return!1;c.removeClass(this._data.oLI,this._data.className);this._data.className=c.css.sPaused;c.addClass(this._data.oLI,this._data.className);a.setPageTitle();
+a.resetPageIcon()},resume:function(){if(c.dragActive)return!1;c.removeClass(this._data.oLI,this._data.className);this._data.className=c.css.sPlaying;c.addClass(this._data.oLI,this._data.className)},finish:function(){c.removeClass(this._data.oLI,this._data.className);this._data.className="";this._data.oPosition.style.width="0px";a.config.playNext?c.playNext(this):(a.setPageTitle(),a.resetPageIcon())},whileloading:function(){function b(){this._data.oLoading.style.width=this.bytesLoaded/this.bytesTotal*
+100+"%";!this._data.didRefresh&&this._data.metadata&&(this._data.didRefresh=!0,this._data.metadata.refresh())}if(c.config.useThrottling){var e=new Date;if(e&&50<e-a.lastWLExec||this.bytesLoaded===this.bytesTotal)b.apply(this),a.lastWLExec=e}else b.apply(this)},onload:function(){if(this.loaded)this._data.metadata&&this._data.metadata.refresh();else{var a=this._data.oLI.getElementsByTagName("a")[0],c=a.innerHTML;a.innerHTML=c+' <span style="font-size:0.5em"> | Load failed, d\'oh! '+(b.sandbox.noRemote?
+" Possible cause: Flash sandbox is denying remote URL access.":b.sandbox.noLocal?"Flash denying local filesystem access":"404?")+"</span>";setTimeout(function(){a.innerHTML=c},5E3)}},whileplaying:function(){var e=null;c.dragActive||!c.config.useThrottling?(a.updateTime.apply(this),9<=b.flashVersion&&(c.config.usePeakData&&this.instanceOptions.usePeakData&&a.updatePeaks.apply(this),(c.config.useWaveformData&&this.instanceOptions.useWaveformData||c.config.useEQData&&this.instanceOptions.useEQData)&&
+a.updateGraph.apply(this)),this._data.metadata&&(e=new Date)&&500<e-a.lastWPExec&&(this._data.metadata.refreshMetadata(this),a.lastWPExec=e),this._data.oPosition.style.width=this.position/a.getDurationEstimate(this)*100+"%"):(e=new Date,30<e-a.lastWPExec&&(a.updateTime.apply(this),9<=b.flashVersion&&(c.config.usePeakData&&this.instanceOptions.usePeakData&&a.updatePeaks.apply(this),(c.config.useWaveformData&&this.instanceOptions.useWaveformData||c.config.useEQData&&this.instanceOptions.useEQData)&&
+a.updateGraph.apply(this)),this._data.metadata&&this._data.metadata.refreshMetadata(this),this._data.oPosition.style.width=this.position/a.getDurationEstimate(this)*100+"%",a.lastWPExec=e))}};this.setPageIcon=function(b){if(!a.config.useFavIcon||!a.config.usePeakData||!b)return!1;var c=document.getElementById("sm2-favicon");c&&(h.removeChild(c),c=null);c||(c=document.createElement("link"),c.id="sm2-favicon",c.rel="shortcut icon",c.type="image/png",c.href=b,document.getElementsByTagName("head")[0].appendChild(c))};
+this.resetPageIcon=function(){if(!a.config.useFavIcon)return!1;var b=document.getElementById("favicon");b&&(b.href="/favicon.ico")};this.updatePeaks=function(){var c=this._data.oPeak.getElementsByTagName("span");c[0].style.marginTop=13-Math.floor(15*this.peakData.left)+"px";c[1].style.marginTop=13-Math.floor(15*this.peakData.right)+"px";8<b.flashVersion&&a.config.useFavIcon&&a.config.usePeakData&&a.setPageIcon(a.vuMeterData[parseInt(16*this.peakData.left,10)][parseInt(16*this.peakData.right,10)])};
+this.updateGraph=function(){if(9>c.config.flashVersion||!c.config.useWaveformData&&!c.config.useEQData)return!1;var a=this._data.oGraph.getElementsByTagName("div"),b;if(c.config.useWaveformData)for(b=255;b--;)a[255-b].style.marginTop=9+Math.ceil(-8*this.waveformData.left[b])+"px";else for(b=255;b--;)a[255-b].style.marginTop=17+Math.ceil(-9*this.eqData[b])+"px"};this.resetGraph=function(){if(!c.config.useEQData||9>c.config.flashVersion)return!1;var a=this._data.oGraph.getElementsByTagName("div"),b=
+c.config.useEQData?"17px":"9px",l=c.config.fillGraph?"32px":"1px",p;for(p=255;p--;)a[255-p].style.marginTop=b,a[255-p].style.height=l};this.updateTime=function(){var b=a.strings.timing.replace("%s1",a.getTime(this.position,!0)),b=b.replace("%s2",a.getTime(a.getDurationEstimate(this),!0));this._data.oTiming.innerHTML=b};this.getTheDamnTarget=function(a){return a.target||(window.event?window.event.srcElement:null)};this.withinStatusBar=function(b){return a.isChildOfClass(b,"playlist")&&a.isChildOfClass(b,
+"controls")};this.handleClick=function(d){if(2===d.button)return c.config.allowRightClick||c.stopEvent(d),c.config.allowRightClick;var f=a.getTheDamnTarget(d),l,p,h;if(!f)return!0;a.dragActive&&a.stopDrag();if(a.withinStatusBar(f))return!1;"a"!==f.nodeName.toLowerCase()&&(f=a.getParentByNodeName(f,"a"));if(!f)return!0;f.getAttribute("href");if(!f.href||!b.canPlayLink(f)&&!a.hasClass(f,"playable")||a.hasClass(f,"exclude"))return!0;a.initUL(a.getParentByNodeName(f,"ul"));a.initItem(f);l=f.href;(p=a.getSoundByObject(f))?
+(a.setPageTitle(p._data.originalTitle),p===a.lastSound?2!==p.readyState?1!==p.playState?p.play():p.togglePause():b._writeDebug("Warning: sound failed to load (security restrictions, 404 or bad format)",2):(a.lastSound&&a.stopSound(a.lastSound),e&&p._data.oTimingBox.appendChild(e),p.togglePause())):(p=b.createSound({id:f.id,url:decodeURI(l),onplay:a.events.play,onstop:a.events.stop,onpause:a.events.pause,onresume:a.events.resume,onfinish:a.events.finish,type:f.type||null,whileloading:a.events.whileloading,
+whileplaying:a.events.whileplaying,onmetadata:a.events.metadata,onload:a.events.onload}),l=a.oControls.cloneNode(!0),h=f.parentNode,h.appendChild(l),e&&h.appendChild(e),a.soundsByObject[f.id]=p,p._data={oLink:f,oLI:h,oControls:a.select("controls",h),oStatus:a.select("statusbar",h),oLoading:a.select("loading",h),oPosition:a.select("position",h),oTimingBox:a.select("timing",h),oTiming:a.select("timing",h).getElementsByTagName("div")[0],oPeak:a.select("peak",h),oGraph:a.select("spectrum-box",h),className:a.css.sPlaying,
+originalTitle:f.innerHTML,metadata:null},e&&p._data.oTimingBox.appendChild(e),p._data.oLI.getElementsByTagName("ul").length&&(p._data.metadata=new Metadata(p)),f=a.strings.timing.replace("%s1",a.config.emptyTime),f=f.replace("%s2",a.config.emptyTime),p._data.oTiming.innerHTML=f,a.sounds.push(p),a.lastSound&&a.stopSound(a.lastSound),a.resetGraph.apply(p),p.play());a.lastSound=p;return a.stopEvent(d)};this.handleMouseDown=function(b){q&&b.touches&&(b=b.touches[0]);if(2===b.button)return c.config.allowRightClick||
+c.stopEvent(b),c.config.allowRightClick;var e=a.getTheDamnTarget(b);if(!e||!a.withinStatusBar(e))return!0;a.dragActive=!0;a.lastSound.pause();a.setPosition(b);q?d.add(document,"touchmove",a.handleMouseMove):d.add(document,"mousemove",a.handleMouseMove);a.addClass(a.lastSound._data.oControls,"dragging");return a.stopEvent(b)};this.handleMouseMove=function(b){q&&b.touches&&(b=b.touches[0]);if(a.dragActive)if(a.config.useThrottling){var c=new Date;20<c-a.dragExec?a.setPosition(b):(window.clearTimeout(a.dragTimer),
+a.dragTimer=window.setTimeout(function(){a.setPosition(b)},20));a.dragExec=c}else a.setPosition(b);else a.stopDrag();b.stopPropagation=!0;return!1};this.stopDrag=function(b){if(a.dragActive)return a.removeClass(a.lastSound._data.oControls,"dragging"),q?d.remove(document,"touchmove",a.handleMouseMove):d.remove(document,"mousemove",a.handleMouseMove),c.hasClass(a.lastSound._data.oLI,a.css.sPaused)||a.lastSound.resume(),a.dragActive=!1,a.stopEvent(b)};this.handleStatusClick=function(b){a.setPosition(b);
+c.hasClass(a.lastSound._data.oLI,a.css.sPaused)||a.resume();return a.stopEvent(b)};this.stopEvent=function(a){"undefined"!==typeof a&&("undefined"!==typeof a.preventDefault?a.preventDefault():(a.stopPropagation=!0,a.returnValue=!1));return!1};this.setPosition=function(b){var c=a.getTheDamnTarget(b),l;if(!c)return!0;for(l=c;!a.hasClass(l,"controls")&&l.parentNode;)l=l.parentNode;c=a.lastSound;b=parseInt(b.clientX,10);b=Math.floor((b-a.getOffX(l)-4)/l.offsetWidth*a.getDurationEstimate(c));isNaN(b)||
+(b=Math.min(b,c.duration));isNaN(b)||c.setPosition(b)};this.stopSound=function(a){b._writeDebug("stopping sound: "+a.id);b.stop(a.id);q||b.unload(a.id)};this.getDurationEstimate=function(a){return a.instanceOptions.isMovieStar?a.duration:a._data.metadata&&a._data.metadata.data.givenDuration?a._data.metadata.data.givenDuration:a.durationEstimate||0};this.createVUData=function(){var b=0,c=0,l=g.getContext("2d"),e=l.createLinearGradient(0,16,0,0),f;e.addColorStop(0,"rgb(0,192,0)");e.addColorStop(.3,
+"rgb(0,255,0)");e.addColorStop(.625,"rgb(255,255,0)");e.addColorStop(.85,"rgb(255,0,0)");f=l.createLinearGradient(0,16,0,0);f.addColorStop(0,"rgba(0,0,0,0.2)");f.addColorStop(1,"rgba(0,0,0,0.5)");for(b=0;16>b;b++)a.vuMeterData[b]=[];for(b=0;16>b;b++)for(c=0;16>c;c++)g.setAttribute("width",16),g.setAttribute("height",16),l.fillStyle=f,l.fillRect(0,0,7,15),l.fillRect(8,0,7,15),l.fillStyle=e,l.fillRect(0,15-b,7,16-(16-b)),l.fillRect(8,15-c,7,16-(16-c)),l.clearRect(0,3,16,1),l.clearRect(0,7,16,1),l.clearRect(0,
+11,16,1),a.vuMeterData[b][c]=g.toDataURL("image/png")};this.testCanvas=function(){var a=document.createElement("canvas"),b=null;if(!a||"undefined"===typeof a.getContext)return null;b=a.getContext("2d");if(!b||"function"!==typeof a.toDataURL)return null;try{a.toDataURL("image/png")}catch(c){return null}return a};this.initItem=function(b){b.id||(b.id="pagePlayerMP3Sound"+a.soundCount++);a.addClass(b,a.css.sDefault)};this.initUL=function(c){9<=b.flashVersion&&a.addClass(c,a.cssBase)};this.init=function(h){function k(b){d[b](document,
+"click",a.handleClick);q?(d[b](document,"touchstart",a.handleMouseDown),d[b](document,"touchend",a.stopDrag)):(d[b](document,"mousedown",a.handleMouseDown),d[b](document,"mouseup",a.stopDrag));d[b](window,"unload",r)}h?(b._writeDebug("pagePlayer.init(): Using custom configuration"),this.config=this._mergeObjects(h,this.config)):b._writeDebug("pagePlayer.init(): Using default configuration");var l,p,u,x;this.cssBase=[];b.useFlashBlock=!0;9<=b.flashVersion?(b.defaultOptions.usePeakData=this.config.usePeakData,
+b.defaultOptions.useWaveformData=this.config.useWaveformData,b.defaultOptions.useEQData=this.config.useEQData,this.config.usePeakData&&this.cssBase.push("use-peak"),(this.config.useWaveformData||this.config.useEQData)&&this.cssBase.push("use-spectrum"),this.cssBase=this.cssBase.join(" "),this.config.useFavIcon&&((g=a.testCanvas())&&m?a.createVUData():this.config.useFavIcon=!1)):(this.config.usePeakData||this.config.useWaveformData||this.config.useEQData)&&b._writeDebug("Page player: Note: soundManager.flashVersion = 9 is required for peak/waveform/EQ features.");
+f=document.createElement("div");f.innerHTML=' <div class="controls">\n <div class="statusbar">\n <div class="loading"></div>\n <div class="position"></div>\n </div>\n </div>\n <div class="timing">\n <div id="sm2_timing" class="timing-data">\n <span class="sm2_position">%s1</span> / <span class="sm2_total">%s2</span>\n </div>\n </div>\n <div class="peak">\n <div class="peak-box"><span class="l"></span><span class="r"></span></div>\n </div>\n <div class="spectrum-container">\n <div class="spectrum-box">\n <div class="spectrum"></div>\n </div>\n </div>';
+if(9<=b.flashVersion){e=a.select("spectrum-container",f);e=f.removeChild(e);l=a.select("spectrum-box",e);p=l.getElementsByTagName("div")[0];u=document.createDocumentFragment();x=null;for(h=256;h--;)x=p.cloneNode(!1),x.style.left=h+"px",u.appendChild(x);l.removeChild(p);l.appendChild(u)}else f.removeChild(a.select("spectrum-container",f)),f.removeChild(a.select("peak",f));a.oControls=f.cloneNode(!0);h=a.select("timing-data",f);a.strings.timing=h.innerHTML;h.innerHTML="";h.id="";r=function(){k("remove")};
+k("add");b._writeDebug("pagePlayer.init(): Ready",1);a.config.autoStart&&c.handleClick({target:c.getByClassName("playlist","ul")[0].getElementsByTagName("a")[0]})}}soundManager.useFlashBlock=!0;soundManager.onready(function(){pagePlayer=new PagePlayer;pagePlayer.init("undefined"!==typeof PP_CONFIG?PP_CONFIG:null)});
+function BasicMP3Player(){var a=this,c=this,b=soundManager,d=navigator.userAgent.match(/ipad|iphone/i),g=navigator.userAgent.match(/msie/i);this.excludeClass="button-exclude";this.links=[];this.sounds=[];this.soundsByURL={};this.indexByURL={};this.lastSound=null;this.soundCount=0;this.config={playNext:!1,autoPlay:!1};this.css={sDefault:"sm2_button",sLoading:"sm2_loading",sPlaying:"sm2_playing",sPaused:"sm2_paused"};this.includeClass=this.css.sDefault;this.addEventHandler="undefined"!==typeof window.addEventListener?
+function(a,b,c){return a.addEventListener(b,c,!1)}:function(a,b,c){a.attachEvent("on"+b,c)};this.removeEventHandler="undefined"!==typeof window.removeEventListener?function(a,b,c){return a.removeEventListener(b,c,!1)}:function(a,b,c){return a.detachEvent("on"+b,c)};this.classContains=function(a,b){return"undefined"!==typeof a.className?a.className.match(new RegExp("(\\s|^)"+b+"(\\s|$)")):!1};this.addClass=function(b,c){if(!b||!c||a.classContains(b,c))return!1;b.className=(b.className?b.className+
+" ":"")+c};this.removeClass=function(b,c){if(!b||!c||!a.classContains(b,c))return!1;b.className=b.className.replace(new RegExp("( "+c+")|("+c+")","g"),"")};this.getSoundByURL=function(b){return"undefined"!==typeof a.soundsByURL[b]?a.soundsByURL[b]:null};this.isChildOfNode=function(a,b){if(!a||!a.parentNode)return!1;b=b.toLowerCase();do a=a.parentNode;while(a&&a.parentNode&&a.nodeName.toLowerCase()!==b);return a.nodeName.toLowerCase()===b?a:null};this.events={play:function(){c.removeClass(this._data.oLink,
+this._data.className);this._data.className=c.css.sPlaying;c.addClass(this._data.oLink,this._data.className)},stop:function(){c.removeClass(this._data.oLink,this._data.className);this._data.className=""},pause:function(){c.removeClass(this._data.oLink,this._data.className);this._data.className=c.css.sPaused;c.addClass(this._data.oLink,this._data.className)},resume:function(){c.removeClass(this._data.oLink,this._data.className);this._data.className=c.css.sPlaying;c.addClass(this._data.oLink,this._data.className)},
+finish:function(){c.removeClass(this._data.oLink,this._data.className);this._data.className="";if(c.config.playNext){var a=c.indexByURL[this._data.oLink.href]+1;a<c.links.length&&c.handleClick({target:c.links[a]})}}};this.stopEvent=function(a){"undefined"!==typeof a&&"undefined"!==typeof a.preventDefault?a.preventDefault():"undefined"!==typeof window.event&&(window.event.returnValue=!1);return!1};this.getTheDamnLink=g?function(a){return a&&a.target?a.target:window.event.srcElement}:function(a){return a.target};
+this.handleClick=function(c){if("undefined"!==typeof c.button&&1<c.button)return!0;var d=a.getTheDamnLink(c),e,k;if("a"!==d.nodeName.toLowerCase()&&(d=a.isChildOfNode(d,"a"),!d))return!0;d.getAttribute("href");if(!d.href||!soundManager.canPlayLink(d)||a.classContains(d,a.excludeClass)||!a.classContains(d,a.includeClass))return!0;b._writeDebug("handleClick()");e=d.href;(k=a.getSoundByURL(e))?k===a.lastSound?k.togglePause():(k.togglePause(),b._writeDebug("sound different than last sound: "+a.lastSound.id),
+a.lastSound&&a.stopSound(a.lastSound)):(k=b.createSound({id:"basicMP3Sound"+a.soundCount++,url:e,onplay:a.events.play,onstop:a.events.stop,onpause:a.events.pause,onresume:a.events.resume,onfinish:a.events.finish,type:d.type||null}),k._data={oLink:d,className:a.css.sPlaying},a.soundsByURL[e]=k,a.sounds.push(k),a.lastSound&&a.stopSound(a.lastSound),k.play());a.lastSound=k;return a.stopEvent(c)};this.stopSound=function(a){soundManager.stop(a.id);d||soundManager.unload(a.id)};this.init=function(){b._writeDebug("basicMP3Player.init()");
+var c,d,e=0,k=document.getElementsByTagName("a");c=0;for(d=k.length;c<d;c++)a.classContains(k[c],a.css.sDefault)&&!a.classContains(k[c],a.excludeClass)&&(a.links[e]=k[c],a.indexByURL[k[c].href]=e,e++);0<e&&(a.addEventHandler(document,"click",a.handleClick),a.config.autoPlay&&a.handleClick({target:a.links[0],preventDefault:function(){}}));b._writeDebug("basicMP3Player.init(): Found "+e+" relevant items.")};this.init()}var basicMP3Player=null;
+soundManager.setup({preferFlash:!1,onready:function(){basicMP3Player=new BasicMP3Player}});function Animator(a){this.setOptions(a);var c=this;this.timerDelegate=function(){c.onTimerEvent()};this.subjects=[];this.subjectScopes=[];this.state=this.target=0;this.lastTime=null}
+Animator.prototype={setOptions:function(a){this.options=Animator.applyDefaults({interval:20,duration:400,onComplete:function(){},onStep:function(){},transition:Animator.tx.easeInOut},a)},seekTo:function(a){this.seekFromTo(this.state,a)},seekFromTo:function(a,c){this.target=Math.max(0,Math.min(1,c));this.state=Math.max(0,Math.min(1,a));this.lastTime=(new Date).getTime();this.intervalId||(this.intervalId=window.setInterval(this.timerDelegate,this.options.interval))},jumpTo:function(a){this.target=this.state=
+Math.max(0,Math.min(1,a));this.propagate()},toggle:function(){this.seekTo(1-this.target)},addSubject:function(a,c){this.subjects[this.subjects.length]=a;this.subjectScopes[this.subjectScopes.length]=c;return this},clearSubjects:function(){this.subjects=[];this.subjectScopes=[]},propagate:function(){for(var a=this.options.transition(this.state),c=0;c<this.subjects.length;c++)this.subjects[c].setState?this.subjects[c].setState(a):this.subjects[c].apply(this.subjectScopes[c],[a])},onTimerEvent:function(){var a=
+(new Date).getTime(),c=a-this.lastTime;this.lastTime=a;a=c/this.options.duration*(this.state<this.target?1:-1);Math.abs(a)>=Math.abs(this.state-this.target)?this.state=this.target:this.state+=a;try{this.propagate()}finally{this.options.onStep.call(this),this.target==this.state&&(window.clearInterval(this.intervalId),this.intervalId=null,this.options.onComplete.call(this))}},play:function(){this.seekFromTo(0,1)},reverse:function(){this.seekFromTo(1,0)},inspect:function(){for(var a="#<Animator:\n",
+c=0;c<this.subjects.length;c++)a+=this.subjects[c].inspect();return a+">"}};Animator.applyDefaults=function(a,c){c=c||{};var b,d={};for(b in a)d[b]=void 0!==c[b]?c[b]:a[b];return d};Animator.makeArray=function(a){if(null==a)return[];if(!a.length)return[a];for(var c=[],b=0;b<a.length;b++)c[b]=a[b];return c};
+Animator.camelize=function(a){var c=a.split("-");if(1==c.length)return c[0];a=0==a.indexOf("-")?c[0].charAt(0).toUpperCase()+c[0].substring(1):c[0];for(var b=1,d=c.length;b<d;b++){var g=c[b];a+=g.charAt(0).toUpperCase()+g.substring(1)}return a};Animator.apply=function(a,c,b){return c instanceof Array?(new Animator(b)).addSubject(new CSSStyleSubject(a,c[0],c[1])):(new Animator(b)).addSubject(new CSSStyleSubject(a,c))};Animator.makeEaseIn=function(a){return function(c){return Math.pow(c,2*a)}};
+Animator.makeEaseOut=function(a){return function(c){return 1-Math.pow(1-c,2*a)}};Animator.makeElastic=function(a){return function(c){c=Animator.tx.easeInOut(c);return(1-Math.cos(c*Math.PI*a))*(1-c)+c}};Animator.makeADSR=function(a,c,b,d){null==d&&(d=.5);return function(g){return g<a?g/a:g<c?1-(g-a)/(c-a)*(1-d):g<b?d:d*(1-(g-b)/(1-b))}};Animator.makeBounce=function(a){var c=Animator.makeElastic(a);return function(a){a=c(a);return 1>=a?a:2-a}};
+Animator.tx={easeInOut:function(a){return-Math.cos(a*Math.PI)/2+.5},linear:function(a){return a},easeIn:Animator.makeEaseIn(1.5),easeOut:Animator.makeEaseOut(1.5),strongEaseIn:Animator.makeEaseIn(2.5),strongEaseOut:Animator.makeEaseOut(2.5),elastic:Animator.makeElastic(1),veryElastic:Animator.makeElastic(3),bouncy:Animator.makeBounce(1),veryBouncy:Animator.makeBounce(3)};
+function NumericalStyleSubject(a,c,b,d,g){this.els=Animator.makeArray(a);this.property="opacity"==c&&window.ActiveXObject?"filter":Animator.camelize(c);this.from=parseFloat(b);this.to=parseFloat(d);this.units=null!=g?g:"px"}
+NumericalStyleSubject.prototype={setState:function(a){a=this.getStyle(a);for(var c=0,b=0;b<this.els.length;b++){try{this.els[b].style[this.property]=a}catch(d){if("fontWeight"!=this.property)throw d;}if(20<c++)break}},getStyle:function(a){a=this.from+(this.to-this.from)*a;return"filter"==this.property?"alpha(opacity="+Math.round(100*a)+")":"opacity"==this.property?a:Math.round(a)+this.units},inspect:function(){return"\t"+this.property+"("+this.from+this.units+" to "+this.to+this.units+")\n"}};
+function ColorStyleSubject(a,c,b,d){this.els=Animator.makeArray(a);this.property=Animator.camelize(c);this.to=this.expandColor(d);this.from=this.expandColor(b);this.origFrom=b;this.origTo=d}
+ColorStyleSubject.prototype={expandColor:function(a){var c,b;if(c=ColorStyleSubject.parseColor(a))return a=parseInt(c.slice(1,3),16),b=parseInt(c.slice(3,5),16),c=parseInt(c.slice(5,7),16),[a,b,c];window.DEBUG&&alert("Invalid colour: '"+a+"'")},getValueForState:function(a,c){return Math.round(this.from[a]+(this.to[a]-this.from[a])*c)},setState:function(a){a="#"+ColorStyleSubject.toColorPart(this.getValueForState(0,a))+ColorStyleSubject.toColorPart(this.getValueForState(1,a))+ColorStyleSubject.toColorPart(this.getValueForState(2,
+a));for(var c=0;c<this.els.length;c++)this.els[c].style[this.property]=a},inspect:function(){return"\t"+this.property+"("+this.origFrom+" to "+this.origTo+")\n"}};
+ColorStyleSubject.parseColor=function(a){var c="#",b;if(b=ColorStyleSubject.parseColor.rgbRe.exec(a)){for(var d=1;3>=d;d++)a=Math.max(0,Math.min(255,parseInt(b[d]))),c+=ColorStyleSubject.toColorPart(a);return c}if(b=ColorStyleSubject.parseColor.hexRe.exec(a)){if(3==b[1].length){for(d=0;3>d;d++)c+=b[1].charAt(d)+b[1].charAt(d);return c}return"#"+b[1]}return!1};ColorStyleSubject.toColorPart=function(a){255<a&&(a=255);var c=a.toString(16);return 16>a?"0"+c:c};ColorStyleSubject.parseColor.rgbRe=/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;
+ColorStyleSubject.parseColor.hexRe=/^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;function DiscreteStyleSubject(a,c,b,d,g){this.els=Animator.makeArray(a);this.property=Animator.camelize(c);this.from=b;this.to=d;this.threshold=g||.5}DiscreteStyleSubject.prototype={setState:function(a){for(var c=0;c<this.els.length;c++)this.els[c].style[this.property]=a<=this.threshold?this.from:this.to},inspect:function(){return"\t"+this.property+"("+this.from+" to "+this.to+" @ "+this.threshold+")\n"}};
+function CSSStyleSubject(a,c,b){a=Animator.makeArray(a);this.subjects=[];if(0!=a.length){var d;if(b)c=this.parseStyle(c,a[0]),b=this.parseStyle(b,a[0]);else for(d in b=this.parseStyle(c,a[0]),c={},b)c[d]=CSSStyleSubject.getStyle(a[0],d);for(d in c)c[d]==b[d]&&(delete c[d],delete b[d]);var g,f,h,e;for(d in c){var k=String(c[d]),m=String(b[d]);if(null==b[d])window.DEBUG&&alert("No to style provided for '"+d+'"');else{if(h=ColorStyleSubject.parseColor(k))e=ColorStyleSubject.parseColor(m),f=ColorStyleSubject;
+else if(k.match(CSSStyleSubject.numericalRe)&&m.match(CSSStyleSubject.numericalRe))h=parseFloat(k),e=parseFloat(m),f=NumericalStyleSubject,g=CSSStyleSubject.numericalRe.exec(k),m=CSSStyleSubject.numericalRe.exec(m),g=null!=g[1]?g[1]:null!=m[1]?m[1]:m;else if(k.match(CSSStyleSubject.discreteRe)&&m.match(CSSStyleSubject.discreteRe))h=k,e=m,f=DiscreteStyleSubject,g=0;else{window.DEBUG&&alert("Unrecognised format for value of "+d+": '"+c[d]+"'");continue}this.subjects[this.subjects.length]=new f(a,d,
+h,e,g)}}}}
+CSSStyleSubject.prototype={parseStyle:function(a,c){var b={};if(-1!=a.indexOf(":"))for(var d=a.split(";"),g=0;g<d.length;g++){var f=CSSStyleSubject.ruleRe.exec(d[g]);f&&(b[f[1]]=f[2])}else{var h;h=c.className;c.className=a;for(g=0;g<CSSStyleSubject.cssProperties.length;g++)d=CSSStyleSubject.cssProperties[g],f=CSSStyleSubject.getStyle(c,d),null!=f&&(b[d]=f);c.className=h}return b},setState:function(a){for(var c=0;c<this.subjects.length;c++)this.subjects[c].setState(a)},inspect:function(){for(var a="",
+c=0;c<this.subjects.length;c++)a+=this.subjects[c].inspect();return a}};CSSStyleSubject.getStyle=function(a,c){var b;if(document.defaultView&&document.defaultView.getComputedStyle&&(b=document.defaultView.getComputedStyle(a,"").getPropertyValue(c)))return b;c=Animator.camelize(c);a.currentStyle&&(b=a.currentStyle[c]);return b||a.style[c]};CSSStyleSubject.ruleRe=/^\s*([a-zA-Z\-]+)\s*:\s*(\S(.+\S)?)\s*$/;CSSStyleSubject.numericalRe=/^-?\d+(?:\.\d+)?(%|[a-zA-Z]{2})?$/;CSSStyleSubject.discreteRe=/^\w+$/;
+CSSStyleSubject.cssProperties="azimuth background background-attachment background-color background-image background-position background-repeat border-collapse border-color border-spacing border-style border-top border-top-color border-right-color border-bottom-color border-left-color border-top-style border-right-style border-bottom-style border-left-style border-top-width border-right-width border-bottom-width border-left-width border-width bottom clear clip color content cursor direction display elevation empty-cells css-float font font-family font-size font-size-adjust font-stretch font-style font-variant font-weight height left letter-spacing line-height list-style list-style-image list-style-position list-style-type margin margin-top margin-right margin-bottom margin-left max-height max-width min-height min-width orphans outline outline-color outline-style outline-width overflow padding padding-top padding-right padding-bottom padding-left pause position right size table-layout text-align text-decoration text-indent text-shadow text-transform top vertical-align visibility white-space width word-spacing z-index opacity outline-offset overflow-x overflow-y".split(" ");
+function AnimatorChain(a,c){this.animators=a;this.setOptions(c);for(var b=0;b<this.animators.length;b++)this.listenTo(this.animators[b]);this.forwards=!1;this.current=0}
+AnimatorChain.prototype={setOptions:function(a){this.options=Animator.applyDefaults({resetOnPlay:!0},a)},play:function(){this.forwards=!0;this.current=-1;if(this.options.resetOnPlay)for(var a=0;a<this.animators.length;a++)this.animators[a].jumpTo(0);this.advance()},reverse:function(){this.forwards=!1;this.current=this.animators.length;if(this.options.resetOnPlay)for(var a=0;a<this.animators.length;a++)this.animators[a].jumpTo(1);this.advance()},toggle:function(){this.forwards?this.seekTo(0):this.seekTo(1)},
+listenTo:function(a){var c=a.options.onComplete,b=this;a.options.onComplete=function(){c&&c.call(a);b.advance()}},advance:function(){this.forwards?null!=this.animators[this.current+1]&&(this.current++,this.animators[this.current].play()):null!=this.animators[this.current-1]&&(this.current--,this.animators[this.current].reverse())},seekTo:function(a){0>=a?(this.forwards=!1,this.animators[this.current].seekTo(0)):(this.forwards=!0,this.animators[this.current].seekTo(1))}};
+function Accordion(a){this.setOptions(a);a=this.options.initialSection;var c;this.options.rememberance&&(c=document.location.hash.substring(1));this.rememberanceTexts=[];this.ans=[];for(var b=this,d=0;d<this.options.sections.length;d++){var g=this.options.sections[d],f=new Animator(this.options.animatorOptions);f.addSubject(new NumericalStyleSubject(g,this.options.property,this.options.from+this.options.shift*d,this.options.to+this.options.shift*d,this.options.units));f.jumpTo(0);g=this.options.getActivator(g);
+g.index=d;g.onclick=function(){b.show(this.index)};this.ans[this.ans.length]=f;this.rememberanceTexts[d]=g.innerHTML.replace(/\s/g,"");this.rememberanceTexts[d]===c&&(a=d)}this.show(a)}
+Accordion.prototype={setOptions:function(a){this.options=Object.extend({sections:null,getActivator:function(a){return document.getElementById(a.getAttribute("activator"))},shift:0,initialSection:0,rememberance:!0,animatorOptions:{}},a||{})},show:function(a){for(var c=0;c<this.ans.length;c++)this.ans[c].seekTo(c>a?1:0);this.options.rememberance&&(document.location.hash=this.rememberanceTexts[a])}};var threeSixtyPlayer,ThreeSixtyPlayer;
+(function(a){function c(){var b=this,c=this,g=soundManager,f=navigator.userAgent,h=f.match(/msie/i),e=f.match(/opera/i),k=f.match(/safari/i),m=f.match(/chrome/i);f.match(/firefox/i);var q=f.match(/ipad|iphone/i),r="undefined"===typeof a.G_vmlCanvasManager&&"undefined"!==typeof document.createElement("canvas").getContext("2d"),n=e||m?359.9:360,t=navigator.userAgent.match(/msie [678]/i)?1:2;this.excludeClass="threesixty-exclude";this.links=[];this.sounds=[];this.soundsByURL=[];this.indexByURL=[];this.lastTouchedSound=
+this.lastSound=null;this.soundCount=0;this.vuMeter=this.oUIImageMap=this.oUITemplate=null;this.callbackCount=0;this.peakDataHistory=[];this.config={playNext:!1,autoPlay:!1,allowMultiple:!1,loadRingColor:"#ccc",playRingColor:"#000",backgroundRingColor:"#eee",segmentRingColor:"rgba(255,255,255,0.33)",segmentRingColorAlt:"rgba(0,0,0,0.1)",loadRingColorMetadata:"#ddd",playRingColorMetadata:"rgba(128,192,256,0.9)",circleDiameter:null,circleRadius:null,animDuration:500,animTransition:a.Animator.tx.bouncy,
+showHMSTime:!1,scaleFont:!0,useWaveformData:!1,waveformDataColor:"#0099ff",waveformDataDownsample:3,waveformDataOutside:!1,waveformDataConstrain:!1,waveformDataLineRatio:.64,useEQData:!1,eqDataColor:"#339933",eqDataDownsample:4,eqDataOutside:!0,eqDataLineRatio:.54,usePeakData:!0,peakDataColor:"#ff33ff",peakDataOutside:!0,peakDataLineRatio:.5,useAmplifier:!0,fontSizeMax:null,scaleArcWidth:1,useFavIcon:!1};this.css={sDefault:"sm2_link",sBuffering:"sm2_buffering",sPlaying:"sm2_playing",sPaused:"sm2_paused"};
+this.addEventHandler="undefined"!==typeof a.addEventListener?function(a,b,c){return a.addEventListener(b,c,!1)}:function(a,b,c){a.attachEvent("on"+b,c)};this.removeEventHandler="undefined"!==typeof a.removeEventListener?function(a,b,c){return a.removeEventListener(b,c,!1)}:function(a,b,c){return a.detachEvent("on"+b,c)};this.hasClass=function(a,b){return"undefined"!==typeof a.className?a.className.match(new RegExp("(\\s|^)"+b+"(\\s|$)")):!1};this.addClass=function(a,c){if(!a||!c||b.hasClass(a,c))return!1;
+a.className=(a.className?a.className+" ":"")+c};this.removeClass=function(a,c){if(!a||!c||!b.hasClass(a,c))return!1;a.className=a.className.replace(new RegExp("( "+c+")|("+c+")","g"),"")};this.getElementsByClassName=function(a,c,e){var d=e||document;e=[];var f,k=[];if("undefined"!==typeof c&&"string"!==typeof c)for(f=c.length;f--;)k&&k[c[f]]||(k[c[f]]=d.getElementsByTagName(c[f]));else k=c?d.getElementsByTagName(c):d.all||d.getElementsByTagName("*");if("string"!==typeof c)for(f=c.length;f--;)for(d=
+k[c[f]].length;d--;)b.hasClass(k[c[f]][d],a)&&e.push(k[c[f]][d]);else for(f=0;f<k.length;f++)b.hasClass(k[f],a)&&e.push(k[f]);return e};this.getParentByNodeName=function(a,b){if(!a||!b)return!1;for(b=b.toLowerCase();a.parentNode&&b!==a.parentNode.nodeName.toLowerCase();)a=a.parentNode;return a.parentNode&&b===a.parentNode.nodeName.toLowerCase()?a.parentNode:null};this.getParentByClassName=function(a,c){if(!a||!c)return!1;for(;a.parentNode&&!b.hasClass(a.parentNode,c);)a=a.parentNode;return a.parentNode&&
+b.hasClass(a.parentNode,c)?a.parentNode:null};this.getSoundByURL=function(a){return"undefined"!==typeof b.soundsByURL[a]?b.soundsByURL[a]:null};this.isChildOfNode=function(a,b){if(!a||!a.parentNode)return!1;b=b.toLowerCase();do a=a.parentNode;while(a&&a.parentNode&&a.nodeName.toLowerCase()!==b);return a&&a.nodeName.toLowerCase()===b?a:null};this.isChildOfClass=function(a,c){if(!a||!c)return!1;for(;a.parentNode&&!b.hasClass(a,c);)a=b.findParent(a);return b.hasClass(a,c)};this.findParent=function(a){if(!a||
+!a.parentNode)return!1;a=a.parentNode;if(2===a.nodeType)for(;a&&a.parentNode&&2===a.parentNode.nodeType;)a=a.parentNode;return a};this.getStyle=function(b,c){try{if(b.currentStyle)return b.currentStyle[c];if(a.getComputedStyle)return document.defaultView.getComputedStyle(b,null).getPropertyValue(c)}catch(e){}return null};this.findXY=function(a){var b=0,c=0;do b+=a.offsetLeft,c+=a.offsetTop;while(a=a.offsetParent);return[b,c]};this.getMouseXY=function(c){c=c?c:a.event;q&&c.touches&&(c=c.touches[0]);
+if(c.pageX||c.pageY)return[c.pageX,c.pageY];if(c.clientX||c.clientY)return[c.clientX+b.getScrollLeft(),c.clientY+b.getScrollTop()]};this.getScrollLeft=function(){return document.body.scrollLeft+document.documentElement.scrollLeft};this.getScrollTop=function(){return document.body.scrollTop+document.documentElement.scrollTop};this.events={play:function(){c.removeClass(this._360data.oUIBox,this._360data.className);this._360data.className=c.css.sPlaying;c.addClass(this._360data.oUIBox,this._360data.className);
+b.fanOut(this)},stop:function(){c.removeClass(this._360data.oUIBox,this._360data.className);this._360data.className="";b.fanIn(this)},pause:function(){c.removeClass(this._360data.oUIBox,this._360data.className);this._360data.className=c.css.sPaused;c.addClass(this._360data.oUIBox,this._360data.className)},resume:function(){c.removeClass(this._360data.oUIBox,this._360data.className);this._360data.className=c.css.sPlaying;c.addClass(this._360data.oUIBox,this._360data.className)},finish:function(){var a;
+c.removeClass(this._360data.oUIBox,this._360data.className);this._360data.className="";this._360data.didFinish=!0;b.fanIn(this);c.config.playNext&&(a=c.indexByURL[this._360data.oLink.href]+1,a<c.links.length&&c.handleClick({target:c.links[a]}))},whileloading:function(){this.paused&&b.updatePlaying.apply(this)},whileplaying:function(){b.updatePlaying.apply(this);this._360data.fps++},bufferchange:function(){this.isBuffering?c.addClass(this._360data.oUIBox,c.css.sBuffering):c.removeClass(this._360data.oUIBox,
+c.css.sBuffering)}};this.stopEvent=function(b){"undefined"!==typeof b&&"undefined"!==typeof b.preventDefault?b.preventDefault():"undefined"!==typeof a.event&&"undefined"!==typeof a.event.returnValue&&(a.event.returnValue=!1);return!1};this.getTheDamnLink=h?function(b){return b&&b.target?b.target:a.event.srcElement}:function(a){return a.target};this.handleClick=function(c){if(1<c.button)return!0;var e=b.getTheDamnLink(c),d,f,k,h,m,n;if("a"!==e.nodeName.toLowerCase()&&(e=b.isChildOfNode(e,"a"),!e)||
+!b.isChildOfClass(e,"ui360"))return!0;e.getAttribute("href");if(!e.href||!g.canPlayLink(e)||b.hasClass(e,b.excludeClass))return!0;g._writeDebug("handleClick()");f=e.href;(k=b.getSoundByURL(f))?k===b.lastSound?k.togglePause():(k.togglePause(),g._writeDebug("sound different than last sound: "+b.lastSound.id),!b.config.allowMultiple&&b.lastSound&&b.stopSound(b.lastSound)):(h=e.parentNode,m=b.getElementsByClassName("ui360-vis","div",h.parentNode).length,k=g.createSound({id:"ui360Sound"+b.soundCount++,
+url:f,onplay:b.events.play,onstop:b.events.stop,onpause:b.events.pause,onresume:b.events.resume,onfinish:b.events.finish,onbufferchange:b.events.bufferchange,type:e.type||null,whileloading:b.events.whileloading,whileplaying:b.events.whileplaying,useWaveformData:m&&b.config.useWaveformData,useEQData:m&&b.config.useEQData,usePeakData:m&&b.config.usePeakData}),n=parseInt(b.getElementsByClassName("sm2-360ui","div",h)[0].offsetWidth*t,10),d=b.getElementsByClassName("sm2-canvas","canvas",h),k._360data=
+{oUI360:b.getParentByClassName(e,"ui360"),oLink:e,className:b.css.sPlaying,oUIBox:b.getElementsByClassName("sm2-360ui","div",h)[0],oCanvas:d[d.length-1],oButton:b.getElementsByClassName("sm2-360btn","span",h)[0],oTiming:b.getElementsByClassName("sm2-timing","div",h)[0],oCover:b.getElementsByClassName("sm2-cover","div",h)[0],circleDiameter:n,circleRadius:n/2,lastTime:null,didFinish:null,pauseCount:0,radius:0,fontSize:1,fontSizeMax:b.config.fontSizeMax,scaleFont:m&&b.config.scaleFont,showHMSTime:m,
+amplifier:m&&b.config.usePeakData?.9:1,radiusMax:.175*n,width:0,widthMax:.4*n,lastValues:{bytesLoaded:0,bytesTotal:0,position:0,durationEstimate:0},animating:!1,oAnim:new a.Animator({duration:b.config.animDuration,transition:b.config.animTransition,onComplete:function(){}}),oAnimProgress:function(a){this._360data.radius=parseInt(this._360data.radiusMax*this._360data.amplifier*a,10);this._360data.width=parseInt(this._360data.widthMax*this._360data.amplifier*a,10);this._360data.scaleFont&&null!==this._360data.fontSizeMax&&
+(this._360data.oTiming.style.fontSize=parseInt(Math.max(1,this._360data.fontSizeMax*a),10)+"px",this._360data.oTiming.style.opacity=a);(this.paused||0===this.playState||0===this._360data.lastValues.bytesLoaded||0===this._360data.lastValues.position)&&b.updatePlaying.apply(this)},fps:0},"undefined"!==typeof b.Metadata&&b.getElementsByClassName("metadata","div",k._360data.oUI360).length&&(k._360data.metadata=new b.Metadata(k,b)),k._360data.scaleFont&&null!==k._360data.fontSizeMax&&(k._360data.oTiming.style.fontSize=
+"1px"),k._360data.oAnim.addSubject(k._360data.oAnimProgress,k),b.refreshCoords(k),b.updatePlaying.apply(k),b.soundsByURL[f]=k,b.sounds.push(k),!b.config.allowMultiple&&b.lastSound&&b.stopSound(b.lastSound),k.play());b.lastSound=k;"undefined"!==typeof c&&"undefined"!==typeof c.preventDefault?c.preventDefault():"undefined"!==typeof a.event&&(a.event.returnValue=!1);return!1};this.fanOut=function(c){if(1===c._360data.animating)return!1;c._360data.animating=0;soundManager._writeDebug("fanOut: "+c.id+
+": "+c._360data.oLink.href);c._360data.oAnim.seekTo(1);a.setTimeout(function(){c._360data.animating=0},b.config.animDuration+20)};this.fanIn=function(c){if(-1===c._360data.animating)return!1;c._360data.animating=-1;soundManager._writeDebug("fanIn: "+c.id+": "+c._360data.oLink.href);c._360data.oAnim.seekTo(0);a.setTimeout(function(){c._360data.didFinish=!1;c._360data.animating=0;b.resetLastValues(c)},b.config.animDuration+20)};this.resetLastValues=function(a){a._360data.lastValues.position=0};this.refreshCoords=
+function(a){a._360data.canvasXY=b.findXY(a._360data.oCanvas);a._360data.canvasMid=[a._360data.circleRadius,a._360data.circleRadius];a._360data.canvasMidXY=[a._360data.canvasXY[0]+a._360data.canvasMid[0],a._360data.canvasXY[1]+a._360data.canvasMid[1]]};this.stopSound=function(a){soundManager._writeDebug("stopSound: "+a.id);soundManager.stop(a.id);q||soundManager.unload(a.id)};this.buttonClick=function(c){b.handleClick({target:b.getParentByClassName(c?c.target?c.target:c.srcElement:a.event.srcElement,
+"sm2-360ui").nextSibling});return!1};this.buttonMouseDown=function(a){q?b.addEventHandler(document,"touchmove",b.mouseDown):document.onmousemove=function(a){b.mouseDown(a)};b.stopEvent(a);return!1};this.mouseDown=function(c){if(!q&&1<c.button)return!0;if(!b.lastSound)return b.stopEvent(c),!1;var e=c?c:a.event;q&&e.touches&&(e=e.touches[0]);e=b.getSoundByURL(b.getElementsByClassName("sm2_link","a",b.getParentByClassName(e.target||e.srcElement,"ui360"))[0].href);b.lastTouchedSound=e;b.refreshCoords(e);
+e=e._360data;b.addClass(e.oUIBox,"sm2_dragging");e.pauseCount=b.lastTouchedSound.paused?1:0;b.mmh(c?c:a.event);q?(b.removeEventHandler(document,"touchmove",b.mouseDown),b.addEventHandler(document,"touchmove",b.mmh),b.addEventHandler(document,"touchend",b.mouseUp)):(document.onmousemove=b.mmh,document.onmouseup=b.mouseUp);b.stopEvent(c);return!1};this.mouseUp=function(a){a=b.lastTouchedSound._360data;b.removeClass(a.oUIBox,"sm2_dragging");0===a.pauseCount&&b.lastTouchedSound.resume();q?(b.removeEventHandler(document,
+"touchmove",b.mmh),b.removeEventHandler(document,"touchend",b.mouseUP)):(document.onmousemove=null,document.onmouseup=null)};this.mmh=function(c){"undefined"===typeof c&&(c=a.event);var e=b.lastTouchedSound,d=b.getMouseXY(c),d=Math.floor(n-(b.rad2deg(Math.atan2(d[0]-e._360data.canvasMidXY[0],d[1]-e._360data.canvasMidXY[1]))+180));e.setPosition(d/n*e.durationEstimate);b.stopEvent(c);return!1};this.drawSolidArc=function(a,c,d,f,h,g,m){var n=a,q;n.getContext&&(q=n.getContext("2d"));a=q;m||b.clearCanvas(n);
+c&&(q.fillStyle=c);a.beginPath();isNaN(h)&&(h=0);c=d-f;f=e||k;if(!f||f&&0<d)a.arc(0,0,d,g,h,!1),d=b.getArcEndpointCoords(c,h),a.lineTo(d.x,d.y),a.arc(0,0,c,h,g,!0),a.closePath(),a.fill()};this.getArcEndpointCoords=function(a,b){return{x:a*Math.cos(b),y:a*Math.sin(b)}};this.deg2rad=function(a){return a*Math.PI/180};this.rad2deg=function(a){return 180*a/Math.PI};this.getTime=function(a,b){var c=Math.floor(a/1E3),e=Math.floor(c/60),c=c-60*e;return b?e+":"+(10>c?"0"+c:c):{min:e,sec:c}};this.clearCanvas=
+function(a){var b=null,c;a.getContext&&(b=a.getContext("2d"));b&&(c=a.offsetWidth,a=a.offsetHeight,b.clearRect(-(c/2),-(a/2),c,a))};this.updatePlaying=function(){var a=this._360data.showHMSTime?b.getTime(this.position,!0):parseInt(this.position/1E3,10),c=b.config.scaleArcWidth;this.bytesLoaded&&(this._360data.lastValues.bytesLoaded=this.bytesLoaded,this._360data.lastValues.bytesTotal=this.bytesTotal);this.position&&(this._360data.lastValues.position=this.position);this.durationEstimate&&(this._360data.lastValues.durationEstimate=
+this.durationEstimate);b.drawSolidArc(this._360data.oCanvas,b.config.backgroundRingColor,this._360data.width,this._360data.radius*c,b.deg2rad(n),!1);b.drawSolidArc(this._360data.oCanvas,this._360data.metadata?b.config.loadRingColorMetadata:b.config.loadRingColor,this._360data.width,this._360data.radius*c,b.deg2rad(this._360data.lastValues.bytesLoaded/this._360data.lastValues.bytesTotal*n),0,!0);0!==this._360data.lastValues.position&&b.drawSolidArc(this._360data.oCanvas,this._360data.metadata?b.config.playRingColorMetadata:
+b.config.playRingColor,this._360data.width,this._360data.radius*c,b.deg2rad(1===this._360data.didFinish?n:this._360data.lastValues.position/this._360data.lastValues.durationEstimate*n),0,!0);this._360data.metadata&&this._360data.metadata.events.whileplaying();a!==this._360data.lastTime&&(this._360data.lastTime=a,this._360data.oTiming.innerHTML=a);(this.instanceOptions.useWaveformData||this.instanceOptions.useEQData)&&r&&b.updateWaveform(this);b.config.useFavIcon&&b.vuMeter&&b.vuMeter.updateVU(this)};
+this.updateWaveform=function(a){if(!b.config.useWaveformData&&!b.config.useEQData||!g.features.waveformData&&!g.features.eqData||!a.waveformData.left.length&&!a.eqData.length&&!a.peakData.left)return!1;a._360data.oCanvas.getContext("2d");var c=parseInt(a._360data.circleDiameter/2,10)/2,e,d,f,k,h,m,n,q,t;if(b.config.useWaveformData)for(f=b.config.waveformDataDownsample,f=Math.max(1,f),k=256/f,n=b.config.waveformDataOutside?1:b.config.waveformDataConstrain?.5:.565,c=b.config.waveformDataOutside?.7:
+.75,q=b.deg2rad(360/k*b.config.waveformDataLineRatio),e=0;256>e;e+=f)h=b.deg2rad(e/k*1/f*360),m=h+q,d=a.waveformData.left[e],0>d&&b.config.waveformDataConstrain&&(d=Math.abs(d)),b.drawSolidArc(a._360data.oCanvas,b.config.waveformDataColor,a._360data.width*n*(2-b.config.scaleArcWidth),a._360data.radius*c*1.25*d,m,h,!0);if(b.config.useEQData)for(f=b.config.eqDataDownsample,f=Math.max(1,f),k=192,n=b.config.eqDataOutside?1:.565,d=b.config.eqDataOutside?-1:1,c=b.config.eqDataOutside?.5:.75,q=b.deg2rad(360/
+(k/f)*b.config.eqDataLineRatio),t=b.deg2rad(1===a._360data.didFinish?360:a._360data.lastValues.position/a._360data.lastValues.durationEstimate*360),e=0;e<k;e+=f)h=b.deg2rad(e/k*360),m=h+q,b.drawSolidArc(a._360data.oCanvas,m>t?b.config.eqDataColor:b.config.playRingColor,a._360data.width*n,a._360data.radius*c*a.eqData.left[e]*d,m,h,!0);if(b.config.usePeakData&&!a._360data.animating){c=a.peakData.left||a.peakData.right;k=3;for(e=0;e<k;e++)c=c||a.eqData[e];a._360data.amplifier=b.config.useAmplifier?.9+
+.1*c:1;a._360data.radiusMax=.175*a._360data.circleDiameter*a._360data.amplifier;a._360data.widthMax=.4*a._360data.circleDiameter*a._360data.amplifier;a._360data.radius=parseInt(a._360data.radiusMax*a._360data.amplifier,10);a._360data.width=parseInt(a._360data.widthMax*a._360data.amplifier,10)}};this.getUIHTML=function(a){return['<canvas class="sm2-canvas" width="'+a+'" height="'+a+'"></canvas>',' <span class="sm2-360btn sm2-360btn-default"></span>',' <div class="sm2-timing'+(navigator.userAgent.match(/safari/i)?
+" alignTweak":"")+'"></div>',' <div class="sm2-cover"></div>']};this.uiTest=function(a){var c=document.createElement("div"),e,d,f;c.className="sm2-360ui";e=document.createElement("div");e.className="ui360"+(a?" "+a:"");c=e.appendChild(c.cloneNode(!0));e.style.position="absolute";e.style.left="-9999px";a=document.body.appendChild(e);d=c.offsetWidth*t;f=b.getUIHTML(d);c.innerHTML=f[1]+f[2]+f[3];c=parseInt(d,10);d=parseInt(c/2,10);a=b.getElementsByClassName("sm2-timing","div",a)[0];a=parseInt(b.getStyle(a,
+"font-size"),10);isNaN(a)&&(a=null);e.parentNode.removeChild(e);return{circleDiameter:c,circleRadius:d,fontSizeMax:a}};this.init=function(){g._writeDebug("threeSixtyPlayer.init()");var c=b.getElementsByClassName("ui360","div"),e,d,f=[],k=!1,m=0,n,r,w,v,z;e=0;for(d=c.length;e<d;e++)f.push(c[e].getElementsByTagName("a")[0]),c[e].style.backgroundImage="none";b.oUITemplate=document.createElement("div");b.oUITemplate.className="sm2-360ui";b.oUITemplateVis=document.createElement("div");b.oUITemplateVis.className=
+"sm2-360ui";r=b.uiTest();b.config.circleDiameter=r.circleDiameter;b.config.circleRadius=r.circleRadius;w=b.uiTest("ui360-vis");b.config.fontSizeMax=w.fontSizeMax;b.oUITemplate.innerHTML=b.getUIHTML(b.config.circleDiameter).join("");b.oUITemplateVis.innerHTML=b.getUIHTML(w.circleDiameter).join("");e=0;for(d=f.length;e<d;e++)!g.canPlayLink(f[e])||b.hasClass(f[e],b.excludeClass)||b.hasClass(f[e],b.css.sDefault)||(b.addClass(f[e],b.css.sDefault),b.links[m]=f[e],b.indexByURL[f[e].href]=m,m++,k=b.hasClass(f[e].parentNode,
+"ui360-vis"),n=(k?w:r).circleDiameter,c=(k?w:r).circleRadius,k=f[e].parentNode.insertBefore((k?b.oUITemplateVis:b.oUITemplate).cloneNode(!0),f[e]),h&&"undefined"!==typeof a.G_vmlCanvasManager?(v=document.createElement("canvas"),v.className="sm2-canvas",z="sm2_canvas_"+e+(new Date).getTime(),v.id=z,v.width=n,v.height=n,k.appendChild(v),a.G_vmlCanvasManager.initElement(v),n=document.getElementById(z),k=n.parentNode.getElementsByTagName("canvas"),1<k.length&&(n=k[k.length-1])):n=f[e].parentNode.getElementsByTagName("canvas")[0],
+1<t&&b.addClass(n,"hi-dpi"),k=b.getElementsByClassName("sm2-cover","div",f[e].parentNode)[0],v=f[e].parentNode.getElementsByTagName("span")[0],b.addEventHandler(v,"click",b.buttonClick),q?b.addEventHandler(k,"touchstart",b.mouseDown):b.addEventHandler(k,"mousedown",b.mouseDown),n=n.getContext("2d"),n.translate(c,c),n.rotate(b.deg2rad(-90)));0<m&&(b.addEventHandler(document,"click",b.handleClick),b.config.autoPlay&&b.handleClick({target:b.links[0],preventDefault:function(){}}));g._writeDebug("threeSixtyPlayer.init(): Found "+
+m+" relevant items.");b.config.useFavIcon&&"undefined"!==typeof this.VUMeter&&(this.vuMeter=new this.VUMeter(this))}}c.prototype.VUMeter=function(a){var c=this,g=document.getElementsByTagName("head")[0],f=navigator.userAgent.match(/opera/i),h=navigator.userAgent.match(/firefox/i);this.vuMeterData=[];this.vuDataCanvas=null;this.setPageIcon=function(c){if(!a.config.useFavIcon||!a.config.usePeakData||!c)return!1;var d=document.getElementById("sm2-favicon");d&&(g.removeChild(d),d=null);d||(d=document.createElement("link"),
+d.id="sm2-favicon",d.rel="shortcut icon",d.type="image/png",d.href=c,document.getElementsByTagName("head")[0].appendChild(d))};this.resetPageIcon=function(){if(!a.config.useFavIcon)return!1;var c=document.getElementById("favicon");c&&(c.href="/favicon.ico")};this.updateVU=function(e){9<=soundManager.flashVersion&&a.config.useFavIcon&&a.config.usePeakData&&c.setPageIcon(c.vuMeterData[parseInt(16*e.peakData.left,10)][parseInt(16*e.peakData.right,10)])};this.createVUData=function(){var a=0,b=0,f=c.vuDataCanvas.getContext("2d"),
+h=f.createLinearGradient(0,16,0,0),g=f.createLinearGradient(0,16,0,0);h.addColorStop(0,"rgb(0,192,0)");h.addColorStop(.3,"rgb(0,255,0)");h.addColorStop(.625,"rgb(255,255,0)");h.addColorStop(.85,"rgb(255,0,0)");g.addColorStop(0,"rgba(0,0,0,0.2)");g.addColorStop(1,"rgba(0,0,0,0.5)");for(a=0;16>a;a++)c.vuMeterData[a]=[];for(a=0;16>a;a++)for(b=0;16>b;b++)c.vuDataCanvas.setAttribute("width",16),c.vuDataCanvas.setAttribute("height",16),f.fillStyle=g,f.fillRect(0,0,7,15),f.fillRect(8,0,7,15),f.fillStyle=
+h,f.fillRect(0,15-a,7,16-(16-a)),f.fillRect(8,15-b,7,16-(16-b)),f.clearRect(0,3,16,1),f.clearRect(0,7,16,1),f.clearRect(0,11,16,1),c.vuMeterData[a][b]=c.vuDataCanvas.toDataURL("image/png")};this.testCanvas=function(){var a=document.createElement("canvas"),b=null;if(!a||"undefined"===typeof a.getContext)return null;b=a.getContext("2d");if(!b||"function"!==typeof a.toDataURL)return null;try{a.toDataURL("image/png")}catch(c){return null}return a};this.init=function(){a.config.useFavIcon&&(c.vuDataCanvas=
+c.testCanvas(),c.vuDataCanvas&&(h||f)?c.createVUData():a.config.useFavIcon=!1)};this.init()};c.prototype.Metadata=function(a,c){soundManager._wD("Metadata()");var g=this,f=a._360data.oUI360,h=f.getElementsByTagName("ul")[0].getElementsByTagName("li");navigator.userAgent.match(/firefox/i);var e;this.lastWPExec=0;this.refreshInterval=250;this.totalTime=0;this.events={whileplaying:function(){var e=a._360data.width,f=a._360data.radius,h=a.durationEstimate||1E3*g.totalTime,r=null,n,t;n=0;for(t=g.data.length;n<
+t;n++)r=0===n%2,c.drawSolidArc(a._360data.oCanvas,r?c.config.segmentRingColorAlt:c.config.segmentRingColor,e,f/2,c.deg2rad(g.data[n].endTimeMS/h*360),c.deg2rad((g.data[n].startTimeMS||1)/h*360),!0);e=new Date;e-g.lastWPExec>g.refreshInterval&&(g.refresh(),g.lastWPExec=e)}};this.refresh=function(){var c,e,d=null,f=a.position,h=a._360data.metadata.data;c=0;for(e=h.length;c<e;c++)if(f>=h[c].startTimeMS&&f<=h[c].endTimeMS){d=c;break}d!==h.currentItem&&d<h.length&&(a._360data.oLink.innerHTML=h.mainTitle+
+' <span class="metadata"><span class="sm2_divider"> | </span><span class="sm2_metadata">'+h[d].title+"</span></span>",h.currentItem=d)};this.strToTime=function(a){a=a.split(":");var b=0,c;for(c=a.length;c--;)b+=parseInt(a[c],10)*Math.pow(60,a.length-1-c);return b};this.data=[];this.data.givenDuration=null;this.data.currentItem=null;this.data.mainTitle=a._360data.oLink.innerHTML;for(e=0;e<h.length;e++)this.data[e]={o:null,title:h[e].getElementsByTagName("p")[0].innerHTML,startTime:h[e].getElementsByTagName("span")[0].innerHTML,
+startSeconds:g.strToTime(h[e].getElementsByTagName("span")[0].innerHTML.replace(/[()]/g,"")),duration:0,durationMS:null,startTimeMS:null,endTimeMS:null,oNote:null};f=c.getElementsByClassName("duration","div",f);this.data.givenDuration=f.length?1E3*g.strToTime(f[0].innerHTML):0;for(e=0;e<this.data.length;e++)this.data[e].duration=parseInt(this.data[e+1]?this.data[e+1].startSeconds:(g.data.givenDuration?g.data.givenDuration:a.durationEstimate)/1E3,10)-this.data[e].startSeconds,this.data[e].startTimeMS=
+1E3*this.data[e].startSeconds,this.data[e].durationMS=1E3*this.data[e].duration,this.data[e].endTimeMS=this.data[e].startTimeMS+this.data[e].durationMS,this.totalTime+=this.data[e].duration};navigator.userAgent.match(/webkit/i)&&navigator.userAgent.match(/mobile/i)&&soundManager.setup({useHTML5Audio:!0});soundManager.setup({html5PollingInterval:50,debugMode:a.location.href.match(/debug=1/i),consoleOnly:!0,flashVersion:9,useHighPerformance:!0});soundManager.debugMode&&a.setInterval(function(){var b=
+a.threeSixtyPlayer;b&&b.lastSound&&b.lastSound._360data.fps&&"undefined"===typeof a.isHome&&(soundManager._writeDebug("fps: ~"+b.lastSound._360data.fps),b.lastSound._360data.fps=0)},1E3);a.ThreeSixtyPlayer=c})(window);threeSixtyPlayer=new ThreeSixtyPlayer;soundManager.onready(threeSixtyPlayer.init);
+(function(a){function c(c,e){function d(a){f.css.add(t.o,a)}function m(a){f.css.remove(t.o,a)}function q(a){if(a)if(n.on&&n.on[a])n.on[a](n);else if(b.on[a])b.on[a](n)}function r(){0<=l.tonearm.angle&&(t.tonearm.style[f.features.transform.prop]="rotate("+l.tonearm.angle+"deg)")}var n,t,l,p,u;p="tt_"+g;g++;e=e||{};void 0===e.hideLabelWithArtwork&&(e.hideLabelWithArtwork=!0);l={power:{turntable:!1,motor:!1,motorVelocity:0},tonearm:{angle:0,maxAngle:42,minAngle:0},record:{hasArtwork:!1}};u={start:function(){l.power.turntable&&
+!l.power.motor&&(l.power.motor=!0,d("motor-on"),q("start"))},stop:function(){l.power.motor&&(l.power.motor=!1,m("motor-on"),q("stop"))},toggle:function(){l.power.motor?u.stop():u.start()},powerOn:function(){l.power.turntable||(l.power.turntable=!0,d("power-on"),q("powerOn"))},powerOff:function(){l.power.turntable&&(l.power.turntable=!1,m("power-on"),q("powerOff"));u.stop()},powerToggle:function(){l.power.turntable?u.powerOff():u.powerOn()},setTonearmAngle:function(a){isNaN(a)||(l.tonearm.angle=Math.max(l.tonearm.minAngle,
+Math.min(l.tonearm.maxAngle,a)),f.features.transform.prop&&(f.features.getAnimationFrame?f.features.getAnimationFrame(r):r()))},addSlipmat:function(){d("has-slipmat")},removeSlipmat:function(){m("has-slipmat")},toggleSlipmat:function(){f.css.toggle(t.o,"has-slipmat")},addRecord:function(){d("has-record")},removeRecord:function(){m("has-record")},toggleRecord:function(){f.css.toggle(t.o,"has-record")},setArtwork:function(a){a?(t.record.style.backgroundImage="url("+a+")",l.record.hasArtwork||(d("has-artwork"),
+l.record.hasArtwork=!0)):l.record.hasArtwork&&(t.record.style.backgroundImage="none",m("has-artwork"),l.record.hasArtwork=!1);e.hideLabelWithArtwork?d("hide-label-with-artwork"):m("hide-label-with-artwork")}};t={o:c,platter:f.dom.get(c,".platter"),record:f.dom.get(c,".record"),slipmat:f.dom.get(c,".slipmat"),tonearm:f.dom.get(c,".tonearm")};t.o.id?p=t.o.id:t.o.id=p;f.events.add(t.o,"mousedown",function(a){var b;if((b=a.target)&&(b=b.getAttribute("data-method"))&&u[b])u[b](a)});f.events.add(t.o,"click",
+function(a){if(a.target&&"A"===a.target.nodeName)return f.events.preventDefault(a),!1});a.setTimeout(u.powerToggle,500);return n={id:p,data:l,methods:u,on:{}}}var b=[],d={},g=0,f;b.on={};f={array:function(){return{compare:function(a){var b;return function(c,d){return b=c[a]<d[a]?-1:c[a]>d[a]?1:0}},shuffle:function(a){var b,c,d;for(b=a.length-1;0<b;b--)c=Math.floor(Math.random()*(b+1)),d=a[b],a[b]=a[c],a[c]=d;return a}}}(),css:function(){function a(b,c){return void 0!==b.className?(new RegExp("(^|\\s)"+
+c+"(\\s|$)")).test(b.className):!1}function b(c,e){if(!c||!e||a(c,e))return!1;c.className=(c.className?c.className+" ":"")+e}function c(b,e){if(!b||!e||!a(b,e))return!1;b.className=b.className.replace(new RegExp("( "+e+")|("+e+")","g"),"")}return{has:a,add:b,remove:c,swap:function(a,d,f){var h={className:a.className};c(h,d);b(h,f);a.className=h.className},toggle:function(d,f){var g;g=a(d,f);(g?c:b)(d,f);return!g}}}(),dom:function(){function a(b,c){var d,f,h;1===arguments.length?(d=document.documentElement,
+f=b):(d=b,f=c);d&&d.querySelectorAll&&(h=d.querySelectorAll(f));return h}return{get:function(){var b=a.apply(this,arguments);return b&&b.length?b[b.length-1]:b&&0===b.length?null:b},getAll:a}}(),position:function(){return{getOffX:function(a){var b=0;if(a.offsetParent)for(;a.offsetParent;)b+=a.offsetLeft,a=a.offsetParent;else a.x&&(b+=a.x);return b},getOffY:function(a){var b=0;if(a.offsetParent)for(;a.offsetParent;)b+=a.offsetTop,a=a.offsetParent;else a.y&&(b+=a.y);return b}}}(),style:function(){return{get:function(b,
+c){var d;b.currentStyle?d=b.currentStyle[c]:a.getComputedStyle&&(d=document.defaultView.getComputedStyle(b,null).getPropertyValue(c));return d}}}(),events:function(){var b;b=void 0!==a.removeEventListener?function(a,b,c){return a.removeEventListener(b,c,!1)}:function(a,b,c){return a.detachEvent("on"+b,c)};return{add:function(c,d,f){a.addEventListener?c.addEventListener(d,f,!1):c.attachEvent("on"+d,f);return{detach:function(){return b(c,d,f)}}},preventDefault:function(a){a.preventDefault?a.preventDefault():
+(a.returnValue=!1,a.cancelBubble=!0);return!1},remove:b}}(),features:function(){function b(a){return void 0!==r.style[a]?a:null}function c(a){try{r.style[n]=a}catch(b){return!1}return!!r.style[n]}var d,f,g,r,n;r=document.createElement("div");d=(f=a.requestAnimationFrame||a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame||a.msRequestAnimationFrame||null)?function(){return f.apply(a,arguments)}:null;d={transform:{ie:b("-ms-transform"),moz:b("MozTransform"),opera:b("OTransform"),
+webkit:b("webkitTransform"),w3:b("transform"),prop:null},rotate:{has3D:!1,prop:null},getAnimationFrame:d};d.transform.prop=d.transform.w3||d.transform.moz||d.transform.webkit||d.transform.ie||d.transform.opera;d.transform.prop&&(n=d.transform.prop,c("rotate3d(0,0,0,0deg)")?(d.rotate.has3D=!0,g="rotate3d"):c("rotate(0deg)")&&(g="rotate"),d.rotate.prop=g);r=null;return d}()};soundManager.setup({html5PollingInterval:50,flashVersion:9});soundManager.onready(function(){var a,e,g,m;if((a=f.dom.getAll(".turntable"))&&
+a.length)for(e=0,g=a.length;e<g;e++)m=new c(a[e]),b.push(m),d[m.id]=m});a.turntables=b;a.turntablesById=d;a.turntables.utils=f})(window);
+(function(a){var c;function b(a){return a&&soundManager.canPlayLink(a)&&(!e.requireCSS||h.css.has(a,e.requireCSS))&&(!e.excludeCSS||!h.css.has(a,e.excludeCSS))}function d(){var a,b;g.on.start=function(a){soundManager.play(a.id,e.soundOptions)};g.on.stop=function(a){soundManager.pause(a.id);k.endOfRecordNoise&&k.endOfRecordNoise.stop()};if(q.load.bind)for(a=0,b=g.length;a<b;a++)g[a].methods.load=q.load.bind(g[a]);g.config=e}var g,f,h,e,k,m,q,r;e={requireCSS:null,excludeCSS:"turntable-exclude",playNext:!0,
+hasRecordAtStart:!1,useEndOfRecordNoise:!0,endOfRecordNoise:["audio/record-noise-1.mp3","audio/record-noise-2.mp3"],htmlAttribute:"data-turntable",turntable:{tonearm:{angleToRecord:16,recordAngleSpan:26}},soundOptions:{multiShot:!1,onload:function(a){a||this.duration||f.sound.error.apply(this,arguments)},whileplaying:function(){f.sound.whileplaying.apply(this,arguments)},onfinish:function(){f.sound.finish.apply(this,arguments)}}};c=[];k={endOfRecordNoise:null,soundFinished:!1,lastLink:null};m=navigator.userAgent.match(/iphone|ipad|android|tablet|mobile/i);
+f={mouse:{click:function(a){var c,d;c=a.target;if((!c||"A"!==c.nodeName)&&c&&c.parentNode){do c=c.parentNode;while(c&&"A"!==c.nodeName&&c.parentNode)}if(b(c))return d=c.getAttribute("data-turntable"),d=turntablesById[d]||g[0],k.lastLink=c,r(d,c.href),d.methods.setArtwork(c.getAttribute("data-artwork")||""),h.events.preventDefault(a)}},sound:{whileplaying:function(){var a=this.position/this.durationEstimate;0<=a&&this._turntable&&this._turntable.methods.setTonearmAngle(e.turntable.tonearm.angleToRecord+
+e.turntable.tonearm.recordAngleSpan*a)},error:function(){a.console&&console.warn&&console.warn("Turntable failed to load "+this.url);f.sound.finish.apply(this)},finish:function(){var a;k.finished=!0;if(e.playNext){a=k.lastLink;var d,g,h,m,q,r,y;y=a.getAttribute(e.htmlAttribute);m=document.getElementsByTagName("a");q=[];g=0;for(h=m.length;g<h;g++)if(b(m[g])&&(!y||m[g].getAttribute(e.htmlAttribute)===y)){q.push(m[g]);if(d){r=m[g];break}a===m[g]&&(d=!0)}d||(r=q[0]);r===a&&(r=null);(a=r)&&f.mouse.click({target:a})}!a&&
+this._turntable&&(e.useEndOfRecordNoise&&c.length?(this._turntable.methods.setTonearmAngle(e.turntable.tonearm.angleToRecord+e.turntable.tonearm.recordAngleSpan),k.endOfRecordNoise=c[parseInt(Math.random()*c.length,10)],k.endOfRecordNoise.play({loops:999})):this._turntable.methods.stop())}}};r=function(a,b,c){var d,h;d=a||g[0];d.id&&(h=soundManager.getSoundById(d.id,!0));h?h.url!==b&&h.stop():h=soundManager.createSound({id:d.id,url:b});k.finished=!1;h._turntable=a;e.soundOptions.url=b;k.endOfRecordNoise&&
+(k.endOfRecordNoise.stop(),k.endOfRecordNoise=null);!d.data.power.motor||h.playState||c||h.play(e.soundOptions);d.methods.addSlipmat();d.methods.addRecord();c||(d.methods.powerOn(),d.methods.start(),f.sound.whileplaying.apply(h))};q={load:function(a,b){r(this,a,!0);b&&this.methods.setArtwork(b)}};soundManager.onready(function(){var b,k;if(!m&&e.useEndOfRecordNoise&&e.endOfRecordNoise.length)for(b=0,k=e.endOfRecordNoise.length;b<k;b++)c.push(soundManager.createSound({url:e.endOfRecordNoise[b]}));if(e.hasRecordAtStart)for(b=
+0,k=g.length;b<k;b++)g[b].methods.addRecord();g=a.turntables;d();h=g.utils;h.events.add(document,"click",f.mouse.click)})})(window);var IS_CHRISTMAS=document.domain.match(/schillmania.com/i)&&11==(new Date).getMonth()||window.location.toString().match(/christmas/i);function _id(a){return document.getElementById(a)}getSoundByURL=function(a){return"undefined"!=typeof self.soundsByURL[a]?self.soundsByURL[a]:null};
+function init(){for(var a=document.getElementById("main"),c=a.getElementsByTagName("dt"),b=c.length;b--;)0==(b+1)%2&&utils.addClass(c[b],"alt");c=a.getElementsByTagName("dl");for(b=c.length;b--;)0==(b+1)%2&&utils.addClass(c[b],"alt");IS_CHRISTMAS&&(a=document.body.className.split(" "),a.push("has-lights"),document.body.className=a.join(" "))}
+function Utils(){var a=this;this.hasClass=function(a,b){return"undefined"!=typeof a.className?(new RegExp("(^|\\s)"+b+"(\\s|$)")).test(a.className):!1};this.addClass=function(c,b){if(!c||!b||a.hasClass(c,b))return!1;c.className=(c.className?c.className+" ":"")+b};this.removeClass=function(c,b){if(!c||!b||!a.hasClass(c,b))return!1;c.className=c.className.replace(new RegExp("( "+b+")|("+b+")","g"),"")};this.toggleClass=function(c,b){(a.hasClass(c,b)?a.removeClass:a.addClass)(c,b)};this.getElementsByClassName=
+function(c,b,d){var g=d||document;d=[];var f,h=[];if("undefined"!=typeof b&&"string"!=typeof b)for(f=b.length;f--;)h&&h[b[f]]||(h[b[f]]=g.getElementsByTagName(b[f]));else h=b?g.getElementsByTagName(b):g.all||g.getElementsByTagName("*");if("string"!=typeof b)for(f=b.length;f--;)for(g=h[b[f]].length;g--;)a.hasClass(h[b[f]][g],c)&&(d[d.length]=h[b[f]][g]);else for(f=0;f<h.length;f++)a.hasClass(h[f],c)&&(d[d.length]=h[f]);return d};this.findParent=function(a){if(!a||!a.parentNode)return!1;a=a.parentNode;
+if(2==a.nodeType)for(;a&&a.parentNode&&2==a.parentNode.nodeType;)a=a.parentNode;return a};this.getOffY=function(a){var b=0;if(a.offsetParent)for(;a.offsetParent;)b+=a.offsetTop,a=a.offsetParent;else a.y&&(b+=a.y);return b};this.isChildOfClass=function(c,b){if(!c||!b)return!1;for(;c.parentNode&&!a.hasClass(c,b);)c=a.findParent(c);return a.hasClass(c,b)};this.getParentByClassName=function(c,b){if(!c||!b)return!1;for(b=b.toLowerCase();c.parentNode&&!a.hasClass(c.parentNode,b);)c=a.findParent(c);return c.parentNode&&
+a.hasClass(c.parentNode,b)?c.parentNode:null}}var utils=new Utils,lastSelected=null;function resetFilter(a){var c=null;_id("filter-box").style.display="none";utils.removeClass(_id("main"),"filtered");for(var b=utils.getElementsByClassName("f-block",["div","dl"],_id("main")),d=b.length;d--;)if(b[d].style.display="block",c=utils.getParentByClassName(b[d],"columnar",_id("main")))c.style.display="block";lastSelected&&utils.removeClass(lastSelected,"active");a&&(lastSelected=a);return!1}
+function setFilter(a,c){var b=a?a.target||a.srcElement:event.srcElement;utils.addClass(_id("main"),"filtered");var d=b.nodeName.toLowerCase();if("a"==d){var g=utils.findParent(b);g&&"li"==g.nodeName.toLowerCase()&&(b=g,d=b.nodeName.toLowerCase())}var f="",g=utils.getElementsByClassName("f-block",["div","dl"],_id("main")),h=utils.getElementsByClassName("columnar","div",_id("main")),e=null,k=[];if("li"!=d||"ignore"==b.className)return!0;var m=lastSelected&&lastSelected==b&&utils.hasClass(lastSelected,
+"active");if("li"==d&&m)return"undefined"!==typeof a.preventDefault&&a.preventDefault(),resetFilter();if("li"==d){f=b.getElementsByTagName("a").length?b.getElementsByTagName("a")[0].innerHTML:b.innerHTML;f=c+f.substr(0,-1!=f.indexOf("(")?f.indexOf("("):999).toLowerCase().replace(/\s+/i,"-");d=f.substr(f.length-1);if("-"==d||" "==d)f=f.substr(0,f.length-1);for(d=g.length;d--;)e=utils.getParentByClassName(g[d],"columnar",_id("main")),utils.hasClass(g[d],f)?(g[d].style.display="block",e&&k.push(e)):
+g[d].style.display="none";for(d=h.length;d--;)h[d].style.display="none";for(d=k.length;d--;)k[d].style.display="block";_id("search-results").innerHTML='<h3><span class="option"><a href="#" title="Restore full content" onclick="resetFilter();return false" style="text-decoration:none"> clear filter </a></span>Content filter: '+("f-"==c?"soundManager.":"s-"==c?"[SMSound object].":"")+'<b style="font-weight:bold">'+b.innerHTML+"</b></h3>";_id("search-results").style.display="block";_id("filter-box").style.display=
+"block";m?(_id("filter-box").style.paddingBottom="0px",_id("filter-box").style.display="none"):(_id("filter-box").style.paddingBottom="0px",navigator.userAgent.match(/msie/i)||(_id("filter-box").style.paddingBottom=Math.max(0,(document.documentElement.scrollTop||window.scrollY)-utils.getOffY(_id("filter-box"))-parseInt(_id("filter-box").offsetHeight)-20)+"px"),_id("filter-box").style.display="block");lastSelected?lastSelected==b?utils.toggleClass(lastSelected,"active"):(utils.removeClass(lastSelected,
+"active"),utils.addClass(b,"active")):utils.addClass(b,"active");lastSelected=b;"undefined"!==typeof a.preventDefault&&a.preventDefault();return!1}}function getLiveData(){getDynamicData()}function getDynamicData(){loadScript("http://www.schillmania.com/services/soundmanager2/info/?version="+soundManager.versionNumber+"&rnd="+parseInt(1048576*Math.random()))}
+function loadScript(a,c){function b(){this.onload=this.onreadystatechange=null;window.setTimeout(c,20)}var d=function(){var a=this.readyState;if("loaded"==a||"complete"==a)this.onload=this.onreadystatechange=null,window.setTimeout(c,20)},g=document.createElement("script");g.type="text/javascript";c&&(g.onreadystatechange=d,g.onload=b);g.src=a;document.getElementsByTagName("head")[0].appendChild(g)}function doAltShortcuts(){}
+function fixLinks(){if(document.location.protocol.match(/http/i))return!1;for(var a=document.getElementsByTagName("a"),c=null,b=null,d=a.length;d--;)c=a[d].href.toString(),c.match(/http/i)||utils.hasClass(a[d],"norewrite")||!(c.match(/doc/i)||c.match(/demo/i)||c.match(/../))||(b=Math.max(c.lastIndexOf("?"),-1),b=Math.max(c.lastIndexOf("#"),b),b=Math.max(c.lastIndexOf("/")+1,b),-1==b&&(b=c.length),c.match(/\.html/i)||a[d].setAttribute("href",c.substr(0,b)+"index.html"+c.substr(b)))}
+function ie6Sucks(){if(!navigator.userAgent.match(/msie 6/i))return!1;var a=_id("nav").getElementsByTagName("li")[1],c=a.getElementsByTagName("a")[0],b=a.getElementsByTagName("ul")[0];c.onclick=function(){b.style.display="block";setTimeout(function(){document.onclick=function(){b.style.display="none";document.onclick=null}},20);return!1}}function doVersion(){var a=_id("version");if(!a)return!1;a.innerHTML=soundManager.versionNumber}
+function doChristmasLights(){IS_CHRISTMAS&&(window.XLSF_URL_BASE="demo/christmas-lights/",window.XLSF_LIGHT_CLASS="pico",loadScript("demo/christmas-lights/christmaslights.js",function(){"undefined"!=typeof smashInit&&setTimeout(function(){smashInit()},20)}))}
+if(window.is_home){var checkBadSafari=function(){var a=navigator.userAgent;document.location.href.match(/sm2-usehtml5audio/i)||window.location.toString().match(/sm2\-ignorebadua/i)||!a.match(/safari/i)||a.match(/chrome/i)||!a.match(/OS X 10_6_([3-7])/i)||(a=document.createElement("li"),a.innerHTML='<b>Note</b>: Partial HTML5 in effect. Using Flash for MP3/MP4 formats (if available) for this browser/OS due to HTML5 audio load/play failures in Safari 4 + 5 on Snow Leopard 10.6.3 - 10.6.7 (purportedly fixed in OS X 10.6.8 and 10.7 "Lion.") Issue caused by bugs in QuickTime X and/or underlying frameworks. See <a href="https://bugs.webkit.org/show_bug.cgi?id=32159#c9">bugs.webkit.org #32519</a>. (Safari on iOS, Leopard and Windows OK, however.) <p style="margin:0.5em 0px 0.5em 0px">Try <a href="?sm2-ignorebadua&sm2-usehtml5audio=1">HTML5 anyway?</a> (some MP3 playback may intermittently fail.)',
+_id("html5-audio-notes").appendChild(a))};soundManager.useHTML5Audio=!0;document.location.href.match(/sm2-usehtml5audio=1/i)?soundManager.useHTML5Audio=!0:document.location.href.match(/sm2-usehtml5audio=0/i)&&(soundManager.useHTML5Audio=!1);soundManager.setup({preferFlash:!1,useFlashBlock:!0,useHighPerformance:!0,bgColor:"#ffffff",debugMode:!1,url:"swf/",wmode:"transparent"});var PP_CONFIG={autoStart:!1,playNext:!0,useThrottling:!1,usePeakData:!0,useWaveformData:!1,useEQData:!1,useFavIcon:!1};threeSixtyPlayer.config=
+{playNext:!1,autoPlay:!1,allowMultiple:!0,loadRingColor:"#ccc",playRingColor:"#000",backgroundRingColor:"#eee",circleDiameter:256,circleRadius:128,scaleArcWidth:1,animDuration:500,animTransition:Animator.tx.bouncy,showHMSTime:!0,useWaveformData:!0,waveformDataColor:"#0099ff",waveformDataDownsample:2,waveformDataOutside:!1,waveformDataConstrain:!1,waveformDataLineRatio:.73,useEQData:!0,eqDataColor:"#339933",eqDataDownsample:2,eqDataOutside:!0,eqDataLineRatio:.69,usePeakData:!0,peakDataColor:"#ff33ff",
+peakDataOutside:!0,peakDataLineRatio:.5,useAmplifier:!0};navigator.platform.match(/win32/i)&&navigator.userAgent.match(/firefox/i)&&(soundManager.useHighPerformance=!1);soundManager.onready(function(){_id("sm2-support").style.display="none";_id("sm2-support-warning").style.display="none";soundManager.didFlashBlock&&soundManager.createSound({id:"success",url:"demo/_mp3/mouseover.mp3"}).play();doChristmasLights();var a,c=!1;a=navigator;var b=a.plugins,d,g=window.ActiveXObject;if(b&&b.length)(a=a.mimeTypes)&&
+a["application/x-shockwave-flash"]&&a["application/x-shockwave-flash"].enabledPlugin&&a["application/x-shockwave-flash"].enabledPlugin.description&&(c=!0);else if("undefined"!==typeof g){try{d=new g("ShockwaveFlash.ShockwaveFlash")}catch(f){}c=!!d}a=c;b=soundManager;if(b.useHTML5Audio&&b.hasHTML5){(c=document.getElementById("html5-support-li"))&&c.parentNode.removeChild(c);d=document.createElement("div");d.id="html5-support-li";d.className="html5support";c=[];g=!1;for(item in b.audioFormats)b.audioFormats.hasOwnProperty(item)&&
+(g=soundManager.filePattern.test("."+item),c.push('<span class="'+(b.html5[item]?"true":"false")+(!b.html5[item]&&g?" partial":"")+'" title="'+(b.html5[item]?"Native HTML5 support found":"No HTML5 support found"+(g?", using Flash fallback if present":", no Flash support either"))+'">'+(b.html5[item]?"<":"")+item+(b.html5[item]?">":"")+"</span>"));d.innerHTML=['<b>This browser\'s <em class="true"><HTML5></em> vs. <em class="partial">Flash</em> support:<p style="margin:0.5em 0px 0.5em 0px"></b>',
+c.join(""),'<br /><b class="note">',soundManager.html5.mp3||soundManager.html5.mp4?a&&soundManager.preferFlash?'Preferring flash for MP3/MP4; try <a href="?sm2-preferFlash=0" title="Try using soundManager.preferFlash=false to have HTML5 actually play MP3/MP4 formats and depending on support, run SM2 entirely without flash." class="cta">preferFlash=false</a> for HTML5-only mode.':soundManager.html5Only?"HTML5-only mode."+(soundManager.canPlayMIME("audio/aac")?"":' Try <a href="?sm2-preferFlash=1,flash9" title="Try using soundManager.preferFlash=true to have Flash play MP3/MP4 formats." class="cta">preferFlash=true</a> for MP4 support as needed.'):
+" Some flash required; allowing HTML5 to play MP3/MP4, as supported.</p>":"Flash is required for this browser to play MP3/MP4.","</b>"].join("");_id("html5-audio-notes").appendChild(d);_id("without-html5").style.display="inline"}else _id("without-html5").style.display="none";checkBadSafari();c=utils.getElementsByClassName("button-exclude","a",_id("inline-playlist")).concat(utils.getElementsByClassName("exclude","a",_id("graphic-playlist")));a=0;for(b=c.length;a<b;a++)soundManager.canPlayLink(c[a])||
+(c[a].className+=" not-supported",c[a].title+=". \n\nNOTE: "+(soundManager.useHTML5Audio?"Format apparently not supported under this configuration or browser.":"SoundManager 2's HTML5 feature is not currently enabled. (Try turning it on, see +html5 link.)"))});soundManager.ontimeout(function(){if(navigator.userAgent.match(/msie 6/i))return!1;var a=_id("sm2-support"),c=_id("sm2-support-warning"),b='<div style="margin:0.5em;margin-top:-0.25em"><h3>Oh snap!</h3><p>'+(soundManager.hasHTML5?"The flash portion of ":
+"")+"SoundManager 2 was unable to start. "+(soundManager.useHTML5Audio?soundManager.hasHTML5?"</p><p>Some HTML5 audio support is present, but flash is needed for MP3/MP4 support on this page.":"</p><p>No HTML5 support was found, so flash is required.":"")+'</p><p>All links to audio will degrade gracefully.</p><p id="flashblocker">If you have a flash blocker, try allowing the SWF to run - it may be visible below.</p><p id="flash-offline">'+(soundManager.useAltURL?"<b>Viewing offline</b>? You may need to change a Flash security setting.":
+"Other possible causes: Missing .SWF, or no Flash?")+' Not to worry, as guided help is provided.</p><p><a href="doc/getstarted/index.html#troubleshooting" class="feature-hot" style="display:inline-block;margin-left:0px">Troubleshooting</a></p></div>',d=navigator.userAgent.match(/(ipad|iphone|ipod)/i);if(soundManager.html5.mp3&&soundManager.html5.mp4)return soundManager._wD("Special homepage case: Flash appears to blocked, HTML5 support for MP3/MP4 exists; trying HTML5-only mode..."),soundManager.useHTML5Audio=
+!0,soundManager.preferFlash=!1,setTimeout(function(){soundManager.reboot();soundManager.onready(function(){a.innerHTML='<div style="margin:0.5em;margin-top:-0.25em"><h3>Support note</h3><p>SoundManager 2 tried to start using HTML5 + Flash, but rebooted in HTML5-only mode as flash was blocked. Visualization demo features will not be shown in this mode. To enable flash, whitelist the blocked movie and reload this page.</p>'+(soundManager.useAltURL?'<p><b>Running offline?</b> Flash may be blocked due to security restrictions; see <a href="doc/getstarted/index.html#troubleshooting">troubleshooting</a> for more.':
+"")+"</div>";a.style.marginBottom="1.5em";a.style.display="block"})},1),!1;a.innerHTML=b;c.innerHTML='<p style="margin:0px">SoundManager 2 could not start. <a href="#sm2-support">See below</a> for details.</p>';if(d||soundManager.getMoviePercent())_id("flashblocker").style.display="none",d&&(_id("flash-offline").style.display="none");a.style.marginBottom="1.5em";a.style.display="block";c.style.display="inline-block"})}
+function startStuff(){navigator.userAgent.match(/safari/i)&&(document.getElementsByTagName("html")[0].className="isSafari");doVersion();ie6Sucks();fixLinks();getLiveData();doAltShortcuts();soundManager.onready(function(){window.turntables&&(turntables.config.requireCSS="turntable-include")})}document.addEventListener?document.addEventListener("DOMContentLoaded",startStuff,!1):window.onload=startStuff;
--- /dev/null
+body {\r
+ background:#fff;\r
+ color: #333; /* scandalous. */\r
+ margin:0px;\r
+ padding:0px;\r
+ font:76% "helvetica neue",helvetica,arial,verdana,tahoma,"sans serif";\r
+ /* wacky IE 6 horizontal scrollbar hack */\r
+ _width:99.5%;\r
+ /* a little fun: transition font size with media shift. */\r
+ -moz-transition: font-size 0.1s;\r
+ -webkit-transition: font-size 0.1s;\r
+ /* font trickery */\r
+ -moz-osx-font-smoothing: grayscale;\r
+ -webkit-font-smoothing: antialiased;\r
+}\r
+\r
+@media all and (min-width: 1280px) {\r
+ /* holy CSS3 media queries, Batman! (in this case, larger screen widths get this rule.) */\r
+ body {\r
+ font-size: 85%;\r
+ }\r
+}\r
+\r
+@media all and (min-width: 1600px) {\r
+ /* holy CSS3 media queries, Batman! (in this case, larger screen widths get this rule.) */\r
+ body {\r
+ font-size: 90%;\r
+ }\r
+ /* nav vertical align tweak */\r
+ #nav > ul > li > strong > a {\r
+ padding-bottom: 0.5em !important;\r
+ }\r
+}\r
+\r
+@media all and (min-width: 1800px) {\r
+ /* holy CSS3 media queries, Batman! (in this case, larger screen widths get this rule.) */\r
+ body {\r
+ font-size: 105%;\r
+ }\r
+}\r
+\r
+body.home {\r
+ min-width: 80em;\r
+}\r
+\r
+body,\r
+#main-wrapper,\r
+#nav ul li strong a {\r
+ background: #fff url(../demo/_image/noise.png);\r
+}\r
+\r
+body,\r
+#main-wrapper,\r
+#nav ul li strong a {\r
+ background: #fff url(../demo/_image/tiny_grid.png);\r
+ background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaAgMAAADUJKRdAAAADFBMVEX8/Pz19fX09PT29vY9qbYoAAAAaElEQVR4Xk2MoREDMRADrzSDBQcEQj71GBw4kBbSQKp4YBBw9PsJyLxtsR2tZNfx/LyPhzX7R1Ue2SfjKlicDKBNdpBXsz790Nj8kUlo+WR47PvEPfY+gb7+kMhm5801EBsLvq/z3v8Apg8pkRmgbrsAAAAASUVORK5CYII=);\r
+ /* old IE */\r
+ *background: #fff url(../demo/_image/tiny_grid.png);\r
+}\r
+\r
+#nav ul li strong a {\r
+ background-position: 0px 5px;\r
+}\r
+\r
+/* below block commented out as it crashes YUI Compressor (as of 12/2011) - moved out to make-rollups script. */\r
+\r
+/*\r
+* "Chunk" font by Meredith Mandel - http://work.meredithmandel.com/#379252/Typeface-Chunk-Five\r
+* http://www.theleagueofmoveabletype.com/fonts/4-chunk\r
+* Provided under the SIL Open Font License (OFL)\r
+* http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL&_sc=1\r
+*/\r
+\r
+/*\r
+@font-face {\r
+ font-family: 'ChunkFiveRegular';\r
+ src: url('_image/chunk-webfont.woff') format('woff'),\r
+ url('_image/chunk-webfont.ttf') format('truetype'),\r
+ url('_image/chunk-webfont.svg#ChunkFiveRegular') format('svg');\r
+ font-weight: normal;\r
+ font-style: normal;\r
+}\r
+*/\r
+\r
+@font-face {\r
+ /**\r
+ * DejaVu font license\r
+ * http://dejavu-fonts.org/wiki/index.php?title=Main_Page\r
+ */\r
+ font-family: 'DejaVuSansMonoBook';\r
+ src: url('../demo/_image/dejavusansmono-webfont.eot');\r
+ src: url('../demo/_image/dejavusansmono-webfont.eot?#iefix') format('embedded-opentype'),\r
+ url('../demo/_image/dejavusansmono-webfont.woff') format('woff'),\r
+ url('../demo/_image/dejavusansmono-webfont.ttf') format('truetype');\r
+ font-weight: normal;\r
+ font-style: normal;\r
+}\r
+\r
+h2.special {\r
+ font-family:"ChunkFive","ChunkFiveRegular","helvetica neue",helvetica,arial,verdana,tahoma,"sans serif";\r
+ font-weight: normal;\r
+ display: inline;\r
+}\r
+\r
+h1, h2, h3, h4 {\r
+ font-size: 1em;\r
+ margin: 0px;\r
+ padding: 0px;\r
+ vertical-align: middle;\r
+ font-weight: 500;\r
+}\r
+\r
+h4.new,\r
+h4.recent,\r
+h4.flash9 {\r
+ min-height: 24px;\r
+}\r
+\r
+h1 {\r
+ font-size: 2em;\r
+ font-weight: 500;\r
+}\r
+\r
+h2 {\r
+ font-size: 1.5em;\r
+}\r
+\r
+h3 {\r
+ font-size: 1.17em;\r
+ font-weight: bold;\r
+ border-top: 0.25em solid #333;\r
+ border-bottom: 1px dotted #999;\r
+ padding-top: 0.25em;\r
+ padding-bottom: 0.25em;\r
+ _margin-top: 1.5em; /* fark IE6 */\r
+}\r
+\r
+body.home h3 {\r
+ border-top: 0.25em solid #444;\r
+ margin-top: 1.25em;\r
+}\r
+\r
+#doc .c2 h3 {\r
+ position: relative;\r
+ background: #333;\r
+ color: #fff;\r
+ padding: 0.25em 0.75em;\r
+ border: none;\r
+ line-height: 1.4em; /* windoze alignment */\r
+}\r
+\r
+h3,\r
+.likeh3,\r
+.home .columnar .c2 #about-sm2 h3:first-child { /* silly override */\r
+ margin-top:1.5em;\r
+}\r
+\r
+h4 {\r
+ margin:1.5em 0px 0.5em 0px;\r
+ font-size:1.15em;\r
+ font-weight: 500;\r
+}\r
+\r
+h5 {\r
+ font-size:1.2em;\r
+ font-weight: 500;\r
+ color:#333;\r
+}\r
+\r
+.c2 h5 {\r
+ border-bottom:1px solid #ccc;\r
+ padding-bottom:0.25em;\r
+}\r
+\r
+.sub-heading {\r
+ color: #666;\r
+ font-weight: 400;\r
+}\r
+\r
+h2.special a {\r
+ /* download SM2 link */\r
+ top: -0.65em;\r
+}\r
+\r
+#turntable-video {\r
+ width: 100%;\r
+ max-width: 1920px;\r
+ /* Safari 7.0.5 rendering bug makes <video> go full viewport height before loading? */\r
+ max-height: 500px;\r
+ overflow: hidden;\r
+}\r
+\r
+body.home #about-header {\r
+ /* speaker image, etc. */\r
+ position: relative;\r
+ /* margin-left: 18%; */\r
+ background-size: contain;\r
+ padding-left: 18%;\r
+ margin-right: 19em; /* room for right support column */\r
+ min-height: 175px;\r
+ padding-top: 1.75em;\r
+}\r
+\r
+body.home .sm2-speaker {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 20%;\r
+ height: 120%; /* hackish, but works. */\r
+ background: transparent url(../demo/_image/soundmanager2-speaker.png) no-repeat 50% 50%;\r
+ max-width: 256px;\r
+ max-height: 250px;\r
+ background-size: contain;\r
+}\r
+\r
+body.home #about-header .feature {\r
+ /* special alignment tweak */\r
+ position: relative;\r
+ vertical-align: middle;\r
+ font-size: 1.2em;\r
+}\r
+\r
+body.home #about-sm2 h2.special,\r
+body.home #about-sm2 h3,\r
+body.home #about-sm2 h4 {\r
+ font-weight:500;\r
+ font-size:2em;\r
+ border-bottom:none;\r
+ padding-bottom:0px;\r
+}\r
+\r
+body.home #about-sm2 h2.special {\r
+ font-size:3.5em;\r
+ color: #333;\r
+ margin-top:0.1em;\r
+}\r
+\r
+body.home #about-sm2 h3 {\r
+ font-size: 2.25em;\r
+}\r
+\r
+body.home #about-sm2 b {\r
+ font-weight: 500;\r
+}\r
+\r
+body.home #about-sm2 ul b {\r
+ /* restore regular bold */\r
+ font-weight: 600;\r
+}\r
+\r
+body.home #about-sm2 strong {\r
+ font-weight: 500;\r
+ color: #333;\r
+}\r
+\r
+#col3 a.button, /* "newer version available" */\r
+a.feature-hot,\r
+a.feature {\r
+ display: inline-block;\r
+ -moz-transition: all 0.25s ease-in-out;\r
+ -webkit-transition: all 0.25s ease-in-out;\r
+ transition: all 0.25s ease-in-out;\r
+ text-shadow: 0px 1px 0px rgba(0,0,0,0.33);\r
+}\r
+\r
+@-moz-keyframes highlight {\r
+ from {\r
+ box-shadow: 0px 0px 0px rgba(255,64,64,0);\r
+ }\r
+ to {\r
+ box-shadow: 0px 0px 16px rgba(255,64,64,0.75);\r
+ }\r
+}\r
+\r
+@-webkit-keyframes highlight {\r
+ from {\r
+ box-shadow: 0px 0px 0px rgba(255,64,64,0);\r
+ }\r
+ to {\r
+ box-shadow: 0px 0px 16px rgba(255,64,64,0.75);\r
+ }\r
+}\r
+\r
+#col3 a.feature {\r
+ /* "newer version available" hack */\r
+ margin-top: 0px;\r
+}\r
+\r
+a.feature-hot:hover,\r
+a.feature:hover,\r
+#col3 a.button:hover {\r
+ -moz-animation-duration: 0.5s;\r
+ -moz-animation-name: highlight;\r
+ -moz-animation-iteration-count: infinite;\r
+ -moz-animation-direction: alternate;\r
+ -webkit-animation-duration: 0.5s;\r
+ -webkit-animation-name: highlight;\r
+ -webkit-animation-iteration-count: infinite;\r
+ -webkit-animation-direction: alternate;\r
+}\r
+\r
+body.home #about-sm2 h3 {\r
+ color:#444;\r
+ font-weight: bold;\r
+ padding-bottom: 0px;\r
+ margin-bottom: 0px;\r
+ font-weight: 300;\r
+}\r
+\r
+body.home h4 {\r
+ border-bottom: 1px solid #e9e9e9;\r
+ padding-bottom: 0.33em;\r
+ margin-bottom: 0.75em;\r
+}\r
+\r
+body.home #about-sm2 h4 {\r
+ font-weight: 600;\r
+ color: #777;\r
+ font-size: 1.3em;\r
+ margin-bottom: 1.25em;\r
+ margin-top: 0.15em;\r
+}\r
+\r
+body.home #about-sm2 h4 b {\r
+ color: #777;\r
+}\r
+\r
+body.home #about-sm2 h3 + h4 {\r
+ /* sub-headers directly under headers */\r
+ color: #666;\r
+ font-size: 1.25em;\r
+ font-weight: 400;\r
+ margin-bottom: 2em;\r
+ border-bottom: 1px dotted #b0b0b0;\r
+ padding-bottom: 0.75em;\r
+}\r
+\r
+body.home .demo-more,\r
+body.home .demo-more-abs {\r
+ text-align:right;\r
+ font-size: 100%;\r
+ margin-right:0.25em;\r
+ white-space:nowrap;\r
+}\r
+\r
+body.home .demo-more-abs {\r
+ position:absolute;\r
+ right:0px;\r
+ bottom:0px;\r
+}\r
+\r
+body.home #about-sm2 h4.home-shopping-network {\r
+ font-style:italic;\r
+}\r
+\r
+em em {\r
+ /* special highlight */\r
+ color:#003366;\r
+ background:#e9f3ff;\r
+ font-weight:bold;\r
+ margin-top:-0.3em;\r
+ padding:0.2em 0.25em;\r
+}\r
+\r
+pre {\r
+ border-left:2px solid #f3f3f3;\r
+ padding-left:0.5em;\r
+}\r
+\r
+dl pre {\r
+ border-color:#e9f3ff;\r
+}\r
+\r
+dl.alt pre {\r
+ border-color:#f3f3f3;\r
+}\r
+\r
+pre,\r
+code,\r
+pre code,\r
+.code,\r
+.code-block,\r
+dt,\r
+#soundmanager-debug,\r
+.c3 ul li ul li {\r
+ font-family:Menlo,"DejaVu Sans Mono","DejaVuSansMonoBook",monaco,"Andale Mono","VT-100","Lucida Console","Courier New",monospace,courier,system,sans-serif;\r
+}\r
+\r
+pre,\r
+code,\r
+.code,\r
+dt,\r
+#soundmanager-debug {\r
+ font-weight:normal;\r
+ line-height:auto;\r
+ color:#006699;\r
+ background:#f6fcff;\r
+}\r
+\r
+.no-code-highlight pre,\r
+.no-code-highlight code,\r
+.no-code-highlight .code\r
+.no-code-highlight {\r
+ background: transparent;\r
+}\r
+\r
+pre,\r
+#soundmanager-debug {\r
+ font-size: 100%;\r
+}\r
+\r
+body.home p code {\r
+ font-size: 91%;\r
+}\r
+\r
+pre code {\r
+ /* don't scale further down, of course... */\r
+ font-size: 100%;\r
+}\r
+\r
+pre {\r
+ line-height:1.75em;\r
+}\r
+\r
+pre.specialcommentblock span span {\r
+ *line-height:1.75em;\r
+}\r
+\r
+.block.small {\r
+ font-size:92%;\r
+}\r
+\r
+p pre,\r
+p.in pre {\r
+ font-size:0.97em;\r
+}\r
+\r
+#soundmanager-debug {\r
+ background:#fff;\r
+ padding-left:0.75em;\r
+ border:2px solid #ddeeff;\r
+ font-size: 85%;\r
+ line-height:1.7em;\r
+}\r
+\r
+body.home #soundmanager-debug {\r
+ position:fixed;\r
+ _position:absolute; /* IE <7 */\r
+ bottom:1em;\r
+ right:1em;\r
+ height:12em;\r
+ width:auto;\r
+ overflow:auto;\r
+ padding:0px;\r
+ margin:1em 6px 6px 1em;\r
+ opacity:0.95;\r
+ color:#333;\r
+ border:1px solid #ccddee;\r
+ border-radius:3px;\r
+ background:#f3f9ff;\r
+ z-index:10;\r
+ font-size: 85%;\r
+ line-height:1.2em;\r
+}\r
+\r
+body.home #soundmanager-debug div {\r
+ padding-left:0.5em;\r
+}\r
+\r
+#soundmanager-debug div {\r
+ margin:0px;\r
+ padding:0.25em 0px;\r
+ font-size: 100%;\r
+ color:#333;\r
+}\r
+\r
+#soundmanager-debug div {\r
+ background-color:#fff;\r
+}\r
+\r
+#soundmanager-debug div.sm2-alt {\r
+ background-color: #f3f9ff;\r
+ color:#336699;\r
+}\r
+\r
+#live-debug {\r
+ display:table;\r
+ *display:block;\r
+}\r
+\r
+dd pre,\r
+dd code {\r
+ background:transparent;\r
+}\r
+\r
+pre code {\r
+ font-size:1em;\r
+}\r
+\r
+pre {\r
+ white-space:-moz-pre-wrap;\r
+ white-space:pre-wrap;\r
+ word-wrap:break-word; /* IE */\r
+}\r
+\r
+ul.code-block em,\r
+pre span,\r
+code span,\r
+dt span {\r
+ color:#339933;\r
+}\r
+\r
+ul.code-block em {\r
+ font-style: normal;\r
+}\r
+\r
+ul.code-block span,\r
+pre span span,\r
+code span span,\r
+dt span span {\r
+ color:#556677;\r
+}\r
+\r
+pre.block,\r
+pre.block code,\r
+div.block div.code,\r
+ul.code-block {\r
+ position:relative;\r
+ display:table;\r
+ *display:block;\r
+ border:1px solid #ccc;\r
+ border-radius:3px;\r
+}\r
+\r
+div.block,\r
+pre.block {\r
+ background:#e9f3ff;\r
+ border-color:#eee;\r
+ padding:3px;\r
+}\r
+\r
+pre.block code,\r
+.block .code {\r
+ background:#fff;\r
+ border:1px solid #ccddee;\r
+ padding:0.5em;\r
+ font-size: 100%;\r
+ line-height:1.75em;\r
+ background-image: -webkit-linear-gradient(#fcfcfc 50%, #fff 50%);\r
+ background-image: -o-linear-gradient(#fcfcfc 50%, #fff 50%);\r
+ background-image: linear-gradient(#fcfcfc 50%, #fff 50%);\r
+ background-size: 100% 3.5em;\r
+ background-origin: content-box;\r
+}\r
+\r
+#sm2-properties .code {\r
+ /* special case: no zebra striping for this one. */\r
+ background-image: none;\r
+}\r
+\r
+pre.block code {\r
+ padding: 1em;\r
+}\r
+\r
+h2 code {\r
+ /* common header stuffs */\r
+ background: none;\r
+ font-size: 93%;\r
+}\r
+\r
+dl {\r
+ background:#f9fcff;\r
+ padding-bottom: 1px;\r
+ border: 1px solid #ccddee;\r
+ border-radius: 3px;\r
+ margin-top: 1em;\r
+}\r
+\r
+dd {\r
+ margin:1em 0px;\r
+ padding:0px 1em;\r
+ line-height:1.75em;\r
+}\r
+\r
+dt {\r
+ padding:0px;\r
+ margin:0px;\r
+ border-bottom:1px solid #ddeeff;\r
+ padding:0.5em 0.5em 0.5em 0.75em;\r
+ background:#eef6ff;\r
+ font-size:1.15em;\r
+}\r
+\r
+dt.alt {\r
+ background:#f3f3f3;\r
+ border-bottom-color:#e6e6e6;\r
+}\r
+\r
+dl:nth-child(2n+1),\r
+dl.alt {\r
+ background:#fcfcfc;\r
+ padding:0px 0px 1px 0px;\r
+ border-color:#ddd;\r
+}\r
+\r
+dl.tight dt.alt {\r
+ background: #fcfcfc;\r
+}\r
+\r
+#smsound-methods dl a {\r
+ font-weight: normal;\r
+}\r
+\r
+#smsound-methods dt:last-of-type {\r
+ border-bottom: none;\r
+}\r
+\r
+h2 {\r
+ padding-top:0.5em;\r
+}\r
+\r
+#top {\r
+ position:relative;\r
+ padding:1em 1em 0px 1.5em;\r
+ max-width: 95.5em;\r
+ color:#fff;\r
+ z-index:3;\r
+ margin: 0px auto;\r
+}\r
+\r
+#content { /* #top #content */\r
+ background: #222 url(../demo/_image/noise-dark.png);\r
+}\r
+\r
+#top,\r
+#top div {\r
+ *zoom:1;\r
+}\r
+\r
+#top h1 {\r
+ /* special christmas light case */\r
+ display:inline;\r
+}\r
+\r
+#top h2 {\r
+ /* tagline */\r
+ font-size:1.25em;\r
+ font-weight:300;\r
+ padding-top:2px;\r
+}\r
+\r
+#top h1,\r
+#top h2,\r
+#version {\r
+ text-shadow: 0px 1px 0px rgba(0,0,0,0.5);\r
+}\r
+\r
+#main-wrapper {\r
+ position: relative;\r
+ /* fade out the body texture */\r
+ /*\r
+ border: 1px solid #fff;\r
+ */\r
+ box-shadow: inset 0px 0px 16px #fff;\r
+}\r
+\r
+#main {\r
+ position:relative;\r
+ padding:0px 0px 2em 0px;\r
+ padding-top:1px;\r
+ margin:0px auto;\r
+ *padding:0px 1em 2em 1em;\r
+ zoom:1;\r
+ /*\r
+ box-shadow: 0px 0px 32px rgba(0,0,0,0.05);\r
+ */\r
+}\r
+\r
+#main {\r
+ max-width: 98em;\r
+}\r
+\r
+body.home #main {\r
+ box-shadow: none;\r
+ max-width: 104em;\r
+}\r
+\r
+.columnar {\r
+ position:relative;\r
+ margin:0px;\r
+ padding:0px;\r
+ margin:1.9em 0.5em 0.5em 1em; /* slight left tweak */\r
+}\r
+\r
+.columnar .c1 {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:20em;\r
+ height:30px;\r
+ _position:relative; /* IE 6 hackery */\r
+ _height:auto;\r
+}\r
+\r
+#doc .columnar .c1 {\r
+ left:auto;\r
+ right:1em;\r
+ _right:auto;\r
+}\r
+\r
+.columnar .c1 h2 {\r
+ position:relative;\r
+ font-size:1.2em;\r
+ padding:0.37em 0.5em;\r
+ vertical-align:middle;\r
+ background:#333;\r
+ color:#fff;\r
+ text-indent: 0.25em;\r
+}\r
+\r
+.columnar .c1 p {\r
+ margin:0.5em 0px 1em 0px;\r
+ padding-left:0.5em;\r
+ padding-right:0.5em;\r
+ font-size:0.95em;\r
+ line-height:1.35em;\r
+ color:#666;\r
+}\r
+\r
+.columnar .c1 p code {\r
+ color:#336699;\r
+}\r
+\r
+.columnar .c2 {\r
+ position:relative;\r
+ margin-top:0px;\r
+ margin-left:22em;\r
+ margin-bottom:1.5em;\r
+}\r
+\r
+.triple .columnar .c2 {\r
+ margin-right:21.25em;\r
+ min-width:20em;\r
+}\r
+\r
+#doc .triple .columnar .c2 {\r
+ margin-left:21.5em;\r
+ margin-right:23em;\r
+ _margin-right:0px; /* not you, IE 6. */\r
+}\r
+\r
+#doc.special .triple .columnar .c2 {\r
+ /* override case: make c2 extra-wide. */\r
+ margin-right: 0.75em;\r
+ max-width: 70em;\r
+}\r
+\r
+#doc .triple .columnar .c1 {\r
+ margin-right:0px;\r
+ margin-left:21.25em;\r
+}\r
+\r
+.columnar .c2 p:first-child {\r
+ margin-top:0.2em;\r
+}\r
+\r
+.columnar .c2 > .f-block:first-child > h4 {\r
+ margin-top:0.5em;\r
+}\r
+\r
+.columnar .c2 strong strong {\r
+ display:block;\r
+ padding:0.5em;\r
+ border-bottom:1px solid #999;\r
+ background:#f0f6ff;\r
+ color:#336699;\r
+}\r
+\r
+.columnar .c2 p {\r
+ line-height:1.75em;\r
+ padding-top: 0.25em;\r
+ padding-bottom: 0.25em;\r
+}\r
+\r
+p code,\r
+.columnar .c2 p code {\r
+ font-size: 97%;\r
+}\r
+\r
+.three .columnar {\r
+ position:relative;\r
+}\r
+\r
+.three .columnar .c1 {\r
+ position:relative;\r
+ width:20em;\r
+}\r
+\r
+.three .columnar .c2 {\r
+ position:relative;\r
+ margin-right:16em;\r
+}\r
+\r
+.c3 {\r
+ position:absolute;\r
+ right:1em;\r
+ margin-right:16px;\r
+ top:2em;\r
+ width:16em;\r
+ margin-top:-0.5em;\r
+}\r
+\r
+#doc .c3 {\r
+ right:auto;\r
+ margin-right:0px;\r
+ margin-left:16px;\r
+ left:1.25em;\r
+ z-index: 1;\r
+}\r
+\r
+#nav {\r
+ position:relative;\r
+ margin-top:0.75em;\r
+ margin-left:-0.5em;\r
+}\r
+\r
+ul {\r
+ /* lists inside main content area */\r
+ line-height: 1.75em;\r
+}\r
+\r
+ul li {\r
+ margin-bottom: 0.75em;\r
+}\r
+\r
+#nav ul {\r
+ margin:0px;\r
+ padding:0px;\r
+ line-height:1em;\r
+ list-style-type:none;\r
+}\r
+\r
+#nav ul li {\r
+ position:relative;\r
+ margin:0px;\r
+ padding:0px;\r
+ float:left;\r
+ display:inline;\r
+ padding-right:1px;\r
+}\r
+\r
+#nav ul li ul {\r
+ position:absolute;\r
+ z-index:1;\r
+ display:none;\r
+ min-width:19em;\r
+ max-width:21em;\r
+ background:#3399cc;\r
+ background: -moz-linear-gradient(top, rgba(51,153,204,0.99) 0%, rgba(35,96,127,0.96) 100%); /* FF3.6+ */\r
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(51,153,204,0.99)), color-stop(100%,rgba(35,96,127,0.96))); /* Chrome,Safari4+ */\r
+ background: -webkit-linear-gradient(top, rgba(51,153,204,0.99) 0%,rgba(35,96,127,0.96) 100%); /* Chrome10+,Safari5.1+ */\r
+ background: -o-linear-gradient(top, rgba(51,153,204,0.99) 0%,rgba(35,96,127,0.96) 100%); /* Opera 11.10+ */\r
+ background: -ms-linear-gradient(top, rgba(51,153,204,0.99) 0%,rgba(35,96,127,0.96) 100%); /* IE10+ */\r
+ background: linear-gradient(top, rgba(51,153,204,0.99) 0%,rgba(35,96,127,0.96) 100%); /* W3C */\r
+ text-shadow: 0px 1px 0px rgba(0,0,0,0.25);\r
+ _width:19em;\r
+ *top:2.3em;\r
+ *left:0px;\r
+}\r
+\r
+#nav ul li:last-child ul {\r
+ right:1px;\r
+}\r
+\r
+#nav ul li:hover ul,\r
+#nav ul li ul:hover {\r
+ display:block;\r
+}\r
+\r
+#nav ul li ul li {\r
+ float: none;\r
+ display: block;\r
+ width: 100%;\r
+}\r
+\r
+#nav ul li ul li a {\r
+ display: block;\r
+ width: auto;\r
+ border: none;\r
+ padding: 0.5em 0px 0.5em 1em;\r
+ font-size: 1.1em;\r
+ line-height: 1.1em;\r
+ color: #fff;\r
+ font-weight: 400;\r
+ color:rgba(255,255,255,0.9);\r
+ border-bottom: 1px dotted rgba(0,0,0,0.2);\r
+ border-top: 1px dotted rgba(255,255,255,0.2);\r
+}\r
+\r
+#nav ul li ul li:first-of-type a {\r
+ border-top: none;\r
+}\r
+\r
+#nav ul li a {\r
+ display: inline-block;\r
+ padding: 0.5em 1em;\r
+ text-decoration: none;\r
+ font-weight: bold;\r
+ color: #fff;\r
+}\r
+\r
+#nav ul li ul li a:hover {\r
+ background-color: #336699;\r
+ background-color: rgba(0,0,0,0.45);\r
+}\r
+\r
+#nav>ul>li>a,\r
+#nav>ul>li>strong>a {\r
+ /* top-level links */\r
+ color:#ddd;\r
+ font-size: 1.25em;\r
+ font-weight: 400;\r
+ vertical-align: bottom;\r
+}\r
+\r
+#nav ul li strong a {\r
+ color:#333;\r
+}\r
+\r
+#nav > ul > li > strong > a {\r
+ /* tweak for good browsers that respect larger font size */\r
+ padding-bottom: 9px;\r
+}\r
+\r
+#nav ul li a:hover,\r
+#nav>ul>li:hover>a {\r
+ /* top-level */\r
+ background: #3399cc;\r
+ color:#fff;\r
+ text-shadow: 0px 1px 0px rgba(0,0,0,0.25);\r
+}\r
+\r
+#version {\r
+ position:relative;\r
+ float:right;\r
+ display:inline;\r
+ margin-left:1em;\r
+ font-size:90%;\r
+ margin-bottom:0px;\r
+ bottom: -0.9em;\r
+ color:#ccc;\r
+}\r
+\r
+div.clear {\r
+ clear:both;\r
+ font-size:1px;\r
+ line-height:1px;\r
+}\r
+\r
+.note {\r
+ margin-top:0.5em;\r
+ font-size:0.95em;\r
+ color:#999;\r
+}\r
+\r
+.note a {\r
+ color:#666;\r
+ padding:1px;\r
+ margin:-1px;\r
+}\r
+\r
+.note a:hover {\r
+ color:#fff;\r
+ background:#666;\r
+}\r
+\r
+.medium-note {\r
+ padding-top:1.5em;\r
+ font-size:1em;\r
+}\r
+\r
+ul.standard {\r
+ line-height:1.5em;\r
+ padding-left:1.2em;\r
+ *padding-left:0px;\r
+ color:#333;\r
+ margin-top:1em;\r
+ margin-bottom:1em;\r
+ list-style-type:square;\r
+}\r
+\r
+ul.standard li {\r
+ margin-bottom:0.5em;\r
+}\r
+\r
+ul.standard ul {\r
+ margin-top:0.5em;\r
+ margin-bottom:1.5em;\r
+ padding-left:1.2em;\r
+}\r
+\r
+.c3 ul {\r
+ list-style-type:none;\r
+}\r
+\r
+.c3 ul,\r
+.c3 ul li {\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+.c3 h2 {\r
+ font-size:1.1em;\r
+ text-indent:0.4em;\r
+}\r
+\r
+.c3 ul li a {\r
+ display: block;\r
+ text-decoration:none;\r
+}\r
+\r
+.c3 ul li,\r
+.c3 ul li a,\r
+.c3 ul li a:hover,\r
+.c3 ul li a:focus {\r
+ color:#333;\r
+ _color:#333;\r
+ outline:none;\r
+}\r
+\r
+.c3 ul li.active {\r
+ box-shadow: 0 0 6px #003366 inset;\r
+ border-radius: 1px;\r
+}\r
+\r
+.c3 ul li.active a {\r
+ border-radius: 2px;\r
+ text-shadow: 0px 1px 0px rgba(0,0,0,0.25);\r
+}\r
+\r
+.c3 ul li.active,\r
+.c3 ul li.active a,\r
+.c3 ul li ul li:hover,\r
+.c3 ul li ul li:hover a {\r
+ color: #fff;\r
+}\r
+\r
+.c3 ul li.active a:hover {\r
+ _color:#fff;\r
+}\r
+\r
+.c3 .box {\r
+ margin-top:6px;\r
+}\r
+\r
+.wedge,\r
+.c3 h2 {\r
+ position:relative;\r
+ background:#333;\r
+ color:#fff;\r
+ margin:0px;\r
+ padding:0px;\r
+ height:2.101em;\r
+ line-height:1.65em;\r
+}\r
+\r
+.c3 h2 {\r
+ height:2em;\r
+ line-height:2em;\r
+}\r
+\r
+.c3 h2,\r
+#doc .c2 h3 {\r
+ text-shadow: 0px 1px 0px #000;\r
+}\r
+\r
+.wedge {\r
+ background-color:#3399cc;\r
+}\r
+\r
+.wedge-dark {\r
+ background:#333;\r
+}\r
+\r
+.wedge .l,\r
+.wedge .r {\r
+ border-top:1.75em solid #333;\r
+}\r
+\r
+.c3 h2 .l,\r
+.c3 h2 .r {\r
+ border-top: 2em solid #333;\r
+ border-top: 2.1em solid #333\9; /* IE 8 */\r
+}\r
+\r
+.wedge .l,\r
+.c3 h2 .l,\r
+.wedge .r,\r
+.wedge-dark .r,\r
+.c3 h2 .r {\r
+ background:transparent url(../demo/_image/wedge.png) no-repeat;\r
+ background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAAEABAMAAACJ12OUAAAAGFBMVEUREREAZpkYGBgAZpkiIiIAZpkREREAZpkArR2CAAAABnRSTlMAAOvrEhJBIv9yAAAC0UlEQVR42u3ZuW0cQRCF4cIPhrG2MhDkLZgDM5ChBGQoKBlMgdgElAQ9gVACNMTZ2WOO7rraI2rcna33cdjTTTzyQ7++fzFuQPTrdDBuMAa8H04vQwNOL++HkQHTtw0CBmAekh0wf1cnYAEsAibAIGACDAI2QCdgA3QCDoBKwAFQCXgAGgEPQCPgAigEXACFgA/QJ+AD9Ak4AV0CTkCXgBfQI+C/tT0W952dubgBncH4Ae3J+AHt0QQAzdkEAM3hRACt6UQArfGEAI35hACNAGKAfQIxwD6CIGCXQRCwCyEK2KYQBWxjCAM2OYQBmyDigHUSccA6igRglUUCsAojA1imkQEs40gBFnmkAItAcoB7IjnAPZIk4JZJEnALJQu4ppIFXGNJAy65pAGXYPKAOZk8YI5mAHDOZgBwJjACmAiMACYCT7/U6+c3/fOv1R9Uf1D9QfUH1R9Uf1D9QfUH1R9Uf1D9QfUH1R9Uf1D9wefvD/4NXhwfRwQPrzy8jgw4PiIjhI90ZITwEY4MEKZsZIAwRSN5wjkZyRPOwUiaMOciacIci2QJl1QkS7iEIknCNRNJEq6RSI5wS0RyhFsgkiLc85AU4R6HZAiLNCRDWIQhCcIyC0kQllFInLBKQuKEVRASJqxzkDBhHYNECZsUJErYhCBBwjYDCRK2EUiMsEtAYoRdABIi7OcjIcJ+PBIhNKYjEUJjOBIgtGYjAUJrNOInNCcjfkJzMO47O3Px39oeixvb+cFwP67Oo8X7vHpPFu9vrPe7xblmuqsL56rtrm98y7a/vPG9OP0XDNerq7ziuDYPZZPBs3toewye/Uvb5XDsoOo+i2MPV3d67E1c3+ixjxH9qME8yIzDDvMoNY5brLPUOm2xTnPrvLf++3+0/uLgz2/1ev6rf/5W/UH1B9UfVH9Q/UH1B9UfVH9Q/UH1B9UfVH9Q/UH1B9UffPr+4D+tsZObsTO2qgAAAABJRU5ErkJggg==);\r
+ *background-image:url(../demo/_image/wedge.png);\r
+}\r
+\r
+.wedge .l,\r
+.c3 h2 .l {\r
+ background-position: -64px 0px;\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:16px;\r
+ height:100%;\r
+ margin-left:-16px;\r
+}\r
+\r
+.wedge .r,\r
+.wedge-dark .r,\r
+.c3 h2 .r {\r
+ background-position: -48px 0px;\r
+ position:absolute;\r
+ right:0px;\r
+ top:0px;\r
+ width:16px;\r
+ height:100%;\r
+ margin-right:-16px;\r
+}\r
+\r
+.wedge .l,\r
+.wedge .r {\r
+ border-color:#3399cc;\r
+}\r
+\r
+.wedge .l {\r
+ background-position:-64px -64px;\r
+ border-top: 2em solid #3399cc\r
+}\r
+\r
+.wedge .r {\r
+ margin-top:-15px;\r
+ border-top:none;\r
+ height:16px;\r
+ border-bottom:2em solid #3399cc;\r
+ background-position:0px -192px;\r
+}\r
+\r
+.wedge-dark .l,\r
+.wedge-dark .r {\r
+ border-color:#333;\r
+}\r
+\r
+.wedge-dark .l {\r
+ background-position:-64px 0px;\r
+}\r
+\r
+.wedge-dark .r {\r
+ background-position:0px -128px;\r
+}\r
+\r
+.c3 h2 .r.up {\r
+ margin-top:-16px;\r
+ border-top:none;\r
+ height:16px;\r
+ border-bottom:1.66em solid #333;\r
+ background-position:0px -128px;\r
+}\r
+\r
+.c3 h2 .l.flat,\r
+.wedge .l.flat,\r
+.c3 h2 .r.flat,\r
+.wedge .r.flat {\r
+ background-image:none;\r
+}\r
+\r
+.c3 ul {\r
+ margin:0px;\r
+ padding:0px;\r
+ list-style-type:none;\r
+}\r
+\r
+.c3 ul li {\r
+ border:1px solid #f3f3f3;\r
+ border-top:none;\r
+ border-bottom:none;\r
+}\r
+\r
+.c3 ul ul li {\r
+ border:none;\r
+}\r
+\r
+.c3 ul li {\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+.c3 ul li ul li {\r
+ background-color: #fcfcfc;\r
+ background-color: rgba(255,255,255,0.5);\r
+ font-size: 97%;\r
+ line-height:2.4em;\r
+ text-indent:0.5em;\r
+ padding: 0px 0.25em;\r
+ cursor:hand;\r
+ border-bottom: 1px dotted #eee;\r
+}\r
+\r
+.c3 ul li ul li:hover {\r
+ background-color:#999;\r
+ cursor:pointer;\r
+ cursor:hand;\r
+}\r
+\r
+.c3 ul li ul li.active {\r
+ background-color:#3399cc;\r
+ color:#fff;\r
+}\r
+\r
+.c3 h3 {\r
+ position: relative;\r
+ margin: 0px;\r
+ padding: 0px;\r
+ height: auto;\r
+ min-height: 25px;\r
+ background: #3399cc;\r
+ border: none;\r
+ color: #fff;\r
+ text-indent: 0.5em;\r
+ font-size: 1em;\r
+ line-height: 2em;\r
+ text-shadow: 0px 1px 0px rgba(0,0,0,0.25);\r
+}\r
+\r
+.c3 h4 {\r
+ font-size:1em;\r
+ margin:0px;\r
+ padding:0.4em 0.2em 0.4em 0.75em;\r
+ vertical-align:middle;\r
+ color:#333;\r
+ background-color: #f3f3f3;\r
+ background-color: rgba(0,0,0,0.05);\r
+ border-top: 1px dotted #d6d6d6;\r
+ border-bottom: 1px dashed #e9e9e9;\r
+ text-shadow: 0px 1px 0px #fff;\r
+}\r
+\r
+.c3 h4:first-of-type {\r
+ border-top-color: transparent;\r
+}\r
+\r
+#get-satisfaction h2 a {\r
+ color:#fff;\r
+}\r
+\r
+#get-satisfaction a {\r
+ color:#444;\r
+}\r
+\r
+#get-satisfaction a:hover {\r
+ color:#fff;\r
+}\r
+\r
+.c3 h2 a {\r
+ color:#fff;\r
+}\r
+\r
+.c3 h2 a:hover {\r
+ color:#fff;\r
+ text-decoration:underline;\r
+}\r
+\r
+.flash9 {\r
+ background-image:url(../demo/_image/flash9.png);\r
+ background-repeat:no-repeat;\r
+ background-position:bottom right;\r
+ _background-image:none;\r
+}\r
+\r
+li.flash9 {\r
+ background-position:bottom right;\r
+}\r
+\r
+.flash9:hover,\r
+.flash9.active {\r
+ background-image:url(../demo/_image/flash9-dark.png);\r
+ _background-image:none;\r
+}\r
+\r
+.new {\r
+ background-image:url(../demo/_image/new.png);\r
+ background-repeat:no-repeat;\r
+ background-position:bottom right;\r
+ _background-image:none;\r
+}\r
+\r
+.recent {\r
+ background-image:url(../demo/_image/new-bw.png);\r
+ background-repeat:no-repeat;\r
+ background-position:bottom right;\r
+ _background-image:none;\r
+}\r
+\r
+.new:hover,\r
+.new.active,\r
+.recent:hover,\r
+.recent.active {\r
+ background-image:url(../demo/_image/new-dark.png);\r
+ background-repeat:no-repeat;\r
+ background-position:bottom right;\r
+ _background-image:none;\r
+}\r
+\r
+.deprecated {\r
+ font-style: italic;\r
+ color: #333 !important;\r
+}\r
+\r
+span.nevermind,\r
+.removed {\r
+ text-decoration:line-through;\r
+ opacity:0.33;\r
+}\r
+\r
+strong.removed {\r
+ font-weight: normal;\r
+ opacity:0.5;\r
+}\r
+\r
+.padded {\r
+ padding:0.5em;\r
+}\r
+\r
+dd.deprecation-note {\r
+ color: #993333;\r
+ background-color: #fff6f6;\r
+}\r
+\r
+.c3 p {\r
+ font-size:0.9em;\r
+ padding-left:0.75em;\r
+ padding-right:0.5em;\r
+}\r
+\r
+.c1 pre code {\r
+ margin-top:0px;\r
+ color:#336699;\r
+ margin-left:0px;\r
+}\r
+\r
+.c1 pre {\r
+ margin-top:0px;\r
+ padding-top:0px;\r
+ margin-left:0.5em;\r
+}\r
+\r
+#reset-filter {\r
+ position:relative;\r
+ font-family:"Helvetica Neue","Helvetica",helvetica,arial,verdana,sans-serif;\r
+ font-weight:300;\r
+ font-size:2.5em;\r
+}\r
+\r
+.c2 .option {\r
+ font-size:85%;\r
+ float:right;\r
+ display:inline;\r
+ margin-left:1em;\r
+ margin-right:0.5em;\r
+ margin-top:3px;\r
+ line-height:1em;\r
+ white-space:nowrap;\r
+}\r
+\r
+.c2 .option a {\r
+ padding:0.1em 0.35em 0.1em 0.35em;\r
+ color:#3399cc;\r
+}\r
+\r
+#filter-box {\r
+ position:relative;\r
+ display:none;\r
+}\r
+\r
+#get-satisfaction {\r
+ position:relative;\r
+}\r
+\r
+#support-wrapper {\r
+ position: relative;\r
+ background: #fff;\r
+ border: 1px solid rgba(0,0,0,0.03);\r
+ box-shadow: 0px 0px 1px rgba(0,0,0,0.075);\r
+}\r
+\r
+body.home #support-wrapper {\r
+ position: absolute;\r
+ width: 100%;\r
+}\r
+\r
+#gsfn_content {\r
+ position: relative;\r
+ padding:0.5em 0px 0.5em 0px;\r
+}\r
+\r
+#gsfn_content ul {\r
+ position: relative;\r
+ /* initially, hide and then expand. */\r
+ overflow: hidden;\r
+ height: 0px;\r
+ margin: 0px;\r
+ /* smooth height transitions, why not */\r
+ -webkit-transition: height 0.5s ease-in-out;\r
+ -moz-transition: height 0.5s ease-in-out;\r
+ transition: height 0.5s ease-in-out;\r
+}\r
+\r
+#gsfn_list_widget.loaded ul {\r
+ /* JS callback assigns this class when load is complete */\r
+}\r
+\r
+#gsfn_content ul li {\r
+ border:none;\r
+}\r
+\r
+div#gsfn_list_widget img {\r
+ border: none;\r
+}\r
+\r
+div#gsfn_list_widget a {\r
+ text-decoration:none;\r
+}\r
+\r
+div#gsfn_list_widget a.widget_title {\r
+ display: block;\r
+ margin-bottom: 10px;\r
+ font-weight: bold;\r
+}\r
+\r
+div#gsfn_list_widget .powered_by {\r
+ font-family:verdana,arial;\r
+ margin:-0.25em 1em 0px 1em;\r
+ padding:0.25em 0px 0.5em 0px;\r
+ border-top: 1px dotted #ddd;\r
+ font-size:75%;\r
+}\r
+\r
+body.home div#gsfn_list_widget .powered_by {\r
+ padding-bottom: 0px;\r
+}\r
+\r
+div#gsfn_list_widget .powered_by a {\r
+ font-style: italic;\r
+ color: #999;\r
+}\r
+\r
+div#gsfn_list_widget .powered_by a:hover {\r
+ color:#333;\r
+}\r
+\r
+div#gsfn_list_widget div#gsfn_content {\r
+ font-size:0.88em;\r
+ padding-left:0.5em;\r
+ padding-right:0.5em;\r
+}\r
+\r
+div#gsfn_list_widget div#gsfn_content li {\r
+ text-align:left;\r
+ position: relative;\r
+ clear:right;\r
+ *zoom:1;\r
+}\r
+\r
+div#gsfn_list_widget div#gsfn_content li:hover,\r
+div#gsfn_list_widget div#gsfn_content li:hover a {\r
+ background:#3399cc;\r
+ color:#fff;\r
+}\r
+\r
+div#gsfn_list_widget div#gsfn_content a.gsfn_link {\r
+ display:block;\r
+ line-height:1.2em;\r
+ padding:5px 0px 5px 5px;\r
+}\r
+\r
+div#gsfn_list_widget div#gsfn_content a.gsfn_link:hover {\r
+ _color:#fff;\r
+ _background-color:#3399cc;\r
+}\r
+\r
+div#gsfn_list_widget div#gsfn_content span.time {\r
+ font-size: 85%;\r
+ color:#999;\r
+ padding-left:3px;\r
+ padding-right:3px;\r
+ text-align:right;\r
+ float:right;\r
+ display:inline;\r
+ margin-top:1px;\r
+}\r
+\r
+div#gsfn_list_widget div#gsfn_content li:hover span.time {\r
+ color:#fff;\r
+}\r
+\r
+div#gsfn_list_widget div#gsfn_content p.gsfn_summary {\r
+ margin-top: 2px;\r
+ position:relative;\r
+ z-index:2;\r
+}\r
+\r
+.tight {\r
+ margin-top:0px;\r
+}\r
+\r
+.compact {\r
+ margin-bottom:0.25em !important;\r
+}\r
+\r
+.smaller {\r
+ margin-top: 0px !important;\r
+ margin-bottom: 0.25em !important;\r
+ line-height: 1.2em !important;\r
+}\r
+\r
+.c2 a,\r
+a.cta {\r
+ margin-top:-0.3em;\r
+ padding:0.2em 0.25em;\r
+ margin-left: -0.25em;\r
+ margin-right: -0.25em;\r
+ *margin: 0px;\r
+ *padding: 0px 2px;\r
+ *margin: 0px -2px 0px -2px;\r
+ text-decoration:none;\r
+ color:#3399cc;\r
+ font-weight: 500;\r
+ border-radius:0.25em;\r
+ zoom:1;\r
+}\r
+\r
+body.home .c2 a,\r
+body.home a.cta {\r
+/*\r
+ text-shadow: 0px 1px 0px #fff;\r
+*/\r
+}\r
+\r
+\r
+body.home .c2 a:hover,\r
+body.home a.cta:hover {\r
+ text-shadow: none;\r
+}\r
+\r
+pre code a,\r
+.c2 pre code a {\r
+ color: #3399cc;\r
+ font-weight: 400;\r
+ text-decoration: none;\r
+ text-shadow: none;\r
+}\r
+\r
+pre code a:hover,\r
+.c2 pre code a:hover {\r
+ background-color: #3399cc;\r
+ color: #fff;\r
+ font-weight: 400;\r
+}\r
+\r
+/* redefine for simple mp3 button demo */\r
+.c2 a.sm2_button {\r
+ border-radius:6px;\r
+}\r
+\r
+.c2 a.sm2_button.type-2 {\r
+ border-radius:9px;\r
+}\r
+\r
+.c2 a {\r
+ color:#3399cc;\r
+ font-weight:500;\r
+ text-decoration:none;\r
+}\r
+\r
+.c2 a.cta {\r
+ text-decoration:none;\r
+}\r
+\r
+a.cta span {\r
+ font-size:1.5em;\r
+ line-height:1em;\r
+}\r
+\r
+a.cta:hover,\r
+.c2 a:hover,\r
+#sm2-options a:hover {\r
+ position: relative;\r
+ z-index: 1;\r
+ background-color:#3399cc;\r
+ border-color:#3399cc;\r
+ color:#fff;\r
+ text-decoration:none;\r
+}\r
+\r
+.c2 a.sm2_button:hover {\r
+ /* arg. not specific enough, redefine here. */\r
+ background-color:#cc3333;\r
+}\r
+\r
+dt a:hover span {\r
+ color: #fff;\r
+}\r
+\r
+a.cta-more {\r
+ color:#ddeeff;\r
+ font-size:0.8em;\r
+ position:absolute;\r
+ right:0px;\r
+ margin:0px;\r
+ padding:1px;\r
+ bottom:0.9em;\r
+ line-height:1em;\r
+}\r
+\r
+a.cta-more:hover {\r
+ background:#fff;\r
+ color:#3399cc;\r
+}\r
+\r
+div.html5support {\r
+ clear: both;\r
+ padding-top: 2em;\r
+}\r
+\r
+div.html5support span {\r
+ padding:0px 5px;\r
+ display:inline-block;\r
+ text-align:center;\r
+ font-weight:400;\r
+ background:#ccc;\r
+ color:#fff;\r
+ margin-bottom:0.25em;\r
+ border-right: 1px dotted #fff;\r
+ border-radius: 0px;\r
+ margin-right: none;\r
+}\r
+\r
+div.html5support em {\r
+ font-weight:bold;\r
+}\r
+\r
+div.html5support span.true {\r
+ background:#669966;\r
+}\r
+\r
+div.html5support span.partial {\r
+ background:#993333;\r
+}\r
+\r
+div.html5support em.partial {\r
+ color:#993333;\r
+}\r
+\r
+div.html5support em.true {\r
+ color:#669966;\r
+}\r
+\r
+#nav ul li ul {\r
+ /* eh, why not. */\r
+ box-shadow:2px 2px 2px rgba(51,153,204,0.2);\r
+}\r
+\r
+.newer {\r
+ vertical-align: middle;\r
+ margin-top: 1em;\r
+ margin-bottom: 1em;\r
+}\r
+\r
+.newer a,\r
+a.feature,\r
+.feature-hot {\r
+ position:relative;\r
+ display:inline-block;\r
+ background:#3399ff;\r
+ font-size: 1.1em;\r
+ line-height: 1.75em;\r
+ padding: 0px 0.5em;\r
+ margin: 0px 0.125em;\r
+ color:#fff;\r
+ font-weight:bold;\r
+ border:3px solid #cce6ff;\r
+ border:3px solid rgba(255,255,255,0.66);\r
+ border-radius:8px;\r
+ text-decoration:none;\r
+}\r
+\r
+a.feature {\r
+ margin-left:0px;\r
+}\r
+\r
+.newer a,\r
+.feature-hot {\r
+ background:#ff0000;\r
+ border-color:#ff6666;\r
+ color:#fff;\r
+}\r
+\r
+.newer a:hover,\r
+.c2 .feature-hot:hover {\r
+ background:#990000;\r
+ border-color:#cc0000;\r
+}\r
+\r
+a.feature:focus,\r
+a.feature:hover {\r
+ background:#ff0000;\r
+ border-color:#ff6666;\r
+ color:#fff;\r
+}\r
+#\r
+a.warning,\r
+span.warning {\r
+ font-weight:bold;\r
+}\r
+\r
+a.warning,\r
+span.warning,\r
+a.warning code,\r
+span.warning code {\r
+ color:#993300;\r
+}\r
+\r
+a.warning:hover {\r
+ color:#fff;\r
+ background:#993300;\r
+}\r
+\r
+.newer p {\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+.scratched-out {\r
+ display: inline-block;\r
+ text-decoration:line-through;\r
+ color:#999;\r
+ font-size:0.9em;\r
+ margin-top:-0.75em;\r
+ -webkit-transform:rotate(-15deg);\r
+ -moz-transform:rotate(-15deg);\r
+ transform:rotate(-15deg);\r
+}\r
+\r
+div.inthewild {\r
+ position: relative;\r
+ margin-top:1em;\r
+}\r
+\r
+ul.inthewild {\r
+ display: inline;\r
+ margin: 0px auto;\r
+ list-style-type: none;\r
+}\r
+\r
+ul.inthewild,\r
+ul.inthewild li {\r
+ position: relative;\r
+ margin: 0px;\r
+ padding: 0px;\r
+}\r
+\r
+ul.inthewild {\r
+ margin-bottom: 2em;\r
+}\r
+\r
+ul.inthewild li {\r
+ display: inline-block;\r
+ *float: left;\r
+ *display: inline;\r
+ width: 128px;\r
+ width: 24%;\r
+ min-width: 64px;\r
+ height: 64px;\r
+ vertical-align: middle;\r
+ text-align: center;\r
+ margin: 2px 0px;\r
+ background-color: #fcfcfc;\r
+ background-color: rgba(255,255,255,0.5);\r
+ border-radius: 2px;\r
+ border: 1px solid #eee;\r
+ border-color: rgba(0,0,0,0.05)\r
+}\r
+\r
+ul.inthewild a,\r
+ul.inthewild a img {\r
+ border:none;\r
+ vertical-align:middle;\r
+}\r
+\r
+ul.inthewild a {\r
+ position: absolute;\r
+ left: 50%;\r
+ top: 50%;\r
+ overflow:hidden;\r
+ margin: 0px;\r
+ padding: 0px;\r
+ border-radius: 0px;\r
+ background: transparent url(../demo/_image/logo-sprite.png) no-repeat 0px 0px;\r
+ line-height: 96px;\r
+ vertical-align: middle;\r
+}\r
+\r
+ul.inthewild a:hover {\r
+ background-color: transparent;\r
+}\r
+\r
+ul.inthewild a span {\r
+ position:absolute;\r
+ text-indent:-9999em;\r
+}\r
+\r
+#tidal {\r
+ background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMCIgeT0iMCIgdmlld0JveD0iMCAwIDMzMC4yIDQzLjciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDMzMC4yIDQzLjciIHhtbDpzcGFjZT0icHJlc2VydmUiPjxwYXRoIGZpbGw9IiMwMDAwMDAiIGQ9Ik0xMjAuMSA0Mi44aC04LjVWMTIuN2gtMTFWNS41aDMwLjR2Ny4zaC0xMUwxMjAuMSA0Mi44ek0xNjUgNDIuOGgtOC41VjUuNWg4LjVWNDIuOHpNMzE1LjQgMzUuNGgxNC43djcuNGgtMjMuM1Y1LjVoOC41VjM1LjR6Ii8+PHBhdGggZmlsbD0iIzAwMDAwMCIgZD0iTTE5My40IDUuNWgxMy44YzEwLjIgMCAyMC4zIDUuNCAyMC4zIDE4LjYgMCAxMi40LTkuOSAxOC44LTE5LjggMTguOGwtMTQuMyAwTDE5My40IDUuNXpNMjAxLjYgMzUuNWg1LjNjNy4xIDAgMTEuOS00LjQgMTEuOS0xMS41IDAtNi43LTQuOC0xMS4yLTExLjctMTEuMmgtNS41VjM1LjV6TTI3NC44IDQyLjhoOS40TDI2OC44IDUuNUgyNjBsLTE1LjUgMzcuM2g5LjFsMi44LTcuNGgxNS43TDI3NC44IDQyLjh6TTI1OC42IDI4LjhsNS42LTE0LjYgNS42IDE0LjZIMjU4LjZ6Ii8+PHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgcG9pbnRzPSI0My43IDEwLjkgMzIuOCAyMS44IDIxLjkgMTAuOSAzMi44IDAgIi8+PHJlY3QgeD0iMjUiIHk9IjI1LjEiIHRyYW5zZm9ybT0ibWF0cml4KC0wLjcwNzEgMC43MDcxIC0wLjcwNzEgLTAuNzA3MSA3OS4xMjA0IDMyLjc4MTMpIiBmaWxsPSIjMDAwMDAwIiB3aWR0aD0iMTUuNCIgaGVpZ2h0PSIxNS41Ii8+PHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgcG9pbnRzPSIyMS45IDEwLjkgMTAuOSAyMS44IDAgMTAuOSAxMC45IDAgIi8+PHBvbHlnb24gZmlsbD0iIzAwMDAwMCIgcG9pbnRzPSI2NS41IDEwLjkgNTQuNiAyMS44IDQzLjcgMTAuOSA1NC42IDAgIi8+PC9zdmc+) 50% 50% no-repeat;\r
+ color: #000;\r
+ width: 85%;\r
+ height: 85%;\r
+ left: 0px;\r
+ color: rgb(255, 255, 255);\r
+ top: 0%;\r
+ margin: 3.5% 0px 5% 7%;\r
+}\r
+\r
+#eight-tracks {\r
+ background-position: 0 0;\r
+ width: 64px;\r
+ height: 20px;\r
+ margin: -10px 0px 0px -32px;\r
+}\r
+\r
+#audiogalaxy {\r
+ width: 100px;\r
+ height: 22px;\r
+ background-position: 0 -37px;\r
+ margin: -11px 0px 0px -50px;\r
+}\r
+\r
+#discogs {\r
+ background-position: 0 -72px;\r
+ width: 55px;\r
+ height: 20px;\r
+ margin: -10px 0px 0px -27px;\r
+}\r
+\r
+#hypem {\r
+ background-position: 0 -111px;\r
+ width: 80px;\r
+ height: 38px;\r
+ margin: -19px 0px 0px -40px;\r
+}\r
+\r
+#lastfm {\r
+ background-position: 0 -176px;\r
+ width: 80px;\r
+ height: 28px;\r
+ margin: -14px 0px 0px -40px;\r
+}\r
+\r
+#pitchfork {\r
+ background-position: 0 -688px;\r
+ width: 100px;\r
+ height: 20px;\r
+ margin: -10px 0px 0px -50px;\r
+}\r
+\r
+#nyancat {\r
+ background-position: 0 -312px;\r
+ width: 64px;\r
+ height: 40px;\r
+ margin: -20px 0px 0px -32px;\r
+}\r
+\r
+#earbits {\r
+ background-position: 0 -471px;\r
+ width: 100px;\r
+ height: 58px;\r
+ margin: -29px 0px 0px -50px;\r
+}\r
+\r
+#songza {\r
+ background-position: 0 -424px;\r
+ width: 100px;\r
+ height: 58px;\r
+ margin: -29px 0px 0px -50px;\r
+}\r
+\r
+#beats-music {\r
+ background-position: 0 -230px;\r
+ width: 100px;\r
+ height: 64px;\r
+ margin: -34px 0px 0px -48px;\r
+}\r
+\r
+#baroque-me {\r
+ background-position: 0 -541px;\r
+ width: 88px;\r
+ height: 47px;\r
+ margin: -23px 0px 0px -42px;\r
+}\r
+\r
+#freesound {\r
+ background-position: 0 -635px;\r
+ width: 100px;\r
+ height: 27px;\r
+ margin: -15px 0px 0px -50px;\r
+}\r
+\r
+div.inthewild.active li:hover {\r
+ background-color: rgba(255,255,255,0.9);\r
+ border-color: #ccc;\r
+ box-shadow: 0px 0px 3px rgba(0,0,0,0.075);\r
+}\r
+\r
+/* homepage-specific demo shiz */\r
+\r
+.sidenote {\r
+ font-size:85%;\r
+ opacity:0.75;\r
+}\r
+\r
+ul.playlist {\r
+ font-size:85%;\r
+}\r
+\r
+ul.playlist li {\r
+ margin-bottom:0.2em;\r
+}\r
+\r
+ul.playlist li a {\r
+ font-size:1em;\r
+ color:#333;\r
+}\r
+\r
+ul.playlist li a,\r
+ul.playlist li a:hover {\r
+ background:transparent;\r
+ border-radius:0px;\r
+ line-height:1em;\r
+}\r
+\r
+ul.playlist li .timing {\r
+ margin-right: 0.1em;\r
+ font-size: 50%;\r
+ top: 0.5em;\r
+}\r
+\r
+ul.playlist.use-peak li .peak {\r
+ /* overrides */\r
+ height:0.61em;\r
+ margin-top:-5px;\r
+ width:0.92em;\r
+}\r
+\r
+html.isSafari ul.playlist.use-peak li .peak {\r
+ margin-top:-4px; /* dumb tweak */\r
+}\r
+\r
+ul.playlist.use-peak li .timing {\r
+ right:4em;\r
+}\r
+\r
+ul.playlist.use-peak li .peak-box {\r
+ height:0.66em;\r
+}\r
+\r
+ul.playlist li .peak .l {\r
+ margin-right:0px;\r
+}\r
+\r
+ul.playlist li .peak .l,\r
+ul.playlist li .peak .r {\r
+ width:6px;\r
+}\r
+\r
+ul.playlist li .peak .r {\r
+ left:9px;\r
+}\r
+\r
+a.not-supported {\r
+ /* give user a hint that the format doesn't work */\r
+ text-decoration:line-through;\r
+ color:#666;\r
+ opacity:0.25;\r
+}\r
+\r
+ul.graphic li {\r
+ line-height:1.5em;\r
+}\r
+\r
+ul.graphic li a,\r
+ul.graphic li a.sm2_link {\r
+ min-width:17.75em;\r
+ width:auto;\r
+}\r
+\r
+ul.graphic li a,\r
+ul.graphic li a.sm2_link {\r
+ background-color:#ddd;\r
+ border-color:#ddd;\r
+ color:#333;\r
+ vertical-align:middle;\r
+}\r
+\r
+ul.graphic li a {\r
+ background:#ddd url(../demo/play-mp3-links/image/icon_play.png) no-repeat 3px 50%;\r
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAA6ElEQVR42q2UvQqDMBRGC47dAj6rgygIDg5OfQlHF30GX0JFURddnEQU+eoNLaSJFRUvnPzA/c4QkjwA3AIf1tJWnitsRT8I+2Q0UfTM8/yFk0UZyooiNk0ThmE4BWUoK4r0cRxxBcr+iMh+AVW0LAtkoihCURS0/ocqwkaZpgnbtrmwrmts1DGR67owDIPjeR7iOEbXdfuisiwh4zgOSb5wcZIkYo8qapoGMpZlkYALwzBElmWoqkrsUUVt20LG930EQUAHTvstVFHf95BJ05TmPVQR3dQLKCI2zzOuQNnbHu3t38gtvAF1L6rpAc8MDwAAAABJRU5ErkJggg==);\r
+ *background-image: url(../demo/play-mp3-links/image/icon_play.png);\r
+ _background-image:url(../demo/play-mp3-links/image/icon_play.gif);\r
+}\r
+\r
+ul.graphic li a:hover,\r
+ul.graphic li a.sm2_paused:hover,\r
+ul.graphic li a.sm2_link:hover,\r
+ul.graphic li a.sm2_playing,\r
+ul.graphic li a.sm2_playing:hover {\r
+ background-color:#336699;\r
+ border-color:#336699;\r
+ color:#fff;\r
+}\r
+\r
+ul.graphic li a.sm2_link {\r
+ /* Doesn't work on this page. */\r
+ -webkit-transition-property: none;\r
+ -webkit-transition: none;\r
+}\r
+\r
+.c2 ul.playlist li a {\r
+ margin:0px;\r
+ padding:0px;\r
+ letter-spacing: -0.02em;\r
+}\r
+\r
+ul.inline-playlist {\r
+ min-height:49px;\r
+ min-width:512px;\r
+ margin-top:4em;\r
+}\r
+\r
+ul.inline-playlist li {\r
+ float:left;\r
+ display:inline;\r
+ width:45%;\r
+ margin-right:0.25%;\r
+}\r
+\r
+body.home .sm2-inline-list .ui360-vis {\r
+ margin-right:0px;\r
+}\r
+\r
+body.home #special-demo-left .ui360:last-child {\r
+ margin-right: 0px;\r
+}\r
+\r
+body.home .columnar .c2 p {\r
+ font-size: 1.1em;\r
+ line-height:1.6em;\r
+ color:#333;\r
+}\r
+\r
+body.home .c2 ul.playlist li a {\r
+ _color:#000; /* stupid IE */\r
+}\r
+\r
+body.home .c2 ul.playlist li.sm2_paused a,\r
+body.home .c2 ul.playlist li.sm2_playing a {\r
+ _color:#fff; /* argh */\r
+}\r
+\r
+body.home .c2 ul.standard {\r
+ _margin-left:1.5em;\r
+}\r
+\r
+body.home .ie6sucks {\r
+ _background: transparent !important;\r
+ _display: none !important;\r
+}\r
+\r
+body.home .ie7sucks {\r
+ *display: none !important;\r
+}\r
+\r
+/* Flash positioning and flashblock / clicktoflash handling */\r
+\r
+/* special-case for the SM2 homepage only */\r
+\r
+body.home #sm2-container {\r
+ position: fixed;\r
+ bottom: 0px;\r
+ left: 0px;\r
+ width: 48px;\r
+ height: 48px;\r
+ /* IE 6 hax, unlikely to have flashblock anyway... */\r
+ _margin:-8px 0px 0px 0px;\r
+}\r
+\r
+@-moz-keyframes flashblock {\r
+ from {\r
+ border-color: #ff3333;\r
+ }\r
+ \r
+ to {\r
+ border-color: #fff;\r
+ }\r
+}\r
+\r
+@-webkit-keyframes flashblock {\r
+ from {\r
+ border-color: #ff3333;\r
+ }\r
+ \r
+ to {\r
+ border-color: #fff;\r
+ }\r
+}\r
+\r
+body.home #sm2-container.swf_timedout {\r
+ /* blocked state */\r
+ border:1px solid #ff3333;\r
+ -moz-animation-duration: 1s;\r
+ -moz-animation-name: flashblock;\r
+ -moz-animation-iteration-count: 5;\r
+ -webkit-animation-duration: 1s;\r
+ -webkit-animation-name: flashblock;\r
+ -webkit-animation-iteration-count: 5;\r
+ width:48px;\r
+ height:48px;\r
+}\r
+\r
+body.home #sm2-container.swf_unblocked {\r
+ /* unblocked state */\r
+}\r
+\r
+body.home #sm2-container.swf_unblocked,\r
+body.home #sm2-container.swf_loaded {\r
+ top:auto;\r
+ left:0px;\r
+ bottom:0px;\r
+ margin:0px;\r
+ width: 6px;\r
+ height: 6px;\r
+}\r
+\r
+#sm2-support-warning {\r
+ display:none;\r
+ border:1px solid #ff9999;\r
+ padding:0.5em;\r
+ margin-top:1.5em;\r
+ font-weight:bold;\r
+}\r
+\r
+#sm2-support {\r
+ display:none;\r
+ font-size:0.9em !important;\r
+ margin-top: 1.5em;\r
+}\r
+\r
+#sm2-support-warning,\r
+#sm2-support {\r
+ background:#fff6f0;\r
+ border:1px solid #ff3333;\r
+}\r
+\r
+body.home #about-sm2 #sm2-support h3 {\r
+ border-color:#ff9999;\r
+ margin-top:0.25em;\r
+}\r
+\r
+body.home #special-demo-left {\r
+ min-height:70px;\r
+ position:relative;\r
+ float:left;\r
+ display:inline;\r
+ margin-right:14px;\r
+ padding-right:0.9em;\r
+ border-right:1px dotted #e0e0e0;\r
+ *border-right:none;\r
+ _width:210px;\r
+}\r
+\r
+body.home #special-demo-right {\r
+ min-height:51px;\r
+ position:relative;\r
+ float:left;\r
+ display:inline;\r
+ margin-top:18px;\r
+ /*\r
+ padding-right:15px;\r
+ */\r
+ *width: 90px;\r
+ _display: none;\r
+}\r
+\r
+body.home #inline-playlist {\r
+ clear:both;\r
+ float:right;\r
+ display:inline;\r
+ width:256px;\r
+ min-height:49px;\r
+ margin-top:2em;\r
+ padding-bottom:0px;\r
+}\r
+\r
+#demo-box {\r
+ position:relative;\r
+ float:right;\r
+ display:inline;\r
+ margin-top:-4px;\r
+ background:#fff;\r
+ padding-left:3em;\r
+ width:256px;\r
+ z-index: 1;\r
+}\r
+\r
+hr {\r
+ visibility:hidden;\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+.demo-block {\r
+ position:relative;\r
+ background:#f9f9f9;\r
+ border:1px solid #e6e6e6;\r
+ padding:4px;\r
+ padding-top:0.5em;\r
+ margin-top:-0.55em;\r
+ border-top:none;\r
+}\r
+\r
+#demo-header {\r
+ color:#333;\r
+ background:#f9f9f9;\r
+ border:1px solid #e6e6e6;\r
+ border-bottom:0px;\r
+ margin-bottom:0px;\r
+ padding:0.5em;\r
+}\r
+\r
+#demos h3 {\r
+ padding-bottom:0px;\r
+ text-indent:0.5em;\r
+ font-weight:normal;\r
+}\r
+\r
+#demos h3 a {\r
+ font-weight:normal;\r
+}\r
+\r
+#revision-list > li {\r
+ margin-top:3em;\r
+ margin-bottom:2em;\r
+}\r
+\r
+#revision-list > li:first-child {\r
+ margin-top:2em;\r
+}\r
+\r
+/* seasonal decorations */\r
+\r
+body.home.has-lights {\r
+ /* prevent ugly scrollbars from explosion fragments */\r
+ overflow-x: hidden;\r
+}\r
+\r
+body.home #lights {\r
+ position:absolute;\r
+ border-top:1px solid #006600;\r
+ left:0px;\r
+ top:0px;\r
+ width:100%;\r
+ z-index:4;\r
+ display:none;\r
+}\r
+\r
+.xlsf-light {\r
+ position:absolute;\r
+ margin-top:-1px;\r
+}\r
+\r
+body.fast .xlsf-light {\r
+ opacity:0.9;\r
+}\r
+\r
+.xlsf-light {\r
+ opacity:0.9;\r
+}\r
+\r
+#explosion-box {\r
+ position: absolute;\r
+ left: 0px;\r
+ top: 0px;\r
+ width: 100%;\r
+ z-index: 10;\r
+}\r
+\r
+.xlsf-fragment {\r
+ position:absolute;\r
+ background:transparent url(christmas-lights/image/bulbs-50x50-fragments.png) no-repeat 0px 0px;\r
+ width:50px;\r
+ height:50px;\r
+}\r
+\r
+.xlsf-fragment-box {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:50px;\r
+ height:50px;\r
+ *width:100%;\r
+ *height:100%;\r
+ display:none;\r
+}\r
+\r
+.figure {\r
+ display:inline;\r
+ display:inline-block;\r
+ border:1px solid #ddeeff;\r
+ padding:0.5em;\r
+ margin:0.5em 0px 0.5em 0px;\r
+}\r
+\r
+.figure .code span {\r
+ padding:0.25em;\r
+ border:1px solid #f0f9ff;\r
+ background:#fff;\r
+}\r
+\r
+.figure .code span.mid {\r
+ color:#666;\r
+}\r
+\r
+#sm2-container.flash_debug {\r
+ /* flash movie, when soundManager.debugFlash = true */\r
+ position:relative;\r
+ width:auto;\r
+ height:300px;\r
+ width:100%;\r
+ background:#f6f6f6;\r
+ border:1px solid #ccc;\r
+}\r
+\r
+#sm2-container.flash_debug object,\r
+#sm2-container.flash_debug embed {\r
+ width:100%;\r
+ height:100%;\r
+ left:auto;\r
+ top:auto;\r
+}\r
+\r
+ul.file-structure ul {\r
+ padding-left:1.5em;\r
+}\r
+\r
+ul.file-structure li {\r
+ list-style-type:square;\r
+ margin-top:0.25em;\r
+ margin-left:0px;\r
+}\r
+\r
+ul.file-structure li span {\r
+ color:#999;\r
+}\r
+\r
+#sm2-filesizes {\r
+ border:1px solid #ddd;\r
+ background:#fff;\r
+}\r
+\r
+#sm2-filesizes tr:nth-child(2n+1) {\r
+ background:#f9f9f9;\r
+}\r
+\r
+#sm2-filesizes th {\r
+ background:#eee;\r
+ font-weight:bold;\r
+ text-align:left;\r
+}\r
+\r
+#sm2-filesizes th {\r
+ padding:4px 6px;\r
+}\r
+\r
+#sm2-filesizes td {\r
+ padding:0px 6px;\r
+ border:1px solid #eee;\r
+}\r
+\r
+#sm2-filesizes p {\r
+ margin-top:0.5em;\r
+ margin-bottom:0px;\r
+}\r
+\r
+#sm2-filesizes pre {\r
+ border-left:none;\r
+ margin-top:0.5em;\r
+ margin-bottom:0.5em;\r
+}\r
+\r
+#sm2-filesizes .nw {\r
+ white-space:nowrap;\r
+}\r
+\r
+#sm2-filesizes .booyaa {\r
+ /* in the words of Paris Hilton, "that's hot." (in the nerdy sense, I suppose.) */\r
+ background:#fff9f9;\r
+ color:#990000;\r
+}\r
+\r
+#history li.in > p.compact {\r
+ font-weight:bold;\r
+}\r
+\r
+#sm2-options {\r
+ /* -html5, -debug etc. */\r
+ position: relative;\r
+ clear: both;\r
+ color: #666;\r
+ margin: 0.33em 0.75em 0px 0.75em;\r
+ border-top: 1px dotted #ddd;\r
+}\r
+\r
+#sm2-options .options-divider {\r
+ font-size: 85%;\r
+ color: #ccc;\r
+}\r
+\r
+#sm2-options p {\r
+ font-size: 85%;\r
+ padding-left: 0px;\r
+ padding-bottom: 0px;\r
+ margin-bottom: 0.75em;\r
+}\r
+\r
+#sm2-options p:first-child {\r
+ margin-top: 0.75em;\r
+}\r
+\r
+#sm2-options a {\r
+ color: #3399cc;\r
+ text-decoration: none;\r
+ padding: 1px;\r
+ margin-top: -2px 0px 0px -2px;\r
+}\r
+\r
+#without-html5 {\r
+ display: none;\r
+}\r
+\r
+body.home #about-sm2 #inline-demo-header {\r
+ margin-top: 1.5em;\r
+ border-bottom: 1px solid #eee;\r
+ padding-bottom: 0.5em;\r
+}\r
+\r
+body.home #about-sm2 #inline-demo-header,\r
+body.home #about-sm2 .home-shopping-network {\r
+ display: block;\r
+}\r
+\r
+#about-sm2 a img {\r
+ border: none;\r
+}\r
+\r
+/* alternate code + comment blocks */\r
+\r
+ul.code-block {\r
+ list-style-type: none;\r
+ position: relative;\r
+ padding: 3px;\r
+ font-size: 85%;\r
+}\r
+\r
+ul.code-block,\r
+ul.code-block li {\r
+ position: relative;\r
+ margin: 0px;\r
+ padding: 0px;\r
+ line-height: 1.5em;\r
+}\r
+\r
+ul.code-block li {\r
+ padding: 0.75em 0.5em;\r
+}\r
+\r
+ul.code-block li:nth-child(2n+1) {\r
+ background-color: #fcfcfc;\r
+}\r
+\r
+ul.code-block li:last-child {\r
+ padding-bottom: 0px;\r
+}\r
+\r
+ul.code-block li div {\r
+ position: absolute;\r
+ left: 0.5em;\r
+ top: 0.75em; /* note: match LI padding */\r
+ width: 22em; /* left gutter */\r
+ z-index: 2; /* sit on top */\r
+}\r
+\r
+ul.code-block li span {\r
+ position: relative;\r
+ display: block;\r
+ padding-left: 22.5em; /* room for left gutter */\r
+ text-indent: -2em;\r
+}\r
+\r
+/* special min-width case */\r
+#soundmanager-properties ul.code-block {\r
+ min-width: 43em;\r
+}\r
+\r
+/**\r
+* November 2011 homepage redesign\r
+*/\r
+\r
+div.oneup,\r
+div.twoup,\r
+div.threeup {\r
+ position: relative;\r
+ clear: both;\r
+ padding: 2em 1em 2.5em 1em;\r
+ *zoom:1; /* god damn shite IE */\r
+}\r
+\r
+div.oneup .column {\r
+ position: relative;\r
+ width: 100%;\r
+}\r
+\r
+div.twoup .column,\r
+div.threeup .column {\r
+ position: relative;\r
+ float: left;\r
+ display: inline;\r
+ width: 33.3%;\r
+ _width: 32%; /* IE 6 */\r
+}\r
+\r
+div.twoup .column {\r
+ width: 50%;\r
+ _width: 49%; /* IE 6 can die */\r
+}\r
+\r
+div.oneup .column,\r
+div.twoup .column,\r
+div.threeup .column {\r
+ padding-bottom: 0.5em;\r
+}\r
+\r
+div.oneup .column-wrapper,\r
+div.twoup .column-wrapper,\r
+div.threeup .column-wrapper {\r
+/*\r
+ border-top: 1px dotted #d0d0d0;\r
+*/\r
+ margin: 0px 2.5em;\r
+}\r
+\r
+div.oneup .column-wrapper.spaced-out,\r
+div.twoup .column-wrapper.spaced-out,\r
+div.threeup .column-wrapper.spaced-out {\r
+ /* spacing for columns without an <h3> header */\r
+ padding-top: 6.25em;\r
+}\r
+\r
+div.threeup.first {\r
+ padding-top: 0.75em;\r
+}\r
+\r
+div.threeup.first .column-wrapper {\r
+ border-top: none;\r
+}\r
+\r
+body.home #main .oneup p,\r
+body.home #main .twoup p,\r
+body.home #main .threeup p {\r
+ font-size: 1.1em;\r
+ line-height: 1.5em;\r
+ margin-bottom: 1.5em;\r
+}\r
+\r
+body.home #main p.sidenote {\r
+ /* disclaimer */\r
+ font-size: 92%;\r
+ color: #666;\r
+}\r
+\r
+body.home h2 {\r
+ margin-top: 0px;\r
+}\r
+\r
+body.home div.c3 {\r
+ /* pop discussion/support on top of margin */\r
+ position: relative;\r
+ float: right;\r
+ display: inline;\r
+ margin-left: 30px; /* a little extra spacing, so the <h2> doesn't overlap */\r
+ margin-top: -6px;\r
+ z-index: 2;\r
+ margin-bottom: 2.5em;\r
+}\r
+\r
+body.home #inline-playlist {\r
+ float: none;\r
+ display: block;\r
+ width: auto;\r
+}\r
+\r
+body.home .sm2-inline-list .ui360-vis {\r
+ /* center */\r
+ margin: 0px auto;\r
+}\r
+\r
+body.home ul.playlist {\r
+ font-size: 85%;\r
+}\r
+\r
+body.home ul.playlist li {\r
+ font-size: 1.75em;\r
+ letter-spacing: -0.02em;\r
+}\r
+\r
+body.home ul.playlist .sidenote {\r
+ font-size: 85%;\r
+}\r
+\r
+body.home ul.graphic {\r
+ margin-top: 1em;\r
+}\r
+\r
+body.home ul.graphic {\r
+ position: relative;\r
+}\r
+\r
+body.home ul.graphic li {\r
+ float: left;\r
+ display: inline;\r
+ width: 50%;\r
+ margin-bottom: 0px;\r
+}\r
+\r
+body.home ul.graphic li a,\r
+body.home ul.graphic li a.sm2_link {\r
+ display: block;\r
+ width: auto;\r
+ min-width: 8em;\r
+ margin-right: 0.5em;\r
+ margin-bottom: 0.5em;\r
+}\r
+\r
+body.home ul li a:hover,\r
+body.home ul.graphic a.sm2_playing,\r
+body.home #inline-playlist li.sm2_paused a,\r
+body.home #inline-playlist li.sm2_playing a,\r
+body.home ul.playlist li div.timing,\r
+body.home .feature-hot,\r
+body.home #html5-support-li span {\r
+ /* take out shadow on most demo links */\r
+ text-shadow: none;\r
+}\r
+\r
+body.home .feature-hot {\r
+ /* hack: font size fix */\r
+ font-size: 13px;\r
+}\r
+\r
+body.home ul.graphic li a,\r
+ul.playlist li a {\r
+ /* "..." on titles */\r
+ overflow: hidden;\r
+ white-space: nowrap;\r
+ text-overflow: ellipsis;\r
+ /* crap IE */\r
+ *overflow: auto;\r
+ *white-space: wrap;\r
+}\r
+\r
+body.home ul.playlist li a,\r
+body.home ul.playlist li a:hover {\r
+ line-height: 1.2em;\r
+}\r
+\r
+body.home .demo-more a span,\r
+body.home .demo-more-abs a span {\r
+ font-size: 1.5em;\r
+ line-height: 1em;\r
+ vertical-align: bottom;\r
+}\r
+\r
+body.home #sm2-visualization {\r
+ clear: both;\r
+ margin-top: 2em;\r
+}\r
+\r
+body.home #sm2-visualization .ui360 {\r
+ float: none;\r
+ display: block;\r
+}\r
+\r
+body.home #sm2-visualization .ui360 .sm2-360ui {\r
+ border-color: rgba(0,0,0,0.05);\r
+ background-color: rgba(255,255,255,0.5);\r
+ box-shadow: inset 0px 0px 32px rgba(0,0,0,0.075);\r
+}\r
+\r
+body.home #sm2-visualization .ui360 canvas,\r
+body.home #sm2-visualization .ui360 .sm2-360ui,\r
+body.home #sm2-visualization .ui360 a {\r
+ border-radius: 100%;\r
+}\r
+\r
+body.home #sm2-visualization .ui360 a {\r
+ /* put title underneath button */\r
+ line-height: 340px;\r
+ *line-height: 480px; /* not crap IE, though. */\r
+ line-height: 480px\9; /* nor IE 8. */\r
+ color: #666 !important; /* hax */\r
+ text-shadow: 0px 1px 0px #fff;\r
+}\r
+\r
+:root body.home #sm2-visualization .ui360 a {\r
+ /* IE 9 correction */\r
+ line-height: 340px\0/IE9;\r
+}\r
+\r
+body.home #sm2-visualization .ui360 a,\r
+body.home #sm2-visualization .ui360 canvas {\r
+ -webkit-transition: all 0.2s ease-in-out;\r
+ -moz-transition: all 0.2s ease-in-out;\r
+ transition: all 0.2s ease-in-out;\r
+ -moz-transition-property: background-color, border, box-shadow;\r
+ -webkit-transition-property: background-color, border, box-shadow;\r
+ transition-property: background-color, border, box-shadow;\r
+}\r
+\r
+body.home #sm2-visualization .ui360:hover {\r
+ background-color: rgba(0,0,0,0);\r
+}\r
+\r
+body.home #sm2-visualization .ui360:hover a {\r
+ background-color: rgba(0,0,0,0.01);\r
+ border-color: rgba(0,0,0,0.1);\r
+ box-shadow: inset 0px 0px 32px rgba(0,0,0,0.05);\r
+}\r
+\r
+body.home #sm2-visualization .ui360 .sm2_playing canvas,\r
+body.home #sm2-visualization .ui360 .sm2_paused canvas {\r
+ /* hide song title while playing */\r
+ background-color: #fafafa;\r
+ *background-color: transparent; /* not you, crap IE. */\r
+ background-color: transparent\9; /* nor IE 8. */\r
+}\r
+\r
+body.home #sm2-visualization .ui360 .sm2_playing canvas,\r
+body.home #sm2-visualization .ui360 .sm2_paused canvas {\r
+ background-color: #fafafa;\r
+ box-shadow: inset 0px 0px 32px rgba(0,0,0,0.066);\r
+}\r
+\r
+body.home #sm2-visualization .ui360:hover .sm2_playing canvas,\r
+body.home #sm2-visualization .ui360:hover .sm2_paused canvas {\r
+ background-color: #fafafa;\r
+ box-shadow: inset 0px 0px 32px rgba(0,0,0,0.1);\r
+}\r
+\r
+body.home .gsfn_topic_list li {\r
+ /* by default, hide (and only show first X items.) */\r
+ display: none;\r
+}\r
+\r
+body.home .gsfn_topic_list .gsfn-item-1,\r
+body.home .gsfn_topic_list .gsfn-item-2,\r
+body.home .gsfn_topic_list .gsfn-item-3 {\r
+ /* show these items only. */\r
+ display: block;\r
+}\r
+\r
+div.clearfix {\r
+ font-size: 0px;\r
+ height: 0px;\r
+ overflow: hidden;\r
+}\r
+\r
+div.icons ul {\r
+ list-style-type: none;\r
+}\r
+\r
+div.icons ul,\r
+div.icons ul li {\r
+ margin: 0px;\r
+ padding: 0px;\r
+}\r
+\r
+div.icons ul li,\r
+.icon {\r
+ position: relative;\r
+ display: inline-block;\r
+ vertical-align: middle;\r
+ *display: none; /* not you, crap IE. */\r
+ background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYAAAAAwCAYAAAAYeq1+AAAHLklEQVR42uydT4jcVBzHH6LbLV11wGIVL6OClFbL1P3zEtvDFCsIKqyn0tseFBFKXTwpIu7B017mLBSymwwevBSsiCdjdzOpW5DVg3izXsSbsf5Z3aWd+M1M3jTENpvJTEzS/X7hy0szL+l0d/r95P2SeU9QFEVRFEVRFEVRFEVRFEVRFEVRFEVRFEVRFEVRFEVRFEVRVAFqX5m91+rIMyKFLEf7QFAURVF3jwCAV3ft4849AgAcERRFUXlpenraj7rE77MG27A/pG24VioArOsHTEcum472vtXR/Nv4HLzcducOCIqqqk6fPl2Dbdgfk224Jqg9BwAV/hlti5JoZWN2H8J/E+F/sx/2euBu29W7wZ/R9iHgyC2zI9cERVVVKvzHbFtQuUCgIqCKuxXp01L7ywg2BPtjKOtcR+vDN8LA77Y7OloYreVqPRCYHW2730/+iHZSUEMFzxLs5+wlQSUqr5+9oAiAIS1KINORvyDkEe7yc9OVhwGDLSsI/ltG+MsADt9ZjjyM9mvYx3FfCKr44Im7gNJJpUopsb+zOaJ95ZKWupqhF+EluAXbob0yvXcEYhM24GvxoAz3GXAjVn/fhA0CIHP4XwhLPl0E/0Vs1+E/wqt/WJWC0MfRrqJE9Djay+jThYN9rwgqnTKETqYwqljpJG6bABheYcDHgj29Cw7++pC1dBtuwG9G9hlFAWCkYwvU6rp8AIH+s4Vw7wU6DCD80ysBYTsyAoiUgORfaPv9cdwqoLCycfIeVlBKBAC+/6oBoHg4Fxj+87AXu9Jvwc2YW7GRQdybBMDQtf9HEfh/9gIeRuhHr/r/ux1reyAIjnfmHmYFhQAgAKpVXrwW/XOB4e+H9uDFFMcsKmBE/AZcIwCGLv88CL+F8s7bWWx1YEeeN525/QQAAUAAlAcANrwUej7yXmt3Oqagso8XCf9G2pvAQd8oBNSxBECyrCDwO/I1BPcLpisncCU/ZblyBu1sFltB6+jTpqMH3yKexPnPAihn8HfsJwAIAAIgf2UP8+IBYMfDPxEAyRCwCYA0ANA+UV/qQkifRYhPY3sb5ZybWQ0IeOYV7X6c+yN1bmy/QwAQAAQAASASwtsPvZj1MdDg2Mh5mgRAsqLP92P7M9ORR9DuYJ+fxZYbhL3urX51YgLbv+MeQm8f2nVBEQAEAAFwh+Az1A3fUb8HEJyDTwGlBwDcDW/gfgoAHO0BAPszQ8DRvBVbm8B5foPVDeJcAJDnVT5HAAQAAZC/4qHdGgMAWgomBECyVGgrAKA92nbkjpUt/NV5PNPVJgCTPgBcAoAAIAAIgASlKdvgtZci/V5M6NdU/QiA4QFgAQAjhL8PeHjGBkpAjhYBgEYAEAAEAAEwEgD8qAmA8QNAlYCsEUtApv1caUYAYhcRAAQAAUAAEABqBKBuAmc0gt+7YE/HRwAEAAFAABAAIwHgVKTfKQJgXADQxgaAMPA9c+MkRwAEAAFQYgDEJ4dr8Cbw3gNA/xFNXT0FdAkeCQDh+TzD0SNPAWk4N28CF/JFBgKAALjDh7uZMFdQmR8DbQbmY6Bjewz0V8sdfFlrBe3T4ygBrXwpJ3GenxD86tyXqgAAtEZgAoAAqBIA1JX8ImzAF+OzJMb6LhT1mUlTtkkz/0/KL4I1CIBkmR3t9cE3gR35DK7WJba3RwUA/BDO83L/3DLY93wF8tOIbhMAnA66CgBQge6l+f1ju57Ut+xTQShxKojxadWdO77izh4MRwS6AoDl6t0hw78bziDqmR39UHiP4anVdf0J5icXhOGCMPm87/lhfv/hKMFPYa8Mk8FlCf+wrRMAmWYDPYEA37EGyz9qcHRaaOxXrZr6IVr/x/7eY6Dr8hBnA+WSkGMTAXB7qSmcd3OGz9tShaeDnueSkJknhwtmB/0Bo4C/UbrZAgRuIPzVQvBdbG9hewvbcAABuF9C2u69huNMR9tsX9GnCICc/7Fc0pIAGPbnp97fLjYEVMEFYTx4nmsCj6a2Iw8i0J9FkNfRfm91+iEflneOAQoN7JsZ7OuvDLbcduUxtMexqtgU82fvAMCA/ZxtEAAj/QdoxY5pJSwIMwjQCi4JWS/7ovCp+pRICPerquSDkcHgvZmXZ+4zw/CHgxHAeRETl4TMGwDU2FThkUsry4cX+xvwknKxwZ9c20+xKHxT9ScAxv6Y6FW1/KPpRgCwNhsCAFYAoHK7yeol3ayDa4L6vwCwELpoAMSvgrzYZ8KA64ISRT3NlNF2qQCgRgAhBNT+NgAwePKnQwBQ1QeAnQMAbEHtRQDUMkLAhmslGwF8M1gzAK3a//GaNmHduvoHBOQ5QVF5q0KPs9ocmVFVl+Vo70aWjPw2tp7w9f4KYHjNlWcFRVEUdfcIoT9lOvK86WjvwbXYa08CDB/i9QXAYJ+gKIqiqH/bgwMSAAAAAEH/X7cjUAEAAAAAAAAAAAAAAA4CNogIgRLqd00AAAAASUVORK5CYII=) no-repeat;\r
+ width: 32px;\r
+ height: 24px;\r
+ padding-right: 4px;\r
+ text-indent: -999em;\r
+ overflow: hidden;\r
+ cursor: help;\r
+ opacity: 0.75;\r
+}\r
+\r
+div.icons ul li:hover,\r
+.icon:hover {\r
+ opacity: 1;\r
+}\r
+\r
+.icon {\r
+ display: inline-block;\r
+ *display: none;\r
+ width: 32px;\r
+ height: 30px;\r
+ margin-left: 16px;\r
+ margin-top: 5px;\r
+ opacity: 0.85;\r
+ cursor: default;\r
+}\r
+\r
+div.icons ul li.desktop {\r
+ background-position: -11px -12px;\r
+ height: 24px;\r
+}\r
+\r
+div.icons ul li.laptop {\r
+ background-position: -59px -13px;\r
+ height: 22px;\r
+}\r
+\r
+div.icons ul li.ipad {\r
+ background-position: -109px -10px;\r
+ width: 28px;\r
+ height: 28px;\r
+}\r
+\r
+div.icons ul li.iphone {\r
+ background-position: -256px -9px;\r
+ width: 22px;\r
+ height: 28px;\r
+}\r
+\r
+div.icons ul li.android {\r
+ background-position: -299px -7px;\r
+ width: 28px;\r
+ height: 32px;\r
+}\r
+\r
+.icon.performance,\r
+div.icons ul li.performance {\r
+ background-position: -205px -9px;\r
+}\r
+\r
+.icon.performance {\r
+ width: 18px;\r
+ height: 28px;\r
+ margin-top: -7px;\r
+}\r
+\r
+.icon.music-note,\r
+div.icons ul li.music-note {\r
+ background-position: -155px -13px;\r
+}\r
+\r
+.icon.music-note {\r
+ width: 19px;\r
+ height: 23px;\r
+ margin-top: -4px;\r
+}\r
+\r
+.icon.package,\r
+div.icons ul li.package {\r
+ background-position: -347px -7px;\r
+ height: 28px;\r
+}\r
+\r
+.icon.package {\r
+ width: 22px;\r
+ margin-top: -8px;\r
+}\r
+\r
+.bonus-demos {\r
+ position: relative;\r
+ list-style-type: none;\r
+}\r
+\r
+.bonus-demos,\r
+.bonus-demos li {\r
+ margin: 0px;\r
+ padding: 0px;\r
+}\r
+\r
+.bonus-demos li {\r
+ float: left;\r
+ display: inline;\r
+ width: 24%;\r
+ margin-right: 1%;\r
+ text-align: center;\r
+}\r
+\r
+.bonus-demos li img {\r
+ border-radius: 4px;\r
+}\r
+\r
+#client-requests ul.flat {\r
+ /* nested examples as in HTML5 vs. flash download behaviours */\r
+ list-style-type: none;\r
+ padding-left: 0.5em;\r
+ margin-top: 0.5em;\r
+}\r
+\r
+#client-requests ul.flat li {\r
+ margin-bottom: 0px;\r
+}\r
+\r
+#inline-video {\r
+ position: relative;\r
+ margin-top: 4.25em;\r
+ margin-right: 0.5em;\r
+}\r
+\r
+#bar-ui-1 {\r
+ position: relative;\r
+ top: -45px;\r
+}\r
+\r
+#bar-ui-1 .bd,\r
+#bar-ui-1 .sm2-bar-ui .sm2-extra-controls,\r
+#bar-ui-1 .sm2-bar-ui .sm2-playlist-drawer {\r
+ background-color: #2299cc; /* non-RGBA fallback */\r
+ background-color: rgba(0,128,224,0.65);\r
+}\r
+\r
+#about-sm2 .sm2-bar-ui .sm2-playlist-drawer {\r
+ /* weird Chrome mac (retina display?) fix, otherwise BG color doesn't draw. */\r
+ transform: scale3d(1,1,1);\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>MP3 player demo</title>
+<meta name="robots" content="noindex" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta name="language" content="en-us" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<meta name="keywords" content="javascript sound library api" />\r
+<meta name="description" content="Demo page for soundmanager mp3 player" />\r
+<script type="text/javascript" src="../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/default.js"></script>\r
+</head>\r
+\r
+<body>\r
+\r
+<div>\r
+\r
+ <h1>SoundManager 2 Demos</h1>\r
+\r
+ <p>\r
+ <a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2 project page</a>\r
+ </p>\r
+\r
+</div>\r
+\r
+</body>\r
--- /dev/null
+/* SoundManager 2 - project home utility JS */\r
+\r
+var IS_CHRISTMAS = (document.domain.match(/schillmania.com/i) && new Date().getMonth() == 11) || window.location.toString().match(/christmas/i);\r
+\r
+function _id(sID) {\r
+ return document.getElementById(sID);\r
+}\r
+\r
+getSoundByURL = function(sURL) {\r
+ return (typeof self.soundsByURL[sURL] != 'undefined'?self.soundsByURL[sURL]:null);\r
+}\r
+\r
+function init() {\r
+ var o = document.getElementById('main');\r
+ var el = o.getElementsByTagName('dt');\r
+ for (var i=el.length; i--;) {\r
+ if ((i+1)%2==0) {\r
+ utils.addClass(el[i],'alt');\r
+ }\r
+ }\r
+ var el = o.getElementsByTagName('dl');\r
+ for (var i=el.length; i--;) {\r
+ if ((i+1)%2==0) {\r
+ utils.addClass(el[i],'alt');\r
+ }\r
+ }\r
+ var newCSS;\r
+ if (IS_CHRISTMAS) {\r
+ // overflow-x: hidden hack for homepage during christmas light season (so explosion fragments don't cause horizontal scrollbars.)\r
+ var newCSS = document.body.className.split(' ');\r
+ newCSS.push('has-lights');\r
+ document.body.className = newCSS.join(' ');\r
+ }\r
+}\r
+\r
+function Utils() {\r
+ var self = this;\r
+\r
+ this.hasClass = function(o,cStr) {\r
+ return (typeof(o.className)!='undefined'?new RegExp('(^|\\s)'+cStr+'(\\s|$)').test(o.className):false);\r
+ }\r
+\r
+ this.addClass = function(o,cStr) {\r
+ if (!o || !cStr) return false; // safety net\r
+ if (self.hasClass(o,cStr)) return false;\r
+ o.className = (o.className?o.className+' ':'')+cStr;\r
+ }\r
+\r
+ this.removeClass = function(o,cStr) {\r
+ if (!o || !cStr) return false; // safety net\r
+ if (!self.hasClass(o,cStr)) return false;\r
+ o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');\r
+ }\r
+\r
+ this.toggleClass = function(o,cStr) {\r
+ var m = (self.hasClass(o,cStr)?self.removeClass:self.addClass);\r
+ m(o,cStr);\r
+ }\r
+\r
+ this.getElementsByClassName = function(className,tagNames,oParent) {\r
+ var doc = (oParent||document);\r
+ var matches = [];\r
+ var i,j;\r
+ var nodes = [];\r
+ if (typeof(tagNames)!='undefined' && typeof(tagNames)!='string') {\r
+ for (i=tagNames.length; i--;) {\r
+ if (!nodes || !nodes[tagNames[i]]) {\r
+ nodes[tagNames[i]] = doc.getElementsByTagName(tagNames[i]);\r
+ }\r
+ }\r
+ } else if (tagNames) {\r
+ nodes = doc.getElementsByTagName(tagNames);\r
+ } else {\r
+ nodes = doc.all||doc.getElementsByTagName('*');\r
+ }\r
+ if (typeof(tagNames)!='string') {\r
+ for (i=tagNames.length; i--;) {\r
+ for (j=nodes[tagNames[i]].length; j--;) {\r
+ if (self.hasClass(nodes[tagNames[i]][j],className)) {\r
+ matches[matches.length] = nodes[tagNames[i]][j];\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ for (i=0; i<nodes.length; i++) {\r
+ if (self.hasClass(nodes[i],className)) {\r
+ matches[matches.length] = nodes[i];\r
+ }\r
+ }\r
+ }\r
+ return matches;\r
+ }\r
+\r
+ this.findParent = function(o) {\r
+ if (!o || !o.parentNode) return false;\r
+ o = o.parentNode;\r
+ if (o.nodeType == 2) {\r
+ while (o && o.parentNode && o.parentNode.nodeType == 2) {\r
+ o = o.parentNode;\r
+ }\r
+ }\r
+ return o;\r
+ }\r
+\r
+ this.getOffY = function(o) {\r
+ // http://www.xs4all.nl/~ppk/js/findpos.html\r
+ var curtop = 0;\r
+ if (o.offsetParent) {\r
+ while (o.offsetParent) {\r
+ curtop += o.offsetTop;\r
+ o = o.offsetParent;\r
+ }\r
+ }\r
+ else if (o.y) curtop += o.y;\r
+ return curtop;\r
+ }\r
+\r
+ this.isChildOfClass = function(oChild,oClass) {\r
+ if (!oChild || !oClass) return false;\r
+ while (oChild.parentNode && !self.hasClass(oChild,oClass)) {\r
+ oChild = self.findParent(oChild);\r
+ }\r
+ return (self.hasClass(oChild,oClass));\r
+ }\r
+\r
+ this.getParentByClassName = function(oChild,sParentClassName) {\r
+ if (!oChild || !sParentClassName) return false;\r
+ sParentClassName = sParentClassName.toLowerCase();\r
+ while (oChild.parentNode && !self.hasClass(oChild.parentNode,sParentClassName)) {\r
+ oChild = self.findParent(oChild);\r
+ }\r
+ return (oChild.parentNode && self.hasClass(oChild.parentNode,sParentClassName)?oChild.parentNode:null);\r
+ }\r
+\r
+}\r
+\r
+var utils = new Utils();\r
+\r
+var lastSelected = null;\r
+\r
+function resetFilter(o) {\r
+ // reset everything\r
+ var oParent = null;\r
+ _id('filter-box').style.display = 'none';\r
+ utils.removeClass(_id('main'),'filtered');\r
+ var blocks = utils.getElementsByClassName('f-block',['div','dl'],_id('main'));\r
+ for (var i=blocks.length; i--;) {\r
+ blocks[i].style.display = 'block';\r
+ oParent = utils.getParentByClassName(blocks[i],'columnar',_id('main'));\r
+ if (oParent) oParent.style.display = 'block';\r
+ }\r
+ if (lastSelected) utils.removeClass(lastSelected,'active');\r
+ if (o) lastSelected = o;\r
+ return false;\r
+}\r
+\r
+function setFilter(e,sFilterPrefix) {\r
+ var o = e?e.target||e.srcElement:event.srcElement;\r
+ utils.addClass(_id('main'),'filtered');\r
+ var oName = o.nodeName.toLowerCase();\r
+ if (oName == 'a') {\r
+ var parent = utils.findParent(o);\r
+ if (parent && parent.nodeName.toLowerCase() == 'li') {\r
+ // normalize to LI instead.\r
+ o = parent;\r
+ oName = o.nodeName.toLowerCase();\r
+ }\r
+ }\r
+ var sClass = '';\r
+ var blocks = utils.getElementsByClassName('f-block',['div','dl'],_id('main'));\r
+ var oParents = utils.getElementsByClassName('columnar','div',_id('main'));\r
+ var oParent = null;\r
+ var matchingParents = [];\r
+ if (oName != 'li' || o.className == 'ignore') {\r
+ return true;\r
+ }\r
+ var isClear = (lastSelected && lastSelected == o && utils.hasClass(lastSelected,'active'));\r
+ if (oName == 'li' && isClear) {\r
+ if (typeof e.preventDefault !== 'undefined') {\r
+ e.preventDefault();\r
+ }\r
+ return resetFilter();\r
+ }\r
+ if (oName == 'li') {\r
+ // from shortcuts/filter menu\r
+ var innerText = (o.getElementsByTagName('a').length?o.getElementsByTagName('a')[0].innerHTML:o.innerHTML); // get inner text (minus link, if one is there)\r
+ sClass = sFilterPrefix+innerText.substr(0,innerText.indexOf('(')!=-1?innerText.indexOf('('):999).toLowerCase().replace(/\s+/i,'-');\r
+ var last = sClass.substr(sClass.length-1);\r
+ if (last == '-' || last == ' ') {\r
+ sClass = sClass.substr(0,sClass.length-1); // IE innerHTML trailing whitespace hack (?)\r
+ }\r
+ for (var i=blocks.length; i--;) {\r
+ oParent = utils.getParentByClassName(blocks[i],'columnar',_id('main'));\r
+ if (utils.hasClass(blocks[i],sClass)) {\r
+ blocks[i].style.display = 'block';\r
+ if (oParent) {\r
+ matchingParents.push(oParent);\r
+ }\r
+ } else {\r
+ blocks[i].style.display = 'none';\r
+ }\r
+ }\r
+ for (i=oParents.length; i--;) {\r
+ oParents[i].style.display = 'none';\r
+ }\r
+ for (i=matchingParents.length; i--;) {\r
+ matchingParents[i].style.display = 'block';\r
+ }\r
+ _id('search-results').innerHTML = '<h3><span class="option"><a href="#" title="Restore full content" onclick="resetFilter();return false" style="text-decoration:none"> clear filter </a></span>Content filter: '+(sFilterPrefix=='f-'?'soundManager.':(sFilterPrefix=='s-'?'[SMSound object].':''))+'<b style="font-weight:bold">'+o.innerHTML+'</b></h3>';\r
+ _id('search-results').style.display = 'block';\r
+ _id('filter-box').style.display = 'block';\r
+ if (isClear) {\r
+ _id('filter-box').style.paddingBottom = '0px';\r
+ _id('filter-box').style.display = 'none';\r
+ } else {\r
+ _id('filter-box').style.paddingBottom = '0px';\r
+ if (!navigator.userAgent.match(/msie/i)) {\r
+ _id('filter-box').style.paddingBottom = Math.max(0,(document.documentElement.scrollTop || window.scrollY)-utils.getOffY(_id('filter-box'))-parseInt(_id('filter-box').offsetHeight)-20)+'px';\r
+ }\r
+ _id('filter-box').style.display = 'block';\r
+ // if ((!document.documentElement.scrollTop && !window.scrollY)) _id('filter-box').style.display = 'none';\r
+ }\r
+ if (lastSelected) {\r
+ if (lastSelected == o) {\r
+ utils.toggleClass(lastSelected,'active');\r
+ } else {\r
+ utils.removeClass(lastSelected,'active');\r
+ utils.addClass(o,'active');\r
+ }\r
+ } else {\r
+ utils.addClass(o,'active');\r
+ }\r
+ lastSelected = o;\r
+ if (typeof e.preventDefault !== 'undefined') {\r
+ e.preventDefault();\r
+ }\r
+ // cancel bubble, too?\r
+ return false;\r
+ }\r
+}\r
+\r
+function getLiveData() {\r
+ getDynamicData();\r
+}\r
+\r
+function getDynamicData() {\r
+ // Attempt to fetch data from schillmania.com: "Get Satisfaction" topics, version updates etc.\r
+ loadScript('http://www.schillmania.com/services/soundmanager2/info/?version='+soundManager.versionNumber+'&rnd='+parseInt(Math.random()*1048576));\r
+}\r
+\r
+function loadScript(sURL,onLoad) {\r
+ var loadScriptHandler = function() {\r
+ var rs = this.readyState;\r
+ if (rs == 'loaded' || rs == 'complete') {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ window.setTimeout(onLoad,20);\r
+ }\r
+ }\r
+ function scriptOnload() {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ window.setTimeout(onLoad,20);\r
+ }\r
+ var oS = document.createElement('script');\r
+ oS.type = 'text/javascript';\r
+ if (onLoad) {\r
+ oS.onreadystatechange = loadScriptHandler;\r
+ oS.onload = scriptOnload;\r
+ }\r
+ oS.src = sURL;\r
+ document.getElementsByTagName('head')[0].appendChild(oS);\r
+}\r
+\r
+function doAltShortcuts() {\r
+/*\r
+ var o = _id('shortcuts-list');\r
+ if (!o) {\r
+ return false; \r
+ }\r
+ var oParents = [];\r
+ var oLIs = o.getElementsByTagName('li');\r
+ var isIgnore = null;\r
+ var offset = 0;\r
+ for (var i=0; i<oLIs.length; i++) {\r
+ isIgnore = utils.hasClass(oLIs[i],'ignore');\r
+ if (isIgnore) {\r
+ offset = 0;\r
+ }\r
+ offset++;\r
+ if ((offset)%2 == 0 && !isIgnore) {\r
+ utils.addClass(oLIs[i],'alt');\r
+ }\r
+ }\r
+*/\r
+}\r
+\r
+function fixLinks() {\r
+ if (document.location.protocol.match(/http/i)) {\r
+ return false;\r
+ }\r
+ // presumably offline - add index.html to local links, so offline browsing is seamless\r
+ var l = document.getElementsByTagName('a');\r
+ var s = null;\r
+ var tmp = null;\r
+ for (var i=l.length; i--;) {\r
+ s = l[i].href.toString();\r
+ if (!s.match(/http/i) && !utils.hasClass(l[i],'norewrite') && (s.match(/doc/i) || s.match(/demo/i) || s.match(/../))) {\r
+ // yep, local.\r
+ tmp = Math.max(s.lastIndexOf('?'),-1);\r
+ tmp = Math.max(s.lastIndexOf('#'),tmp);\r
+ tmp = Math.max(s.lastIndexOf('/')+1,tmp);\r
+ // console.log(s+' '+s.lastIndexOf('?')+', '+s.lastIndexOf('#')+', '+s.lastIndexOf('/')+' = '+tmp);\r
+ if (tmp == -1) {\r
+ tmp = s.length;\r
+ }\r
+ if (!s.match(/\.html/i)) {\r
+ l[i].setAttribute('href',s.substr(0,tmp)+'index.html'+s.substr(tmp));\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+function ie6Sucks() {\r
+ // no :hover, generally-broken layout etc.\r
+ if (!navigator.userAgent.match(/msie 6/i)) {\r
+ return false; \r
+ }\r
+ var o = _id('nav').getElementsByTagName('li')[1];\r
+ var oA = o.getElementsByTagName('a')[0];\r
+ var oUL = o.getElementsByTagName('ul')[0];\r
+ oA.onclick = function() {\r
+ oUL.style.display = 'block';\r
+ setTimeout(function(){\r
+ document.onclick = function() {\r
+ oUL.style.display = 'none';\r
+ document.onclick = null;\r
+ }\r
+ },20);\r
+ return false;\r
+ }\r
+}\r
+\r
+function doVersion() {\r
+ var o = _id('version');\r
+ if (!o) {\r
+ return false;\r
+ }\r
+ o.innerHTML = soundManager.versionNumber;\r
+}\r
+\r
+function doChristmasLights() {\r
+ if (IS_CHRISTMAS) {\r
+ // homepage overrides\r
+ window.XLSF_URL_BASE = 'demo/christmas-lights/';\r
+ window.XLSF_LIGHT_CLASS = 'pico';\r
+ loadScript('demo/christmas-lights/christmaslights.js',function(){\r
+ if (typeof smashInit != 'undefined') {\r
+ setTimeout(function() {\r
+ smashInit()\r
+ },20);\r
+ }\r
+ });\r
+ }\r
+}\r
+\r
+// ---------- home JS ------------\r
+\r
+if (window.is_home) {\r
+\r
+ // by default, enable native audio (with all its potential caveats.)\r
+ soundManager.useHTML5Audio = true;\r
+\r
+ // URL overrides for demo/testing..\r
+ if (document.location.href.match(/sm2-usehtml5audio=1/i)) {\r
+ soundManager.useHTML5Audio = true; // w00t.\r
+ } else if (document.location.href.match(/sm2-usehtml5audio=0/i)) {\r
+ soundManager.useHTML5Audio = false;\r
+ }\r
+\r
+ soundManager.setup({\r
+ // HTML5 by default.\r
+ preferFlash: false,\r
+ useFlashBlock: true,\r
+ useHighPerformance: true,\r
+ bgColor: '#ffffff',\r
+ debugMode: false,\r
+ url: 'swf/',\r
+ // hide initial flash of white on everything except firefox, IE 8 and Safari on Windoze\r
+ wmode: 'transparent'\r
+ });\r
+\r
+ var PP_CONFIG = {\r
+ autoStart: false, // begin playing first sound when page loads\r
+ playNext: true, // stop after one sound, or play through list until end\r
+ useThrottling: false, // try to rate-limit potentially-expensive calls (eg. dragging position around)</span>\r
+ usePeakData: true, // [Flash 9 only] whether or not to show peak data (left/right channel values) - nor noticable on CPU\r
+ useWaveformData: false,// [Flash 9 only] show raw waveform data - WARNING: LIKELY VERY CPU-HEAVY\r
+ useEQData: false, // [Flash 9 only] show EQ (frequency spectrum) data\r
+ useFavIcon: false // try to apply peakData to address bar (Firefox + Opera) - performance note: appears to make Firefox 3 do some temporary, heavy disk access/swapping/garbage collection at first(?) - may be too heavy on CPU\r
+ }\r
+\r
+ threeSixtyPlayer.config = {\r
+\r
+ playNext: false,\r
+ autoPlay: false,\r
+ allowMultiple: true,\r
+ loadRingColor: '#ccc',\r
+ playRingColor: '#000',\r
+ backgroundRingColor: '#eee',\r
+ circleDiameter: 256,\r
+ circleRadius: 128,\r
+ scaleArcWidth: 1,\r
+ animDuration: 500,\r
+ animTransition: Animator.tx.bouncy,\r
+ showHMSTime: true,\r
+\r
+ useWaveformData: true,\r
+ waveformDataColor: '#0099ff',\r
+ waveformDataDownsample: 2,\r
+ waveformDataOutside: false,\r
+ waveformDataConstrain: false,\r
+ waveformDataLineRatio: 0.73,\r
+\r
+ useEQData: true,\r
+ eqDataColor: '#339933',\r
+ eqDataDownsample: 2,\r
+ eqDataOutside: true,\r
+ eqDataLineRatio: 0.69,\r
+\r
+ usePeakData: true,\r
+ peakDataColor: '#ff33ff',\r
+ peakDataOutside: true,\r
+ peakDataLineRatio: 0.5,\r
+\r
+ useAmplifier: true\r
+\r
+ }\r
+\r
+ if (navigator.platform.match(/win32/i) && navigator.userAgent.match(/firefox/i)) {\r
+ // extra-special homepage case (you should never see this), prevent out-of-view SWF load failure WITH high performance AND flashblock AND SWF in a placed element\r
+ soundManager.useHighPerformance = false;\r
+ }\r
+\r
+ function checkBadSafari() {\r
+ var _ua = navigator.userAgent;\r
+ if (!document.location.href.match(/sm2-usehtml5audio/i) && !window.location.toString().match(/sm2\-ignorebadua/i) && _ua.match(/safari/i) && !_ua.match(/chrome/i) && _ua.match(/OS X 10_6_([3-7])/i)) { // Safari 4 and 5 occasionally fail to load/play HTML5 audio on Snow Leopard due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Known Apple "radar" bug. https://bugs.webkit.org/show_bug.cgi?id=32159\r
+ var complaint = document.createElement('li');\r
+ complaint.innerHTML = '<b>Note</b>: Partial HTML5 in effect. Using Flash for MP3/MP4 formats (if available) for this browser/OS due to HTML5 audio load/play failures in Safari 4 + 5 on Snow Leopard 10.6.3 - 10.6.7 (purportedly fixed in OS X 10.6.8 and 10.7 "Lion.") Issue caused by bugs in QuickTime X and/or underlying frameworks. See <a href="https://bugs.webkit.org/show_bug.cgi?id=32159#c9">bugs.webkit.org #32519</a>. (Safari on iOS, Leopard and Windows OK, however.) <p style="margin:0.5em 0px 0.5em 0px">Try <a href="?sm2-ignorebadua&sm2-usehtml5audio=1">HTML5 anyway?</a> (some MP3 playback may intermittently fail.)';\r
+ _id('html5-audio-notes').appendChild(complaint);\r
+ }\r
+ }\r
+\r
+ soundManager.onready(function() {\r
+\r
+ _id('sm2-support').style.display = 'none';\r
+ _id('sm2-support-warning').style.display = 'none';\r
+\r
+ if (soundManager.didFlashBlock) {\r
+ soundManager.createSound({\r
+ id: 'success',\r
+ url: 'demo/_mp3/mouseover.mp3'\r
+ }).play();\r
+ }\r
+\r
+ doChristmasLights();\r
+\r
+ // 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\r
+\r
+ var _hasFlash;\r
+ var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = window.ActiveXObject;\r
+\r
+ if (nP && nP.length) {\r
+\r
+ type = 'application/x-shockwave-flash';\r
+ types = n.mimeTypes;\r
+\r
+ if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) {\r
+ hasPlugin = true;\r
+ }\r
+\r
+ } else if (typeof AX !== 'undefined') {\r
+\r
+ try {\r
+ obj = new AX('ShockwaveFlash.ShockwaveFlash');\r
+ } catch(e) {\r
+ // oh well\r
+ }\r
+ hasPlugin = (!!obj);\r
+\r
+ }\r
+\r
+ _hasFlash = hasPlugin;\r
+\r
+ // if using HTML5, show some additional format support info\r
+ // written while watching The Big Lebowski for the Nth time. Donny, you're out of your element!\r
+ var s = soundManager;\r
+\r
+ if (s.useHTML5Audio && s.hasHTML5) {\r
+ var liID = 'html5-support-li';\r
+ var oldLI = document.getElementById(liID);\r
+ if (oldLI) {\r
+ oldLI.parentNode.removeChild(oldLI);\r
+ }\r
+ // what lies. not an <li> at all. ;)\r
+ var li = document.createElement('div');\r
+ li.id = liID;\r
+ li.className = 'html5support';\r
+ var items = [];\r
+ var needsFlash = false;\r
+ for (item in s.audioFormats) {\r
+ if (s.audioFormats.hasOwnProperty(item)) {\r
+ needsFlash = (soundManager.filePattern.test('.' + item));\r
+ items.push('<span class="' + (s.html5[item] ? 'true' : 'false') + (!s.html5[item] && needsFlash ? ' partial' : '') + '" title="' + (s.html5[item] ? 'Native HTML5 support found' : 'No HTML5 support found' + (needsFlash ? ', using Flash fallback if present' : ', no Flash support either')) + '">' + (s.html5[item] ? '<' : '') + item + (s.html5[item] ? '>' : '') + '</span>');\r
+ }\r
+ }\r
+\r
+ li.innerHTML = [\r
+ '<b>This browser\'s <em class="true"><HTML5></em> vs. <em class="partial">Flash</em> support:<p style="margin:0.5em 0px 0.5em 0px"></b>',\r
+ items.join(''),\r
+ '<br />',\r
+ '<b class="note">',\r
+ (soundManager.html5.mp3 || soundManager.html5.mp4 ? (_hasFlash && soundManager.preferFlash ? 'Preferring flash for MP3/MP4; try <a href="?sm2-preferFlash=0" title="Try using soundManager.preferFlash=false to have HTML5 actually play MP3/MP4 formats and depending on support, run SM2 entirely without flash." class="cta">preferFlash=false</a> for HTML5-only mode.' : (soundManager.html5Only ? 'HTML5-only mode.' + (!soundManager.canPlayMIME('audio/aac') ? ' Try <a href="?sm2-preferFlash=1,flash9" title="Try using soundManager.preferFlash=true to have Flash play MP3/MP4 formats." class="cta">preferFlash=true</a> for MP4 support as needed.' : '') : ' Some flash required; allowing HTML5 to play MP3/MP4, as supported.' + '</p>')) : 'Flash is required for this browser to play MP3/MP4.'),\r
+ '</b>'\r
+ ].join('');\r
+ _id('html5-audio-notes').appendChild(li);\r
+ _id('without-html5').style.display = 'inline';\r
+\r
+ } else {\r
+\r
+ _id('without-html5').style.display = 'none';\r
+\r
+ }\r
+\r
+ checkBadSafari();\r
+\r
+ // check inline player / HTML 5 bits\r
+ var items = utils.getElementsByClassName('button-exclude', 'a', _id('inline-playlist')).concat(utils.getElementsByClassName('exclude', 'a', _id('graphic-playlist')));\r
+ for (var i = 0, j = items.length; i < j; i++) {\r
+ if (!soundManager.canPlayLink(items[i])) {\r
+ items[i].className += ' not-supported';\r
+ items[i].title += '. \n\nNOTE: '+(soundManager.useHTML5Audio?'Format apparently not supported under this configuration or browser.':'SoundManager 2\'s HTML5 feature is not currently enabled. (Try turning it on, see +html5 link.)');\r
+ }\r
+ }\r
+\r
+ });\r
+\r
+ soundManager.ontimeout(function() {\r
+\r
+ // failed to load\r
+\r
+ if (navigator.userAgent.match(/msie 6/i)) {\r
+ // we don't care.\r
+ return false;\r
+ }\r
+\r
+ var o = _id('sm2-support');\r
+ var o2 = _id('sm2-support-warning');\r
+ var smLoadFailWarning = '<div style="margin:0.5em;margin-top:-0.25em"><h3>Oh snap!</h3><p>' + (soundManager.hasHTML5 ? 'The flash portion of ' : '') + 'SoundManager 2 was unable to start. ' + (soundManager.useHTML5Audio ? (soundManager.hasHTML5 ? '</p><p>Some HTML5 audio support is present, but flash is needed for MP3/MP4 support on this page.' : '</p><p>No HTML5 support was found, so flash is required.') : '' ) + '</p><p>All links to audio will degrade gracefully.</p><p id="flashblocker">If you have a flash blocker, try allowing the SWF to run - it may be visible below.</p><p id="flash-offline">' + (soundManager.useAltURL ? '<b>Viewing offline</b>? You may need to change a Flash security setting.' : 'Other possible causes: Missing .SWF, or no Flash?') + ' Not to worry, as guided help is provided.</p><p><a href="doc/getstarted/index.html#troubleshooting" class="feature-hot" style="display:inline-block;margin-left:0px">Troubleshooting</a></p></div>';\r
+ var hatesFlash = (navigator.userAgent.match(/(ipad|iphone|ipod)/i));\r
+\r
+ if (soundManager.html5.mp3 && soundManager.html5.mp4) {\r
+ // flash portion was blocked, but support exists. We'll "downgrade" to HTML5-only.\r
+ soundManager._wD('Special homepage case: Flash appears to blocked, HTML5 support for MP3/MP4 exists; trying HTML5-only mode...');\r
+ soundManager.useHTML5Audio = true;\r
+ soundManager.preferFlash = false;\r
+ setTimeout(function() {\r
+ soundManager.reboot();\r
+ soundManager.onready(function() {\r
+ // for when things start up in HTML5-only mode...\r
+ o.innerHTML = '<div style="margin:0.5em;margin-top:-0.25em"><h3>Support note</h3><p>SoundManager 2 tried to start using HTML5 + Flash, but rebooted in HTML5-only mode as flash was blocked. Visualization demo features will not be shown in this mode. To enable flash, whitelist the blocked movie and reload this page.</p>'+(soundManager.useAltURL?'<p><b>Running offline?</b> Flash may be blocked due to security restrictions; see <a href="doc/getstarted/index.html#troubleshooting">troubleshooting</a> for more.':'')+'</div>';\r
+ o.style.marginBottom = '1.5em';\r
+ o.style.display = 'block';\r
+ });\r
+ }, 1);\r
+ return false;\r
+ }\r
+\r
+ o.innerHTML = smLoadFailWarning;\r
+ o2.innerHTML = '<p style="margin:0px">SoundManager 2 could not start. <a href="#sm2-support">See below</a> for details.</p>';\r
+ if (hatesFlash || soundManager.getMoviePercent()) {\r
+ // movie loaded at least somewhat, so don't show flashblock things\r
+ _id('flashblocker').style.display = 'none';\r
+ if (hatesFlash) {\r
+ // none of that here.\r
+ _id('flash-offline').style.display = 'none';\r
+ }\r
+ }\r
+ o.style.marginBottom = '1.5em';\r
+ o.style.display = 'block';\r
+ o2.style.display = 'inline-block';\r
+ });\r
+\r
+}\r
+\r
+// side note: If it's not december but you want to smash things, try #christmas=1 in the homepage URL.\r
+\r
+// --------- /home JS ------------\r
+\r
+function startStuff() {\r
+ if (navigator.userAgent.match(/safari/i)) {\r
+ document.getElementsByTagName('html')[0].className = 'isSafari';\r
+ }\r
+ doVersion();\r
+ ie6Sucks();\r
+ fixLinks();\r
+ getLiveData();\r
+ doAltShortcuts();\r
+ soundManager.onready(function() {\r
+ if (window.turntables) {\r
+ // require this for links to play on the turntable UI demo.\r
+ turntables.config.requireCSS = 'turntable-include';\r
+ }\r
+ });\r
+}\r
+\r
+if (document.addEventListener) {\r
+ document.addEventListener("DOMContentLoaded", startStuff, false);\r
+} else {\r
+ window.onload = startStuff;\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2 Demo: Basic MP3 Play Button (Simple Demo)</title>
+<meta name="robots" content="noindex" />\r
+<style type="text/css">\r
+\r
+/* \r
+\r
+ -------------------------------------------------------------\r
+\r
+ In-page demo CSS - see external CSS for actual relevant stuff.\r
+\r
+ --------------------------------------------------------------\r
+\r
+ */\r
+\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, makes debug more useable) */\r
+ position:absolute;position:fixed;*position:absolute;bottom:10px;right:10px;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);\r
+}\r
+\r
+body {\r
+ font:75% normal verdana,arial,tahoma,"sans serif";\r
+}\r
+\r
+</style>\r
+<link rel="stylesheet" type="text/css" href="css/mp3-player-button.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/mp3-player-button.js"></script>\r
+<script>\r
+soundManager.setup({\r
+ // required: path to directory containing SM2 SWF files\r
+ url: '../../swf/'\r
+});\r
+</script>\r
+\r
+</head>\r
+\r
+<body>\r
+\r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Play MP3s inline with javascript using SoundManager 2">SoundManager 2</a> / Basic MP3 Play Button: Template</h1>\r
+\r
+ <p>View the source code of this page for detail. Don't forget to set <b>debugMode: false</b> to disable debug output.</p>\r
+\r
+ <p><a href="../_mp3/walking.mp3" class="sm2_button">Walking</a> Walking</p>\r
+\r
+ <p><a href="http://www.freshly-ground.com/misc/music/20060826%20-%20Armstrong.mp3" class="sm2_button">Armstrong Beat</a> Armstrong Beat</p>\r
+\r
+ <p><a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 project page">SoundManager 2 project home</a></p>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+/*
+
+ SoundManager 2: Basic MP3 player CSS
+ ------------------------------------
+
+ Clicks on links to MP3s are intercepted via JS, calls are
+ made to SoundManager to load/play sounds. CSS classes are
+ appended to the link, which are used to highlight the
+ current play state and so on.
+
+ Class names are applied in addition to "sm2_button" base.
+
+ Default:
+
+ sm2_button
+
+ Additional states:
+
+ sm2_playing
+ sm2_paused
+
+ eg.
+
+ <!-- default -->
+ <a href="some.mp3" class="sm2_button">some.mp3</a>
+
+ <!-- playing -->
+ <a href="some.mp3" class="sm2_button sm2_playing">some.mp3</a>
+
+
+ Note you don't require ul.graphic / ul.flat etc. for your use
+ if only using one style on a page. You can just use .sm2_button{}
+ and so on, but isolate the CSS you want.
+
+ Side note: Would do multiple class definitions eg.
+
+ a.sm2_default.sm2_playing{}
+
+ .. except IE 6 has a parsing bug which may break behaviour,
+ applying sm2_playing {} even when the class is set to sm2_default.
+
+
+ If you want to make your own UI from scratch, here is the base:
+
+ Default + hover state, "click to play":
+
+ a.sm2_button {}
+ a.sm2_button:hover {}
+
+ Playing + hover state, "click to pause":
+
+ a.sm2_playing {}
+ a.sm2_playing:hover {}
+
+ Paused + hover state, "click to resume":
+
+ a.sm2_paused {}
+ a.sm2_paused:hover {}
+
+*/
+
+a.sm2_button {
+ position:relative;
+ display:inline-block; /* If you worry about old browser bugs, Firefox 2 might not like this and may need -moz-inline-box instead. :D */
+ width:18px;
+ height:18px;
+ text-indent:-9999px; /* don't show link text */
+ overflow:hidden; /* don't draw inner link text */
+ vertical-align:middle;
+ /* and, a bit of round-ness for the cool browsers. */
+ border-radius:2px;
+ margin-top:-1px; /* vertical align tweak */
+ /* safari 3.1+ fun (/W3 working draft extension, TBD.) */
+ -webkit-transition-property: hover;
+ -webkit-transition: all 0.2s ease-in-out;
+ -moz-transition: all 0.2s ease-in-out 0s; /* firefox 4 (couldn't sort out -moz-transform vs. MozTransform, so, "all" for now) */
+ -o-transition-property: background-color; /* opera 10.5 */
+ -o-transition-duration: 0.15s;
+ /* weird IE 6/7 display fixes, and/or I'm doing it wrong */
+ *text-indent:0px;
+ *line-height:99em;
+ *vertical-align: top;
+}
+
+a.sm2_button:focus {
+ outline:none; /* maybe evil, but don't show the slight border outline on focus. */
+}
+
+a.sm2_button,
+a.sm2_button.sm2_paused:hover {
+ background-color:#3399cc;
+ background-image:url(../image/arrow-right-white.png);
+ /* where possible, use data: and skip the HTTP request. Fancy-pants. Would use short-hand background: for above, but IE 8 doesn't override background-image. */
+ background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAKCAYAAABmBXS+AAAAbklEQVQY02NgQAL//v1jZMAF/v//vwuIs9HEUBUBTbj4HwIeA3EGVsVAxtn/qOAVUGM8uknIiv4hsV8A5ZKxKfoLVvnvHwifAzLtMKwDSQLBVSBti27dJajkcSD2RJODO3wtkOOMz/tMSJJYAxMA5dmsL0IfubQAAAAASUVORK5CYII=);
+ background-image: none, url(../image/arrow-right-white-2x.png);
+ background-size: 9px 10px;
+ *background-image:url(../image/arrow-right-white.gif); /* IE 6+7 don't do DATA: URIs */
+ background-repeat:no-repeat;
+ background-position:5px 50%;
+ *background-position:5px 4px; /* IE 6 again */
+}
+
+a.sm2_button:hover,
+a.sm2_button.sm2_playing,
+a.sm2_button.sm2_playing:hover {
+ background-color:#cc3333;
+}
+
+a.sm2_button.sm2_playing,
+a.sm2_button.sm2_playing:hover {
+ -moz-transform:rotate(90deg);
+ -webkit-transform:rotate(90deg);
+ -ms-transform:rotate(90deg);
+}
+
+a.sm2_button.sm2_paused,
+a.sm2_button.sm2_paused:hover {
+ background-color:#666;
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2 Demo: Basic MP3 Play Button</title>
+<meta name="robots" content="noindex" />\r
+<style type="text/css">\r
+\r
+/* \r
+\r
+ -------------------------------------------------------------\r
+\r
+ In-page demo CSS - see external CSS for actual relevant stuff.\r
+\r
+ --------------------------------------------------------------\r
+\r
+ */\r
+\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, makes debug more useable) */\r
+ position:absolute;position:fixed;*position:absolute;bottom:10px;right:10px;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);\r
+}\r
+\r
+body {\r
+ font:75% normal verdana,arial,tahoma,"sans serif";\r
+}\r
+\r
+h1, h2, h3 {\r
+ font:2.5em arial,tahoma,verdana;\r
+ font-weight:normal;\r
+ margin-bottom:0px;\r
+}\r
+\r
+h1, h2 {\r
+ letter-spacing:-1px; /* zomg web x.0! ;) */ \r
+ margin-top:0.5em;\r
+}\r
+\r
+h2, h3 {\r
+ color:#333;\r
+}\r
+\r
+h2 {\r
+ font-size:2em;\r
+}\r
+\r
+h3 {\r
+ font-size:1.5em;\r
+}\r
+\r
+h1 a,\r
+h1 a:hover {\r
+ color:#000;\r
+ text-decoration:none;\r
+}\r
+\r
+h1 a:hover {\r
+ text-decoration:underline;\r
+}\r
+\r
+ul li {\r
+ margin-bottom:0.5em;\r
+}\r
+\r
+ul.notes {\r
+ margin-left:0px;\r
+ padding-left:1.5em;\r
+}\r
+\r
+.note {\r
+ margin-top:0px;\r
+ font-style:italic;\r
+ color:#666;\r
+}\r
+\r
+pre {\r
+ font-weight:bold;\r
+ font-size:1.2em;\r
+ _font-size:1em;\r
+}\r
+\r
+pre code {\r
+ color:#228822;\r
+}\r
+\r
+#left {\r
+ max-width:56em;\r
+}\r
+\r
+</style>\r
+<link rel="stylesheet" type="text/css" href="css/mp3-player-button.css" />\r
+<!-- soundManager.useFlashBlock: related CSS -->\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/mp3-player-button.js"></script>\r
+<script>\r
+soundManager.setup({\r
+ useFlashBlock: true, // optional - if used, required flashblock.css\r
+ url: '../../swf/' // required: path to directory containing SM2 SWF files\r
+});\r
+</script>\r
+\r
+</head>\r
+\r
+<body>\r
+\r
+<div id="left">\r
+ \r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Play MP3s inline with javascript using SoundManager 2">SoundManager 2</a> / Inline MP3 Player Button</h1>\r
+\r
+ <h2 style="display:inline">Basic MP3 Play Button Examples</h2> (also see <a title="MP3 Play Button, Basic Example demo" href="basic.html">basic demo</a>.)\r
+\r
+ <hr />\r
+\r
+ <div id="sm2-container">\r
+ <!-- flash movie ends up here -->\r
+ </div>\r
+\r
+ <h3>Inline text, with "play" button</h3>\r
+\r
+ <p>Example code (link with a <b>sm2_button</b> CSS class):</p>\r
+<pre><p> <code><a href="/path/to/coins.mp3" title="Play &quot;coins&quot;" class="sm2_button">coins.mp3</a></code> Spare change</p></pre>\r
+ <p>Renders as:</p>\r
+<div>\r
+ <p><a href="../../demo/_mp3/coins.mp3" class="sm2_button" title="Play "coins"">coins.mp3</a> Spare change</p>\r
+ <p class="note">Note that the text inside the link is hidden and replaced with an image, but should be descriptive - or at least should say something generic, like "play".</p>\r
+</div>\r
+ <h3>Basic MP3 play button, no text</h3>\r
+\r
+ <p>Code:</p>\r
+\r
+ <pre><code><a href="../_mp3/office_lobby.mp3" title="Play &quot;Office Lobby&quot;" class="sm2_button">Office Lobby</a></code></pre>\r
+\r
+ <p>Renders as:</p>\r
+ <p>\r
+ <a href="../_mp3/office_lobby.mp3" title="Play "Office Lobby"" class="sm2_button">Office Lobby</a>\r
+ </p>\r
+ <h2>How It Works</h2>\r
+\r
+ <p><a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 Javascript Sound API">SoundManager 2</a> intercepts clicks to MP3 links and plays them inline. The script assigns additional CSS classes to the links to indicate their state (playing/paused, etc.)</p>\r
+\r
+ <h3>Static Examples</h3>\r
+\r
+ <p>CSS classes are dynamically applied as follows:</p>\r
+\r
+ <ul>\r
+ <li><a href="#" class="sm2_button" title=""Click to play" state">Default: class="sm2_button"</a> Default: class="sm2_button"</li>\r
+ <li><a href="#" class="sm2_button sm2_playing" title=""Click to pause" state">Playing: class="sm2_button sm2_playing"</a> Playing: class="sm2_button sm2_playing"</li>\r
+ <li><a href="#" class="sm2_button sm2_paused" title=""Click to resume" state">Paused: class="sm2_button sm2_paused"</a> Paused: class="sm2_button sm2_paused"</li>\r
+ </ul>\r
+\r
+ <h3>Basic CSS</h3>\r
+\r
+ <p>If you want to make your own UI from scratch, here is the base:</p>\r
+\r
+<pre>\r
+ Default + hover state, "click to play":\r
+<code>\r
+ a.sm2_button {}\r
+ a.sm2_button:hover {}\r
+</code>\r
+ Playing + hover state, "click to pause":\r
+<code>\r
+ a.sm2_button.sm2_playing {}\r
+ a.sm2_button.sm2_playing:hover {}\r
+</code>\r
+ Paused + hover state, "click to resume":\r
+<code>\r
+ a.sm2_button.sm2_paused {}\r
+ a.sm2_button.sm2_paused:hover {}\r
+</code></pre>\r
+\r
+ <h3>Other Options</h3>\r
+ \r
+ <p>By default, one sound will be played at a time; you can easily change a "config" object value to turn on playlist-like behaviour (i.e., play the next MP3 when the current one finishes.)</p>\r
+ \r
+<pre>\r
+<code>\r
+// (within mp3-player-button.js)\r
+this.config = {\r
+ playNext: false // stop after one sound, or play through list until end\r
+}\r
+</code></pre>\r
+\r
+ <h3>I'd like to use this.</h3>\r
+ <p>See this <a href="basic.html" title="basic template: inline mp3 player">basic demo</a> for reference.</p>\r
+\r
+ <p>\r
+ <a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)\r
+ </p>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+/**\r
+ * SoundManager 2 Demo: Play MP3 links via button\r
+ * ----------------------------------------------\r
+ *\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * A simple demo making MP3s playable "inline"\r
+ * and easily styled/customizable via CSS.\r
+ *\r
+ * A variation of the "play mp3 links" demo.\r
+ *\r
+ * Requires SoundManager 2 Javascript API.\r
+ */\r
+\r
+/*jslint white: false, onevar: true, undef: true, nomen: false, eqeqeq: true, plusplus: false, bitwise: true, regexp: false, newcap: true, immed: true */\r
+/*global document, window, soundManager, navigator */\r
+\r
+function BasicMP3Player() {\r
+ var self = this,\r
+ pl = this,\r
+ sm = soundManager, // soundManager instance\r
+ isTouchDevice = (navigator.userAgent.match(/ipad|iphone/i)),\r
+ isIE = (navigator.userAgent.match(/msie/i));\r
+ this.excludeClass = 'button-exclude'; // CSS class for ignoring MP3 links\r
+ this.links = [];\r
+ this.sounds = [];\r
+ this.soundsByURL = {};\r
+ this.indexByURL = {};\r
+ this.lastSound = null;\r
+ this.soundCount = 0;\r
+\r
+ this.config = {\r
+ // configuration options\r
+ playNext: false, // stop after one sound, or play through list until end\r
+ autoPlay: false // start playing the first sound right away\r
+ };\r
+\r
+ this.css = {\r
+ // CSS class names appended to link during various states\r
+ sDefault: 'sm2_button', // default state\r
+ sLoading: 'sm2_loading',\r
+ sPlaying: 'sm2_playing',\r
+ sPaused: 'sm2_paused'\r
+ };\r
+\r
+ // event + DOM utils\r
+\r
+ this.includeClass = this.css.sDefault;\r
+\r
+ this.addEventHandler = (typeof window.addEventListener !== 'undefined' ? function(o, evtName, evtHandler) {\r
+ return o.addEventListener(evtName,evtHandler,false);\r
+ } : function(o, evtName, evtHandler) {\r
+ o.attachEvent('on'+evtName,evtHandler);\r
+ });\r
+\r
+ this.removeEventHandler = (typeof window.removeEventListener !== 'undefined' ? function(o, evtName, evtHandler) {\r
+ return o.removeEventListener(evtName,evtHandler,false);\r
+ } : function(o, evtName, evtHandler) {\r
+ return o.detachEvent('on'+evtName,evtHandler);\r
+ });\r
+\r
+ this.classContains = function(o,cStr) {\r
+ return (typeof(o.className)!=='undefined'?o.className.match(new RegExp('(\\s|^)'+cStr+'(\\s|$)')):false);\r
+ };\r
+\r
+ this.addClass = function(o,cStr) {\r
+ if (!o || !cStr || self.classContains(o,cStr)) {\r
+ return false;\r
+ }\r
+ o.className = (o.className?o.className+' ':'')+cStr;\r
+ };\r
+\r
+ this.removeClass = function(o,cStr) {\r
+ if (!o || !cStr || !self.classContains(o,cStr)) {\r
+ return false;\r
+ }\r
+ o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');\r
+ };\r
+\r
+ this.getSoundByURL = function(sURL) {\r
+ return (typeof self.soundsByURL[sURL] !== 'undefined' ? self.soundsByURL[sURL] : null);\r
+ };\r
+\r
+ this.isChildOfNode = function(o,sNodeName) {\r
+ if (!o || !o.parentNode) {\r
+ return false;\r
+ }\r
+ sNodeName = sNodeName.toLowerCase();\r
+ do {\r
+ o = o.parentNode;\r
+ } while (o && o.parentNode && o.nodeName.toLowerCase() !== sNodeName);\r
+ return (o.nodeName.toLowerCase() === sNodeName ? o : null);\r
+ };\r
+\r
+ this.events = {\r
+\r
+ // handlers for sound events as they're started/stopped/played\r
+\r
+ play: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = pl.css.sPlaying;\r
+ pl.addClass(this._data.oLink,this._data.className);\r
+ },\r
+\r
+ stop: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = '';\r
+ },\r
+\r
+ pause: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = pl.css.sPaused;\r
+ pl.addClass(this._data.oLink,this._data.className);\r
+ },\r
+\r
+ resume: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = pl.css.sPlaying;\r
+ pl.addClass(this._data.oLink,this._data.className); \r
+ },\r
+\r
+ finish: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = '';\r
+ if (pl.config.playNext) {\r
+ var nextLink = (pl.indexByURL[this._data.oLink.href]+1);\r
+ if (nextLink<pl.links.length) {\r
+ pl.handleClick({'target':pl.links[nextLink]});\r
+ }\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ this.stopEvent = function(e) {\r
+ if (typeof e !== 'undefined' && typeof e.preventDefault !== 'undefined') {\r
+ e.preventDefault();\r
+ } else if (typeof window.event !== 'undefined') {\r
+ window.event.returnValue = false;\r
+ }\r
+ return false;\r
+ };\r
+\r
+ this.getTheDamnLink = (isIE) ? function(e) {\r
+ // I really didn't want to have to do this.\r
+ return (e && e.target ? e.target : window.event.srcElement);\r
+ } : function(e) {\r
+ return e.target;\r
+ };\r
+\r
+ this.handleClick = function(e) {\r
+ // a sound link was clicked\r
+ if (typeof e.button !== 'undefined' && e.button>1) {\r
+ // ignore right-click\r
+ return true;\r
+ }\r
+ var o = self.getTheDamnLink(e),\r
+ sURL,\r
+ soundURL,\r
+ thisSound;\r
+ if (o.nodeName.toLowerCase() !== 'a') {\r
+ o = self.isChildOfNode(o,'a');\r
+ if (!o) {\r
+ return true;\r
+ }\r
+ }\r
+ sURL = o.getAttribute('href');\r
+ if (!o.href || !soundManager.canPlayLink(o) || self.classContains(o,self.excludeClass)) {\r
+ return true; // pass-thru for non-MP3/non-links\r
+ }\r
+ if (!self.classContains(o,self.includeClass)) {\r
+ return true;\r
+ }\r
+ sm._writeDebug('handleClick()');\r
+ soundURL = (o.href);\r
+ thisSound = self.getSoundByURL(soundURL);\r
+ if (thisSound) {\r
+ // already exists\r
+ if (thisSound === self.lastSound) {\r
+ // and was playing (or paused)\r
+ thisSound.togglePause();\r
+ } else {\r
+ // different sound\r
+ thisSound.togglePause(); // start playing current\r
+ sm._writeDebug('sound different than last sound: '+self.lastSound.id);\r
+ if (self.lastSound) {\r
+ self.stopSound(self.lastSound);\r
+ }\r
+ }\r
+ } else {\r
+ // create sound\r
+ thisSound = sm.createSound({\r
+ id:'basicMP3Sound'+(self.soundCount++),\r
+ url:soundURL,\r
+ onplay:self.events.play,\r
+ onstop:self.events.stop,\r
+ onpause:self.events.pause,\r
+ onresume:self.events.resume,\r
+ onfinish:self.events.finish,\r
+ type:(o.type||null)\r
+ });\r
+ // tack on some custom data\r
+ thisSound._data = {\r
+ oLink: o, // DOM node for reference within SM2 object event handlers\r
+ className: self.css.sPlaying\r
+ };\r
+ self.soundsByURL[soundURL] = thisSound;\r
+ self.sounds.push(thisSound);\r
+ if (self.lastSound) {\r
+ // stop last sound\r
+ self.stopSound(self.lastSound);\r
+ }\r
+ thisSound.play();\r
+ }\r
+ self.lastSound = thisSound; // reference for next call\r
+ return self.stopEvent(e);\r
+ };\r
+\r
+ this.stopSound = function(oSound) {\r
+ soundManager.stop(oSound.id);\r
+ if (!isTouchDevice) { // iOS 4.2+ security blocks onfinish() -> playNext() if we set a .src in-between(?)\r
+ soundManager.unload(oSound.id);\r
+ }\r
+ };\r
+\r
+ this.init = function() {\r
+ sm._writeDebug('basicMP3Player.init()');\r
+ var i, j,\r
+ foundItems = 0,\r
+ oLinks = document.getElementsByTagName('a');\r
+ // grab all links, look for .mp3\r
+ for (i=0, j=oLinks.length; i<j; i++) {\r
+ if (self.classContains(oLinks[i],self.css.sDefault) && !self.classContains(oLinks[i],self.excludeClass)) {\r
+ // self.addClass(oLinks[i],self.css.sDefault); // add default CSS decoration - good if you're lazy and want ALL MP3/playable links to do this\r
+ self.links[foundItems] = (oLinks[i]);\r
+ self.indexByURL[oLinks[i].href] = foundItems; // hack for indexing\r
+ foundItems++;\r
+ }\r
+ }\r
+ if (foundItems>0) {\r
+ self.addEventHandler(document,'click',self.handleClick);\r
+ if (self.config.autoPlay) {\r
+ self.handleClick({target:self.links[0],preventDefault:function(){}});\r
+ }\r
+ }\r
+ sm._writeDebug('basicMP3Player.init(): Found '+foundItems+' relevant items.');\r
+ };\r
+\r
+ this.init();\r
+\r
+}\r
+\r
+var basicMP3Player = null;\r
+\r
+soundManager.setup({\r
+ preferFlash: false,\r
+ onready: function() {\r
+ basicMP3Player = new BasicMP3Player();\r
+ }\r
+});
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+\r
+<!--\r
+ Acoustic drumkit example sounds\r
+ Source credit: http://www.akaipro.com/arc_kotw.html\r
+-->\r
+\r
+<!-- SoundManager Flash configuration -->\r
+<!-- Sound IDs are referenced from JS -->\r
+\r
+<items baseHref="audio/"> <!-- baseHref is optional, but note the trailing slash if used. -->\r
+\r
+ <sound id="s0" href="AMB_BD_1.mp3" />\r
+ <sound id="s1" href="AMB_FTM2.mp3" />\r
+ <sound id="s2" href="AMB_HHCL.mp3" />\r
+ <sound id="s3" href="AMB_HHOP.mp3" />\r
+ <sound id="s4" href="AMB_HHPD.mp3" />\r
+ <sound id="s5" href="AMB_HTM.mp3" />\r
+ <sound id="s6" href="AMB_LTM2.mp3" />\r
+ <sound id="s7" href="AMB_MTM.mp3" />\r
+ <sound id="s8" href="AMB_RIM1.mp3" />\r
+ <sound id="s9" href="AMB_SN13.mp3" />\r
+ <sound id="s10" href="AMB_SN_5.mp3" />\r
+ <sound id="s11" href="CHINA_1.mp3" />\r
+ <sound id="s12" href="CRASH_1.mp3" />\r
+ <sound id="s13" href="CRASH_5.mp3" />\r
+ <sound id="s14" href="CRASH_6.mp3" />\r
+ <sound id="s15" href="RIDE_1.mp3" />\r
+<!--\r
+ <sound id="s16" href="RIDE_3.mp3" />\r
+ <sound id="s17" href="SPLASH_1.mp3" />\r
+-->\r
+</items>
\ No newline at end of file
--- /dev/null
+/* Demo/example CSS - not needed for general use */\r
+\r
+body {\r
+ background:#000;\r
+ font:normal 75% "helvetica neue",helvetica,verdana,arial,tahoma,"times new roman","sans serif";\r
+ color:#fff;\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+#background {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:100%;\r
+ height:100%;\r
+ background:transparent url(http://farm1.static.flickr.com/45/191496680_97cdc5351b_b.jpg) no-repeat 50% 50%;\r
+}\r
+\r
+#site {\r
+ position:relative;\r
+ z-index:2;\r
+ background:rgba(0,0,0,0.5);\r
+ padding:1em;\r
+}\r
+\r
+#site h1 {\r
+ margin-top:0px;\r
+}\r
+\r
+#site p {\r
+ margin:0.5em 0px 0.5em 0px;\r
+}\r
+\r
+#site p:last-child {\r
+ margin:0px;\r
+}\r
+\r
+.clear {\r
+ float:none;\r
+ clear:both;\r
+ font-size:1px;\r
+ line-height:1px;\r
+ height:1px;\r
+ overflow:hidden;\r
+}\r
+\r
+#mpc {\r
+ position:absolute;\r
+ left:50%;\r
+ top:50%;\r
+ margin-left:-19em;\r
+ margin-top:-19em;\r
+ width:38em;\r
+ _width:37.3em;\r
+ border:3px solid #666;\r
+ border:3px solid rgba(255,255,255,0.25);\r
+ border-radius:12px;\r
+ z-index:2;\r
+}\r
+\r
+#mpc #wrapper {\r
+ position:relative;\r
+ background:#333;\r
+ background:rgba(0,0,0,0.5);\r
+ padding:0.5em;\r
+ border-radius:12px;\r
+}\r
+\r
+#mpc ul {\r
+ margin:0px;\r
+ padding:0px;\r
+ margin-left:2px;\r
+ *margin-left:1em;\r
+ _margin-left:2px;\r
+ padding:2px 0px 2px 0px;\r
+}\r
+\r
+#mpc ul li {\r
+ position:relative;\r
+ float:left;\r
+ display:inline;\r
+ width:7em;\r
+ height:7em;\r
+ margin:0.5em;\r
+ background:#999;\r
+ border:1px solid rgba(0,0,0,0.75);\r
+ border-radius:2px;\r
+ font:normal 1em/1em "helvetica",verdana,arial,system;\r
+ padding:0.5em;\r
+ cursor:pointer;\r
+ cursor:hand;\r
+ color:#eee;\r
+ text-transform:uppercase;\r
+ font-weight:bold;\r
+}\r
+\r
+#mpc ul li span {\r
+ text-transform:none;\r
+ font-weight:normal;\r
+ color:#ccc;\r
+}\r
+\r
+#mpc ul li.active {\r
+ background:#666;\r
+}\r
+\r
+#mpc ul li div {\r
+ /* progress indicator */\r
+ position:absolute;\r
+ left:0px;\r
+ bottom:1em;\r
+ font-size:1em;\r
+ line-height:1em;\r
+ height:1em;\r
+ margin:0px 0px 0px 1em;\r
+ width:6em;\r
+ background:#888 url(../image/progress.png) no-repeat -256px 0px;\r
+ background-repeat:no-repeat;\r
+ border:1px solid #666;\r
+ visibility:hidden;\r
+}\r
+\r
+#mpc ul li.active div,\r
+#mpc ul li.loading div {\r
+ visibility:visible;\r
+}\r
+\r
+#soundmanager-debug {\r
+ position:absolute;\r
+ right:20px;\r
+ bottom:20px;\r
+ height:12em;\r
+ width:50em;\r
+ overflow:auto;\r
+ margin-left:1em;\r
+}\r
+\r
+#soundmanager-debug div {\r
+ font-size:11px;\r
+ font-family: "lucida console",system,verdana,arial; /* IE doesn't seem to obey short-hand font family here? */\r
+ padding:0px 1em 0.5em 0px;\r
+}\r
+\r
+#mpc-debug,\r
+.note {\r
+ color:#999;\r
+}\r
+\r
+#mpc-debug a,\r
+.note a {\r
+ color:#6699cc;\r
+ text-decoration:none;\r
+}\r
+\r
+#isHTML5 {\r
+ display:none;\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: A Javascript Sound API - MPC Demo</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="An example drum machine (MPC) demo using the SoundManager 2 JavaScript Audio API" />\r
+<meta name="keywords" content="javascript mpc, javascript drum machine, javascript sound, javascript audio, DHTML sound, work by Scott Schiller, schillmania, javascript to flash communication" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />\r
+<link rel="stylesheet" href="css/mpc.css" media="screen" />\r
+<!-- soundManager.useFlashBlock: related CSS -->\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/mpc.js"></script>\r
+</head>\r
+<body>\r
+\r
+<div id="background"></div>\r
+\r
+<div id="site">\r
+\r
+ <h1 style="margin-bottom:0px"><a href="../" style="color:#99ccff;text-decoration:none">SoundManager 2</a>: Javascript Drum Machine Demo<span id="isHTML5"></span></h1>\r
+ <h2 style="margin-top:0px;color:#999">Trigger the pads to play different sounds.</h2>\r
+ <p id="mpc-debug" class="note">View <a href="#debug=1" onclick="window.location.hash='debug=1';window.location.reload()">with debug output</a></p>\r
+ <p class="note">Photo: <a href="http://www.flickr.com/photos/schill/191496680/">MPC 2500</a> by .schill on Flickr</a></p>\r
+ <p class="note"><span style="display:none">(If supported): </span><span id="isHTML5">Your browser is cool and is using 100% HTML5 Audio. Look ma, no Flash!</span></p>\r
+</div>\r
+\r
+<div id="mpc">\r
+\r
+ <div id="wrapper">\r
+\r
+ <ul>\r
+ <li id="btn-s0" onmousedown="soundManager.play('s0')">1<div></div></li>\r
+ <li id="btn-s1" onmousedown="soundManager.play('s1')">2<div></div></li>\r
+ <li id="btn-s2" onmousedown="soundManager.play('s2')">3<div></div></li>\r
+ <li id="btn-s3" onmousedown="soundManager.play('s3')">4<div></div></li>\r
+ </ul>\r
+\r
+ <ul>\r
+ <li id="btn-s4" onmousedown="soundManager.play('s4')">q<div></div></li>\r
+ <li id="btn-s5" onmousedown="soundManager.play('s5')">w<div></div></li>\r
+ <li id="btn-s6" onmousedown="soundManager.play('s6')">e<div></div></li>\r
+ <li id="btn-s7" onmousedown="soundManager.play('s7')">r<div></div></li>\r
+ </ul>\r
+\r
+ <ul>\r
+ <li id="btn-s8" onmousedown="soundManager.play('s8')">a<div></div></li>\r
+ <li id="btn-s9" onmousedown="soundManager.play('s9')">s<div></div></li>\r
+ <li id="btn-s10" onmousedown="soundManager.play('s10')">d<div></div></li>\r
+ <li id="btn-s11" onmousedown="soundManager.play('s11')">f<div></div></li>\r
+ </ul>\r
+\r
+ <ul>\r
+ <li id="btn-s12" onmousedown="soundManager.play('s12')">z<div></div></li>\r
+ <li id="btn-s13" onmousedown="soundManager.play('s13')">x<div></div></li>\r
+ <li id="btn-s14" onmousedown="soundManager.play('s14')">c<div></div></li>\r
+ <li id="btn-s15" onmousedown="soundManager.play('s15')">v<div></div></li>\r
+ </ul>\r
+\r
+ <div class="clear"></div>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+ <script type="text/javascript">if (window.location.href.toString().match(/debug/i)) { document.getElementById('mpc-debug').style.display = 'none'; }</script>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>
--- /dev/null
+/**\r
+ * SoundManager 2: MPC (Drum Machine) demo\r
+ */\r
+\r
+var MPC = function() {\r
+ var self = this;\r
+ this.idPrefix = 'btn-'; // HTML ID prefix\r
+ this.statusWidth = 6;\r
+ this.progressWidth = 256;\r
+ this.keys = {'1':0,'2':1,'3':2,'4':3,'q':4,'w':5,'e':6,'r':7,'a':8,'s':9,'d':10,'f':11,'z':12,'x':13,'c':14,'v':15}\r
+\r
+ // scope within these event handler methods: "this" = SMSound() object instance (see SMSound() in soundmanager.js for reference) \r
+\r
+ this.showProgress = function() {\r
+ // sound is loading, update bytes received using this.bytesLoaded / this.bytesTotal\r
+ if (self._getButton(this.id).className != 'loading') self._getButton(this.id).className = 'loading'; // a bit inefficient here..\r
+ self._showStatus(this.id,this.bytesLoaded,this.bytesTotal);\r
+ }\r
+\r
+ this.onload = function() {\r
+ var sID = this.id;\r
+ self._getButton(this.id).className = '';\r
+ self._getButton(this.id).title = ('Sound ID: '+this.id+' ('+this.url+')');\r
+ }\r
+\r
+ this.onfinish = function() {\r
+ self._getButton(this.id).className = '';\r
+ self._reset(this.id);\r
+ }\r
+\r
+ this.onplay = function() {\r
+ self._getButton(this.id).className = 'active';\r
+ }\r
+\r
+ this.whileplaying = function() {\r
+ self._showStatus(this.id,this.position,this.duration);\r
+ }\r
+\r
+ this._keyHandler = function(e) {\r
+ var oEvt = e?e:event;\r
+ var sChar = String.fromCharCode(oEvt.keyCode).toLowerCase();\r
+ if (typeof self.keys[sChar] != 'undefined') soundManager.play('s'+self.keys[sChar]);\r
+ }\r
+\r
+ this._showStatus = function(sID,n1,n2) {\r
+ var o = self._getButton(sID).getElementsByTagName('div')[0];\r
+ var offX = (n2>0?(-self.progressWidth+parseInt((n1/n2)*o.offsetWidth)):-self.progressWidth);\r
+ o.style.backgroundPosition = offX+'px 0px';\r
+ }\r
+\r
+ this._getButton = function(sID) {\r
+ return document.getElementById(self.idPrefix+sID);\r
+ }\r
+\r
+ this._reset = function(sID) {\r
+ var id = sID;\r
+ self._showStatus(sID,1,1);\r
+ setTimeout(function(){self._showStatus(sID,0,0);},200);\r
+ }\r
+\r
+ this.init = function() {\r
+ document.onkeydown = self._keyHandler;\r
+ }\r
+\r
+}\r
+\r
+var mpc = new MPC();\r
+\r
+soundManager.flashVersion = (window.location.toString().match(/#flash8/i)?8:9);\r
+if (soundManager.flashVersion != 8) {\r
+ soundManager.useHighPerformance = true;\r
+}\r
+\r
+soundManager.setup({\r
+ url: '../../swf/', // path to load SWF from (overriding default)\r
+ bgColor: '#333333',\r
+ wmode: 'transparent',\r
+ debugMode: false,\r
+ preferFlash: false,\r
+ html5PollingInterval: 50,\r
+ ignoreMobileRestrictions: true,\r
+ onready: function() {\r
+\r
+ soundManager.setup({\r
+ defaultOptions: {\r
+ autoLoad: true,\r
+ multiShot: true,\r
+ whileloading: mpc.showProgress,\r
+ onid3: mpc.onid3,\r
+ onload: mpc.onload,\r
+ onplay: mpc.onplay,\r
+ whileplaying: mpc.whileplaying,\r
+ onfinish: mpc.onfinish\r
+ }\r
+ });\r
+\r
+ // This is the "onload" equivalent which is called when SoundManager has been initialised (sounds can be created, etc.)\r
+ mpc.init();\r
+\r
+ if (!soundManager.html5.needsFlash) {\r
+ document.getElementById('isHTML5').style.display = 'inline';\r
+ }\r
+\r
+ var soundURLs = 'AMB_BD_1,AMB_FTM2,AMB_HHCL,AMB_HHOP,AMB_HHPD,AMB_HTM,AMB_LTM2,AMB_MTM,AMB_RIM1,AMB_SN13,AMB_SN_5,CHINA_1,CRASH_1,CRASH_5,CRASH_6,RIDE_1'.split(',');\r
+ for (var i=0; i<soundURLs.length; i++) {\r
+ soundManager.createSound({\r
+ id: 's'+i,\r
+ url: 'audio/'+soundURLs[i]+'.mp3'\r
+ });\r
+ }\r
+\r
+ /**\r
+ * createSound options can also be set on a per-file basis, with specific option overrides.\r
+ * (Options not specified here will inherit defaults as defined in soundManager.defaultOptions.)\r
+ *\r
+ * eg.\r
+ *\r
+ * soundManager.createSound({\r
+ * id: 'mySound',\r
+ * url: '/path/to/some.mp3',\r
+ * stream: true,\r
+ * autoPlay: true,\r
+ * multiShot: false,\r
+ * whileloading: function() { alert('sound '+this.id+': '+this.bytesLoaded+' of '+this.bytesTotal+' bytes loaded.'); } // event handler: "this" is scoped to SMSound() object instance for easy access to methods/properties\r
+ * });\r
+ *\r
+ * - OR -\r
+ *\r
+ * If you just want a sound with all default options, you can also specify just the required id and URL as string parameters:\r
+ *\r
+ * soundManager.createSound('mySound','/path/to/some.mp3');\r
+ */\r
+ }\r
+});\r
+\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2 Demo: Play MP3 links on a page, "page as playlist" style</title>
+<meta name="robots" content="noindex" />\r
+<style type="text/css">\r
+\r
+/* \r
+\r
+ -------------------------------------------------------------\r
+\r
+ In-page demo CSS - see external CSS for actual relevant stuff.\r
+\r
+ --------------------------------------------------------------\r
+\r
+ */\r
+\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, makes debug more useable) */\r
+ position:absolute;position:fixed;*position:absolute;bottom:10px;right:10px;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);z-index:99;\r
+}\r
+\r
+body {\r
+ font:75% normal verdana,arial,tahoma,"sans serif";\r
+}\r
+</style>\r
+<link rel="stylesheet" type="text/css" href="css/page-player.css" />\r
+<!-- soundManager.useFlashBlock: related CSS -->\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/page-player.js"></script>\r
+<script type="text/javascript">\r
+\r
+soundManager.setup({\r
+ url: '../../swf/',\r
+ html5PollingInterval: 50\r
+});\r
+\r
+// demo only..\r
+function setTheme(sTheme) {\r
+ var o = document.getElementsByTagName('ul')[0];\r
+ o.className = 'playlist'+(sTheme?' '+sTheme:'');\r
+ return false;\r
+}\r
+</script>\r
+</head>\r
+\r
+<body>\r
+\r
+<div>\r
+\r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Play a page of mp3s with javascript via SoundManager 2">SoundManager 2</a> / page as a playlist, basic template</h1>\r
+\r
+ <div id="sm2-container">\r
+ <!-- SM2 flash movie goes here -->\r
+ </div>\r
+\r
+ <ul class="playlist">\r
+\r
+ <li><a href="../_mp3/rain.mp3">Rain</a></li>\r
+ <li><a href="../_mp3/going_outside.mp3">Going Outside</a></li>\r
+ <li><a href="../_mp3/office_lobby.mp3">Office Lobby</a></li>\r
+ <li><a href="../_mp3/walking.mp3">Walking</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20060812%20-%20Groove.mp3" title="Dr. John Groove">Schill - Dr. John Groove</a></li>\r
+ <!-- files from the web (note that ID3 and waveformData information will *not* load from remote domains without permission, due to Flash security restrictions) -->\r
+ <li><a href="http://www.freshly-ground.com/misc/music/carl-3-barlp.mp3">Barrlping with Carl (featureblend.com)</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Mak.mp3">Angry cow sound?</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Things that open, close and roll.mp3">Things that open, close and roll</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/A%20Trip%20to%20the%20Basement%20Garage.mp3">A Trip To The Basement Garage</a></li>\r
+\r
+ </ul>\r
+\r
+ <p>For alternate themes, add the class to the playlist UL - eg. <a href="#" onclick="return setTheme('dark')"><ul class="playlist dark"></a> or <a href="#" onclick="return setTheme('bubblegum')"><ul class="playlist bubblegum"></a>; the base default is <a href="#" onclick="return setTheme()"><ul class="playlist"></a>.</p>\r
+ \r
+ <p>A reminder that if loading from the local filesystem, Flash will deny access to remote (network/internet) URLs by default unless whitelisted via the <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html">Flash Player Global Security Settings Page</a>. Some URLs in this example are remote to demonstrate this.</p>\r
+\r
+ <p>Note that by default, the Flash 8 version is used and therefore Flash 9-only features such as the VU meter, waveform etc. are not available. Refer to the main "page player" demo for configuration examples, or view the source of page-player.js for the configuration object (similar to that used in SoundManager 2 itself.)</p>\r
+\r
+ <p><a href="http://www.schillmania.com/projects/soundmanager2/" title="Javascript MP3 sound player API">SoundManager 2 project</a></p>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+/* \r
+ -----------------------------------------------------------------\r
+ In-page demo CSS for code, documentation etc.\r
+ See page-player.css for actual playlist-relevant stuff.\r
+ -----------------------------------------------------------------\r
+ */\r
+\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, makes debug more useable) */\r
+ position:absolute;position:fixed;*position:absolute;bottom:10px;right:10px;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);z-index:99;\r
+}\r
+\r
+body {\r
+ font:75% normal verdana,arial,tahoma,"sans serif";\r
+}\r
+\r
+h1, h2, h3 {\r
+ font:300 3em "Helvetica Neue",georgia,"times new roman","Arial Rounded MT Bold",helvetica,verdana,tahoma,arial,"sans serif";\r
+ margin-bottom:0px;\r
+}\r
+\r
+h1, h2 {\r
+ letter-spacing:-1px; /* zomg web x.0! ;) */ \r
+}\r
+\r
+h1, h2, h3 {\r
+ float:left;\r
+ clear:both;\r
+ border-bottom:1px solid #999;\r
+ padding-bottom:1px;\r
+ margin-bottom:0.25em;\r
+ /* font trickery */\r
+ -moz-osx-font-smoothing: grayscale;\r
+ -webkit-font-smoothing: antialiased;\r
+}\r
+\r
+h1 {\r
+ margin-top:0px;\r
+ margin-bottom:0px;\r
+ background-color:#666;\r
+ color:#ccc;\r
+ margin-left:-5px;\r
+ padding-left:5px;\r
+ padding-right:5px;\r
+}\r
+\r
+h1,\r
+h1 a {\r
+ color:#fff;\r
+ text-decoration:none;\r
+}\r
+\r
+h1 a:hover {\r
+ text-decoration:underline;\r
+}\r
+\r
+h2 {\r
+ font-size:2em;\r
+ margin-top:1em;\r
+ background-color:#aaa;\r
+ color:#fff;\r
+ padding:5px;\r
+ margin-left:-5px;\r
+ min-width:23em;\r
+}\r
+\r
+h3 {\r
+ font-size:1.65em;\r
+ margin-top:0.5em;\r
+ margin-bottom:0.25em;\r
+ color:#333;\r
+ min-width:28em;\r
+}\r
+\r
+h3 a {\r
+ font-size:small;\r
+}\r
+\r
+h4 {\r
+ color:#444;\r
+}\r
+\r
+ul.notes {\r
+ margin-left:0px;\r
+ padding-left:1.5em;\r
+}\r
+\r
+.note {\r
+ margin-top:0px;\r
+ font-style:italic;\r
+ color:#999;\r
+}\r
+\r
+pre {\r
+ font-size:1.2em;\r
+ _font-size:1em;\r
+}\r
+\r
+code {\r
+ font-family:"lucida console",monaco,courier,system;\r
+ font-size:1em;\r
+ color:#003366;\r
+}\r
+\r
+code span {\r
+ color:#666;\r
+}\r
+\r
+ul,\r
+p,\r
+pre {\r
+ clear:left;\r
+ max-width:46em;\r
+}\r
+\r
+ul.tight li {\r
+ max-width:44.5em;\r
+}\r
+\r
+ul.playlist {\r
+ /* undo the above nonsense */\r
+ max-width:none;\r
+}\r
+\r
+ul.tight {\r
+ padding-left:1.5em;\r
+}\r
--- /dev/null
+/*\r
+ ------------------------------------------\r
+ -- annotations (sub-tracks, notes etc.) --\r
+ ------------------------------------------\r
+*/\r
+\r
+ul.playlist li a.sm2_link .metadata {\r
+ display:none; /* hide by default */\r
+}\r
+\r
+ul.playlist li.sm2_paused a.sm2_link .metadata,\r
+ul.playlist li.sm2_playing a.sm2_link .metadata {\r
+ display:inline;\r
+}\r
+\r
+ul.playlist li ul {\r
+ list-style-type:none;\r
+ margin:0px;\r
+ padding:0px;\r
+ position:relative;\r
+ font-size:small;\r
+ display:none;\r
+}\r
+\r
+ul.playlist li ul li {\r
+ position:relative;\r
+ margin:0px;\r
+ padding:2px 3px;\r
+ border:1px solid transparent;\r
+ border-radius:6px;\r
+ margin-right:1em;\r
+ font-family:helvetica,verdana,tahoma,arial,"sans serif";\r
+ font-size:x-small;\r
+ font-weight:300;\r
+ letter-spacing:0px;\r
+ background-color:transparent;\r
+ opacity:0.66;\r
+}\r
+\r
+ul.playlist li ul li:hover {\r
+ opacity:1;\r
+ background-color:#fff;\r
+ border-color:#ccc;\r
+ color:#666;\r
+}\r
+\r
+ul.playlist li.sm2_playing ul li,\r
+ul.playlist li.sm2_paused ul li {\r
+ color:#fff;\r
+}\r
+\r
+ul.playlist li.sm2_playing ul li:hover {\r
+ background-color:#fff;\r
+ color:#5588bb;\r
+ border-color:#336699;\r
+ opacity:0.9;\r
+}\r
+\r
+ul.playlist li.sm2_paused ul li:hover {\r
+ background-color:#888;\r
+}\r
+\r
+/* metadata */\r
+\r
+ul.playlist li .metadata .duration {\r
+ /* optional timing data */\r
+ display:none;\r
+}\r
+\r
+ul.playlist li .metadata ul li p {\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+ul.playlist li .metadata ul li span {\r
+ display:none;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .annotation {\r
+ position:absolute;\r
+ background-color:transparent;\r
+ top:0px;\r
+ color:#666;\r
+ text-align:right;\r
+ margin-left:10px;\r
+ height:0.5em;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .annotation:hover {\r
+ z-index:12; /* sit on top of note */\r
+}\r
+\r
+ul.playlist li .controls .statusbar .annotation span.bubble {\r
+ /* using · */\r
+ display:inline-block;\r
+ background-color:#fff;\r
+ border:1px solid #666;\r
+ border-radius:6px;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .annotation span {\r
+ display:block;\r
+ background:transparent url(../image/divot.png) no-repeat 50% 0px;\r
+ width:15px;\r
+ margin-left:-15px;\r
+ height:12px;\r
+ text-align:center;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .annotation.alt {\r
+ top:auto;\r
+ bottom:0px;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .annotation span:hover {\r
+ cursor:none; /* Fx3 rules. */\r
+ margin-top:0.1em;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .annotation.alt span:hover {\r
+ margin-top:-0.1em;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .annotation.alt span {\r
+ background:transparent url(../image/divot-bottom.png) no-repeat 50% bottom;\r
+}\r
+\r
+ul.playlist li .note {\r
+ position:absolute;\r
+ display:none;\r
+ left:0px;\r
+ top:0px;\r
+ z-index:10;\r
+ font-size:x-small;\r
+ padding:2px 4px 2px 4px;\r
+ width:auto;\r
+ color:#666;\r
+ background-color:#fff;\r
+ border:1px solid #ccc;\r
+ border-radius:6px;\r
+ font-style:normal;\r
+ font-weight:bold;\r
+ font-family:arial,tahoma,verdana,"sans serif";\r
+ letter-spacing:0px;\r
+ margin-top:1.1em;\r
+}\r
+\r
+ul.playlist li .note.alt {\r
+ margin-top:-1.32em;\r
+}\r
+\r
+ul.playlist li .note:hover {\r
+ display:block !important;\r
+}\r
+\r
+ul.playlist li .sm2_divider {\r
+ font-size:0.75em;\r
+}\r
+\r
+ul.playlist li .sm2_metadata {\r
+ font-size:0.65em;\r
+}\r
--- /dev/null
+/* \r
+ ---------------------------------\r
+ -- alternate (optional) themes --\r
+ ---------------------------------\r
+*/\r
+\r
+ul.playlist.dark li.sm2_playing a {\r
+ color:#fff;\r
+}\r
+\r
+ul.playlist.dark li.sm2_playing .timing,\r
+ul.playlist.use-peak.dark li.sm2_playing .peak {\r
+ color:#999;\r
+}\r
+\r
+ul.playlist.use-spectrum.dark li.sm2_playing .spectrum-container {\r
+ background-color:#222;\r
+ border-color:#444;\r
+}\r
+\r
+ul.playlist.use-spectrum.dark li.sm2_playing .spectrum-container .spectrum {\r
+ background-color:#999;\r
+}\r
+\r
+ul.playlist.dark li.sm2_paused {\r
+ background-color:#333;\r
+}\r
+\r
+ul.playlist.dark li.sm2_paused a {\r
+ color:#999;\r
+}\r
+\r
+ul.playlist.dark li.sm2_playing,\r
+ul.playlist.dark li.sm2_playing:hover {\r
+ background-color:#333;\r
+}\r
+\r
+ul.playlist.dark li:hover .controls .statusbar {\r
+ background-color:#666;\r
+}\r
+\r
+ul.playlist.dark li .controls {\r
+ background-color:#333;\r
+}\r
+\r
+ul.playlist.dark li .controls .statusbar {\r
+ background-color:#666;\r
+ border-color:#444;\r
+}\r
+\r
+ul.playlist.dark li .controls .statusbar .position {\r
+ background-color:#111;\r
+ border-right:3px solid #111;\r
+ border-radius:3px;\r
+}\r
+\r
+ul.playlist.dark li .controls .statusbar .loading {\r
+ background-color:#444;\r
+}\r
+\r
+ul.playlist.dark li .timing,\r
+ul.playlist.use-peak.dark li .peak {\r
+ background-color:#222;\r
+ border-color:#444;\r
+}\r
+\r
+ul.playlist.dark.use-peak li .peak .l,\r
+ul.playlist.dark.use-peak li .peak .r {\r
+ border-color:#444;\r
+ background-color:#999;\r
+}\r
+\r
+\r
+/* gold theme */\r
+\r
+ul.playlist.gold li.sm2_paused {\r
+ background-color:#996600;\r
+}\r
+\r
+ul.playlist.gold li.sm2_playing,\r
+ul.playlist.gold li.sm2_playing:hover {\r
+ background-color:#cc9900;\r
+}\r
+\r
+ul.playlist.gold li .controls {\r
+ background-color:transparent;\r
+}\r
+\r
+ul.playlist.gold li .controls .statusbar {\r
+ background-color:#fff;\r
+ border-color:#fff;\r
+}\r
+\r
+ul.playlist.gold li .controls .statusbar .position {\r
+ background-color:#996600;\r
+ border-right:3px solid #996600;\r
+ border-radius:3px;\r
+}\r
+\r
+ul.playlist.gold li .controls .statusbar .loading {\r
+ background-color:#ffeedd;\r
+}\r
+\r
+ul.playlist.gold li .timing,\r
+ul.playlist.use-peak.gold li .peak {\r
+ background-color:#CC9900;\r
+ border-color:#ffcc33;\r
+}\r
+\r
+ul.playlist.use-spectrum.gold li.sm2_playing .spectrum-container {\r
+ background-color:#cc9900;\r
+ border-color:#ffcc33;\r
+}\r
+\r
+ul.playlist.use-spectrum.gold li.sm2_playing .spectrum-container .spectrum {\r
+ background-color:#fff;\r
+}\r
+\r
+ul.playlist.gold.use-peak li .peak .l,\r
+ul.playlist.gold.use-peak li .peak .r {\r
+ border-color:#fff;\r
+ background-color:#fff;\r
+}\r
+\r
+\r
+/* ZOMG PONIES!!!ONEONEONE */\r
+\r
+ul.playlist.bubblegum li a {\r
+ font-family:"comic sans ms",verdana,arial,tahoma,"sans serif"; /* heh */\r
+}\r
+\r
+ul.playlist.bubblegum li.sm2_paused,\r
+ul.playlist.bubblegum li.sm2_paused:hover {\r
+ background-color:#ffccee;\r
+}\r
+\r
+ul.playlist.bubblegum li.sm2_paused a,\r
+ul.playlist.bubblegum li.sm2_paused:hover a,\r
+ul.playlist.bubblegum li.sm2_paused .timing,\r
+ul.playlist.use-peak.bubblegum li.sm2_paused .peak {\r
+ color:#ff6699;\r
+}\r
+\r
+ul.playlist.bubblegum li:hover {\r
+ background-color:#ffddee;\r
+}\r
+\r
+ul.playlist.bubblegum li.sm2_playing,\r
+ul.playlist.bubblegum li.sm2_playing:hover {\r
+ background-color:#ff7799;\r
+}\r
+\r
+ul.playlist.bubblegum li .controls {\r
+ background-color:transparent;\r
+}\r
+\r
+ul.playlist.bubblegum li .controls .statusbar {\r
+ background-color:#fff;\r
+ border-color:#fff;\r
+}\r
+\r
+ul.playlist.bubblegum li .controls .statusbar .position {\r
+ background-color:#ffaacc;\r
+ border-right:3px solid #ffaacc;\r
+ border-radius:3px;\r
+}\r
+\r
+ul.playlist.bubblegum li .controls .statusbar .loading {\r
+ background-color:#ffeedd;\r
+}\r
+\r
+ul.playlist.bubblegum li .timing,\r
+ul.playlist.use-peak.bubblegum li .peak {\r
+ background-color:#ffaacc;\r
+ border-color:#ffccee;\r
+}\r
+\r
+ul.playlist.use-spectrum.bubblegum li.sm2_playing .spectrum-container {\r
+ background-color:#ffaacc;\r
+ border-color:#ffccee;\r
+}\r
+\r
+ul.playlist.use-spectrum.bubblegum li.sm2_playing .spectrum-container .spectrum {\r
+ background-color:#fff;\r
+}\r
+\r
+ul.playlist.bubblegum.use-peak li .peak .l,\r
+ul.playlist.bubblegum.use-peak li .peak .r {\r
+ border-color:#fff;\r
+ background-color:#fff;\r
+}\r
+\r
+\r
+ul.playlist.shiny li.sm2_paused,\r
+ul.playlist.shiny li.sm2_playing {\r
+ background-image:url(../image/top-highlight.png);\r
+ background-repeat:repeat-x;\r
+ background-position:0px -1px;\r
+ _background-image:none; /* can't be bothered with IE 6. */\r
+}
\ No newline at end of file
--- /dev/null
+/*\r
+\r
+ SoundManager 2: "page as playlist" example\r
+ ------------------------------------------\r
+ http://schillmania.com/projects/soundmanager2/\r
+\r
+*/\r
+\r
+.spectrum-container {\r
+ display:none;\r
+}\r
+\r
+ul.use-spectrum li.sm2_playing .spectrum-container {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ margin-left:-266px;\r
+ margin-top:-1px;\r
+ display:block;\r
+ background-color:#5588bb;\r
+ border:1px solid #99ccff;\r
+ border-radius:4px;\r
+}\r
+\r
+ul.use-spectrum .spectrum-box {\r
+ position:relative;\r
+ width:255px;\r
+ font-size:1em;\r
+ padding:2px 0px;\r
+ height:1.2em;\r
+ overflow:hidden;\r
+}\r
+\r
+ul.use-spectrum .spectrum-box .spectrum {\r
+ position:absolute;\r
+ left:0px;\r
+ top:-2px;\r
+ margin-top:20px;\r
+ display:block;\r
+ font-size:1px;\r
+ width:1px;\r
+ height:1px; /* set to 50px for a thick line, 1px for a thin line, etc. */\r
+ overflow:hidden;\r
+ background-color:#fff;\r
+}\r
+\r
+ul.playlist {\r
+ list-style-type:none;\r
+ margin:0px;\r
+ padding:0px;\r
+ /* font trickery */\r
+ -moz-osx-font-smoothing: grayscale;\r
+ -webkit-font-smoothing: antialiased;\r
+}\r
+\r
+ul.playlist li {\r
+ /* assume all items will be sounds rather than wait for onload etc. in this example.. may differ for your uses. */\r
+ position:relative;\r
+ display:block;\r
+ width:auto;\r
+ font-size:2em;\r
+ color:#666;\r
+ padding:0.25em 0.5em 0.25em 0.5em;\r
+ border:none;\r
+ letter-spacing:-1px; /* ZOMG WEB X.0. ;) */\r
+ background-color:#f9f9f9;\r
+ -webkit-transition-property: hover;\r
+ -webkit-transition: background-color 0.15s ease-in-out;\r
+ -moz-transition: background-color 0.15s linear 0s; /* firefox 4 */\r
+ -o-transition-property: background-color; /* opera 10.5 */\r
+ -o-transition-duration: 0.15s;\r
+\r
+}\r
+\r
+ul.playlist li a {\r
+ display:block;\r
+ text-decoration:none;\r
+ font-weight:normal;\r
+ color:#000;\r
+ font-size:120%;\r
+ outline:none;\r
+ position:relative;\r
+ z-index:2;\r
+}\r
+\r
+ul.playlist li.sm2_playing,\r
+ul.playlist li.sm2_paused,\r
+ul.playlist li.sm2_playing a {\r
+ color:#fff;\r
+ border-radius:3px;\r
+}\r
+\r
+ul.playlist li:hover {\r
+ background-color:#eee;\r
+}\r
+\r
+ul.playlist li:hover a {\r
+ color:#333;\r
+}\r
+\r
+ul.playlist li.sm2_playing,\r
+ul.playlist li.sm2_playing:hover {\r
+ background-color:#6699cc;\r
+}\r
+\r
+ul.playlist li.sm2_paused {\r
+ background-color:#999;\r
+}\r
+\r
+ul.playlist li.sm2_playing:hover a,\r
+ul.playlist li.sm2_paused a {\r
+ color:#fff;\r
+}\r
+\r
+ul.playlist li .controls {\r
+ display:none;\r
+}\r
+\r
+ul.playlist li .peak,\r
+ul.playlist.use-peak li .peak {\r
+ display:none;\r
+ position:absolute;\r
+ top:0.55em;\r
+ right:0.5em;\r
+}\r
+\r
+ul.playlist li.sm2_playing .controls,\r
+ul.playlist li.sm2_paused .controls {\r
+ position:relative;\r
+ display:block;\r
+}\r
+\r
+ul.playlist.use-peak li.sm2_playing .peak,\r
+ul.playlist.use-peak li.sm2_paused .peak {\r
+ display:inline;\r
+ display:inline-block;\r
+}\r
+\r
+ul.playlist.use-peak li .peak {\r
+ display:none; /* IE 7 */\r
+}\r
+\r
+ul.playlist li.sm2_paused .controls {\r
+ background-color:#666;\r
+}\r
+\r
+ul.playlist li:hover .controls .statusbar {\r
+ position:relative;\r
+ cursor:-moz-grab;\r
+ cursor:-webkit-grab;\r
+ cursor:grab;\r
+}\r
+\r
+ul.playlist li.sm2_paused .controls .statusbar {\r
+ background-color:#ccc;\r
+}\r
+\r
+ul.playlist li .controls {\r
+ position:relative;\r
+ margin-top:0.25em;\r
+ margin-bottom:0.25em;\r
+ background-color:#99ccff;\r
+}\r
+\r
+ul.playlist li .controls .statusbar {\r
+ position:relative;\r
+ height:0.5em;\r
+ background-color:#ccddff;\r
+ border:2px solid #fff;\r
+ border-radius:2px;\r
+ overflow:hidden;\r
+ cursor:-moz-grab;\r
+ cursor:-webkit-grab;\r
+ cursor:grab;\r
+}\r
+\r
+ul.playlist li .controls.dragging .statusbar {\r
+ cursor:-moz-grabbing;\r
+ cursor:-webkit-grabbing;\r
+ cursor:grabbing;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .position,\r
+ul.playlist li .controls .statusbar .loading,\r
+ul.playlist li .controls .statusbar .annotation {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ height:0.5em;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .position {\r
+ background-color:#336699;\r
+ border-right:3px solid #336699;\r
+ border-radius:3px;\r
+}\r
+\r
+ul.playlist li.sm2_paused .controls .statusbar .position {\r
+ background-color:#666;\r
+ border-color:#666;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .loading {\r
+ background-color:#eee;\r
+}\r
+\r
+ul.playlist li .controls .statusbar .position,\r
+ul.playlist li .controls .statusbar .loading {\r
+ width:0px;\r
+}\r
+\r
+ul.playlist li.sm2_playing a.sm2_link,\r
+ul.playlist li.sm2_paused a.sm2_link {\r
+ margin-right:4.5em; /* room for timing stuff */\r
+}\r
+\r
+ul.playlist li .timing {\r
+ position:absolute;\r
+ display:none;\r
+ text-align:right;\r
+ right:1em;\r
+ top:1em;\r
+ width:auto;\r
+ height:1em;\r
+ padding:3px 5px;\r
+ background-color:#5588bb;\r
+ border:1px solid #99ccff;\r
+ border-radius:4px;\r
+ letter-spacing:0px;\r
+ font:44% monaco,"VT-100","lucida console",courier,system;\r
+ line-height:1em;\r
+ vertical-align:middle;\r
+}\r
+\r
+ul.playlist.use-peak li .timing {\r
+ right:4.25em;\r
+}\r
+\r
+ul.playlist li:hover .timing {\r
+ z-index:2;\r
+}\r
+\r
+ul.playlist li .timing div.sm2_timing {\r
+ margin:0px;\r
+ padding:0px;\r
+ margin-top:-1em;\r
+}\r
+\r
+ul.playlist li.sm2_playing .timing,\r
+ul.playlist li.sm2_paused .timing {\r
+ display:block;\r
+}\r
+\r
+ul.playlist li.sm2_paused .timing .sm2_position {\r
+ text-decoration:blink; /* hee hee. first actual appropriate use? :D */\r
+}\r
+\r
+ul.playlist li.sm2_paused .timing,\r
+ul.playlist.use-peak li.sm2_paused .peak {\r
+ background-color:#888;\r
+ border-color:#ccc;\r
+}\r
+\r
+/* peak data */\r
+\r
+/* ul.playlist ... */\r
+\r
+ul.playlist.use-peak li .peak {\r
+ display:none;\r
+ zoom:1;\r
+ border:1px solid #99ccff;\r
+ padding:2px;\r
+ height:0.55em;\r
+ border-radius:4px;\r
+ background-color:#5588bb;\r
+ width:0.8em;\r
+ height:0.55em;\r
+ margin-top:-3px;\r
+}\r
+\r
+ul.playlist.use-peak li .peak-box {\r
+ position:relative;\r
+ width:100%;\r
+ height:0.55em;\r
+ overflow:hidden;\r
+}\r
+\r
+ul.playlist li .peak .l,\r
+ul.playlist li .peak .r {\r
+ position:absolute;\r
+ left:0px;\r
+ top:0px;\r
+ width:7px;\r
+ height:50px;\r
+ background:#fff;\r
+ border:1px solid #fff;\r
+ border-radius:1px;\r
+ margin-top:1em;\r
+}\r
+\r
+ul.playlist li .peak .l {\r
+ margin-right:1px;\r
+}\r
+\r
+ul.playlist li .peak .r {\r
+ left:10px;\r
+}\r
+\r
+#control-template {\r
+ display:none;\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2 Demo: Play MP3 links on a page, "page as playlist" style</title>
+<meta name="robots" content="noindex" />\r
+\r
+<!-- demo.css for this page only, make things pretty -->\r
+<link rel="stylesheet" type="text/css" href="css/demo.css" />\r
+\r
+<!-- Page player core CSS -->\r
+<link rel="stylesheet" type="text/css" href="css/page-player.css" />\r
+\r
+<!-- soundManager.useFlashBlock: related CSS -->\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+\r
+<!-- optional: annotations/sub-tracks/notes, and alternate themes -->\r
+<link rel="stylesheet" type="text/css" href="css/optional-annotations.css" />\r
+<link rel="stylesheet" type="text/css" href="css/optional-themes.css" />\r
+\r
+<style type="text/css">\r
+ul.playlist li .comment {font-size:0.65em;opacity:0.5}\r
+</style>\r
+\r
+<!-- soundManager API -->\r
+<script src="../../script/soundmanager2.js"></script>\r
+\r
+<script>\r
+\r
+/* --------\r
+\r
+ Config override: This demo uses shiny flash 9 stuff, overwriting Flash 8-based defaults\r
+ Alternate PP_CONFIG object must be defined before soundManager.onready()/onload() fire.\r
+ Alternately, edit the config in page-player.js to simply use the values below by default\r
+\r
+-------- */\r
+\r
+// demo only, but you can use these settings too..\r
+soundManager.setup({\r
+ flashVersion: 9,\r
+ // preferFlash: true, // for visualization effects\r
+ useHighPerformance: true, // keep flash on screen, boost performance\r
+ html5PollingInterval: 50,\r
+ wmode: 'transparent', // transparent SWF, if possible\r
+ url: '../../swf/'\r
+});\r
+\r
+// custom page player configuration\r
+\r
+var PP_CONFIG = {\r
+ autoStart: false, // begin playing first sound when page loads\r
+ playNext: true, // stop after one sound, or play through list until end\r
+ useThrottling: false, // try to rate-limit potentially-expensive calls (eg. dragging position around)</span>\r
+ usePeakData: true, // [Flash 9 only] whether or not to show peak data (left/right channel values) - nor noticable on CPU\r
+ useWaveformData: false,// [Flash 9 only] show raw waveform data - WARNING: LIKELY VERY CPU-HEAVY\r
+ useEQData: false, // [Flash 9 only] show EQ (frequency spectrum) data\r
+ useFavIcon: false // try to apply peakData to address bar (Firefox + Opera) - performance note: appears to make Firefox 3 do some temporary, heavy disk access/swapping/garbage collection at first(?) - may be too heavy on CPU\r
+}\r
+\r
+</script>\r
+\r
+<!-- Page player main script -->\r
+<script src="script/page-player.js"></script>\r
+\r
+<!-- optional: Metadata UI prototype (not needed unless you want the bottom-most demo bits) -->\r
+<script src="script/optional-page-player-metadata.js"></script>\r
+\r
+</head>\r
+\r
+<body>\r
+\r
+<div id="left">\r
+\r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Play a page of mp3s with javascript via SoundManager 2">SoundManager 2</a> / "Page as a playlist"</h1>\r
+\r
+ <h2 style="margin-top:0px;border:none">Muxtape.com-style UI, MP3/AAC Player Example</h2>\r
+\r
+ <p style="padding-top:0.5em;color:#333">This page uses Flash 9-based effects where supported. The <a href="basic.html" title="Basic page player demo">default config</a> uses Flash 8.</p>\r
+\r
+ <p id="experimental-features" style="margin-top:0.5em;color:#333">You can also try enabling <a href="#experimental" onclick="window.location.href = this;window.location.reload()">experimental visualization features</a>.</p>\r
+\r
+ <div id="sm2-container">\r
+ <!-- SM2 flash goes here -->\r
+ </div>\r
+\r
+ <ul class="playlist">\r
+ <li><a href="../mpc/audio/CRASH_1.mp3">Crash cymbal</a></li>\r
+ <li><a href="../_mp3/bass.mp3">Bass</a></li>\r
+ <li><a href="../_mp3/sine,%20square,%20sawtooth,%20rando.mp3">440 Hz sine, square, sawtooth, pink noise, random</a></li>\r
+ <li><a href="../_mp3/1hz-10khz-sweep.mp3">1Hz - 10KHz sweep</a></li>\r
+ <!-- files from the web (note that ID3 and waveformData information will *not* load from remote domains without permission, due to Flash security restrictions) -->\r
+ <li><a href="http://freshly-ground.com/misc/music/20060826%20-%20Armstrong.mp3">20060826 - Armstrong</a></li>\r
+ <li><a href="http://freshly-ground.com/misc/music/carl-3-barlp.mp3">Barrlping with Carl <span class="comment">(featureblend.com)</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/binaural/Mak.mp3" class="exclude">Angry cow sound with "exclude" CSS class <span class="comment">(Browser follows link normally)</span></a></li>\r
+ </ul>\r
+\r
+ <h2>MPEG4 / H.264 + HE-AAC (Flash "MovieStar" 9.0r115+) format support - audio-only example</h2>\r
+ <h3>A subset of MPEG4 <a href="http://www.adobe.com/support/documentation/en/flashplayer/9/releasenotes.html#fixes_90115">is supported</a> including AAC, FLV, MP4, M4A, MOV, MP4V, 3GP and 3G2 files.</h3>\r
+\r
+ <ul class="playlist">\r
+ <li><a href="http://freshly-ground.com/data/video/Rain%20on%20Car%20Roof.aac">Rain on Car Roof <span class="comment">(MPEG4 .AAC audio, 128 kbps AAC-LC exported from QuickTime)</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/video/Jellyfish.mov">Jellyfish <span class="comment">(848x480 H.264 video, playing audio portion only)</span></a></li>\r
+ </ul>\r
+\r
+ <h3 style="margin-top:1em">Basics</h3>\r
+\r
+ <p class="note">Don't want a Flash 9 requirement, EQ/waveform, perhaps less CPU? See Flash 8-based <a href="basic.html" title="Page as playlist demo">basic demo</a>.</p>\r
+\r
+ <p>Clicking a title will start loading + playing, or pause, a sound.</p>\r
+ <p>Once loading, click (or click and drag) on the loading/position bar to seek within the sound.</p>\r
+ <p>The document title reflects the currently-playing sound, and by default the list will play sequentially if left alone. (This is configurable.)</p>\r
+ \r
+ <h3>Themes</h3>\r
+ <p>Just for fun, a few color schemes (visible when playing/paused):</p>\r
+ <ul class="themes">\r
+ <li><a href="#" onclick="return setTheme('dark')"><ul class="playlist dark"></a> - #333 and #666, mostly</li>\r
+ <li><a href="#" onclick="return setTheme('gold')"><ul class="playlist gold"></a> - Frontin' the bling</li>\r
+ <li><a href="#" onclick="return setTheme('bubblegum')"><ul class="playlist bubblegum"></a> - ZOMG PONIES!!!ONEONEONE</li>\r
+ <li><a href="#" onclick="return setTheme('')"><ul class="playlist"></a> (default)</li>\r
+ </ul>\r
+ \r
+ <form style="margin:0px;padding:0px" action="#" onsubmit="return false">\r
+ <div>\r
+ <input id="makeShiny" name="makeShiny" type="checkbox" onchange="setShiny(this.checked)" value="Shiny" /> <label for="makeShiny">Also add "shiny", eg. <ul class="shiny playlist">...</label>\r
+ </div>\r
+ </form>\r
+ <script>document.getElementById('makeShiny').checked=false;</script>\r
+\r
+ <h2 id="metadata">Experimental (Alpha) Variant: MP3 "Metadata": Annotations / notes / sub-tracks</h2>\r
+ <p>A potential approach to noting interesting moments in sounds, scene changes, new tracks in seamless DJ mixes etc. Keep in mind this is a single MP3 being loaded, but annotations are placed along the timeline as shown.</p>\r
+ <p>A "metadata" element contains a nested list of data (UL/LI combination) - in this case, a summary of each scene - and the time at which this item occurs/begins. In order to help with positioning, the total length of the sound is also specified up-front. View the source code of this page for the details.</p>\r
+\r
+ <ul class="playlist">\r
+\r
+ <li>\r
+ <a href="http://freshly-ground.com/data/audio/binaural/A%20Virtual%20Haircut%20in%20San%20Francisco%20%283%20Scenes%29.mp3">A Virtual Haircut (3 scenes)</a>\r
+ <div class="metadata">\r
+ <div class="duration">4:43</div> <!-- total track time (for positioning while loading, until determined -->\r
+ <ul>\r
+ <li><p>Electric razor</p><span>0:00</span></li> <!-- first scene -->\r
+ <li><p>Water, scissors</p><span>2:41</span></li> <!-- start time of second scene -->\r
+ <li><p>More razor work</p><span>4:00</span></li>\r
+ </ul>\r
+ </div>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="http://freshly-ground.com/data/audio/binaural/Rubber%20Chicken%20Launch%20%28office%29.mp3">Rubber Chicken Launch (Office)</a>\r
+ <div class="metadata">\r
+ <div class="duration">0:47</div>\r
+ <ul>\r
+ <li><p>First attempt</p><span>0:00</span></li>\r
+ <li><p>Fire!</p><span>0:02</span></li>\r
+ <li><p>"Too much angle"</p><span>0:05</span></li>\r
+ <li><p>Random chicken noise</p><span>0:18</span></li>\r
+ <li><p>"Wait a second"</p><span>0:31</span></li>\r
+ <li><p>Derrr..</p><span>0:34</span></li>\r
+ <li><p>Launch attempt #2</p><span>0:36</span></li>\r
+ <li><p>"Wrong angle"</p><span>0:39</span></li>\r
+ <li><p>"Fail"</p><span>0:42</span></li>\r
+ </ul>\r
+ </div>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ <h2>How It Works</h2>\r
+\r
+ <p>This example uses <a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 Javascript Sound API">SoundManager 2</a> to find links to MP3 files within an unordered list, and makes them playable "in-place" on a page. The script assigns CSS classes to links' parent LI nodes to indicate their state (playing/paused, etc.)</p>\r
+\r
+ <h3>Progressive Enhancement</h3>\r
+\r
+ <p>This provides a nice HTML base for all browsers and user agents, and enhances progressively for those with Javascript and Flash. Links pointing to MP3s are assigned an onclick handler which intercepts the click (preventing the browser from following the link and unloading the page. SM2 will then create sound objects as needed to play the MP3s. In the event there is an error at runtime or a lack of support (no JS/Flash etc.), the browser will simply load the MP3s directly as it normally would. This includes iPhones, etc.</p>\r
+\r
+ <h3>HTML Fragments (UI Element Templates)</h3>\r
+ <p>Each item in the playlist has its own set of controls and progress indicators, etc. This content is defined once as a hidden template of HTML in the player JavaScript file, separate from the playlist markup, and is cloned for each item as needed. This can be easily styled with CSS as well, of course.</p>\r
+\r
+<h2>I'd like to use this.</h2>\r
+<p>See this <a href="basic.html" title="Page as playlist demo">basic demo</a> for reference.</p>\r
+<p>The basic demo uses the default Flash 8 configuration, but you can easily change this to use Flash 9 features. The only difference in code is the configuration.</p>\r
+\r
+<p>A reminder that if loading from the local filesystem, Flash will deny access to remote (network/internet) URLs by default unless whitelisted via the <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html">Flash Player Global Security Settings Page</a>. Some URLs in this example are remote to demonstrate this.</p>\r
+\r
+<h2>Configuration + Options</h2>\r
+\r
+<h3>Default configuration</h3>\r
+\r
+<p>Behaviours such as auto-start and UI elements like VU meters and spectrum graphs are easy configurable, using an object literal format as shown below.</p>\r
+<p>The page player config (see related page-player.js file) as below.</p>\r
+<p>The custom parameters used to make this demo page are highlighted in red.</p>\r
+<pre class="block"><code> <span>// ( within page-player.js )</span>\r
+\r
+ soundManager.setup({\r
+ <span>// If you need flash 9, include this line.</span>\r
+ flashVersion: <span style="color:red">9</span>\r
+ });\r
+\r
+ this.config = {\r
+ usePeakData: <span style="color:red">true</span>, <span>// [Flash 9 only] show peak (VU-meter) data</span>\r
+ useFavIcon: <span style="color:red">true</span>, <span>// try to show peakData in address bar (Firefox + Opera) - requires usePeakData = true too, of course.</span>\r
+ useWaveformData: <span style="color:red">true</span>, <span>// [Flash 9 only] true: show raw waveform data - WARNING: CPU-intensive</span>\r
+ useEQData: false, <span>// [Flash 9 only] show EQ (frequency spectrum) data - WARNING: CPU-intensive</span>\r
+ fillGraph: false, <span>// [Flash 9 only] draw full lines instead of only top (peak) spectrum points</span>\r
+ allowRightClick:true, <span>// let users right-click MP3 links ("save as...", etc.) or discourage (can't prevent.)</span>\r
+ useThrottling: false, <span>// try to rate-limit potentially-expensive calls (eg. dragging position around)</span>\r
+ autoStart: false, <span>// begin playing first sound when page loads</span>\r
+ playNext: true, <span>// stop after one sound, or play through list until end</span>\r
+ updatePageTitle: true, <span>// change the page title while playing sounds</span>\r
+ emptyTime: '-:--' <span>// null/undefined timer values (before data is available)</span>\r
+ }\r
+</code></pre>\r
+\r
+<h3>Per-page configuration override</h3>\r
+\r
+<p>Alternately, you may override the defaults on a per-page basis by defining an "alternate configuration" object <b>before</b> the page-player.js file has been included in your source code:</p>\r
+\r
+<pre class="block"><code> <span>// ( before soundManager.onready() has fired )</span>\r
+\r
+ soundManager.setup({\r
+ <span>// If you need flash 9, include this line.</span>\r
+ flashVersion: <span style="color:red">9</span>\r
+ });\r
+\r
+ var PP_CONFIG = {\r
+ usePeakData: true, <span>// [Flash 9 only] whether or not to show peak data (no notable CPU cost)</span>\r
+ useWaveformData: true <span>// [Flash 9 only] show raw waveform data. WARNING: Experimental, likely CPU-heavy</span>\r
+ }</code></pre>\r
+\r
+<p>Any options specified in PP_CONFIG will override the defaults defined in page-player.js.</p>\r
+\r
+ <h3>Basic CSS</h3>\r
+\r
+<pre>\r
+ If you want to make your own UI from scratch, here is the base:\r
+\r
+ ul.playlist {}\r
+\r
+ Default + hover state, "click to play":\r
+\r
+ li.sm2_link {}\r
+ li.sm2_link:hover {}\r
+\r
+ Playing + hover state, "click to pause":\r
+\r
+ li.sm2_playing {}\r
+ li.sm2_playing:hover {}\r
+\r
+ Paused + hover state, "click to resume":\r
+\r
+ li.sm2_paused {}\r
+ li.sm2_paused:hover {}\r
+</pre>\r
+\r
+<p>The positioning (load status / control bar) template is also applied after each MP3 link, from an element named "control-template"</p>\r
+\r
+<p>"loading" and "position" have background colors applied, and have their width adjusted dynamically by SM2 as the sound(s) load/play. "timing" is replaced with the current time / duration, eg. 1:23 / 4:20</p>\r
+<p>The class names applied can be edited within the source JS also, for convenience.</p>\r
+<p>The controls are shown and hidden via the same dynamic CSS updates. See the source CSS for the timing / status bar layout.</p>\r
+\r
+<h2>Performance Considerations</h2>\r
+<h3>Experimental Flash 9 features</h3>\r
+<ul class="tight" style="padding-top:1px">\r
+ <li>\r
+ <h4>Dynamic "favicon" VU meter</h4>\r
+ <p>The VU meter "favicon" option as shown in the address/location bar for Firefox and Opera can cause a lot of disk access in Firefox (2.x/3.0 at time of writing, from what has been reported.) It may be garbage collection-related.</p>\r
+ <p>The behaviour seems to be connected to the dynamic swapping of <link> elements with data: URIs containing the VU meter data, and looks to be noticeable with the first sound played - after which point things settle down. Perhaps the browser is attempting to cache the favicon data being assigned.</p>\r
+ </li>\r
+ <li>\r
+ <h4>Waveform/spectrum visualization graph</h4>\r
+ <p>Enabling the waveformData and/or eqData features will result in some heavy DOM calls (manipulation of 256 <div> elements with each "frame" drawn) which can eat up a good amount of CPU and may make really old computers cower in fear.</p>\r
+ <p>Ultimately, the UI refresh rate will simply be limited if a CPU ceiling is hit, and audio playback should not be affected.</p>\r
+ </li>\r
+</ul>\r
+\r
+<h3>More CSS comments</h3>\r
+\r
+<div>\r
+<pre>\r
+\r
+ SoundManager 2: "page as playlist" example\r
+ ------------------------------------------\r
+\r
+ Clicks on links to MP3s are intercepted via JS, calls are\r
+ made to SoundManager to load/play sounds. CSS classes are\r
+ appended to the LI parent, which are used to highlight the\r
+ current play state and so on.\r
+\r
+ Class names are applied in addition to "sm2_link" base.\r
+\r
+ Default:\r
+\r
+ sm2_link\r
+\r
+ Additional states:\r
+\r
+ sm2_playing\r
+ sm2_paused\r
+\r
+ eg.\r
+\r
+ <!-- default -->\r
+ <li class="sm2_link"><a href="some.mp3">some.mp3</a></li>\r
+\r
+ <!-- playing -->\r
+ <li class="sm2_link sm2_playing"><a href="some.mp3">some.mp3</a></li>\r
+\r
+ The script also injects an HTML template containing control bar\r
+ and timing elements, which can also be targeted with CSS.\r
+\r
+\r
+ Note you don't necessarily require ul.playlist for your use\r
+ if only using one style on a page. You can just use .sm2_link\r
+ and so on, but isolate the CSS you want.\r
+\r
+ Side note: Would do multiple class definitions eg.\r
+\r
+ li.sm2_default.sm2_playing{}\r
+\r
+ .. except IE 6 has a parsing bug which may break behaviour,\r
+ applying sm2_playing {} even when the class is set to sm2_default.\r
+\r
+\r
+ If you want to make your own UI from scratch, here is the base:\r
+\r
+ Default + hover state, "click to play":\r
+\r
+ li.sm2_link {}\r
+ li.sm2_link:hover {}\r
+\r
+ Playing + hover state, "click to pause":\r
+\r
+ li.sm2_playing {}\r
+ li.sm2_playing:hover {}\r
+\r
+ Paused + hover state, "click to resume":\r
+\r
+ li.sm2_paused {}\r
+ li.sm2_paused:hover {}\r
+</pre>\r
+</div>\r
+\r
+<p><a href="http://www.schillmania.com/projects/soundmanager2/" title="Javascript MP3 sound player API">SoundManager 2 project home</a></p>\r
+\r
+</div>\r
+\r
+<!-- demo-only stuff -->\r
+<script>\r
+\r
+// enable experimental features, if #experimental is in the URL\r
+if (window.location.toString().match(/experimental/i)) {\r
+ PP_CONFIG.usePeakData = true;\r
+ PP_CONFIG.useWaveformData = true;\r
+ PP_CONFIG.useFavIcon = true;\r
+ document.getElementById('experimental-features').style.display = 'none';\r
+}\r
+\r
+var is_shiny = false;\r
+function setTheme(sTheme) {\r
+ var o = pagePlayer.getByClassName('playlist','ul');\r
+ for (var i=o.length; i--;) {\r
+ o[i].className = 'playlist'+(pagePlayer.cssBase?' '+pagePlayer.cssBase:'')+(sTheme?' '+sTheme:'')+(is_shiny?' shiny':'');\r
+ }\r
+ return false;\r
+}\r
+function setShiny(bShiny, e) {\r
+ is_shiny = bShiny;\r
+ var o = pagePlayer.getByClassName('playlist','ul');\r
+ var sClass = 'shiny';\r
+ for (var i=o.length; i--;) {\r
+ if (!bShiny) {\r
+ pagePlayer.removeClass(o[i],sClass);\r
+ } else {\r
+ pagePlayer.addClass(o[i],sClass);\r
+ }\r
+ }\r
+}\r
+</script>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+// SoundManager 2: Page Player demo, MetaData UI prototype\r
+\r
+/*jslint white: false, onevar: true, undef: true, nomen: false, eqeqeq: true, plusplus: false, bitwise: true, newcap: true, immed: true */\r
+/*global pagePlayer, document, window */\r
+\r
+var Metadata = function(oSound) {\r
+\r
+ var self = this,\r
+ pl = pagePlayer,\r
+ oLI = oSound._data.oLI,\r
+ o = oLI.getElementsByTagName('ul')[0],\r
+ oItems = o.getElementsByTagName('li'),\r
+ oTemplate = document.createElement('div'),\r
+ oTemplate2 = document.createElement('div'),\r
+ oTemplate3 = document.createElement('div'),\r
+ oDuration, i;\r
+\r
+ oTemplate.innerHTML = '<span> </span>';\r
+ oTemplate.className = 'annotation';\r
+ oTemplate2.innerHTML = '<span> </span>';\r
+ oTemplate2.className = 'annotation alt';\r
+ oTemplate3.className = 'note';\r
+\r
+ this.totalTime = 0;\r
+ this.data = [];\r
+ this.data.givenDuration = null;\r
+ this.data.currentItem = null;\r
+ this.data.mainTitle = oSound._data.oLink.innerHTML;\r
+\r
+ this.strToTime = function(sTime) {\r
+ var segments = sTime.split(':'),\r
+ seconds = 0, i;\r
+ for (i=segments.length; i--;) {\r
+ seconds += parseInt(segments[i],10)*Math.pow(60,segments.length-1-i); // hours, minutes\r
+ }\r
+ return seconds;\r
+ };\r
+\r
+ // make stuff\r
+ this.createElements = function() {\r
+ var oFrag = document.createDocumentFragment(),\r
+ oNode = null,\r
+ oNodeSpan = null,\r
+ oNode2 = null, i;\r
+ for (i=0; i<self.data.length; i++) {\r
+ oNode = (i%2===0?oTemplate:oTemplate2).cloneNode(true);\r
+ oNodeSpan = oNode.getElementsByTagName('span')[0];\r
+ oNode.rel = i;\r
+ self.data[i].o = oNode;\r
+ oNode2 = oTemplate3.cloneNode(true);\r
+ if (i%2===0) {\r
+ oNode2.className = 'note alt';\r
+ }\r
+ oNode2.innerHTML = this.data[i].title;\r
+ // evil old-skool event handlers, css:hover-only ideally would be nice excluding IE 6\r
+ oNode.onmouseover = self.mouseover;\r
+ oNode.onmouseout = self.mouseout;\r
+ this.data[i].oNote = oNode2;\r
+ oSound._data.oControls.appendChild(oNode2);\r
+ oFrag.appendChild(oNode);\r
+ }\r
+ self.refresh();\r
+ oSound._data.oStatus.appendChild(oFrag);\r
+ };\r
+\r
+ this.refreshMetadata = function(oSound) {\r
+ // Display info as appropriate\r
+ var i, j, index = null,\r
+ now = oSound.position,\r
+ metadata = oSound._data.metadata.data;\r
+ for (i=0, j=metadata.length; i<j; i++) {\r
+ if (now >= metadata[i].startTimeMS && now <= metadata[i].endTimeMS) {\r
+ index = i;\r
+ break;\r
+ }\r
+ }\r
+ if (index !== metadata.currentItem) {\r
+ // update\r
+ oSound._data.oLink.innerHTML = metadata.mainTitle+' <span class="metadata"><span class="sm2_divider"> | </span><span class="sm2_metadata">'+metadata[index].title+'</span></span>';\r
+ pl.setPageTitle(metadata[index].title+' | '+metadata.mainTitle);\r
+ metadata.currentItem = index;\r
+ }\r
+ };\r
+\r
+ this.refresh = function() {\r
+ var offset = 0,\r
+ relWidth = null,\r
+ duration = (self.data.givenDuration?self.data.givenDuration:oSound.durationEstimate), i;\r
+ for (i=0; i<self.data.length; i++) {\r
+ if (duration) {\r
+ relWidth = (((self.data[i].duration*1000)/duration)*100);\r
+ self.data[i].o.style.left = (offset?offset+'%':'-2px');\r
+ self.data[i].oNote.style.left = (offset?offset+'%':'0px');\r
+ offset += relWidth;\r
+ }\r
+ }\r
+ };\r
+\r
+ this.mouseover = function(e) {\r
+ self.data[this.rel].oNote.style.visibility = 'hidden';\r
+ self.data[this.rel].oNote.style.display = 'inline-block';\r
+ self.data[this.rel].oNote.style.marginLeft = -parseInt(self.data[this.rel].oNote.offsetWidth/2,10)+'px';\r
+ self.data[this.rel].oNote.style.visibility = 'visible';\r
+ };\r
+\r
+ this.mouseout = function() { \r
+ self.data[this.rel].oNote.style.display = 'none';\r
+ };\r
+\r
+ // ----\r
+\r
+ for (i=0; i<oItems.length; i++) {\r
+ this.data[i] = {\r
+ o: null,\r
+ title: oItems[i].getElementsByTagName('p')[0].innerHTML,\r
+ startTime: oItems[i].getElementsByTagName('span')[0].innerHTML,\r
+ startSeconds: self.strToTime(oItems[i].getElementsByTagName('span')[0].innerHTML.replace(/[()]/g,'')),\r
+ duration: 0,\r
+ durationMS: null,\r
+ startTimeMS: null,\r
+ endTimeMS: null,\r
+ oNote: null\r
+ };\r
+ }\r
+\r
+ oDuration = pl.getByClassName('duration','div',oLI);\r
+ this.data.givenDuration = (oDuration.length?self.strToTime(oDuration[0].innerHTML)*1000:0);\r
+\r
+ for (i=0; i<this.data.length; i++) {\r
+ this.data[i].duration = parseInt(this.data[i+1]?this.data[i+1].startSeconds:(self.data.givenDuration?self.data.givenDuration:oSound.durationEstimate)/1000,10)-this.data[i].startSeconds;\r
+ this.data[i].startTimeMS = this.data[i].startSeconds*1000;\r
+ this.data[i].durationMS = this.data[i].duration*1000;\r
+ this.data[i].endTimeMS = this.data[i].startTimeMS+this.data[i].durationMS;\r
+ this.totalTime += this.data[i].duration;\r
+ }\r
+\r
+ // ----\r
+\r
+ this.createElements();\r
+ this.refresh();\r
+ \r
+}; // MetaData();
\ No newline at end of file
--- /dev/null
+/**\r
+ * SoundManager 2 Demo: "Page as playlist" UI\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * An example of a Muxtape.com-style UI, where an\r
+ * unordered list of MP3 links becomes a playlist\r
+ *\r
+ * Flash 9 "MovieStar" edition supports MPEG4\r
+ * audio as well.\r
+ *\r
+ * Requires SoundManager 2 Javascript API.\r
+ */\r
+\r
+/*jslint white: false, onevar: true, undef: true, nomen: false, eqeqeq: true, plusplus: false, bitwise: true, newcap: true, immed: true */\r
+/*global soundManager, window, document, navigator, setTimeout, attachEvent, Metadata, PP_CONFIG */\r
+\r
+var pagePlayer = null;\r
+\r
+function PagePlayer() {\r
+\r
+ var self = this,\r
+ pl = this,\r
+ sm = soundManager, // soundManager instance\r
+ _event,\r
+ vuDataCanvas = null,\r
+ controlTemplate = null,\r
+ _head = document.getElementsByTagName('head')[0],\r
+ spectrumContainer = null,\r
+ // sniffing for favicon stuff, IE workarounds and touchy-feely devices\r
+ ua = navigator.userAgent,\r
+ supportsFavicon = (ua.match(/(opera|firefox)/i)),\r
+ isTouchDevice = (ua.match(/ipad|ipod|iphone/i)),\r
+ cleanup;\r
+\r
+ // configuration options\r
+ // note that if Flash 9 is required, you must set soundManager.flashVersion = 9 in your script before this point.\r
+\r
+ this.config = {\r
+ usePeakData: false, // [Flash 9 only]: show peak data\r
+ useWaveformData: false, // [Flash 9 only]: enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire.\r
+ useEQData: false, // [Flash 9 only]: enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.\r
+ fillGraph: false, // [Flash 9 only]: draw full lines instead of only top (peak) spectrum points\r
+ allowRightClick: true, // let users right-click MP3 links ("save as...", etc.) or discourage (can't prevent.)\r
+ useThrottling: true, // try to rate-limit potentially-expensive calls (eg. dragging position around)\r
+ autoStart: false, // begin playing first sound when page loads\r
+ playNext: true, // stop after one sound, or play through list until end\r
+ updatePageTitle: true, // change the page title while playing sounds\r
+ emptyTime: '-:--', // null/undefined timer values (before data is available)\r
+ useFavIcon: false // try to show peakData in address bar (Firefox + Opera) - may be too CPU heavy\r
+ };\r
+\r
+ this.css = { // CSS class names appended to link during various states\r
+ sDefault: 'sm2_link', // default state\r
+ sLoading: 'sm2_loading',\r
+ sPlaying: 'sm2_playing',\r
+ sPaused: 'sm2_paused'\r
+ };\r
+\r
+ this.sounds = [];\r
+ this.soundsByObject = [];\r
+ this.lastSound = null;\r
+ this.soundCount = 0;\r
+ this.strings = [];\r
+ this.dragActive = false;\r
+ this.dragExec = new Date();\r
+ this.dragTimer = null;\r
+ this.pageTitle = document.title;\r
+ this.lastWPExec = new Date();\r
+ this.lastWLExec = new Date();\r
+ this.vuMeterData = [];\r
+ this.oControls = null;\r
+\r
+ this._mergeObjects = function(oMain,oAdd) {\r
+ // non-destructive merge\r
+ var o1 = {}, o2, i, o; // clone o1\r
+ for (i in oMain) {\r
+ if (oMain.hasOwnProperty(i)) {\r
+ o1[i] = oMain[i];\r
+ }\r
+ }\r
+ o2 = (typeof oAdd === 'undefined'?{}:oAdd);\r
+ for (o in o2) {\r
+ if (typeof o1[o] === 'undefined') {\r
+ o1[o] = o2[o];\r
+ }\r
+ }\r
+ return o1;\r
+ };\r
+\r
+ _event = (function() {\r
+\r
+ var old = (window.attachEvent && !window.addEventListener),\r
+ _slice = Array.prototype.slice,\r
+ evt = {\r
+ add: (old?'attachEvent':'addEventListener'),\r
+ remove: (old?'detachEvent':'removeEventListener')\r
+ };\r
+\r
+ function getArgs(oArgs) {\r
+ var args = _slice.call(oArgs), len = args.length;\r
+ if (old) {\r
+ args[1] = 'on' + args[1]; // prefix\r
+ if (len > 3) {\r
+ args.pop(); // no capture\r
+ }\r
+ } else if (len === 3) {\r
+ args.push(false);\r
+ }\r
+ return args;\r
+ }\r
+\r
+ function apply(args, sType) {\r
+ var element = args.shift(),\r
+ method = [evt[sType]];\r
+ if (old) {\r
+ element[method](args[0], args[1]);\r
+ } else {\r
+ element[method].apply(element, args);\r
+ }\r
+ }\r
+\r
+ function add() {\r
+ apply(getArgs(arguments), 'add');\r
+ }\r
+\r
+ function remove() {\r
+ apply(getArgs(arguments), 'remove');\r
+ }\r
+\r
+ return {\r
+ 'add': add,\r
+ 'remove': remove\r
+ };\r
+\r
+ }());\r
+\r
+ // event + DOM utilities\r
+\r
+ this.hasClass = function(o, cStr) {\r
+ return (typeof(o.className)!=='undefined'?new RegExp('(^|\\s)'+cStr+'(\\s|$)').test(o.className):false);\r
+ };\r
+\r
+ this.addClass = function(o, cStr) {\r
+ if (!o || !cStr || self.hasClass(o,cStr)) {\r
+ return false; // safety net\r
+ }\r
+ o.className = (o.className?o.className+' ':'')+cStr;\r
+ };\r
+\r
+ this.removeClass = function(o, cStr) {\r
+ if (!o || !cStr || !self.hasClass(o,cStr)) {\r
+ return false;\r
+ }\r
+ o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');\r
+ };\r
+\r
+ this.select = function(className, oParent) {\r
+ var result = self.getByClassName(className, 'div', oParent||null);\r
+ return (result ? result[0] : null);\r
+ };\r
+\r
+ this.getByClassName = (document.querySelectorAll ? function(className, tagNames, oParent) { // tagNames: string or ['div', 'p'] etc.\r
+\r
+ var pattern = ('.'+className), qs;\r
+ if (tagNames) {\r
+ tagNames = tagNames.split(' ');\r
+ }\r
+ qs = (tagNames.length > 1 ? tagNames.join(pattern+', ') : tagNames[0]+pattern);\r
+ return (oParent?oParent:document).querySelectorAll(qs);\r
+\r
+ } : function(className, tagNames, oParent) {\r
+\r
+ var node = (oParent?oParent:document), matches = [], i, j, nodes = [];\r
+ if (tagNames) {\r
+ tagNames = tagNames.split(' ');\r
+ }\r
+ if (tagNames instanceof Array) {\r
+ for (i=tagNames.length; i--;) {\r
+ if (!nodes || !nodes[tagNames[i]]) {\r
+ nodes[tagNames[i]] = node.getElementsByTagName(tagNames[i]);\r
+ }\r
+ }\r
+ for (i=tagNames.length; i--;) {\r
+ for (j=nodes[tagNames[i]].length; j--;) {\r
+ if (self.hasClass(nodes[tagNames[i]][j], className)) {\r
+ matches.push(nodes[tagNames[i]][j]);\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ nodes = node.all||node.getElementsByTagName('*');\r
+ for (i=0, j=nodes.length; i<j; i++) {\r
+ if (self.hasClass(nodes[i],className)) {\r
+ matches.push(nodes[i]);\r
+ }\r
+ }\r
+ }\r
+ return matches;\r
+\r
+ });\r
+ \r
+ this.isChildOfClass = function(oChild, oClass) {\r
+ if (!oChild || !oClass) {\r
+ return false;\r
+ }\r
+ while (oChild.parentNode && !self.hasClass(oChild,oClass)) {\r
+ oChild = oChild.parentNode;\r
+ }\r
+ return (self.hasClass(oChild,oClass));\r
+ };\r
+\r
+ this.getParentByNodeName = function(oChild, sParentNodeName) {\r
+ if (!oChild || !sParentNodeName) {\r
+ return false;\r
+ }\r
+ sParentNodeName = sParentNodeName.toLowerCase();\r
+ while (oChild.parentNode && sParentNodeName !== oChild.parentNode.nodeName.toLowerCase()) {\r
+ oChild = oChild.parentNode;\r
+ }\r
+ return (oChild.parentNode && sParentNodeName === oChild.parentNode.nodeName.toLowerCase()?oChild.parentNode:null);\r
+ };\r
+\r
+ this.getOffX = function(o) {\r
+ // http://www.xs4all.nl/~ppk/js/findpos.html\r
+ var curleft = 0;\r
+ if (o.offsetParent) {\r
+ while (o.offsetParent) {\r
+ curleft += o.offsetLeft;\r
+ o = o.offsetParent;\r
+ }\r
+ }\r
+ else if (o.x) {\r
+ curleft += o.x;\r
+ }\r
+ return curleft;\r
+ };\r
+\r
+ this.getTime = function(nMSec, bAsString) {\r
+ // convert milliseconds to mm:ss, return as object literal or string\r
+ var nSec = Math.floor(nMSec/1000),\r
+ min = Math.floor(nSec/60),\r
+ sec = nSec-(min*60);\r
+ // if (min === 0 && sec === 0) return null; // return 0:00 as null\r
+ return (bAsString?(min+':'+(sec<10?'0'+sec:sec)):{'min':min,'sec':sec});\r
+ };\r
+\r
+ this.getSoundByObject = function(o) {\r
+ return (typeof self.soundsByObject[o.id] !== 'undefined'?self.soundsByObject[o.id]:null);\r
+ };\r
+\r
+ this.getPreviousItem = function(o) {\r
+ // given <li> playlist item, find previous <li> and then <a>\r
+ if (o.previousElementSibling) {\r
+ o = o.previousElementSibling;\r
+ } else {\r
+ o = o.previousSibling; // move from original node..\r
+ while (o && o.previousSibling && o.previousSibling.nodeType !== 1) {\r
+ o = o.previousSibling;\r
+ }\r
+ }\r
+ if (o.nodeName.toLowerCase() !== 'li') {\r
+ return null;\r
+ } else {\r
+ return o.getElementsByTagName('a')[0];\r
+ }\r
+ };\r
+\r
+ this.playPrevious = function(oSound) {\r
+ if (!oSound) {\r
+ oSound = self.lastSound;\r
+ }\r
+ if (!oSound) {\r
+ return false;\r
+ }\r
+ var previousItem = self.getPreviousItem(oSound._data.oLI);\r
+ if (previousItem) {\r
+ pl.handleClick({target:previousItem}); // fake a click event - aren't we sneaky. ;)\r
+ }\r
+ return previousItem;\r
+ };\r
+\r
+ this.getNextItem = function(o) {\r
+ // given <li> playlist item, find next <li> and then <a>\r
+ if (o.nextElementSibling) {\r
+ o = o.nextElementSibling;\r
+ } else {\r
+ o = o.nextSibling; // move from original node..\r
+ while (o && o.nextSibling && o.nextSibling.nodeType !== 1) {\r
+ o = o.nextSibling;\r
+ }\r
+ }\r
+ if (o.nodeName.toLowerCase() !== 'li') {\r
+ return null;\r
+ } else {\r
+ return o.getElementsByTagName('a')[0];\r
+ }\r
+ };\r
+\r
+ this.playNext = function(oSound) {\r
+ if (!oSound) {\r
+ oSound = self.lastSound;\r
+ }\r
+ if (!oSound) {\r
+ return false;\r
+ }\r
+ var nextItem = self.getNextItem(oSound._data.oLI);\r
+ if (nextItem) {\r
+ pl.handleClick({target:nextItem}); // fake a click event - aren't we sneaky. ;)\r
+ }\r
+ return nextItem;\r
+ };\r
+\r
+ this.setPageTitle = function(sTitle) {\r
+ if (!self.config.updatePageTitle) {\r
+ return false;\r
+ }\r
+ try {\r
+ document.title = (sTitle?sTitle+' - ':'')+self.pageTitle;\r
+ } catch(e) {\r
+ // oh well\r
+ self.setPageTitle = function() {\r
+ return false;\r
+ };\r
+ }\r
+ };\r
+\r
+ this.events = {\r
+\r
+ // handlers for sound events as they're started/stopped/played\r
+\r
+ play: function() {\r
+ pl.removeClass(this._data.oLI,this._data.className);\r
+ this._data.className = pl.css.sPlaying;\r
+ pl.addClass(this._data.oLI,this._data.className);\r
+ self.setPageTitle(this._data.originalTitle);\r
+ },\r
+\r
+ stop: function() {\r
+ pl.removeClass(this._data.oLI,this._data.className);\r
+ this._data.className = '';\r
+ this._data.oPosition.style.width = '0px';\r
+ self.setPageTitle();\r
+ self.resetPageIcon();\r
+ },\r
+\r
+ pause: function() {\r
+ if (pl.dragActive) {\r
+ return false;\r
+ }\r
+ pl.removeClass(this._data.oLI,this._data.className);\r
+ this._data.className = pl.css.sPaused;\r
+ pl.addClass(this._data.oLI,this._data.className);\r
+ self.setPageTitle();\r
+ self.resetPageIcon();\r
+ },\r
+\r
+ resume: function() {\r
+ if (pl.dragActive) {\r
+ return false;\r
+ }\r
+ pl.removeClass(this._data.oLI,this._data.className);\r
+ this._data.className = pl.css.sPlaying;\r
+ pl.addClass(this._data.oLI,this._data.className);\r
+ },\r
+\r
+ finish: function() {\r
+ pl.removeClass(this._data.oLI,this._data.className);\r
+ this._data.className = '';\r
+ this._data.oPosition.style.width = '0px';\r
+ // play next if applicable\r
+ if (self.config.playNext) {\r
+ pl.playNext(this);\r
+ } else {\r
+ self.setPageTitle();\r
+ self.resetPageIcon();\r
+ }\r
+ },\r
+\r
+ whileloading: function() {\r
+ function doWork() {\r
+ this._data.oLoading.style.width = (((this.bytesLoaded/this.bytesTotal)*100)+'%'); // theoretically, this should work.\r
+ if (!this._data.didRefresh && this._data.metadata) {\r
+ this._data.didRefresh = true;\r
+ this._data.metadata.refresh();\r
+ }\r
+ }\r
+ if (!pl.config.useThrottling) {\r
+ doWork.apply(this);\r
+ } else {\r
+ var d = new Date();\r
+ if (d && d-self.lastWLExec > 50 || this.bytesLoaded === this.bytesTotal) {\r
+ doWork.apply(this);\r
+ self.lastWLExec = d;\r
+ }\r
+ }\r
+\r
+ },\r
+\r
+ onload: function() {\r
+ if (!this.loaded) {\r
+ var oTemp = this._data.oLI.getElementsByTagName('a')[0],\r
+ oString = oTemp.innerHTML,\r
+ oThis = this;\r
+ oTemp.innerHTML = oString+' <span style="font-size:0.5em"> | Load failed, d\'oh! '+(sm.sandbox.noRemote?' Possible cause: Flash sandbox is denying remote URL access.':(sm.sandbox.noLocal?'Flash denying local filesystem access':'404?'))+'</span>';\r
+ setTimeout(function(){\r
+ oTemp.innerHTML = oString;\r
+ // pl.events.finish.apply(oThis); // load next\r
+ },5000);\r
+ } else {\r
+ if (this._data.metadata) {\r
+ this._data.metadata.refresh();\r
+ }\r
+ }\r
+ },\r
+\r
+ whileplaying: function() {\r
+ var d = null;\r
+ if (pl.dragActive || !pl.config.useThrottling) {\r
+ self.updateTime.apply(this);\r
+ if (sm.flashVersion >= 9) {\r
+ if (pl.config.usePeakData && this.instanceOptions.usePeakData) {\r
+ self.updatePeaks.apply(this);\r
+ }\r
+ if (pl.config.useWaveformData && this.instanceOptions.useWaveformData || pl.config.useEQData && this.instanceOptions.useEQData) {\r
+ self.updateGraph.apply(this);\r
+ }\r
+ }\r
+ if (this._data.metadata) {\r
+ d = new Date();\r
+ if (d && d-self.lastWPExec>500) {\r
+ this._data.metadata.refreshMetadata(this);\r
+ self.lastWPExec = d;\r
+ }\r
+ }\r
+ this._data.oPosition.style.width = (((this.position/self.getDurationEstimate(this))*100)+'%');\r
+ } else {\r
+ d = new Date();\r
+ if (d-self.lastWPExec>30) {\r
+ self.updateTime.apply(this);\r
+ if (sm.flashVersion >= 9) {\r
+ if (pl.config.usePeakData && this.instanceOptions.usePeakData) {\r
+ self.updatePeaks.apply(this);\r
+ }\r
+ if (pl.config.useWaveformData && this.instanceOptions.useWaveformData || pl.config.useEQData && this.instanceOptions.useEQData) {\r
+ self.updateGraph.apply(this);\r
+ }\r
+ }\r
+ if (this._data.metadata) {\r
+ this._data.metadata.refreshMetadata(this);\r
+ }\r
+ this._data.oPosition.style.width = (((this.position/self.getDurationEstimate(this))*100)+'%');\r
+ self.lastWPExec = d;\r
+ }\r
+ }\r
+ }\r
+\r
+ }; // events{}\r
+\r
+ this.setPageIcon = function(sDataURL) {\r
+ if (!self.config.useFavIcon || !self.config.usePeakData || !sDataURL) {\r
+ return false;\r
+ }\r
+ var link = document.getElementById('sm2-favicon');\r
+ if (link) {\r
+ _head.removeChild(link);\r
+ link = null;\r
+ }\r
+ if (!link) {\r
+ link = document.createElement('link');\r
+ link.id = 'sm2-favicon';\r
+ link.rel = 'shortcut icon';\r
+ link.type = 'image/png';\r
+ link.href = sDataURL;\r
+ document.getElementsByTagName('head')[0].appendChild(link);\r
+ }\r
+ };\r
+\r
+ this.resetPageIcon = function() {\r
+ if (!self.config.useFavIcon) {\r
+ return false;\r
+ }\r
+ var link = document.getElementById('favicon');\r
+ if (link) {\r
+ link.href = '/favicon.ico';\r
+ }\r
+ };\r
+\r
+ this.updatePeaks = function() {\r
+ var o = this._data.oPeak,\r
+ oSpan = o.getElementsByTagName('span');\r
+ oSpan[0].style.marginTop = (13-(Math.floor(15*this.peakData.left))+'px');\r
+ oSpan[1].style.marginTop = (13-(Math.floor(15*this.peakData.right))+'px');\r
+ if (sm.flashVersion > 8 && self.config.useFavIcon && self.config.usePeakData) {\r
+ self.setPageIcon(self.vuMeterData[parseInt(16*this.peakData.left,10)][parseInt(16*this.peakData.right,10)]);\r
+ }\r
+ };\r
+ \r
+ this.updateGraph = function() {\r
+ if (pl.config.flashVersion < 9 || (!pl.config.useWaveformData && !pl.config.useEQData)) {\r
+ return false;\r
+ }\r
+ var sbC = this._data.oGraph.getElementsByTagName('div'),\r
+ scale, i, offset;\r
+ if (pl.config.useWaveformData) {\r
+ // raw waveform\r
+ scale = 8; // Y axis (+/- this distance from 0)\r
+ for (i=255; i--;) {\r
+ sbC[255-i].style.marginTop = (1+scale+Math.ceil(this.waveformData.left[i]*-scale))+'px';\r
+ }\r
+ } else {\r
+ // eq spectrum\r
+ offset = 9;\r
+ for (i=255; i--;) {\r
+ sbC[255-i].style.marginTop = ((offset*2)-1+Math.ceil(this.eqData[i]*-offset))+'px';\r
+ }\r
+ }\r
+ };\r
+ \r
+ this.resetGraph = function() {\r
+ if (!pl.config.useEQData || pl.config.flashVersion<9) {\r
+ return false;\r
+ }\r
+ var sbC = this._data.oGraph.getElementsByTagName('div'),\r
+ scale = (!pl.config.useEQData?'9px':'17px'),\r
+ nHeight = (!pl.config.fillGraph?'1px':'32px'),\r
+ i;\r
+ for (i=255; i--;) {\r
+ sbC[255-i].style.marginTop = scale; // EQ scale\r
+ sbC[255-i].style.height = nHeight;\r
+ }\r
+ };\r
+ \r
+ this.updateTime = function() {\r
+ var str = self.strings.timing.replace('%s1',self.getTime(this.position,true));\r
+ str = str.replace('%s2',self.getTime(self.getDurationEstimate(this),true));\r
+ this._data.oTiming.innerHTML = str;\r
+ };\r
+\r
+ this.getTheDamnTarget = function(e) {\r
+ return (e.target||(window.event?window.event.srcElement:null));\r
+ };\r
+ \r
+ this.withinStatusBar = function(o) {\r
+ return (self.isChildOfClass(o,'playlist')) && (self.isChildOfClass(o,'controls'));\r
+ };\r
+\r
+ this.handleClick = function(e) {\r
+\r
+ // a sound (or something) was clicked - determine what and handle appropriately\r
+\r
+ if (e.button === 2) {\r
+ if (!pl.config.allowRightClick) {\r
+ pl.stopEvent(e);\r
+ }\r
+ return pl.config.allowRightClick; // ignore right-clicks\r
+ }\r
+ var o = self.getTheDamnTarget(e),\r
+ sURL, soundURL, thisSound, oControls, oLI, str;\r
+ if (!o) {\r
+ return true;\r
+ }\r
+ if (self.dragActive) {\r
+ self.stopDrag(); // to be safe\r
+ }\r
+ if (self.withinStatusBar(o)) {\r
+ // self.handleStatusClick(e);\r
+ return false;\r
+ }\r
+ if (o.nodeName.toLowerCase() !== 'a') {\r
+ o = self.getParentByNodeName(o,'a');\r
+ }\r
+ if (!o) {\r
+ // not a link\r
+ return true;\r
+ }\r
+\r
+ // OK, we're dealing with a link\r
+\r
+ sURL = o.getAttribute('href');\r
+\r
+ if (!o.href || (!sm.canPlayLink(o) && !self.hasClass(o,'playable')) || self.hasClass(o,'exclude')) {\r
+\r
+ // do nothing, don't return anything.\r
+ return true;\r
+\r
+ } else {\r
+\r
+ // we have something we're interested in.\r
+\r
+ // find and init parent UL, if need be\r
+ self.initUL(self.getParentByNodeName(o, 'ul'));\r
+\r
+ // and decorate the link too, if needed\r
+ self.initItem(o);\r
+\r
+ soundURL = o.href;\r
+ thisSound = self.getSoundByObject(o);\r
+\r
+ if (thisSound) {\r
+\r
+ // sound already exists\r
+ self.setPageTitle(thisSound._data.originalTitle);\r
+ if (thisSound === self.lastSound) {\r
+ // ..and was playing (or paused) and isn't in an error state\r
+ if (thisSound.readyState !== 2) {\r
+ if (thisSound.playState !== 1) {\r
+ // not yet playing\r
+ thisSound.play();\r
+ } else {\r
+ thisSound.togglePause();\r
+ }\r
+ } else {\r
+ sm._writeDebug('Warning: sound failed to load (security restrictions, 404 or bad format)',2);\r
+ }\r
+ } else {\r
+ // ..different sound\r
+ if (self.lastSound) {\r
+ self.stopSound(self.lastSound);\r
+ }\r
+ if (spectrumContainer) {\r
+ thisSound._data.oTimingBox.appendChild(spectrumContainer);\r
+ }\r
+ thisSound.togglePause(); // start playing current\r
+ }\r
+\r
+ } else {\r
+\r
+ // create sound\r
+ thisSound = sm.createSound({\r
+ id:o.id,\r
+ url:decodeURI(soundURL),\r
+ onplay:self.events.play,\r
+ onstop:self.events.stop,\r
+ onpause:self.events.pause,\r
+ onresume:self.events.resume,\r
+ onfinish:self.events.finish,\r
+ type:(o.type||null),\r
+ whileloading:self.events.whileloading,\r
+ whileplaying:self.events.whileplaying,\r
+ onmetadata:self.events.metadata,\r
+ onload:self.events.onload\r
+ });\r
+\r
+ // append control template\r
+ oControls = self.oControls.cloneNode(true);\r
+ oLI = o.parentNode;\r
+ oLI.appendChild(oControls);\r
+ if (spectrumContainer) {\r
+ oLI.appendChild(spectrumContainer);\r
+ }\r
+ self.soundsByObject[o.id] = thisSound;\r
+\r
+ // tack on some custom data\r
+ thisSound._data = {\r
+ oLink: o, // DOM reference within SM2 object event handlers\r
+ oLI: oLI,\r
+ oControls: self.select('controls',oLI),\r
+ oStatus: self.select('statusbar',oLI),\r
+ oLoading: self.select('loading',oLI),\r
+ oPosition: self.select('position',oLI),\r
+ oTimingBox: self.select('timing',oLI),\r
+ oTiming: self.select('timing',oLI).getElementsByTagName('div')[0],\r
+ oPeak: self.select('peak',oLI),\r
+ oGraph: self.select('spectrum-box',oLI),\r
+ className: self.css.sPlaying,\r
+ originalTitle: o.innerHTML,\r
+ metadata: null\r
+ };\r
+\r
+ if (spectrumContainer) {\r
+ thisSound._data.oTimingBox.appendChild(spectrumContainer);\r
+ }\r
+\r
+ // "Metadata"\r
+ if (thisSound._data.oLI.getElementsByTagName('ul').length) {\r
+ thisSound._data.metadata = new Metadata(thisSound);\r
+ }\r
+\r
+ // set initial timer stuff (before loading)\r
+ str = self.strings.timing.replace('%s1',self.config.emptyTime);\r
+ str = str.replace('%s2',self.config.emptyTime);\r
+ thisSound._data.oTiming.innerHTML = str;\r
+ self.sounds.push(thisSound);\r
+ if (self.lastSound) {\r
+ self.stopSound(self.lastSound);\r
+ }\r
+ self.resetGraph.apply(thisSound);\r
+ thisSound.play();\r
+\r
+ }\r
+\r
+ self.lastSound = thisSound; // reference for next call\r
+ return self.stopEvent(e);\r
+\r
+ }\r
+\r
+ };\r
+ \r
+ this.handleMouseDown = function(e) {\r
+ // a sound link was clicked\r
+ if (isTouchDevice && e.touches) {\r
+ e = e.touches[0];\r
+ }\r
+ if (e.button === 2) {\r
+ if (!pl.config.allowRightClick) {\r
+ pl.stopEvent(e);\r
+ }\r
+ return pl.config.allowRightClick; // ignore right-clicks\r
+ }\r
+ var o = self.getTheDamnTarget(e);\r
+ if (!o) {\r
+ return true;\r
+ }\r
+ if (!self.withinStatusBar(o)) {\r
+ return true;\r
+ }\r
+ self.dragActive = true;\r
+ self.lastSound.pause();\r
+ self.setPosition(e);\r
+ if (!isTouchDevice) {\r
+ _event.add(document,'mousemove',self.handleMouseMove);\r
+ } else {\r
+ _event.add(document,'touchmove',self.handleMouseMove);\r
+ }\r
+ self.addClass(self.lastSound._data.oControls,'dragging');\r
+ return self.stopEvent(e);\r
+ };\r
+ \r
+ this.handleMouseMove = function(e) {\r
+ if (isTouchDevice && e.touches) {\r
+ e = e.touches[0];\r
+ }\r
+ // set position accordingly\r
+ if (self.dragActive) {\r
+ if (self.config.useThrottling) {\r
+ // be nice to CPU/externalInterface\r
+ var d = new Date();\r
+ if (d-self.dragExec>20) {\r
+ self.setPosition(e);\r
+ } else {\r
+ window.clearTimeout(self.dragTimer);\r
+ self.dragTimer = window.setTimeout(function(){self.setPosition(e);},20);\r
+ }\r
+ self.dragExec = d;\r
+ } else {\r
+ // oh the hell with it\r
+ self.setPosition(e);\r
+ }\r
+ } else {\r
+ self.stopDrag();\r
+ }\r
+ e.stopPropagation = true;\r
+ return false;\r
+ };\r
+ \r
+ this.stopDrag = function(e) {\r
+ if (self.dragActive) {\r
+ self.removeClass(self.lastSound._data.oControls,'dragging');\r
+ if (!isTouchDevice) {\r
+ _event.remove(document,'mousemove',self.handleMouseMove);\r
+ } else {\r
+ _event.remove(document,'touchmove',self.handleMouseMove);\r
+ }\r
+ if (!pl.hasClass(self.lastSound._data.oLI,self.css.sPaused)) {\r
+ self.lastSound.resume();\r
+ }\r
+ self.dragActive = false;\r
+ return self.stopEvent(e);\r
+ }\r
+ };\r
+ \r
+ this.handleStatusClick = function(e) {\r
+ self.setPosition(e);\r
+ if (!pl.hasClass(self.lastSound._data.oLI,self.css.sPaused)) {\r
+ self.resume();\r
+ }\r
+ return self.stopEvent(e);\r
+ };\r
+ \r
+ this.stopEvent = function(e) {\r
+ if (typeof e !== 'undefined') {\r
+ if (typeof e.preventDefault !== 'undefined') {\r
+ e.preventDefault();\r
+ } else {\r
+ e.stopPropagation = true;\r
+ e.returnValue = false;\r
+ }\r
+ }\r
+ return false;\r
+ };\r
+ \r
+ this.setPosition = function(e) {\r
+ // called from slider control\r
+ var oThis = self.getTheDamnTarget(e),\r
+ x, oControl, oSound, nMsecOffset;\r
+ if (!oThis) {\r
+ return true;\r
+ }\r
+ oControl = oThis;\r
+ while (!self.hasClass(oControl,'controls') && oControl.parentNode) {\r
+ oControl = oControl.parentNode;\r
+ }\r
+ oSound = self.lastSound;\r
+ x = parseInt(e.clientX,10);\r
+ // play sound at this position\r
+ nMsecOffset = Math.floor((x-self.getOffX(oControl)-4)/(oControl.offsetWidth)*self.getDurationEstimate(oSound));\r
+ if (!isNaN(nMsecOffset)) {\r
+ nMsecOffset = Math.min(nMsecOffset,oSound.duration);\r
+ }\r
+ if (!isNaN(nMsecOffset)) {\r
+ oSound.setPosition(nMsecOffset);\r
+ }\r
+ };\r
+\r
+ this.stopSound = function(oSound) {\r
+ sm._writeDebug('stopping sound: '+oSound.id);\r
+ sm.stop(oSound.id);\r
+ if (!isTouchDevice) { // iOS 4.2+ security blocks onfinish() -> playNext() if we set a .src in-between(?)\r
+ sm.unload(oSound.id);\r
+ }\r
+ };\r
+\r
+ this.getDurationEstimate = function(oSound) {\r
+ if (oSound.instanceOptions.isMovieStar) {\r
+ return (oSound.duration);\r
+ } else {\r
+ return (!oSound._data.metadata || !oSound._data.metadata.data.givenDuration ? (oSound.durationEstimate||0) : oSound._data.metadata.data.givenDuration);\r
+ }\r
+ };\r
+\r
+ this.createVUData = function() {\r
+\r
+ var i=0, j=0,\r
+ canvas = vuDataCanvas.getContext('2d'),\r
+ vuGrad = canvas.createLinearGradient(0, 16, 0, 0),\r
+ bgGrad, outline;\r
+\r
+ vuGrad.addColorStop(0,'rgb(0,192,0)');\r
+ vuGrad.addColorStop(0.30,'rgb(0,255,0)');\r
+ vuGrad.addColorStop(0.625,'rgb(255,255,0)');\r
+ vuGrad.addColorStop(0.85,'rgb(255,0,0)');\r
+ bgGrad = canvas.createLinearGradient(0, 16, 0, 0);\r
+ outline = 'rgba(0,0,0,0.2)';\r
+ bgGrad.addColorStop(0,outline);\r
+ bgGrad.addColorStop(1,'rgba(0,0,0,0.5)');\r
+ for (i=0; i<16; i++) {\r
+ self.vuMeterData[i] = [];\r
+ }\r
+ for (i=0; i<16; i++) {\r
+ for (j=0; j<16; j++) {\r
+ // reset/erase canvas\r
+ vuDataCanvas.setAttribute('width',16);\r
+ vuDataCanvas.setAttribute('height',16);\r
+ // draw new stuffs\r
+ canvas.fillStyle = bgGrad;\r
+ canvas.fillRect(0,0,7,15);\r
+ canvas.fillRect(8,0,7,15);\r
+ /*\r
+ // shadow\r
+ canvas.fillStyle = 'rgba(0,0,0,0.1)';\r
+ canvas.fillRect(1,15-i,7,17-(17-i));\r
+ canvas.fillRect(9,15-j,7,17-(17-j));\r
+ */\r
+ canvas.fillStyle = vuGrad;\r
+ canvas.fillRect(0,15-i,7,16-(16-i));\r
+ canvas.fillRect(8,15-j,7,16-(16-j));\r
+ // and now, clear out some bits.\r
+ canvas.clearRect(0,3,16,1);\r
+ canvas.clearRect(0,7,16,1);\r
+ canvas.clearRect(0,11,16,1);\r
+ self.vuMeterData[i][j] = vuDataCanvas.toDataURL('image/png');\r
+ // for debugging VU images\r
+ /*\r
+ var o = document.createElement('img');\r
+ o.style.marginRight = '5px'; \r
+ o.src = self.vuMeterData[i][j];\r
+ document.documentElement.appendChild(o);\r
+ */\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ this.testCanvas = function() {\r
+ // canvas + toDataURL();\r
+ var c = document.createElement('canvas'),\r
+ ctx = null, ok;\r
+ if (!c || typeof c.getContext === 'undefined') {\r
+ return null;\r
+ }\r
+ ctx = c.getContext('2d');\r
+ if (!ctx || typeof c.toDataURL !== 'function') {\r
+ return null;\r
+ }\r
+ // just in case..\r
+ try {\r
+ ok = c.toDataURL('image/png');\r
+ } catch(e) {\r
+ // no canvas or no toDataURL()\r
+ return null;\r
+ }\r
+ // assume we're all good.\r
+ return c;\r
+ };\r
+\r
+ this.initItem = function(oNode) {\r
+ if (!oNode.id) {\r
+ oNode.id = 'pagePlayerMP3Sound'+(self.soundCount++);\r
+ }\r
+ self.addClass(oNode,self.css.sDefault); // add default CSS decoration\r
+ };\r
+\r
+ this.initUL = function(oULNode) {\r
+ // set up graph box stuffs\r
+ if (sm.flashVersion >= 9) {\r
+ self.addClass(oULNode,self.cssBase);\r
+ }\r
+ };\r
+\r
+ this.init = function(oConfig) {\r
+\r
+ if (oConfig) {\r
+ // allow overriding via arguments object\r
+ sm._writeDebug('pagePlayer.init(): Using custom configuration');\r
+ this.config = this._mergeObjects(oConfig,this.config);\r
+ } else {\r
+ sm._writeDebug('pagePlayer.init(): Using default configuration');\r
+ }\r
+\r
+ var i, spectrumBox, sbC, oF, oClone, oTiming;\r
+\r
+ // apply externally-defined override, if applicable\r
+ this.cssBase = []; // optional features added to ul.playlist\r
+\r
+ // apply some items to SM2\r
+ sm.useFlashBlock = true;\r
+\r
+ if (sm.flashVersion >= 9) {\r
+\r
+ sm.defaultOptions.usePeakData = this.config.usePeakData;\r
+ sm.defaultOptions.useWaveformData = this.config.useWaveformData;\r
+ sm.defaultOptions.useEQData = this.config.useEQData;\r
+\r
+ if (this.config.usePeakData) {\r
+ this.cssBase.push('use-peak');\r
+ }\r
+\r
+ if (this.config.useWaveformData || this.config.useEQData) {\r
+ this.cssBase.push('use-spectrum');\r
+ }\r
+\r
+ this.cssBase = this.cssBase.join(' ');\r
+\r
+ if (this.config.useFavIcon) {\r
+ vuDataCanvas = self.testCanvas();\r
+ if (vuDataCanvas && supportsFavicon) {\r
+ // these browsers support dynamically-updating the favicon\r
+ self.createVUData();\r
+ } else {\r
+ // browser doesn't support doing this\r
+ this.config.useFavIcon = false;\r
+ }\r
+ }\r
+\r
+ } else if (this.config.usePeakData || this.config.useWaveformData || this.config.useEQData) {\r
+\r
+ sm._writeDebug('Page player: Note: soundManager.flashVersion = 9 is required for peak/waveform/EQ features.');\r
+\r
+ }\r
+\r
+ controlTemplate = document.createElement('div');\r
+\r
+ controlTemplate.innerHTML = [\r
+\r
+ // control markup inserted dynamically after each page player link\r
+ // if you want to change the UI layout, this is the place to do it.\r
+\r
+ ' <div class="controls">',\r
+ ' <div class="statusbar">',\r
+ ' <div class="loading"></div>',\r
+ ' <div class="position"></div>',\r
+ ' </div>',\r
+ ' </div>',\r
+\r
+ ' <div class="timing">',\r
+ ' <div id="sm2_timing" class="timing-data">',\r
+ ' <span class="sm2_position">%s1</span> / <span class="sm2_total">%s2</span>',\r
+ ' </div>',\r
+ ' </div>',\r
+\r
+ ' <div class="peak">',\r
+ ' <div class="peak-box"><span class="l"></span><span class="r"></span></div>',\r
+ ' </div>',\r
+\r
+ ' <div class="spectrum-container">',\r
+ ' <div class="spectrum-box">',\r
+ ' <div class="spectrum"></div>',\r
+ ' </div>',\r
+ ' </div>'\r
+\r
+ ].join('\n');\r
+\r
+ if (sm.flashVersion >= 9) {\r
+\r
+ // create the spectrum box ish\r
+ spectrumContainer = self.select('spectrum-container',controlTemplate);\r
+\r
+ // take out of template, too\r
+ spectrumContainer = controlTemplate.removeChild(spectrumContainer);\r
+\r
+ spectrumBox = self.select('spectrum-box',spectrumContainer);\r
+\r
+ sbC = spectrumBox.getElementsByTagName('div')[0];\r
+ oF = document.createDocumentFragment();\r
+ oClone = null;\r
+ for (i=256; i--;) {\r
+ oClone = sbC.cloneNode(false);\r
+ oClone.style.left = (i)+'px';\r
+ oF.appendChild(oClone);\r
+ }\r
+ spectrumBox.removeChild(sbC);\r
+ spectrumBox.appendChild(oF);\r
+\r
+ } else {\r
+\r
+ // flash 8-only, take out the spectrum container and peak elements\r
+ controlTemplate.removeChild(self.select('spectrum-container',controlTemplate));\r
+ controlTemplate.removeChild(self.select('peak',controlTemplate));\r
+\r
+ }\r
+\r
+ self.oControls = controlTemplate.cloneNode(true);\r
+\r
+ oTiming = self.select('timing-data',controlTemplate);\r
+ self.strings.timing = oTiming.innerHTML;\r
+ oTiming.innerHTML = '';\r
+ oTiming.id = '';\r
+\r
+ function doEvents(action) { // action: add / remove\r
+\r
+ _event[action](document,'click',self.handleClick);\r
+\r
+ if (!isTouchDevice) {\r
+ _event[action](document,'mousedown',self.handleMouseDown);\r
+ _event[action](document,'mouseup',self.stopDrag);\r
+ } else {\r
+ _event[action](document,'touchstart',self.handleMouseDown);\r
+ _event[action](document,'touchend',self.stopDrag);\r
+ }\r
+\r
+ _event[action](window, 'unload', cleanup);\r
+\r
+ }\r
+\r
+ cleanup = function() {\r
+ doEvents('remove');\r
+ };\r
+\r
+ doEvents('add');\r
+\r
+ sm._writeDebug('pagePlayer.init(): Ready',1);\r
+\r
+ if (self.config.autoStart) {\r
+ // grab the first ul.playlist link\r
+ pl.handleClick({target:pl.getByClassName('playlist', 'ul')[0].getElementsByTagName('a')[0]});\r
+ }\r
+\r
+ };\r
+\r
+}\r
+\r
+soundManager.useFlashBlock = true;\r
+\r
+soundManager.onready(function() {\r
+ pagePlayer = new PagePlayer();\r
+ pagePlayer.init(typeof PP_CONFIG !== 'undefined' ? PP_CONFIG : null);\r
+});
\ No newline at end of file
--- /dev/null
+<html>
+<head>
+<title>XBM image test</title>
+<meta name="robots" content="noindex" />
+</head>
+
+<body>
+
+<h1>XBM (X-Bitmap) Support Test</h1>
+
+<p>Firefox 3.6 dropped support for XBM images citing lack of use (and a security hole or two), so SoundManager 2 has moved to using canvas for rendering favicon images on-the-fly.</p>
+
+<p>
+XBM with data URI (may be broken image, invalid etc.):<br>
+<img src="data:image/x-bitmap,#define%20img14x14_width%2016%0A#define%20img14x14_height%2016%0Astatic%20char%20img14x14_bits%5B%5D%20=%20%7B%0A0x00,0x00,0x00,0x00,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe,0x7f,0xfe%7D;" title="This should be an XBM image" />
+</p>
+
+<p>See the SoundManager 2 demo with <a href="http://www.schillmania.com/projects/soundmanager2/demo/page-player/#experimental">experimental</a> favicon animation feature enabled, and the <a href="http://www.flickr.com/photos/schill/4143933545/">related screenshot</a> showing the different states.</p>
+
+<p>XBM (X-Bitmap) is neat in that it's an ASCII, C-style declarative image format, and is quite old. See <a href="http://en.wikipedia.org/wiki/XBM">XBM on Wikipedia</a> for more.</p>
+
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2 Demo: Play MP3 Links on a page</title>
+<meta name="robots" content="noindex" />\r
+<style type="text/css">\r
+\r
+/* \r
+\r
+ -------------------------------------------------------------\r
+\r
+ In-page demo CSS - see external CSS for actual relevant stuff.\r
+\r
+ --------------------------------------------------------------\r
+\r
+ */\r
+\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, makes debug more useable) */\r
+ position:absolute;position:fixed;*position:absolute;bottom:10px;right:10px;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);\r
+}\r
+\r
+body {\r
+ font:75% normal verdana,arial,tahoma,"sans serif";\r
+}\r
+\r
+</style>\r
+<link rel="stylesheet" type="text/css" href="css/inlineplayer.css" />\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/inlineplayer.js"></script>\r
+</head>\r
+\r
+<body>\r
+\r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Play a page of mp3s with javascript via SoundManager 2">SoundManager 2</a> / page as a playlist, basic template</h1>\r
+\r
+ <p>Don't forget to set debugMode = false within <em>inlineplayer.js</em> to disable debug output.</p>\r
+\r
+ <div id="sm2-container">\r
+ <!-- SM2 flash goes here -->\r
+ </div>\r
+\r
+ <ul class="graphic">\r
+\r
+ <li><a href="../_mp3/rain.mp3">Rain</a></li>\r
+ <li><a href="../_mp3/walking.mp3">Walking</a></li>\r
+ <li><a href="http://www.freshly-ground.com/misc/music/carl-3-barlp.mp3">Barrlping with Carl (featureblend.com)</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Mak.mp3">Angry cow sound?</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Things that open, close and roll.mp3">Things that open, close and roll</a></li>\r
+ <li><a href="http://www.freshly-ground.com/misc/music/20060826%20-%20Armstrong.mp3">20060826 - Armstrong</a></li>\r
+ <li><a href="http://freshly-ground.com/data/video/Rain%20on%20Car%20Roof.aac">Rain On Car Roof (AAC Audio)</a></li>\r
+ </ul>\r
+\r
+ <p><a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 project page">SoundManager 2 project home</a></p>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+/*\r
+\r
+ SoundManager 2: In-page MP3 player example\r
+ ------------------------------------------\r
+\r
+ Clicks on links to MP3s are intercepted via JS, calls are\r
+ made to SoundManager to load/play sounds. CSS classes are\r
+ appended to the link, which are used to highlight the\r
+ current play state and so on.\r
+\r
+ Class names are applied in addition to "sm2_link" base.\r
+\r
+ Default:\r
+\r
+ sm2_link\r
+\r
+ Additional states:\r
+\r
+ sm2_playing\r
+ sm2_paused\r
+\r
+ eg.\r
+\r
+ <!-- default -->\r
+ <a href="some.mp3" class="sm2_link">some.mp3</a>\r
+\r
+ <!-- playing -->\r
+ <a href="some.mp3" class="sm2_link sm2_playing">some.mp3</a>\r
+\r
+\r
+ Note you don't require ul.graphic / ul.flat etc. for your use\r
+ if only using one style on a page. You can just use .sm2_link{}\r
+ and so on, but isolate the CSS you want.\r
+\r
+ Side note: Would do multiple class definitions eg.\r
+\r
+ a.sm2_default.sm2_playing{}\r
+\r
+ .. except IE 6 has a parsing bug which may break behaviour,\r
+ applying sm2_playing {} even when the class is set to sm2_default.\r
+\r
+\r
+ If you want to make your own UI from scratch, here is the base:\r
+\r
+ Default + hover state, "click to play":\r
+\r
+ a.sm2_link {}\r
+ a.sm2_link:hover {}\r
+\r
+ Playing + hover state, "click to pause":\r
+\r
+ a.sm2_playing {}\r
+ a.sm2_playing:hover {}\r
+\r
+ Paused + hover state, "click to resume":\r
+\r
+ a.sm2_paused {}\r
+ a.sm2_paused:hover {}\r
+\r
+\r
+*/\r
+\r
+/* two different list types */\r
+\r
+ul.flat {\r
+ list-style-type:none;\r
+ padding-left:0px;\r
+}\r
+\r
+ul.flat li,\r
+ul.graphic li {\r
+ padding-bottom:1px;\r
+}\r
+\r
+ul.flat li a {\r
+ display:inline-block;\r
+ padding:2px 4px 2px 4px;\r
+}\r
+\r
+ul.graphic {\r
+ list-style-type:none;\r
+ padding-left:0px;\r
+ margin-left:0px;\r
+}\r
+\r
+/* background-image-based CSS3 example */\r
+\r
+ul.graphic {\r
+ list-style-type:none;\r
+ margin:0px;\r
+ padding:0px;\r
+}\r
+\r
+ul.graphic li {\r
+ margin-bottom:2px;\r
+}\r
+\r
+ul.graphic li a,\r
+ul.graphic li a.sm2_link {\r
+ /* assume all items will be sounds rather than wait for onload etc. in this example.. may differ for your uses. */\r
+ display:inline-block;\r
+ padding-left:22px;\r
+ min-height:16px;\r
+ vertical-align: middle;\r
+ background-color:#336699;\r
+ border-radius:3px;\r
+ padding:3px 3px 3px 25px;\r
+ min-width:19em;\r
+ _width:19em; /* IE 6 */\r
+ text-decoration:none;\r
+ font-weight:normal;\r
+ color:#f6f9ff;\r
+}\r
+\r
+ul.graphic li a.sm2_link {\r
+ /* safari 3.1+ fun (or, proprietary crap. TBD.) */\r
+ -webkit-transition-property: hover;\r
+ -webkit-transition: background-color 0.15s linear;\r
+ -moz-transition: background-color 0.15s linear 0s; /* firefox 4 */\r
+ -o-transition-property: background-color; /* opera 10.5 */\r
+ -o-transition-duration: 0.15s;\r
+}\r
+\r
+ul.graphic li a, /* use a.sm2_link {} if you want play icons showing only if SM2 is supported */\r
+ul.graphic li a.sm2_paused:hover,\r
+ul.graphic li a.sm2_link:hover {\r
+ background-image:url(../image/icon_play.png);\r
+ background-position:3px 50%;\r
+ background-repeat:no-repeat;\r
+ _background-image:url(../image/icon_play.gif); /* IE 6 */\r
+}\r
+\r
+ul.graphic li a.sm2_link:hover {\r
+ /* default hover color, if you'd like.. */\r
+ background-color:#003366;\r
+ color:#fff;\r
+}\r
+\r
+ul.graphic li a.sm2_paused {\r
+ background-color:#999;\r
+}\r
+\r
+ul.graphic li a.sm2_paused:hover {\r
+ background:#003366 url(../image/icon_play.png) no-repeat 3px 50%;\r
+ _background-image:url(../image/icon_play.gif);\r
+}\r
+\r
+ul.graphic li a.sm2_playing,\r
+ul.graphic li a.sm2_playing:hover {\r
+ background:#003366 url(../image/icon_pause.png) no-repeat 3px 50%;\r
+ _background-image:url(../image/icon_pause.gif);\r
+ text-decoration:none;\r
+}\r
+\r
+/* hide button while playing?\r
+ul.graphic li a.sm2_playing {\r
+ background-image:none;\r
+}\r
+*/\r
+\r
+body #sm2-container object,\r
+body #sm2-container embed {\r
+ /*\r
+ flashblock handling: hide SWF off-screen by default (until blocked timeout case.)\r
+ include body prefix to ensure override of flashblock.css.\r
+ */\r
+\r
+ left:-9999em;\r
+ top:-9999em;\r
+}\r
+\r
+/* flat CSS example */\r
+\r
+ul.flat a.sm2_link {\r
+ /* default state: "a playable link" */\r
+ border-left:6px solid #999;\r
+ padding-left:4px;\r
+ padding-right:4px;\r
+}\r
+\r
+ul.flat a.sm2_link:hover {\r
+ /* default (inactive) hover state */\r
+ border-left-color:#333;\r
+}\r
+\r
+\r
+ul.flat a.sm2_playing {\r
+ /* "now playing" */\r
+ border-left-color:#6666ff;\r
+ background-color:#000;\r
+ color:#fff;\r
+ text-decoration:none;\r
+}\r
+\r
+ul.flat a.sm2_playing:hover {\r
+ /* "clicking will now pause" */\r
+ border-left-color:#cc3333;\r
+}\r
+\r
+ul.flat a.sm2_paused {\r
+ /* "paused state" */\r
+ background-color:#666;\r
+ color:#fff;\r
+ text-decoration:none;\r
+}\r
+\r
+ul.flat a.sm2_paused:hover {\r
+ /* "clicking will resume" */\r
+ border-left-color:#33cc33;\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2 Demo: Play MP3 Links on a page</title>
+<meta name="robots" content="noindex" />\r
+<style type="text/css">\r
+\r
+/* \r
+\r
+ -------------------------------------------------------------\r
+\r
+ In-page demo CSS - see external CSS for actual relevant stuff.\r
+\r
+ --------------------------------------------------------------\r
+\r
+ */\r
+\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, makes debug more useable) */\r
+ position:absolute;position:fixed;*position:absolute;bottom:10px;right:10px;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);\r
+}\r
+\r
+body {\r
+ font:75% normal verdana,arial,tahoma,"sans serif";\r
+}\r
+\r
+h1, h2, h3 {\r
+ font:2.5em arial,tahoma,verdana;\r
+ font-weight:normal;\r
+ margin-bottom:0px;\r
+}\r
+\r
+h1, h2 {\r
+ letter-spacing:-1px; /* zomg web x.0! ;) */ \r
+ margin-top:0.5em;\r
+}\r
+\r
+h2, h3 {\r
+ color:#333;\r
+}\r
+\r
+h2 {\r
+ font-size:2em;\r
+}\r
+\r
+h3 {\r
+ font-size:1.5em;\r
+}\r
+\r
+h1 a,\r
+h1 a:hover {\r
+ color:#000;\r
+ text-decoration:none;\r
+}\r
+\r
+h1 a:hover {\r
+ text-decoration:underline;\r
+}\r
+\r
+ul.notes {\r
+ margin-left:0px;\r
+ padding-left:1.5em;\r
+}\r
+\r
+.note {\r
+ margin-top:0px;\r
+ font-style:italic;\r
+ color:#999;\r
+}\r
+\r
+pre {\r
+ font-size:1.2em;\r
+ _font-size:1em;\r
+}\r
+\r
+#left {\r
+ max-width:56em;\r
+}\r
+\r
+code {\r
+ font-size:120%;\r
+ line-height:1.5em;\r
+ color:#006600;\r
+ font-weight:bold;\r
+}\r
+\r
+p {\r
+ line-height:1.75em;\r
+}\r
+\r
+</style>\r
+<link rel="stylesheet" type="text/css" href="css/inlineplayer.css" />\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="script/inlineplayer.js"></script>\r
+</head>\r
+\r
+<body>\r
+\r
+<div id="left">\r
+ \r
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Play MP3s inline with javascript using SoundManager 2">SoundManager 2</a> / Playable MP3 links</h1>\r
+\r
+ <h2>Inline MP3 Player Example: Fancy* CSS 3 version</h2>\r
+ <p class="note">*CSS 3 border-radius supported only by Firefox 2.x+, Safari (2.x?) - sadly, not IE 8.</p>\r
+\r
+ <div id="sm2-container">\r
+ <!-- SM2 flash goes here -->\r
+ </div>\r
+\r
+ <ul class="graphic">\r
+ <li><a href="../_mp3/rain.mp3">Rain</a></li>\r
+ <li><a href="../_mp3/walking.mp3">Walking</a></li>\r
+ <!-- files from the web (note that ID3 information will *not* load from remote domains without permission, Flash restriction) -->\r
+ <li><a href="http://www.freshly-ground.com/misc/music/carl-3-barlp.mp3">Barrlping with Carl (featureblend.com)</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Mak.mp3">Angry cow sound?</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Things that open, close and roll.mp3">Things that open, close and roll</a></li>\r
+ <li><a href="http://www.freshly-ground.com/misc/music/20060826%20-%20Armstrong.mp3">20060826 - Armstrong</a></li>\r
+ <li><a href="http://freshly-ground.com/data/video/Rain%20on%20Car%20Roof.aac">Rain On Car Roof (AAC Audio)</a></li>\r
+ </ul>\r
+\r
+ <h2>How It Works</h2>\r
+\r
+ <ul class="notes">\r
+ <li>Lightweight (single JS click event handler)</li>\r
+ <li>Uses existing SoundManager 2 API</li>\r
+ <li>CSS for UI, easy to modify to taste</li>\r
+ </ul>\r
+\r
+ <p>This example uses <a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 Javascript Sound API">SoundManager 2</a> to find links to MP3 files, and makes them playable "in-place" on a page. The script assigns CSS classes to links to indicate their state (playing/paused, etc.)</p>\r
+ <p>Links pointing to MP3s are assigned an onclick handler which intercepts the click (preventing the browser from following the link and unloading the page. SM2 will then create sound objects as needed to play the MP3s.</p>\r
+\r
+ <h3>Static Examples</h3>\r
+ <p style="margin-top:0px">CSS classes are dynamically applied as follows:</p>\r
+ <ul class="graphic">\r
+ <li><a href="#" class="sm2_link" title="'Click to play' state">Default: class="sm2_link"</a></li>\r
+ <li><a href="#" class="sm2_link sm2_playing" title="'Click to pause' state">Playing: class="sm2_link sm2_playing"</a></li>\r
+ <li><a href="#" class="sm2_link sm2_paused" title="'Click to resume' state">Paused: class="sm2_link sm2_paused"</a></li>\r
+ </ul>\r
+ <p>:hover effects are also active.</p>\r
+\r
+ <h2>Flat (CSS-only) style</h2>\r
+\r
+ <ul class="flat">\r
+\r
+ <li><a href="../_mp3/going_outside.mp3">Going Outside</a></li>\r
+ <li><a href="../_mp3/office_lobby.mp3">Office Lobby Entrance</a></li>\r
+\r
+ <!-- files from the web (note that ID3 information will *not* load from remote domains without permission, Flash restriction) -->\r
+\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Rain 3.mp3">Rain 3</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Frogs @ Yahoo!.mp3">Frogs @ Yahoo!</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Walking past sprinklers, mailbox.mp3">Walking past sprinklers, mailbox</a></li>\r
+ <li><a href="http://www.freshly-ground.com/data/audio/binaural/Cup of Coffee.mp3">Cup of Coffee</a></li>\r
+\r
+ </ul>\r
+\r
+ <h3>Static Examples</h3>\r
+\r
+ <ul class="flat">\r
+\r
+ <li><a href="#" class="sm2_link" title="'Click to play' state">Default: class="sm2_link"</a></li>\r
+ <li><a href="#" class="sm2_link sm2_playing" title="'Click to pause' state">Playing: class="sm2_link sm2_playing"</a></li>\r
+ <li><a href="#" class="sm2_link sm2_paused" title="'Click to resume' state">Paused: class="sm2_link sm2_paused"</a></li>\r
+\r
+ </ul>\r
+\r
+ <h3>Forcing play (or exclusion) of links</h3>\r
+\r
+ <p>If you have a link to a PHP file that serves MP3 files eg. /music.php?fileID=123, it won't be picked up by the script as containing a known, playable .mp3 extension. To tell the script it should be treated as playable, include a <code>type="audio/mpeg"</code> MIME type attribute, or CSS <code>class="inline-playable"</code> in the link. eg:</p>\r
+\r
+ <p>\r
+ <code><a href="/music.php?fileID=123" type="audio/mpeg">A song</a></code>\r
+ </p>\r
+\r
+ <p>Or via CSS class name:</p>\r
+ <code><a href="/music.php?fileID=123" class="inline-playable">A song</a></code>\r
+</p>\r
+\r
+ <p>\r
+ To exclude an .MP3 or otherwise-playable link from being handled by SM2, use <code>class="inline-exclude"</code> and it will be ignored.\r
+ </p>\r
+\r
+ <p>\r
+ <a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)\r
+ </p>\r
+\r
+ <h3>Basic CSS</h3>\r
+\r
+<pre>\r
+ If you want to make your own UI from scratch, here is the base:\r
+\r
+ Default + hover state, "click to play":\r
+\r
+ a.sm2_link {}\r
+ a.sm2_link:hover {}\r
+\r
+ Playing + hover state, "click to pause":\r
+\r
+ a.sm2_playing {}\r
+ a.sm2_playing:hover {}\r
+\r
+ Paused + hover state, "click to resume":\r
+\r
+ a.sm2_paused {}\r
+ a.sm2_paused:hover {}\r
+</pre>\r
+\r
+ <h3>Other Options</h3>\r
+ \r
+ <p>By default, one sound will be played at a time; you can easily change a "config" object value to turn on playlist-like behaviour (i.e., play the next MP3 when the current one finishes.)</p>\r
+ \r
+<pre>\r
+// (within inlineplayer.js)\r
+this.config = {\r
+ playNext: false // stop after one sound, or play through list until end\r
+}\r
+</pre>\r
+\r
+ <h3>I'd like to use this.</h3>\r
+ <p>See this <a href="basic.html" title="basic template: inline mp3 player">basic demo</a> for reference.</p>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+/**\r
+ *\r
+ * SoundManager 2 Demo: Play MP3 links "in-place"\r
+ * ----------------------------------------------\r
+ *\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * A simple demo making MP3s playable "inline"\r
+ * and easily styled/customizable via CSS.\r
+ *\r
+ * Requires SoundManager 2 Javascript API.\r
+ *\r
+ */\r
+\r
+function InlinePlayer() {\r
+ var self = this;\r
+ var pl = this;\r
+ var sm = soundManager; // soundManager instance\r
+ var isIE = (navigator.userAgent.match(/msie/i));\r
+ this.playableClass = 'inline-playable'; // CSS class for forcing a link to be playable (eg. doesn't have .MP3 in it)\r
+ this.excludeClass = 'inline-exclude'; // CSS class for ignoring MP3 links\r
+ this.links = [];\r
+ this.sounds = [];\r
+ this.soundsByURL = [];\r
+ this.indexByURL = [];\r
+ this.lastSound = null;\r
+ this.soundCount = 0;\r
+\r
+ this.config = {\r
+ playNext: false, // stop after one sound, or play through list until end\r
+ autoPlay: false // start playing the first sound right away\r
+ }\r
+\r
+ this.css = {\r
+ // CSS class names appended to link during various states\r
+ sDefault: 'sm2_link', // default state\r
+ sLoading: 'sm2_loading',\r
+ sPlaying: 'sm2_playing',\r
+ sPaused: 'sm2_paused'\r
+ }\r
+\r
+ this.addEventHandler = (typeof window.addEventListener !== 'undefined' ? function(o, evtName, evtHandler) {\r
+ return o.addEventListener(evtName,evtHandler,false);\r
+ } : function(o, evtName, evtHandler) {\r
+ o.attachEvent('on'+evtName,evtHandler);\r
+ });\r
+\r
+ this.removeEventHandler = (typeof window.removeEventListener !== 'undefined' ? function(o, evtName, evtHandler) {\r
+ return o.removeEventListener(evtName,evtHandler,false);\r
+ } : function(o, evtName, evtHandler) {\r
+ return o.detachEvent('on'+evtName,evtHandler);\r
+ });\r
+\r
+ this.classContains = function(o,cStr) {\r
+ return (typeof(o.className)!='undefined'?o.className.match(new RegExp('(\\s|^)'+cStr+'(\\s|$)')):false);\r
+ }\r
+\r
+ this.addClass = function(o,cStr) {\r
+ if (!o || !cStr || self.classContains(o,cStr)) return false;\r
+ o.className = (o.className?o.className+' ':'')+cStr;\r
+ }\r
+\r
+ this.removeClass = function(o,cStr) {\r
+ if (!o || !cStr || !self.classContains(o,cStr)) return false;\r
+ o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');\r
+ }\r
+\r
+ this.getSoundByURL = function(sURL) {\r
+ return (typeof self.soundsByURL[sURL] != 'undefined'?self.soundsByURL[sURL]:null);\r
+ }\r
+\r
+ this.isChildOfNode = function(o,sNodeName) {\r
+ if (!o || !o.parentNode) {\r
+ return false;\r
+ }\r
+ sNodeName = sNodeName.toLowerCase();\r
+ do {\r
+ o = o.parentNode;\r
+ } while (o && o.parentNode && o.nodeName.toLowerCase() != sNodeName);\r
+ return (o.nodeName.toLowerCase() == sNodeName?o:null);\r
+ }\r
+\r
+ this.events = {\r
+\r
+ // handlers for sound events as they're started/stopped/played\r
+\r
+ play: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = pl.css.sPlaying;\r
+ pl.addClass(this._data.oLink,this._data.className);\r
+ },\r
+\r
+ stop: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = '';\r
+ },\r
+\r
+ pause: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = pl.css.sPaused;\r
+ pl.addClass(this._data.oLink,this._data.className);\r
+ },\r
+\r
+ resume: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = pl.css.sPlaying;\r
+ pl.addClass(this._data.oLink,this._data.className); \r
+ },\r
+\r
+ finish: function() {\r
+ pl.removeClass(this._data.oLink,this._data.className);\r
+ this._data.className = '';\r
+ if (pl.config.playNext) {\r
+ var nextLink = (pl.indexByURL[this._data.oLink.href]+1);\r
+ if (nextLink<pl.links.length) {\r
+ pl.handleClick({'target':pl.links[nextLink]});\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ this.stopEvent = function(e) {\r
+ if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {\r
+ e.preventDefault();\r
+ } else if (typeof event != 'undefined' && typeof event.returnValue != 'undefined') {\r
+ event.returnValue = false;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ this.getTheDamnLink = (isIE)?function(e) {\r
+ // I really didn't want to have to do this.\r
+ return (e && e.target?e.target:window.event.srcElement);\r
+ }:function(e) {\r
+ return e.target;\r
+ }\r
+\r
+ this.handleClick = function(e) {\r
+ // a sound link was clicked\r
+ if (typeof e.button != 'undefined' && e.button>1) {\r
+ // ignore right-click\r
+ return true;\r
+ }\r
+ var o = self.getTheDamnLink(e);\r
+ if (o.nodeName.toLowerCase() != 'a') {\r
+ o = self.isChildOfNode(o,'a');\r
+ if (!o) return true;\r
+ }\r
+ var sURL = o.getAttribute('href');\r
+ if (!o.href || (!sm.canPlayLink(o) && !self.classContains(o,self.playableClass)) || self.classContains(o,self.excludeClass)) {\r
+ return true; // pass-thru for non-MP3/non-links\r
+ }\r
+ var soundURL = (o.href);\r
+ var thisSound = self.getSoundByURL(soundURL);\r
+ if (thisSound) {\r
+ // already exists\r
+ if (thisSound == self.lastSound) {\r
+ // and was playing (or paused)\r
+ thisSound.togglePause();\r
+ } else {\r
+ // different sound\r
+ sm._writeDebug('sound different than last sound: '+self.lastSound.id);\r
+ if (self.lastSound) {\r
+ self.stopSound(self.lastSound);\r
+ }\r
+ thisSound.togglePause(); // start playing current\r
+ }\r
+ } else {\r
+ // stop last sound\r
+ if (self.lastSound) {\r
+ self.stopSound(self.lastSound);\r
+ }\r
+ // create sound\r
+ thisSound = sm.createSound({\r
+ id:'inlineMP3Sound'+(self.soundCount++),\r
+ url:soundURL,\r
+ onplay:self.events.play,\r
+ onstop:self.events.stop,\r
+ onpause:self.events.pause,\r
+ onresume:self.events.resume,\r
+ onfinish:self.events.finish,\r
+ type:(o.type||null)\r
+ });\r
+ // tack on some custom data\r
+ thisSound._data = {\r
+ oLink: o, // DOM node for reference within SM2 object event handlers\r
+ className: self.css.sPlaying\r
+ };\r
+ self.soundsByURL[soundURL] = thisSound;\r
+ self.sounds.push(thisSound);\r
+ thisSound.play();\r
+ }\r
+\r
+ self.lastSound = thisSound; // reference for next call\r
+\r
+ if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {\r
+ e.preventDefault();\r
+ } else {\r
+ event.returnValue = false;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ this.stopSound = function(oSound) {\r
+ soundManager.stop(oSound.id);\r
+ soundManager.unload(oSound.id);\r
+ }\r
+\r
+ this.init = function() {\r
+ sm._writeDebug('inlinePlayer.init()');\r
+ var oLinks = document.getElementsByTagName('a');\r
+ // grab all links, look for .mp3\r
+ var foundItems = 0;\r
+ for (var i=0, j=oLinks.length; i<j; i++) {\r
+ if ((sm.canPlayLink(oLinks[i]) || self.classContains(oLinks[i],self.playableClass)) && !self.classContains(oLinks[i],self.excludeClass)) {\r
+ self.addClass(oLinks[i],self.css.sDefault); // add default CSS decoration\r
+ self.links[foundItems] = (oLinks[i]);\r
+ self.indexByURL[oLinks[i].href] = foundItems; // hack for indexing\r
+ foundItems++;\r
+ }\r
+ }\r
+ if (foundItems>0) {\r
+ self.addEventHandler(document,'click',self.handleClick);\r
+ if (self.config.autoPlay) {\r
+ self.handleClick({target:self.links[0],preventDefault:function(){}});\r
+ }\r
+ }\r
+ sm._writeDebug('inlinePlayer.init(): Found '+foundItems+' relevant items.');\r
+ }\r
+\r
+ this.init();\r
+\r
+}\r
+\r
+var inlinePlayer = null;\r
+\r
+soundManager.setup({\r
+ // disable or enable debug output\r
+ debugMode: true,\r
+ // use HTML5 audio for MP3/MP4, if available\r
+ preferFlash: false,\r
+ useFlashBlock: true,\r
+ // path to directory containing SM2 SWF\r
+ url: '../../swf/',\r
+ // optional: enable MPEG-4/AAC support (requires flash 9)\r
+ flashVersion: 9\r
+});\r
+\r
+// ----\r
+\r
+soundManager.onready(function() {\r
+ // soundManager.createSound() etc. may now be called\r
+ inlinePlayer = new InlinePlayer();\r
+});\r
+\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Deferred loading / Lazy-loading / Dynamic script loading Example</title>\r
+<meta name="description" content="How to load soundmanager2.js on-the-fly using JavaScript, and start it dynamically after window.load() has already fired using beginDelayedInit()." />\r
+<style type="text/css">\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, use or customize this as you like - makes in-browser debug output more useable) */\r
+ position:fixed;_position:absolute;right:1em;bottom:1em;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:monaco,"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);\r
+}\r
+</style>\r
+<!-- some CSS for this demo page, not required for SM2 -->\r
+<link rel="stylesheet" href="template.css" />\r
+\r
+<!-- SM2 BAREBONES TEMPLATE: START -->\r
+\r
+<script type="text/javascript">\r
+\r
+function loadScript(sURL, onLoad) {\r
+\r
+ function loadScriptHandler() {\r
+ var rs = this.readyState;\r
+ if (rs == 'loaded' || rs == 'complete') {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ if (onLoad) {\r
+ onLoad();\r
+ }\r
+ }\r
+ }\r
+\r
+ function scriptOnload() {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ window.setTimeout(onLoad,20);\r
+ }\r
+\r
+ var oS = document.createElement('script');\r
+\r
+ oS.type = 'text/javascript';\r
+ if (onLoad) {\r
+ oS.onreadystatechange = loadScriptHandler;\r
+ oS.onload = scriptOnload;\r
+ }\r
+\r
+ oS.src = sURL;\r
+ document.getElementsByTagName('head')[0].appendChild(oS);\r
+\r
+}\r
+\r
+function msg(s) {\r
+\r
+ document.getElementById('sm2-status').innerHTML += '<br />' + s;\r
+\r
+}\r
+\r
+window.onload = function() {\r
+\r
+ msg('Window loaded, waiting 1 second...');\r
+\r
+ setTimeout(function() {\r
+\r
+ msg('Loading soundmanager2.js...');\r
+\r
+ loadScript('../../script/soundmanager2.js', function() {\r
+\r
+ // SM2 script has loaded\r
+\r
+ window.setTimeout(function() {\r
+ msg('soundmanager2.js loaded, delaying before setup()...');\r
+ }, 500);\r
+\r
+ window.setTimeout(function() {\r
+\r
+ soundManager.setup({\r
+\r
+ url: '../../swf/',\r
+\r
+ onready: function() {\r
+\r
+ soundManager.createSound({\r
+ id:'foo',\r
+ url:'../_mp3/mouseover.mp3'\r
+ }).play();\r
+\r
+ msg('Started OK');\r
+\r
+ },\r
+\r
+ ontimeout: function() {\r
+\r
+ msg('Loaded OK, but unable to start: unsupported/flash blocked, etc.');\r
+\r
+ }\r
+\r
+ });\r
+\r
+ // ensure start-up in case document.readyState and/or DOMContentLoaded are unavailable\r
+ soundManager.beginDelayedInit();\r
+\r
+ }, 1000);\r
+\r
+ });\r
+\r
+ },1000);\r
+\r
+}\r
+\r
+</script>\r
+</head>\r
+\r
+<body style="height:100%">\r
+\r
+<div style="margin-right:43em">\r
+\r
+ <h1>SoundManager 2: Lazy Loading Example</h1>\r
+ <p>This is an example of dynamically loading SoundManager 2 using JS, after <code>window.onload()</code> has fired.</p>\r
+\r
+ <h2>How it works</h2>\r
+ <p>This page waits until <code>window.onload()</code>, delays 1 second and loads soundmanager2.js, which should then start up.</p>\r
+ <p><b>Behaviour note:</b> SM2 will not automatically start if it is loaded at or after the <code>DOMContentLoaded</code> event has fired, which may be common with most JS loaders.</p>\r
+ <p>However, SM2 will try to start once <code>soundManager.setup()</code> is called and a <code>url</code> attribute has been provided.</p>\r
+ <p>If you want to ensure that SM2 starts after setup, you can call <code>soundManager.beginDelayedInit()</code> - this should be safe to call after <code>DOMContentLoaded</code> has fired.</p>\r
+\r
+<h2>Pseudo-code Example</h2>\r
+\r
+<p>Once SM2 has been dymamically loaded, you can call its <code>setup()</code> method. Passing a <code>url</code> attribute will trigger the initialization process.</p>\r
+\r
+<pre class="block"><code>loadJS('<span>soundmanager2.js</span>', function() {\r
+ soundManager.setup({\r
+ url: '<span>/path/to/swfs/</span>',\r
+ onready: function() {\r
+ <span><span>// good to go!\r
+ // soundManager.createSound(...), etc.</span></span>\r
+ }\r
+ });\r
+});</code></pre>\r
+\r
+<h2>Live Example</h2>\r
+\r
+<p>SoundManager 2 status: <b id="sm2-status">Waiting for window.onload()...</b></p>\r
+\r
+<pre class="block"><code><span><span>/**\r
+ * Dynamic script loading helper (example)\r
+ * Normalizes good browser onload() vs. IE readyState weirdness\r
+ */\r
+</span></span>\r
+function loadScript(sURL, onLoad) {\r
+\r
+ function loadScriptHandler() {\r
+ var rs = this.readyState;\r
+ if (rs == '<span>loaded</span>' || rs == '<span>complete</span>') {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ if (onLoad) {\r
+ onLoad();\r
+ }\r
+ }\r
+ }\r
+\r
+ function scriptOnload() {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ window.setTimeout(onLoad,20);\r
+ }\r
+\r
+ var oS = document.createElement('<span>script</span>');\r
+ oS.type = '<span>text/javascript</span>';\r
+ if (onLoad) {\r
+ oS.onreadystatechange = loadScriptHandler;\r
+ oS.onload = scriptOnload;\r
+ }\r
+ oS.src = sURL;\r
+ document.getElementsByTagName('<span>head</span>')[0].appendChild(oS);\r
+\r
+}\r
+\r
+<span><span>// Wait for window load, then load soundmanager2.js, let it start and play a test sound</span></span>\r
+\r
+window.onload = function() {</span>\r
+\r
+ msg('<span>Window loaded, waiting 1 second...</span>');\r
+\r
+ setTimeout(function() {\r
+\r
+ msg('<span>Loading soundmanager2.js...</span>');\r
+\r
+ loadScript('<span>../../script/soundmanager2.js</span>', function() {\r
+\r
+ <span><span>// SM2 script has loaded</span></span>\r
+\r
+ window.setTimeout(function() {\r
+ msg('<span>soundmanager2.js loaded, delaying before setup()...</span>');\r
+ }, 500);\r
+\r
+ window.setTimeout(function() {\r
+\r
+ soundManager.setup({\r
+ url: '<span>../../swf/</span>',\r
+ onready: function() {\r
+ soundManager.createSound({\r
+ id: '<span>foo</span>',\r
+ url: '<span>../_mp3/mouseover.mp3</span>'\r
+ }).play();\r
+ msg('<span>Started OK</span>');\r
+ },\r
+ ontimeout: function() {\r
+ msg('<span>Loaded OK, but unable to start: unsupported/flash blocked, etc.</span>');\r
+ }\r
+ });\r
+\r
+ <span><span>// ensure start-up in case document.readyState and/or DOMContentLoaded are unavailable</span></span>\r
+ soundManager.beginDelayedInit();\r
+\r
+ }, 1000);\r
+\r
+ });\r
+\r
+ }, 1000);\r
+\r
+</span>}\r
+</code></pre>\r
+\r
+ <h2 id="flashblock-handling">Handling flash blockers</h2>\r
+ <p>It's good to let users see the flash component of SM2, so those with flash blockers can unblock it and allow SM2 to start. For more info on this, see the <a href="../flashblock/" title="SoundManager 2 with Flash block handling" onclick="if (!document.domain && !this.href.match(/index/i)) this.href=this.href+'index.html'">Flashblock</a> example.</p>\r
+\r
+ <h2 style="margin-top:1em">Preventing auto-init using SM2_DEFER</h2>\r
+ <p>If you want to completely defer the normal start-up of SM2 and call the SoundManager() constructor yourself, you can declare an SM2_DEFER global and set it to true. See the <a href="sm2_defer-example.html" title="SoundManager 2: SM2_DEFER example">SM2_DEFER example</a> for details.</p>\r
+\r
+ <h2 style="margin-top:1em">Disabling debug output</h2>\r
+ <p>SoundManager 2 will write to a debug <div> element or a javascript console if available, by default. To disable it, simply set the relevant property to false:</p>\r
+<code>soundManager.setup({ debugMode: false });</code>\r
+ <p>To see related configuration code, refer to the source of this page which basically does all of the above "for real."</p>\r
+ <h2>Troubleshooting</h2>\r
+ <p>If SM2 is failing to start and throwing errors due to flash security, timeouts or other issues, check out the <a href="../../doc/getstarted/#troubleshooting" title="SoundManager 2 troubleshooting tool" onclick="if (!document.domain && !this.href.match(/index/i)) this.href=this.href.replace(/\#/,'index.html#')">troubleshooting tool</a> which can help you fix things.</p>\r
+ <h2>No-debug, compressed version of soundmanager2.js</h2>\r
+ <p>You can also use the "minified" (60% smaller) version of SM2, which has debug output and comments removed for you: <a href="../../script/soundmanager2-nodebug-jsmin.js">soundmanager2-nodebug-jsmin.js</a>. If you can, serve this with gzip compression for even greater bandwidth savings!</p>\r
+ \r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+<title>SoundManager 2: HTML 5 DTD test</title>\r
+<meta name="description" content="A test page using SoundManager 2 under an HTML 5 DOCTYPE." />\r
+<script>\r
+\r
+// -- Movie size/positioning test case, Firefox/Win32 --\r
+\r
+// SM2 normally works at 6x6px SWF size, position:fixed bottom/left:0px.\r
+// Was failing with this case using HTML 5 doctype? ..\r
+// Started working when 8x8px SWF size was used.\r
+\r
+// Previous notes, courtesy Jacob Seidelin ...\r
+\r
+// This fails to load in Firefox 3.6 (Win7) but will load after one of the following changes:\r
+// 1. Remove the doctype or set it to eg. \r
+// <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\r
+// 2. Set soundManager.useHighPerformance = false\r
+// 3. Set soundManager.debugFlash = true\r
+\r
+function loadScript(sURL,onLoad) {\r
+ try {\r
+ var loadScriptHandler = function() {\r
+ var rs = this.readyState;\r
+ if (rs == 'loaded' || rs == 'complete') {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ if (onLoad) {\r
+ onLoad();\r
+ }\r
+ }\r
+ }\r
+ function scriptOnload() {\r
+ this.onreadystatechange = null;\r
+ this.onload = null;\r
+ window.setTimeout(onLoad,20);\r
+ }\r
+ var oS = document.createElement('script');\r
+ oS.type = 'text/javascript';\r
+ if (onLoad) {\r
+ oS.onreadystatechange = loadScriptHandler;\r
+ oS.onload = scriptOnload;\r
+ }\r
+ oS.src = sURL;\r
+ document.getElementsByTagName('head')[0].appendChild(oS);\r
+ } catch(e) {\r
+ // oh well\r
+ }\r
+}\r
+\r
+window.onload = function() {\r
+\r
+ loadScript('../../script/soundmanager2.js', function() {\r
+\r
+ soundManager.setup({\r
+ // path to directory containing SoundManager2 .SWF file\r
+ url: '../../swf/',\r
+ flashVersion = 9,\r
+ flash9Options: {\r
+ useEQData = true,\r
+ useWaveformData = true\r
+ },\r
+ onready: function() {\r
+ alert('Loaded!');\r
+ }),\r
+ debugMode: true,\r
+ useHighPerformance: true,\r
+ debugFlash: false,\r
+ });\r
+\r
+ // ensure things start, in case document.readyState / domReady are missed (eg. Firefox 3.5.5/win32 with HTML5 DTD, no document.readyState??)\r
+ soundManager.beginDelayedInit();\r
+\r
+ }\r
+\r
+}\r
+\r
+</script>\r
+\r
+</head>\r
+\r
+<body>\r
+\r
+</body>\r
+</html>\r
+\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2 Template</title>\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<style type="text/css">\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, use or customize this as you like - makes in-browser debug output more useable) */\r
+ position:fixed;_position:absolute;right:1em;bottom:1em;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:monaco,"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);\r
+}\r
+</style>\r
+<!-- some CSS for this demo page, not required for SM2 -->\r
+<link rel="stylesheet" href="template.css" />\r
+\r
+<!-- SM2 BAREBONES TEMPLATE: START -->\r
+\r
+<!-- include SM2 library (see builds for optimized versions) -->\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+\r
+<!-- configure SM2 for your use -->\r
+<script type="text/javascript">\r
+\r
+soundManager.setup({\r
+\r
+ // location: path to SWF files, as needed (SWF file name is appended later.)\r
+\r
+ url: '../../swf/',\r
+\r
+ // optional: version of SM2 flash audio API to use (8 or 9; default is 8 if omitted, OK for most use cases.)\r
+ // flashVersion: 9,\r
+\r
+ // optional: use Flash for MP3/MP4/AAC formats, even if HTML5 support present. useful if HTML5 is quirky.\r
+ // preferFlash: true\r
+\r
+ // use soundmanager2-nodebug-jsmin.js, or disable debug mode (enabled by default) after development/testing\r
+ // debugMode: false,\r
+\r
+ // good to go: the onready() callback\r
+\r
+ onready: function() {\r
+\r
+ // SM2 has started - now you can create and play sounds!\r
+\r
+ var mySound = soundManager.createSound({\r
+ id: 'aSound', // optional: an id will be generated if not provided.\r
+ url: '../_mp3/click-high.mp3'\r
+ // onload: function() { console.log('sound loaded!', this); }\r
+ // other options here..\r
+ });\r
+\r
+ mySound.play();\r
+\r
+ },\r
+\r
+ // optional: ontimeout() callback for handling start-up failure, flash required but blocked, etc.\r
+\r
+ ontimeout: function() {\r
+\r
+ // Hrmm, SM2 could not start. Missing SWF? Flash blocked? Show an error, etc.?\r
+ // See the flashblock demo when you want to start getting fancy.\r
+\r
+ }\r
+\r
+});\r
+\r
+</script>\r
+\r
+<!-- SM2 BAREBONES TEMPLATE: END -->\r
+\r
+<script type="text/javascript">\r
+// helper function for this page only, demo purposes\r
+function checkDomain() {\r
+ if (!document.domain && !this.href.match(/index/i)) {\r
+ this.href=this.href+'index.html';\r
+ }\r
+}\r
+</script>\r
+\r
+</head>\r
+\r
+<body style="height:100%">\r
+\r
+<div style="max-width:75em">\r
+\r
+ <h1>SoundManager 2 Template Example</h1>\r
+ <p>This page covers the basics of adding SoundManager 2 to your project.</p>\r
+\r
+ <h2>How it works</h2>\r
+ <p>The minimal code needed to get SoundManager 2 going is below, with <em><em>configurable parts highlighted</em></em>. You can copy/paste it to get started. This page is also running the template code; If available, look at your JavaScript console for debug output from SM2.</p>\r
+\r
+ <h2>Dependencies</h2>\r
+\r
+ <p>You'll need to copy the files inside the <b>script/</b> and <b>swf/</b> subdirectories included with the SoundManager 2 package into your project.</p>\r
+\r
+ <ul class="file-structure">\r
+ <li>\r
+ soundmanager2/\r
+ <ul>\r
+ <li class="core">\r
+ script/ <span>- API core, soundmanager2.js</span>\r
+ </li>\r
+ <li class="core">\r
+ swf/ <span>- API core, SoundManager 2 .SWF files</span>\r
+ </li>\r
+ </ul>\r
+ </li>\r
+ </ul>\r
+\r
+\r
+ <p>At the bare minimum, you will need <b>soundmanager2.js</b>, <b>soundmanager2.swf</b> and <b>soundmanager2_debug.swf</b> for the default flash 8-based configuration. (Optionally, SM2 can use a Flash 9-based audio API which has MP4 support, data visualization and a few other features.)</p>\r
+\r
+ <h2 id="minimal">Template Code: Basic Version</h2>\r
+\r
+ <p>This is a compact version of the template you can copy/paste to get started. For new users, see the <a href="#commented-template">commented version</a>.</p>\r
+\r
+<pre class="block"><code><script src="<em><em>/path/to/soundmanager2.js</em></em>"></script>\r
+<script>\r
+soundManager.setup({\r
+ url: '<em><em>/path/to/swf-files/</em></em>',\r
+ onready: function() {\r
+ var mySound = soundManager.createSound({\r
+ id: '<em><em>aSound</em></em>',\r
+ url: '<em><em>/path/to/an.mp3</em></em>'\r
+ });\r
+ mySound.play();\r
+ },\r
+ ontimeout: function() {\r
+ <span><span>// Hrmm, SM2 could not start. Missing SWF? Flash blocked? Show an error, etc.?</span></span>\r
+ }\r
+});\r
+</script></code></pre>\r
+\r
+\r
+\r
+ <h2 id="commented-template">Template Code: Commented Version</h2>\r
+\r
+<pre class="block"><code><span><span><!-- include SM2 library (see <a href="../../doc/getstarted/#basic-inclusion" title="SoundManager 2: Script build versions" onclick="checkDomain()">builds</a> for optimized versions) --></span></span>\r
+<script type="text/javascript" src="<em><em>/path/to/soundmanager2.js</em></em>"></script>\r
+\r
+<span><span><!-- configure SM2 for your use --></span></span>\r
+<script type="text/javascript">\r
+\r
+soundManager.setup({\r
+\r
+ <span><span>// location: path to SWF files, as needed (SWF file name is appended later.)</span></span>\r
+\r
+ url: '<em><em>/path/to/swf-files/</em></em>',\r
+\r
+ <span><span>// optional: version of SM2 flash audio API to use (8 or 9; default is 8 if omitted, OK for most use cases.)\r
+ // flashVersion: <em><em>9</em></em>,\r
+\r
+ // use soundmanager2-nodebug-jsmin.js, <i>or</i> disable debug mode (enabled by default) after development/testing\r
+ // debugMode: <em><em>false</em></em>,\r
+\r
+ // good to go: the onready() callback</span></span>\r
+\r
+ onready: function() {\r
+\r
+ <span><span>// SM2 has started - now you can create and play sounds!</span></span>\r
+\r
+ var mySound = soundManager.createSound({\r
+ id: '<em><em>aSound</em></em>', <span><span>// optional: provide your own unique id</span></span>\r
+ url: '<em><em>/path/to/an.mp3</em></em>'\r
+ <span><span>// onload: function() { console.log('sound loaded!', this); }\r
+ // <a href="../../doc/#smdefaults" onclick="checkDomain()">other options</a> here..</span></span>\r
+ });\r
+\r
+ mySound.play();\r
+\r
+ },\r
+\r
+ <span><span>// optional: ontimeout() callback for handling start-up failure</span></span>\r
+\r
+ ontimeout: function() {\r
+\r
+ <span><span>// Hrmm, SM2 could not start. Missing SWF? Flash blocked? No HTML5 audio support? Show an error, etc.?\r
+ // See the <a href="../flashblock/" title="SoundManager 2 flashblock handling demo" onclick="checkDomain()">flashblock demo</a> when you want to start getting fancy.</span></span>\r
+\r
+ }\r
+\r
+});\r
+\r
+</script></code></pre>\r
+\r
+ <h2 id="html5-notes">HTML5 Support Notes</h2>\r
+ <p>Read up on <a href="../../doc/#soundmanager-usehtml5audio" onclick="checkDomain()">HTML5 audio support</a>, if you're feeling adventurous. iPad/iPhone and devices without flash installed will always use 100% HTML5 mode. By default, SM2 will use 100% HTML5 mode where supported. If you want to override this, specify <code>preferFlash: true</code> and Flash will be used (if present) for playing MP3 and MP4 (AAC) formats.</p>\r
+\r
+ <h2 id="flashblock-handling">Handling flash blockers</h2>\r
+ <p>It's good to let users see the flash component of SM2, so those with flash blockers can unblock it and allow SM2 to start. For more info, see the <a href="../flashblock/" title="SoundManager 2 with Flash block handling" onclick="checkDomain()">Flashblock</a> example.</p>\r
+\r
+ <h2 style="margin-top:1em">Disabling debug output</h2>\r
+ <p>SoundManager 2 will write debug output via <code>console.log()</code> if available, by default. To disable it, simply specify <code>debugMode: false</code>.</p>\r
+ <p>You can also write HTML-based debug output to the DOM via <code>consoleOnly: false</code> and/or <code>useConsole: false</code>.</p>\r
+ <p>To see related configuration code, refer to the source of this page which basically does all of the above "for real."</p>\r
+\r
+ <h2>Troubleshooting ("failed to start": Viewing offline, missing SWF, flash blockers etc.)</h2>\r
+ <p>If SM2 is failing to start and throwing errors due to flash security, timeouts or other issues, check out the <a href="../../doc/getstarted/#troubleshooting" title="SoundManager 2 troubleshooting tool" onclick="checkDomain()">troubleshooting tool</a> for tips.</p>\r
+\r
+ <h2>No-debug, compressed version of soundmanager2.js</h2>\r
+ <p>Once development is finished, you can also use the "minified" (down to ~8% of original size with gzip!) version of SM2, which has debug output and comments removed for you: <a href="../../script/soundmanager2-nodebug-jsmin.js">soundmanager2-nodebug-jsmin.js</a>. Serve with gzip compression wherever possible for best bandwidth savings.</p>\r
+ \r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<title>SoundManager 2: SM2_DEFER Example</title>
+<meta name="description" content="How to load the SoundManager 2 JavaScript API, and call the SoundManager() constructor yourself." />
+<style type="text/css">
+#soundmanager-debug {
+ /* SM2 debug container (optional, use or customize this as you like - makes in-browser debug output more useable) */
+ position:fixed;_position:absolute;right:1em;bottom:1em;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:monaco,"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);
+}
+</style>
+<!-- some CSS for this demo page, not required for SM2 -->
+<link rel="stylesheet" href="template.css" />
+
+<!-- SM2_DEFER EXAMPLE -->
+
+<script type="text/javascript">
+
+/*
+ * Firstly, define SM2_DEFER and set it to true *before* we load soundmanager2.js.
+ * This prevents the SoundManager() constructor from being called immediately.
+ * SM2_DEFER should be assigned within the global scope.
+*/
+
+window.SM2_DEFER = true;
+
+</script>
+
+<!-- Now, load soundmanager2.js as we normally would. -->
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>
+
+<!-- "Some time later", window.onload() may have fired and you now want to start SM2, etc... -->
+<script type="text/javascript">
+
+// for example purposes, we'll wait until window.onload before starting things.
+window.onload = function() {
+
+ /*
+ * Now that the SM2 constructor is defined, you can call the constructor,
+ * set the options and "kick-start" SM2's init process, and it should work as normal.
+ * WARNING: Do not call beginDelayedInit() before "DOM ready", or things will fail.
+ */
+
+ // construct the instance (must be named soundManager, and scoped globally)
+ window.soundManager = new SoundManager();
+
+ // assign flash url, flashVersion and other SM2 options as usual
+ soundManager.setup({
+ url: '../../swf/',
+ flashVersion: 9
+ // etc...
+ });
+
+ // finally, kick-start init process.
+ // (old IE etc. may miss domloaded/ready/window.load if they've already fired.)
+ soundManager.beginDelayedInit();
+
+}
+
+</script>
+</head>
+
+<body style="height:100%">
+
+<div style="margin-right:43em">
+
+ <h1>SoundManager 2: SM2_DEFER Example</h1>
+
+ <p>This is an example of manually starting SoundManager 2. If you want to pre-load the SM2 script up front and have its onready() events etc. fire much later without delay, this approach makes sense. Otherwise, it's better to <a href="deferred-example.html" title="SoundManager 2: Lazy-loading example">lazy-load</a> or simply load SM2 normally as an external script without deferring.</p>
+
+ <h2>How it works</h2>
+ <p>By default, SM2 will call its own SoundManager() constructor inline and will try to initialize ASAP. This page defines a global boolean - <code>window.SM2_DEFER = true;</code> - before loading soundmanager2.js, preventing the constructor from being called.</p>
+
+ <p>Some time later, you must call <code>soundManager = new SoundManager();</code> manually and set things like <code>soundManager.url</code> etc. Finally, you may then call <code>soundManager.beginDelayedInit()</code> to kick off the initialization process. SM2 should then start as usual.</p>
+
+ <h2>Example code</h2>
+
+<pre class="block"><code><script type="<span>text/javascript</span>">
+
+<span><span>/*
+ * Firstly, define SM2_DEFER and set it to true *before* we load soundmanager2.js.
+ * This prevents the SoundManager() constructor from being called immediately.
+ * SM2_DEFER should be assigned within the global scope.
+*/</span></span>
+
+window.SM2_DEFER = true;
+
+</script>
+
+<span><span><!-- Now, load soundmanager2.js as we normally would. --></span></span>
+<script type="text/javascript" src="<span>../../script/soundmanager2.js</span>"></script>
+
+<span><span><!-- "Some time later", window.onload() may have fired and you now want to start SM2, etc... --></span></span>
+<script type="text/javascript">
+
+<span><span>// for example purposes, we'll wait until window.onload before starting things.</span></span>
+window.onload = function() {
+
+ <span><span>/*
+ * Now that the SM2 constructor is defined, you can call the constructor,
+ * set the options and "kick-start" SM2's init process, and it should work as normal.
+ * WARNING: Do not call beginDelayedInit() before "DOM ready", or things will fail.
+ */</span></span>
+
+ <span><span>// construct the instance (must be named soundManager, and scoped globally)</span></span>
+ window.soundManager = new SoundManager();
+
+ <span><span>// assign flash url, flashVersion and other SM2 options as usual</span></span>
+ soundManager.setup({
+ // path to directory containing SM2 SWF
+ url: '<span>/path/to/swfs/</span>',
+ flashVersion: 9
+ <span><span>// etc...</span></span>
+ });
+
+ <span><span>// finally, kick-start the init process.</span></span>
+ <span><span>// (old IE etc. may miss domloaded/ready/window.load if they've already fired.)</span></span>
+ soundManager.beginDelayedInit();
+
+}
+
+</script></code></pre>
+
+</div>
+
+</body>
+</html>
--- /dev/null
+/**\r
+ *\r
+ * SoundManager 2: TEMPLATE EXAMPLE / DEMO ONLY, just to make the demo page pretty.\r
+ *\r
+ * You don't need this stuff for SM2 to work. :)\r
+ *\r
+ */\r
+\r
+body {\r
+ font-size:75%;\r
+ background: #fff url(../../demo/_image/noise.png);\r
+}\r
+\r
+pre {\r
+ padding: 0.5em;\r
+ background: #f9f9f9;\r
+}\r
+\r
+code, pre {\r
+ font-family:"lucida console",monaco,courier,system;\r
+ font-size:100%;\r
+ color:#2233cc;\r
+}\r
+\r
+em em {\r
+ font-weight:normal;\r
+ font-style:normal;\r
+ color:#339933;\r
+}\r
+\r
+h1,\r
+h2.special {\r
+ letter-spacing: -0.005em;\r
+}\r
+\r
+h1, h2, h3, h4 {\r
+ font-family:"helvetica neue",helvetica,verdana,arial,tahoma,"sans serif";\r
+ font-size:1em;\r
+ margin:0px;\r
+ padding:0px;\r
+ vertical-align:middle;\r
+}\r
+\r
+h1 {\r
+ font-size:2em;\r
+ border-bottom: 1px dotted #999;\r
+}\r
+\r
+h2 {\r
+ font-family:"helvetica neue",helvetica,arial,verdana,tahoma,"sans serif";\r
+ font-size:1.5em;\r
+ margin-top: 1.5em;\r
+ margin-bottom: 0px;\r
+}\r
+\r
+h2 code {\r
+ font-size: 85%;\r
+}\r
+\r
+h3 {\r
+ font-size:1.17em;\r
+ border-bottom:1px solid #ccc;\r
+ padding-bottom:0.25em;\r
+ margin-top:1.5em;\r
+}\r
+\r
+h4 {\r
+ margin:1.5em 0px 0.5em 0px;\r
+ font-size:1.1em;\r
+}\r
+\r
+\r
+p,\r
+li {\r
+ font:normal 1em verdana,tahoma,arial,"sans serif";\r
+ line-height: 1.4em;\r
+}\r
+\r
+code span,\r
+pre span {\r
+ color:#666;\r
+}\r
+\r
+ul.file-structure ul {\r
+ padding-left:1.5em;\r
+}\r
+\r
+ul.file-structure li {\r
+ list-style-type:square;\r
+ margin-top:0.25em;\r
+ margin-left:0px;\r
+}\r
+\r
+ul.file-structure li span {\r
+ color:#999;\r
+}\r
+\r
+/* re-used bits from index.css */\r
+\r
+pre code {\r
+ font-size:1em;\r
+}\r
+\r
+pre {\r
+ white-space:-moz-pre-wrap;\r
+ white-space:pre-wrap;\r
+ word-wrap:break-word; /* IE */\r
+}\r
+\r
+ul.code-block em,\r
+pre span,\r
+code span,\r
+dt span {\r
+ color:#339933;\r
+}\r
+\r
+ul.code-block em {\r
+ font-style: normal;\r
+}\r
+\r
+ul.code-block span,\r
+pre span span,\r
+code span span,\r
+dt span span {\r
+ color:#667788;\r
+}\r
+\r
+pre.block,\r
+pre.block code,\r
+div.block div.code,\r
+ul.code-block {\r
+ position:relative;\r
+ display:table;\r
+ *display:block;\r
+ border:1px solid #ccc;\r
+ border-radius:3px;\r
+}\r
+\r
+div.block,\r
+pre.block {\r
+ background:#e9f3ff;\r
+ border-color:#eee;\r
+ padding:3px;\r
+}\r
+\r
+pre.block code,\r
+.block .code {\r
+ background:#fff;\r
+ border:1px solid #ccddee;\r
+ padding:0.5em;\r
+ font-size: 100%;\r
+ line-height:1.75em;\r
+ background-image: -webkit-linear-gradient(#fcfcfc 50%, #fff 50%);\r
+ background-image: -o-linear-gradient(#fcfcfc 50%, #fff 50%);\r
+ background-image: linear-gradient(#fcfcfc 50%, #fff 50%);\r
+ background-size: 100% 3.5em;\r
+ background-origin: content-box;\r
+}\r
+\r
+pre.block code {\r
+ padding: 1em;\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2 Template</title>\r
+<style type="text/css">\r
+#soundmanager-debug {\r
+ /* SM2 debug container (optional, use or customize this as you like - makes in-browser debug output more useable) */\r
+ position:fixed;_position:absolute;right:1em;bottom:1em;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:monaco,"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);\r
+}\r
+</style>\r
+<!-- some CSS for this demo page, not required for SM2 -->\r
+<link rel="stylesheet" href="template.css" />\r
+\r
+<!-- SM2 BAREBONES TEMPLATE: START -->\r
+\r
+<!-- include SM2 library -->\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+\r
+<!-- And now, customize it! -->\r
+<script type="text/javascript">\r
+\r
+soundManager.setup({\r
+ // debugMode: false, // disable debug output\r
+ url: '../../swf/', // path to directory containing SoundManager2 .SWF file\r
+ flashVersion: 8,\r
+ useFlashBlock: false, // skip for now. See the flashblock demo when you want to start getting fancy.\r
+ onready: function() {\r
+ // soundManager.createSound() etc. may now be called\r
+ soundManager._writeDebug('soundManager.onready() - your code executes here');\r
+ }\r
+});\r
+\r
+</script>\r
+\r
+<!-- SM2 BAREBONES TEMPLATE: END -->\r
+\r
+</head>\r
+\r
+<body style="height:100%">\r
+\r
+<div style="margin-right:43em">\r
+ <h1>SoundManager 2 Template Example</h1>\r
+ <p>This is a basic template for adding SoundManager to your page.</p> \r
+ <h2>How it works</h2>\r
+ <p>This page includes the SM2 script, which starts up on its own as appropriate. By default it will try to start as soon as possible.</p>\r
+ <p>The minimal code needed to get SoundManager 2 going is below, with <em><em>configurable parts</em></em>:</p>\r
+<code>\r
+<pre>\r
+<span><!-- include SM2 library --></span>\r
+<script type="text/javascript" src="<em><em>/path/to/soundmanager2.js</em></em>"></script>\r
+\r
+<span><!-- configure it for your use --></span>\r
+<script type="text/javascript">\r
+\r
+soundManager.setup({\r
+ url: '<em><em>/path/to/sm2-flash-files/</em></em>', <span>// directory where SM2 .SWFs live</span>\r
+\r
+ <span>/*\r
+ * Note that SoundManager will determine and append the appropriate .SWF file to the URL,\r
+ * eg. /path/to/sm2-flash-files/soundmanager2.swf automatically.\r
+ * You should not put soundmanager2.swf in there yourself.\r
+ */</span>\r
+\r
+ <span>// Beta-ish HTML5 audio support (force-enabled for iPad), flash-free sound for Safari + Chrome. Enable if you want to try it!</span>\r
+ <span>// useHTML5Audio: true,</span>\r
+\r
+ <span>// do this to skip flash block handling for now. See the <a href="../flashblock/" title="SoundManager 2 flashblock handling demo" onclick="if (!document.domain && !this.href.match(/index/i)) this.href=this.href+'index.html'">flashblock demo</a> when you want to start getting fancy.</span>\r
+ useFlashBlock: false,\r
+\r
+ <span>// disable debug mode after development/testing..</span>\r
+ <span>// debugMode: false</span>\r
+\r
+});\r
+\r
+<span style="background:#eee;padding:0.25em">// Option 1: Simple onready() + createSound() method</span>\r
+\r
+soundManager.onready(function() {\r
+ <span>// SM2 has loaded - now you can create and play sounds!</span>\r
+ <em><em>soundManager.createSound('helloWorld','/path/to/hello-world.mp3');\r
+ soundManager.play('helloWorld');</em></em>\r
+});\r
+\r
+<span style="background:#eee;padding:0.25em">// Option 2 (better): More flexible onready() + createSound() method</span>\r
+\r
+soundManager.onready(function() {<em><em>\r
+\r
+ var mySound = soundManager.createSound({\r
+ id: 'aSound',\r
+ url: '/path/to/an.mp3'\r
+ <span>// onload: <span>[ event handler function object ],</span></span>\r
+ <span>// other options here..</span>\r
+ });\r
+\r
+ mySound.play();\r
+\r
+</em></em>});\r
+\r
+<span style="background:#eee;padding:0.25em">// Option 3 (best): onready() + createSound() / ontimeout() methods for success/failure:</span>\r
+\r
+soundManager.onready(function() {<em><em>\r
+\r
+ <span>// SM2 has loaded - now you can create and play sounds!</span>\r
+ var mySound = soundManager.createSound({\r
+ id: 'aSound',\r
+ url: '/path/to/an.mp3'\r
+ <span>// onload: <span>[ event handler function object ],</span></span>\r
+ <span>// other options here..</span>\r
+ });\r
+ mySound.play();\r
+\r
+</em></em>});\r
+\r
+soundManager.ontimeout(function() {<em><em>\r
+\r
+ <span>// (Optional) Hrmm, SM2 could not start. Show an error, etc.?</span>\r
+\r
+</em></em>});\r
+\r
+\r
+</script></pre></code>\r
+\r
+ <h2 id="flashblock-handling">Handling flash blockers</h2>\r
+ <p>It's good to let users see the flash component of SM2, so those with flash blockers can unblock it and allow SM2 to start. For more info on this, see the <a href="../flashblock/" title="SoundManager 2 with Flash block handling" onclick="if (!document.domain && !this.href.match(/index/i)) this.href=this.href+'index.html'">Flashblock</a> example.</p>\r
+\r
+ <h2>Making SM2 wait for <code>window.onload()</code></h2>\r
+ <p>If you prefer to have the library wait for <code>window.onload()</code> before making <code>onready()</code> / <code>ontimeout()</code> callbacks, you can specify <code>waitForWindowLoad: true</code>.</p>\r
+\r
+ <h2 style="margin-top:1em">Disabling debug output</h2>\r
+ <p>SoundManager 2 will write debug output via <code>console.log()</code> if available, by default. To disable it, simply specify <code>debugMode: false</code>.</p>\r
+ <p>You can also write HTML-based debug output to the DOM via <code>consoleOnly: false</code> and/or <code>useConsole: false</code>.</p>\r
+ <p>To see related configuration code, refer to the source of this page which basically does all of the above "for real."</p>\r
+\r
+ <h2>Troubleshooting ("failed to start": Viewing offline, missing SWF, flash blockers etc.)</h2>\r
+ <p>If SM2 is failing to start and throwing errors due to flash security, timeouts or other issues, check out the <a href="../../doc/getstarted/#troubleshooting" title="SoundManager 2 troubleshooting tool" onclick="checkDomain()">troubleshooting tool</a> for tips.</p>\r
+\r
+ <h2>No-debug, compressed version of soundmanager2.js</h2>\r
+ <p>Once development is finished, you can also use the "minified" (down to ~8% of original size with gzip!) version of SM2, which has debug output and comments removed for you: <a href="../../script/soundmanager2-nodebug-jsmin.js">soundmanager2-nodebug-jsmin.js</a>. Serve with gzip compression wherever possible for best bandwidth savings.</p>\r
+ \r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+/**
+ * SoundManager 2: "Turntable UI" - CSS
+ * Copyright (c) 2015, Scott Schiller. All rights reserved.
+ * http://www.schillmania.com/projects/soundmanager2/
+ * Code provided under BSD license.
+ * http://schillmania.com/projects/soundmanager2/license.txt
+ */
+
+.turntable {
+ position: relative;
+}
+
+.turntable,
+.turntable img.stub {
+ width: 100%;
+ max-width: 1256px;
+ /* optional: max-width: 628px; if you want nice retina-scale graphics at full-width. */
+}
+
+.turntable .table-bg {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ width: 100%;
+ height: 100%;
+ background: transparent url(../image/tt_table.png) no-repeat 0px 0px;
+ background-size: contain;
+}
+
+.turntable .frame,
+.turntable .bd {
+ position: absolute;
+ top: 9.7%;
+ left: 5.4936%;
+ height: 82.25%;
+ width: 88.15%;
+ padding: 0.054936% 0px 0px 0.099%;
+ border-radius: 5px;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ overflow: hidden;
+}
+
+.turntable .frame {
+ /* If you want to skin the turntable body with a texture etc., apply a background image and/or color here. */
+ /*
+ background: #cdcfc7;
+ background: #a4a4a4;
+ background: #262626;
+ */
+ background: #262626;
+ /* rounding hacks */
+ padding: 1px;
+ margin-left: -1px;
+}
+
+.turntable .platter {
+ position: absolute;
+ top: 0.33%;
+ left: 5.025%;
+ width: 72.75%;
+ height: 100%;
+ background: transparent url(../image/platter.png) no-repeat 50% 50%;
+ background-size: contain;
+ border-radius: 100%;
+ overflow: hidden;
+ }
+
+.turntable .slipmat,
+.turntable .record,
+.turntable .record-grooves {
+ position: absolute;
+ top: 6.3%;
+ left: 8.35%;
+ width: 66.2%;
+ height: 87.994%;
+ border-radius: 100%;
+ overflow: hidden;
+}
+
+.turntable .label {
+ position: absolute;
+ top: 37.25%;
+ left: 31.45%;
+ width: 20%;
+ height: 26.5%;
+ background: #fff;
+ border-radius: 100%;
+}
+
+.turntable.has-artwork.hide-label-with-artwork .label {
+ display: none;
+}
+
+.turntable .slipmat {
+ background: transparent url(../image/slipmat.jpg) no-repeat 50% 50%;
+ background-size: contain;
+}
+
+.turntable.power-on.motor-on .platter,
+.turntable.power-on.motor-on .spindle,
+.turntable.power-on.motor-on .record-grooves,
+.turntable.power-on.motor-on.has-artwork .record,
+.turntable.power-on.motor-on .slipmat {
+ -webkit-transition-property: -webkit-transform;
+ -webkit-transform-origin: 50% 50%;
+ transition-property: transform;
+ transform-origin: 50% 50%;
+ -webkit-animation: spin 2.33s linear infinite;
+ animation: spin 2.33s linear infinite;
+}
+
+.turntable.power-on.motor-on .slipmat {
+ -webkit-animation-duration: 1.75s;
+ animation-duration: 1.75s;
+}
+
+.turntable .record-holder,
+.turntable .slipmat-holder {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ width: 100%;
+ height: 100%;
+ /* hide by default */
+ opacity: 0;
+ /* lazy */
+ -webkit-transition: all 0.35s;
+ transition: all 0.35s;
+ transform: scale3d(1.15,1.15,1.15);
+ transform-origin: 42% 50%;
+}
+
+.turntable.has-record .record-holder,
+.turntable.has-slipmat .slipmat-holder {
+ opacity: 1;
+ transform: scale3d(1,1,1);
+ -webkit-filter: none;
+ filter: none;
+}
+
+.turntable .record {
+ background-color: #000;
+ /* in the event artwork is applied, try to scale and center by default. */
+ /* slightly oversize to fix possible rounding errors. */
+ background-size: cover;
+ background-position: 50% 50%;
+ background-repeat: no-repeat;
+}
+
+.turntable .record-grooves {
+ background: transparent url(../image/record-grooves-1440x1440-white.png) no-repeat 50% 50%;
+ background-size: contain;
+ opacity: 0.15;
+}
+
+.turntable .spindle {
+ position: absolute;
+ left: 40.78%;
+ top: 49.45%;
+ width: 1.17%;
+ height: 1.55%;
+ background-color: rgba(0,0,0,0.65);
+ border-radius: 100%;
+ border: 1px solid rgba(0,0,0,0.15);
+ background-image: -webkit-radial-gradient(center, ellipse cover, rgba(255,255,255,1) 0%,rgba(128,128,128,0) 100%); /* Chrome10+,Safari5.1+ */
+ background-image: -o-radial-gradient(center, ellipse cover, rgba(255,255,255,1) 0%,rgba(128,128,128,0) 100%); /* Opera 12+ */
+ background-image: -ms-radial-gradient(center, ellipse cover, rgba(255,255,255,1) 0%,rgba(128,128,128,0) 100%); /* IE10+ */
+ background-image: radial-gradient(ellipse at center, rgba(255,255,255,1) 0%,rgba(128,128,128,0) 100%); /* W3C */
+ /* fix border bleed */
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+}
+
+.turntable .tonearm-holder,
+.turntable .tonearm {
+ -webkit-transform-origin: 54% 27%;
+ transform-origin: 54% 27%;
+}
+
+.turntable .tonearm-holder {
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ margin-top: -4%;
+ margin-right: 2.75%;
+ width: 28.55%;
+ height: 99.75%;
+}
+
+.turntable .tonearm {
+ position: absolute;
+ right: 0px;
+ top: 0px;
+ width: 100%;
+ height: 100%;
+ background: transparent url(../image/tt_arm.png) no-repeat 0px 0px;
+ background-size: contain;
+ -webkit-transition: -webkit-transform 0.1s;
+ transition: transform 0.1s;
+}
+
+.turntable.motor-on.has-record .tonearm-holder {
+ -webkit-animation: wobble 1s ease-in-out alternate infinite;
+ animation: wobble 1s ease-in-out alternate infinite;
+}
+
+.turntable .button:active {
+ transform-origin: 50% 50%;
+ transform: scale(0.975);
+ opacity: 0.9;
+}
+
+.turntable .start-stop {
+ position: absolute;
+ top: 85.85%;
+ left: 2%;
+ width: 10.58983%;
+ height: 10.65%;
+ background: transparent url(../image/tt_startstop.png) no-repeat 0px 0px;
+ background-size: contain;
+ margin: 0.175% 0px 0px -0.175%;
+ border-radius: 5px;
+}
+
+.turntable .power-light {
+ position: absolute;
+ bottom: 18.5%;
+ left: 5.75%;
+ width: 15.95%;
+ height: 17.9%;
+ background: transparent url(../image/power-light.png) no-repeat 0px 0px;
+ background-size: contain;
+ -webkit-transform: rotate(12.5deg);
+ transform: rotate(12.5deg);
+ -webkit-transform-origin: 50% 50%;
+ transform-origin: 50% 50%;
+ -webkit-transition: opacity 0.25s;
+ transition: opacity 0.25s;
+ opacity: 0;
+}
+
+.turntable.power-on .power-light {
+ opacity: 1;
+}
+
+.turntable.power-on.motor-on .power-light {
+ -webkit-animation: flicker 0.08s linear infinite;
+ animation: flicker 0.08s linear infinite;
+}
+
+.turntable .power-dial {
+ position: absolute;
+ bottom: 17.5%;
+ left: 2.75%;
+ width: 5.95%;
+ height: 7.9%;
+ -webkit-transform: rotate(0deg);
+ -webkit-transform-origin: 50% 50%;
+ -webkit-transition: transform 0.2s ease-out;
+ transform: rotate(0deg);
+ transform-origin: 50% 50%;
+ -webkit-transition: -webkit-transform 0.2s ease-out;
+ transition: transform 0.2s ease-out;
+ background: transparent url(../image/tt_powerdial.png) no-repeat 0px 0px;
+ background-size: contain;
+}
+
+.turntable.power-on .power-dial {
+ -webkit-transform: rotate(22.5deg);
+ transform: rotate(22.5deg);
+}
+
+.turntable .speed-33 {
+ position: absolute;
+ bottom: 4%;
+ left: 13.4%;
+ width: 5.12%;
+ height: 1.85%;
+ background: transparent url(../image/tt_33.png) no-repeat 0px 0px;
+ background-size: contain;
+}
+
+.turntable.power-on .speed-33.on {
+ background-image: url(../image/tt_33_on.png);
+}
+
+.turntable .speed-45 {
+ position: absolute;
+ bottom: 4%;
+ left: 19.05%;
+ width: 5.12%;
+ height: 1.85%;
+ background: transparent url(../image/tt_45.png) no-repeat 0px 0px;
+ background-size: contain;
+}
+
+.turntable.power-on .speed-45.on {
+ background-image: url(../image/tt_45_on.png);
+}
+
+.turntable .light {
+ position: absolute;
+ bottom: 2%;
+ left: 48.25%;
+ width: 21.7%;
+ height: 24.9%;
+ background: transparent url(../image/tt_lightoff.png) no-repeat 0px 0px;
+ background-size: contain;
+}
+
+.turntable .light-on {
+ position: absolute;
+ bottom: 3.15%;
+ left: 52.25%;
+ width: 18.7%;
+ height: 19.9%;
+ background: transparent url(../image/tt_lighton.png) no-repeat 0px 0px;
+ background-size: contain;
+ transform: rotate(12deg);
+ opacity: 0;
+ -webkit-transition: opacity 0.2s;
+ transition: opacity 0.2s;
+}
+
+.turntable.power-on .light-on {
+ opacity: 1;
+}
+
+@-webkit-keyframes flicker {
+ from { opacity: 0.85; }
+ to { opacity: 1; }
+}
+
+@keyframes flicker {
+ from { opacity: 0.85; }
+ to { opacity: 1; }
+}
+
+@-webkit-keyframes spin {
+ from { -webkit-transform: rotate(180deg); }
+ to { -webkit-transform: rotate(540deg); }
+}
+
+@keyframes spin {
+ from { transform: rotate(180deg); }
+ to { transform: rotate(540deg); }
+}
+
+@-webkit-keyframes wobble {
+ from { -webkit-transform: rotate(0deg); }
+ to { -webkit-transform: rotate(0.33deg); }
+}
+
+@keyframes wobble {
+ from { transform: rotate(0deg); }
+ to { transform: rotate(0.33deg); }
+}
\ No newline at end of file
--- /dev/null
+Patterns from subtlepatterns.com.\r
+"If you need more, that's where to get 'em."
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+<head>
+<meta charset="UTF-8" />
+<title>SoundManager 2: Turntable UI</title>
+<meta name="robots" content="noindex" />
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>
+<script src="script/turntable.js"></script>
+<script src="script/turntable-app.js"></script>
+<link rel="stylesheet" href="css/turntable.css" />
+</head>
+
+<body>
+
+<style>
+
+/* a bit of demo CSS - you don't need this. */
+
+body {
+ font-family: helvetica, arial, verdana, sans-serif;
+ font-size: 1rem;
+ font-weight: lighter;
+ color: #fff;
+ background: #393939;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ /* general font niceness? */
+ font-smoothing: antialiased;
+ text-rendering: optimizeLegibility;
+ color: #ccc;
+}
+
+h1,
+h2 {
+ font-family: "Helvetica Neue", helvetica, arial, verdana, sans-serif;
+ font-weight: 100;
+}
+
+/* skin the turntable body? see turntable.css for more. */
+.turntable .frame {
+ background-color: #333;
+ background-image: url(image/textures/textured_paper.png);
+ /* scale for retina, etc. */
+ background-size: 250px 250px;
+ /* classic champagne-ish color? */
+ /* background: #abacac; */
+}
+
+div.about {
+ position: relative;
+ z-index: 2;
+ margin: 0px 0px -4% 5%;
+ color: #fff;
+}
+
+div.about h1 {
+ font-size: 3.275em;
+ margin: 0px 0px 0.1em 0px;
+}
+
+div.about h2 {
+ font-size: 2.5em;
+ margin: 0.75em 0px 0.2em 0px;
+}
+
+div.about a {
+ text-decoration: none;
+ color: #fff;
+}
+
+div.about p {
+ line-height: 1.5em;
+ margin: 0px 0px 0.25em 0px;
+}
+
+div.about p:last-of-type {
+ margin-bottom: 2em;
+}
+
+ul,
+.indent {
+ padding-left: 4em;
+}
+
+ul {
+ clear: both;
+ margin-top: 0px;
+ padding-top: 0px;
+ margin-bottom: 0px;
+ color: #999;
+}
+
+ul li {
+ line-height: 1.4em;
+}
+
+ul li a {
+ position: relative;
+ padding: 0px 3px;
+ margin: 0px -3px;
+ text-decoration: none;
+ display: inline-block;
+ border-radius: 3px;
+}
+
+b {
+ font-weight: 500;
+}
+
+code {
+ font-family: "lucida console", "courier new", monaco, monospace;
+ font-size: 1em;
+ color: #99ff99;
+}
+
+div.about p a,
+ul li a {
+ color: #99ccff;
+}
+
+div.about p a:hover,
+ul li a:hover {
+ background-color: #000;
+ color: #fff;
+ outline: 1px solid rgba(255,255,255,0.1);
+}
+
+</style>
+
+<div style="position:relative">
+
+ <div class="about">
+
+ <h1><a href="http://www.schillmania.com/projects/soundmanager2/">SoundManager 2</a>: Turntable UI</h1>
+
+ <p>An experimental HTML + CSS design inspired by the infamous Technics 1200 turntable.</p>
+
+ <p>This project is a remix of <a href="http://www.schillmania.com/content/entries/2011/wheels-of-steel/" title="The Wheels Of Steel: HTML Turntables in the web browser">The Wheels Of Steel</a>, using a subset of features from the original.</p>
+
+ </div>
+
+ <!-- start turntable: centered and scales up to a predetermined max-width (based on image size) -->
+
+ <div style="position:relative;text-align:center">
+
+ <!-- note: inline-block is just for centering -->
+
+ <div id="turntable-large" class="turntable has-slipmat" style="display:inline-block">
+
+ <div class="frame"></div>
+
+ <div class="table-bg"></div>
+
+ <!-- image that sets the base dimensions-->
+ <img src="image/tt_case_and_lighting.png" alt="" class="stub" />
+
+ <div class="bd">
+
+ <div class="platter"></div>
+
+ <div class="slipmat-holder">
+ <div class="slipmat"></div>
+ </div>
+
+ <div class="record-holder">
+ <div class="record"></div>
+ <div class="record-grooves"></div>
+ <div class="label"></div>
+ </div>
+
+ <div class="spindle"></div>
+ <div class="power-light"></div>
+ <a href="#" class="power-dial" data-method="powerToggle"></a>
+ <a href="#" class="button start-stop" data-method="toggle"></a>
+ <a href="#" class="button speed-33 on"></a>
+ <a href="#" class="button speed-45"></a>
+ <div class="light light-on"></div>
+ <a href="#" class="button light"></a>
+ <div class="tonearm-holder">
+ <div class="tonearm"></div>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+
+ <div>
+
+ <!-- end turntable -->
+
+ <p class="indent" style="margin-top:-3%">Click a link to load it on the turntable.</p>
+
+ <ul>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Figub%20Brazlevi%C4%8D%20-%20Bosnian%20Syndicate.mp3" data-turntable="turntable-large" data-artwork="http://freshly-ground.com/data/image/sm2/trainyards-cover-640.jpg"><b>Figub Brazlevič</b> - Bosnian Syndicate</a> (<span title="Published under a Creative Commons BY-NC-ND license">BY-CC-ND license</span>, <a href="http://figubbrazlevic.bandcamp.com/track/bosnian-syndicate">via</a>)</li>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Beckyoncé%20-%20Single%20Loser.mp3" data-turntable="turntable-large" data-artwork="http://freshly-ground.com/data/image/sm2/beckyonce.jpg">Beckyoncé - Single Loser (Put A Beck On It)</a> (<span title="Published under a Creative Commons BY-NC-SA license">BY-NC-SA license</span>, <a href="https://soundcloud.com/beckyonce/single-loser-put-a-beck-on-it" target="_blank">via</a>)</li>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Chill With Schill (Summer 2012 Session Excerpt).mp3" data-turntable="turntable-large">Chill With Schill (Summer 2012 Session Excerpt)</a></li>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3" data-turntable="turntable-large" data-artwork="http://freshly-ground.com/data/image/sm2/sonreal-onelongday-65.jpg">SonReal - L.A. (Prod. Injetti)</a></li>
+ </ul>
+
+ <p class="indent" style="max-width:42em">HTML <code>data</code> attributes can be used to specify which turntable to use, and an optional album artwork image. You can also skin the turntable with background images, textures and colors.</p>
+
+ </div>
+
+ <div style="clear:both;height:1em"></div>
+
+ <style>
+ /* dark wood, because why not. */
+ #turntable-1 .frame {
+ background: url(image/textures/wood_pattern_dark_color.png);
+ /* scale for retina, etc. */
+ background-size: 101px 158px;
+ }
+ #turntable-2 .frame {
+ background: url(image/textures/pinstriped_suit_vertical.png);
+ background-size: 142px 76px;
+ }
+ </style>
+
+ <!-- two turntables side-by-side -->
+
+ <div style="position:relative;float:left;display:inline-block;width:50%">
+
+ <!-- start turntable -->
+
+ <div id="turntable-1" class="turntable has-slipmat">
+
+ <div class="frame"></div>
+
+ <div class="table-bg"></div>
+
+ <!-- image that sets the base dimensions-->
+ <img src="image/tt_case_and_lighting.png" alt="" class="stub" />
+
+ <div class="bd">
+
+ <div class="platter"></div>
+
+ <div class="slipmat-holder">
+ <div class="slipmat"></div>
+ </div>
+
+ <div class="record-holder">
+ <div class="record"></div>
+ <div class="record-grooves"></div>
+ <div class="label"></div>
+ </div>
+
+ <div class="spindle"></div>
+ <div class="power-light"></div>
+ <a href="#" class="power-dial" data-method="powerToggle"></a>
+ <a href="#" class="button start-stop" data-method="toggle"></a>
+ <a href="#" class="button speed-33 on"></a>
+ <a href="#" class="button speed-45"></a>
+ <div class="light light-on"></div>
+ <a href="#" class="button light"></a>
+ <div class="tonearm-holder">
+ <div class="tonearm"></div>
+ </div>
+ </div>
+
+ </div>
+
+ <!-- end turntable -->
+
+ <ul>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Figub%20Brazlevi%C4%8D%20-%20Bosnian%20Syndicate.mp3" data-turntable="turntable-1" data-artwork="http://freshly-ground.com/data/image/sm2/trainyards-cover-640.jpg"><b>Figub Brazlevič</b> - Bosnian Syndicate</a> (<span title="Published under a Creative Commons BY-NC-ND license">BY-CC-ND</span>, <a href="http://figubbrazlevic.bandcamp.com/track/bosnian-syndicate" target="_blank">via</a>)</li>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Beckyoncé%20-%20Single%20Loser.mp3" data-turntable="turntable-1" data-artwork="http://freshly-ground.com/data/image/sm2/beckyonce.jpg">Beckyoncé - Single Loser (Put A Beck On It)</a> (<span title="Published under a Creative Commons BY-NC-SA license">BY-NC-SA license</span>, <a href="https://soundcloud.com/beckyonce/single-loser-put-a-beck-on-it" target="_blank">via</a>)</li>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3" data-turntable="turntable-1" data-artwork="http://freshly-ground.com/data/image/sm2/sonreal-onelongday-65.jpg">SonReal - L.A. (Prod. Injetti)</a></li>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Everything%20I%20Am.mp3" data-artwork="http://freshly-ground.com/data/image/sm2/sonreal-everythingiam-65.jpg" data-turntable="turntable-1"><b>SonReal</b> - Everything I Am</a></li>
+ </ul>
+
+ </div>
+
+ <div style="position:relative;float:left;display:inline-block;width:50%">
+
+ <!-- start turntable -->
+
+ <div id="turntable-2" class="turntable has-slipmat has-record">
+
+ <div class="frame"></div>
+
+ <div class="table-bg"></div>
+
+ <!-- image that sets the base dimensions-->
+ <img src="image/tt_case_and_lighting.png" alt="" class="stub" />
+
+ <div class="bd">
+
+ <div class="platter"></div>
+
+ <div class="slipmat-holder">
+ <div class="slipmat"></div>
+ </div>
+
+ <div class="record-holder">
+ <div class="record"></div>
+ <div class="record-grooves"></div>
+ <div class="label"></div>
+ </div>
+
+ <div class="spindle"></div>
+ <div class="power-light"></div>
+ <a href="#" class="power-dial" data-method="powerToggle"></a>
+ <a href="#" class="button start-stop" data-method="toggle"></a>
+ <a href="#" class="button speed-33 on"></a>
+ <a href="#" class="button speed-45"></a>
+ <div class="light light-on"></div>
+ <a href="#" class="button light"></a>
+ <div class="tonearm-holder">
+ <div class="tonearm"></div>
+ </div>
+ </div>
+
+ </div>
+
+ <!-- end turntable -->
+
+ <ul>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3" data-turntable="turntable-2" data-artwork="http://freshly-ground.com/data/image/sm2/sonreal-onelongday-65.jpg">SonReal - L.A. (Prod. Injetti)</a></li>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Everything%20I%20Am.mp3" data-artwork="http://freshly-ground.com/data/image/sm2/sonreal-everythingiam-65.jpg" data-turntable="turntable-2"><b>SonReal</b> - Everything I Am</a></li>
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Already%20There%20Remix%20ft.%20Rich%20Kidd%2C%20Saukrates.mp3" data-turntable="turntable-2"><b>SonReal</b> - Already There Remix ft. Rich Kidd, Saukrates</a></li>
+ </ul>
+
+ </div>
+
+ <div class="about" style="clear:both;padding-top:1em;padding-bottom:2em;margin:0em 0px 0px 2.65%;max-width:41em">
+
+ <h2>JavaScript API</h2>
+
+ <p>Refer to the <code>window.turntables</code> array, where you can call methods such as <code>turntables[0].methods.powerToggle()</code>. There is also a <code>turntablesById</code> object, where the ID is based on the HTML <code>id</code> attribute of the top-level turntable <code><div></code>.
+
+ <h2>General Disclaimer</h2>
+
+ <p><em>This is an experimental prototype provided <b>"unsupported"</b> and <b>"as-is"</b></em>, and a million things could be added; few are planned or will be implemented. Pitch bending support would require a Web Audio API implementation, not a part of SM2 at present. See the <a href="http://www.schillmania.com/content/entries/2011/wheels-of-steel/">Wheels Of Steel</a> project for the original feature list. Percentage-based scaling in this prototype means that some elements may shift slightly, and may not always be exactly square or round etc.</p>
+
+ </div>
+
+</div>
+
+</body>
+</html>
--- /dev/null
+/*jslint vars: true, plusplus: true, white: true, nomen: true */
+/*global soundManager, console, document, navigator, turntables, turntablesById, window */
+
+(function(window) {
+
+ /** @license
+ * SoundManager 2: "Turntable UI": Demo application
+ * Copyright (c) 2015, Scott Schiller. All rights reserved.
+ * http://www.schillmania.com/projects/soundmanager2/
+ * Code provided under BSD license.
+ * http://schillmania.com/projects/soundmanager2/license.txt
+ */
+
+ "use strict";
+
+ var turntables;
+ var events;
+ var utils;
+ var sounds;
+ var config;
+ var state;
+ var isMonophonic;
+ var localMethods;
+ var playSound;
+
+ // Default behaviours.
+ config = {
+
+ // if specified, CSS className required for links to be played
+ requireCSS: null,
+
+ // CSS className that will prevent links from being played
+ excludeCSS: 'turntable-exclude',
+
+ // when a sound finishes, find and play the next one?
+ playNext: true,
+
+ // show a record right away? (otherwise, "techniques" slipmat.)
+ hasRecordAtStart: false,
+
+ // play some background noise when end of record is hit.
+ useEndOfRecordNoise: true,
+
+ // samples from a real turntable. add more to taste.
+ endOfRecordNoise: [
+ 'audio/record-noise-1.mp3',
+ 'audio/record-noise-2.mp3'
+ ],
+
+ // for assigning a target (turntable) to play. e.g., <a href="some.mp3" data-turntable="tt-1">some.mp3</a>
+ htmlAttribute: 'data-turntable',
+
+ // turntable innards. modify at own risk.
+ turntable: {
+ tonearm: {
+ angleToRecord: 16, // tonearm angle to outer edge of record
+ recordAngleSpan: 26 // outer edge -> inner edge of record
+ }
+ },
+
+ /**
+ * recommendation: don't edit these, use methods on window.turntables[] instead.
+ * to control sounds, call methods on turntables[0] etc. which will affect sounds in turn.
+ */
+ soundOptions: {
+ multiShot: false,
+ onload: function(ok) {
+ if (!ok && !this.duration) {
+ // treat as a failure.
+ events.sound.error.apply(this, arguments);
+ }
+ },
+ whileplaying: function() {
+ events.sound.whileplaying.apply(this, arguments);
+ },
+ onfinish: function() {
+ events.sound.finish.apply(this, arguments);
+ }
+ }
+
+ };
+
+ sounds = {
+ endOfRecordNoise: []
+ };
+
+ state = {
+ endOfRecordNoise: null,
+ soundFinished: false,
+ lastLink: null
+ };
+
+ // devices that likely block auto-play and only allow one sound to be played at a time
+ isMonophonic = navigator.userAgent.match(/iphone|ipad|android|tablet|mobile/i);
+
+ function findTheDamnLink(o) {
+
+ // click events may have a nested target element instead of the link. Find the parent <a>.
+
+ // link was clicked.
+ if (o && o.nodeName === 'A') {
+ return o;
+ }
+
+ // nested case.
+ if (o && o.parentNode) {
+ do {
+ o = o.parentNode;
+ } while (o && o.nodeName !== 'A' && o.parentNode);
+ }
+
+ return o;
+
+ }
+
+ function canPlayLink(a) {
+
+ // can SM2 play the <a>, and does it specifically include or exclude via CSS?
+ return (
+ a && soundManager.canPlayLink(a)
+ && (!config.requireCSS || utils.css.has(a, config.requireCSS))
+ && (!config.excludeCSS || !utils.css.has(a, config.excludeCSS))
+ );
+
+ }
+
+ function findNextLink(o) {
+
+ // find current link in page, play next in DOM (or first, if no match.)
+
+ var foundCurrent, i, j, links, playableLinks, result, target;
+
+ // check for data- turntable target attribute.
+ target = o.getAttribute(config.htmlAttribute);
+
+ links = document.getElementsByTagName('a');
+
+ playableLinks = [];
+
+ for (i=0, j=links.length; i<j; i++) {
+
+ if (canPlayLink(links[i])) {
+
+ // no data- target attribute, OR same target
+ if (!target || links[i].getAttribute(config.htmlAttribute) === target) {
+
+ playableLinks.push(links[i]);
+
+ // if last-active link found, take this one and exit.
+ if (foundCurrent) {
+ result = links[i];
+ break;
+ }
+
+ // is this the current link?
+ if (o === links[i]) {
+ foundCurrent = true;
+ }
+
+ }
+
+ }
+
+ }
+
+ // no match in DOM, perhaps rewritten via AJAX while playing etc.? Take the first.
+ if (!foundCurrent) {
+ result = playableLinks[0];
+ }
+
+ // if result is current, return null to avoid double-playing.
+ if (result === o) {
+ result = null;
+ }
+
+ return result;
+
+ }
+
+ events = {
+
+ mouse: {
+
+ click: function(e) {
+
+ // look for and play links to sounds.
+
+ var target,
+ ttID,
+ turntable;
+
+ target = findTheDamnLink(e.target);
+
+ if (canPlayLink(target)) {
+
+ // should this play on a particular turntable? (by HTML ID)
+ ttID = target.getAttribute('data-turntable');
+
+ // get the proper turntable.
+ turntable = turntablesById[ttID] || turntables[0];
+
+ // track this link for later.
+ state.lastLink = target;
+
+ playSound(turntable, target.href);
+
+ // artwork URL?
+ turntable.methods.setArtwork(target.getAttribute('data-artwork') || '');
+
+ return utils.events.preventDefault(e);
+
+ }
+
+ }
+
+ },
+
+ sound: {
+
+ whileplaying: function() {
+
+ var progress = (this.position / this.durationEstimate);
+
+ if (progress >= 0 && this._turntable) {
+ // base "tonearm over record" angle, plus additional angle to move across the record.
+ this._turntable.methods.setTonearmAngle(config.turntable.tonearm.angleToRecord + (config.turntable.tonearm.recordAngleSpan * progress));
+ }
+
+ },
+
+ error: function() {
+
+ // something failed. 404, decode error, network loss etc.
+ // handle as though a sound finished.
+ if (window.console && console.warn) {
+ console.warn('Turntable failed to load ' + this.url);
+ }
+ events.sound.finish.apply(this);
+
+ },
+
+ finish: function() {
+
+ var nextLink;
+
+ state.finished = true;
+
+ if (config.playNext) {
+
+ nextLink = findNextLink(state.lastLink);
+
+ // click handler again
+ if (nextLink) {
+ events.mouse.click({
+ target: nextLink
+ });
+ }
+
+ }
+
+ // nothing else to play?
+ if (!nextLink && this._turntable) {
+
+ if (config.useEndOfRecordNoise && sounds.endOfRecordNoise.length) {
+
+ // make sure we're at end of record
+ this._turntable.methods.setTonearmAngle(config.turntable.tonearm.angleToRecord + config.turntable.tonearm.recordAngleSpan);
+
+ // end of record?
+ state.endOfRecordNoise = sounds.endOfRecordNoise[parseInt(Math.random() * sounds.endOfRecordNoise.length, 10)];
+
+ state.endOfRecordNoise.play({
+ loops: 999
+ });
+
+ } else {
+
+ // no more to do?
+ this._turntable.methods.stop();
+
+ }
+
+ }
+
+ }
+
+ }
+
+ };
+
+ playSound = function(turntable, url, load_only) {
+
+ var tt,
+ sound;
+
+ // if no turntable specified, take the first one.
+ tt = (turntable || turntables[0]);
+
+ if (tt.id) {
+ // second param: don't complain to console when sound doesn't exist.
+ sound = soundManager.getSoundById(tt.id, true);
+ }
+
+ // first play?
+ if (!sound) {
+
+ sound = soundManager.createSound({
+ id: tt.id,
+ url: url
+ });
+
+ } else {
+
+ // loading a new URL?
+ if (sound.url !== url) {
+ sound.stop();
+ }
+
+ }
+
+ state.finished = false;
+
+ // associate sound events with the given turntable.
+ // TODO: handle one sound object per table.
+ sound._turntable = turntable;
+
+ config.soundOptions.url = url;
+
+ // stop any previous record noise
+ if (state.endOfRecordNoise) {
+ state.endOfRecordNoise.stop();
+ state.endOfRecordNoise = null;
+ }
+
+ // if motor is already on, and the sound hasn't started yet (i.e., turntable motor was already on), start it now.
+ if (tt.data.power.motor && !sound.playState && !load_only) {
+ sound.play(config.soundOptions);
+ }
+
+ // start the turntable, add a slipmat and record if there isn't one already.
+ tt.methods.addSlipmat();
+ tt.methods.addRecord();
+
+ if (!load_only) {
+
+ tt.methods.powerOn();
+ tt.methods.start();
+
+ events.sound.whileplaying.apply(sound);
+
+ }
+
+ };
+
+ function applyDefaults() {
+
+ var i, j;
+
+ if (!isMonophonic && config.useEndOfRecordNoise && config.endOfRecordNoise.length) {
+ for (i=0, j=config.endOfRecordNoise.length; i<j; i++) {
+ sounds.endOfRecordNoise.push(soundManager.createSound({
+ url: config.endOfRecordNoise[i]
+ }));
+ }
+ }
+
+ if (config.hasRecordAtStart) {
+ for (i=0, j=turntables.length; i<j; i++) {
+ turntables[i].methods.addRecord();
+ }
+ }
+
+ }
+
+ function assignEvents() {
+
+ // default turntable behaviours
+ // TODO: use utils.mixin?
+
+ var i, j;
+
+ turntables.on.start = function(tt) {
+ soundManager.play(tt.id, config.soundOptions);
+ };
+
+ turntables.on.stop = function(tt) {
+ soundManager.pause(tt.id);
+ if (state.endOfRecordNoise) {
+ state.endOfRecordNoise.stop();
+ }
+ };
+
+ // tack on localMethods to turntable object
+ // TODO: use proper mixin
+ // note use of Function.bind (IE 9, Chrome 7, Firefox 4, Opera 11.60, Safari 5.1.4) to correct scope ('this') within handler.
+ if (localMethods.load.bind) {
+ for (i=0, j=turntables.length; i<j; i++) {
+ turntables[i].methods.load = localMethods.load.bind(turntables[i]);
+ }
+ }
+
+ // a little hackish: global for now
+ turntables.config = config;
+
+ }
+
+ // will be mixed into global turntable API. runs within scope of turntable instance.
+ localMethods = {
+ // convenience method for scripting, i.e., if you want to load a sound (and optionally, with associated artwork URL), without playing it.
+ load: function(soundURL, artworkURL) {
+ playSound(this, soundURL, true);
+ if (artworkURL) {
+ this.methods.setArtwork(artworkURL);
+ }
+ }
+ };
+
+ function init() {
+
+ applyDefaults();
+
+ turntables = window.turntables;
+
+ assignEvents();
+
+ // local references
+ utils = turntables.utils;
+
+ // watch clicks, load and play MP3s etc. on the turntable UI.
+ utils.events.add(document, 'click', events.mouse.click);
+
+ }
+
+ soundManager.onready(init);
+
+}(window));
\ No newline at end of file
--- /dev/null
+/*jslint plusplus: true, white: true, nomen: true */
+/*global soundManager, document, console, window */
+
+(function(window) {
+
+ /** @license
+ * SoundManager 2: "Turntable UI": Base and API
+ * Copyright (c) 2015, Scott Schiller. All rights reserved.
+ * http://www.schillmania.com/projects/soundmanager2/
+ * Code provided under BSD license.
+ * http://schillmania.com/projects/soundmanager2/license.txt
+ */
+
+ "use strict";
+
+ var turntables = [],
+ turntablesById = {},
+ // CSS selector for top-level DOM node
+ turntableSelector = '.turntable',
+ tt_prefix = 'tt_',
+ idCounter = 0,
+ utils;
+
+ /**
+ * Slightly hackish: Turntable event callbacks.
+ * Override globally by setting turntables.on = {}, or individually by turntables[0].on = {} etc.
+ */
+ turntables.on = {/*
+ stop: function(tt) {
+ console.log('turntable stopped', tt);
+ },
+ start: function(tt) {
+ console.log('turntable started', tt);
+ },
+ powerOn: function(tt) {
+ console.log('turntable powerOn', tt);
+ },
+ powerOff: function(tt) {
+ console.log('turntable powerOff', tt);
+ }*/
+ };
+
+ function Turntable(o, options) {
+
+ var api, css, dom, data, id, methods;
+
+ // DOM ID + SM2 sound reference
+ id = (tt_prefix + idCounter);
+
+ idCounter++;
+
+ options = options || {};
+
+ function add(className) {
+ utils.css.add(dom.o, className);
+ }
+
+ function remove(className) {
+ utils.css.remove(dom.o, className);
+ }
+
+ function callback(method) {
+ if (method) {
+ // fire callback, passing current turntable object
+ if (api.on && api.on[method]) {
+ api.on[method](api);
+ } else if (turntables.on[method]) {
+ turntables.on[method](api);
+ }
+ }
+ }
+
+ function applyTonearmAngle() {
+ if (data.tonearm.angle >= 0) {
+ dom.tonearm.style[utils.features.transform.prop] = 'rotate(' + data.tonearm.angle + 'deg)';
+ }
+ }
+
+ // TODO: use mixin
+ if (options.hideLabelWithArtwork === undefined) {
+ options.hideLabelWithArtwork = true;
+ }
+
+ css = {
+
+ power: {
+ turntable: 'power-on',
+ motor: 'motor-on'
+ },
+
+ turntable: {
+ hasArtwork: 'has-artwork',
+ hasRecord: 'has-record',
+ hasSlipmat: 'has-slipmat',
+ hideLabelWithArtwork: 'hide-label-with-artwork'
+ }
+
+ };
+
+ data = {
+
+ power: {
+ turntable: false,
+ motor: false,
+ motorVelocity: 0
+ },
+
+ tonearm: {
+ angle: 0,
+ maxAngle: 42,
+ minAngle: 0
+ },
+
+ record: {
+ hasArtwork: false
+ }
+
+ };
+
+ methods = {
+
+ start: function() {
+ if (data.power.turntable && !data.power.motor) {
+ data.power.motor = true;
+ add(css.power.motor);
+ callback('start');
+ }
+ },
+
+ stop: function() {
+ if (data.power.motor) {
+ data.power.motor = false;
+ remove(css.power.motor);
+ callback('stop');
+ }
+ },
+
+ toggle: function() {
+ if (data.power.motor) {
+ methods.stop();
+ } else {
+ methods.start();
+ }
+ },
+
+ powerOn: function() {
+ if (!data.power.turntable) {
+ data.power.turntable = true;
+ add(css.power.turntable);
+ callback('powerOn');
+ }
+ },
+
+ powerOff: function() {
+ if (data.power.turntable) {
+ data.power.turntable = false;
+ remove(css.power.turntable);
+ callback('powerOff');
+ }
+ // no power = no motor, too.
+ methods.stop();
+ },
+
+ powerToggle: function() {
+ if (!data.power.turntable) {
+ methods.powerOn();
+ } else {
+ methods.powerOff();
+ }
+ },
+
+ setTonearmAngle: function(angle) {
+ if (!isNaN(angle)) {
+ data.tonearm.angle = Math.max(data.tonearm.minAngle, Math.min(data.tonearm.maxAngle, angle));
+ if (utils.features.transform.prop) {
+ if (utils.features.getAnimationFrame) {
+ utils.features.getAnimationFrame(applyTonearmAngle);
+ } else {
+ applyTonearmAngle();
+ }
+ }
+ }
+ },
+
+ addSlipmat: function() {
+ add(css.turntable.hasSlipmat);
+ },
+
+ removeSlipmat: function() {
+ remove(css.turntable.hasSlipmat);
+ },
+
+ toggleSlipmat: function() {
+ utils.css.toggle(dom.o, css.turntable.hasSlipmat);
+ },
+
+ addRecord: function() {
+ add(css.turntable.hasRecord);
+ },
+
+ removeRecord: function() {
+ remove(css.turntable.hasRecord);
+ },
+
+ toggleRecord: function() {
+ utils.css.toggle(dom.o, css.turntable.hasRecord);
+ },
+
+ setArtwork: function(url) {
+ if (url) {
+ dom.record.style.backgroundImage = 'url(' + url + ')';
+ if (!data.record.hasArtwork) {
+ add(css.turntable.hasArtwork);
+ data.record.hasArtwork = true;
+ }
+ } else {
+ if (data.record.hasArtwork) {
+ dom.record.style.backgroundImage = 'none';
+ remove(css.turntable.hasArtwork);
+ data.record.hasArtwork = false;
+ }
+ }
+ if (options.hideLabelWithArtwork) {
+ add(css.turntable.hideLabelWithArtwork);
+ } else {
+ remove(css.turntable.hideLabelWithArtwork);
+ }
+ }
+
+ };
+
+ function handleMethod(e) {
+
+ var target, action;
+
+ target = e.target;
+
+ if (target) {
+
+ action = target.getAttribute('data-method');
+
+ if (action && methods[action]) {
+ methods[action](e);
+ }
+
+ }
+
+ }
+
+ function preventDefault(e) {
+
+ if (e.target && e.target.nodeName === 'A') {
+ utils.events.preventDefault(e);
+ return false;
+ }
+
+ }
+
+ function assignEvents() {
+
+ utils.events.add(dom.o, 'mousedown', handleMethod);
+ utils.events.add(dom.o, 'click', preventDefault);
+
+ }
+
+ function initDOM() {
+
+ dom = {
+ o: o,
+ platter: utils.dom.get(o, '.platter'),
+ record: utils.dom.get(o, '.record'),
+ slipmat: utils.dom.get(o, '.slipmat'),
+ tonearm: utils.dom.get(o, '.tonearm')
+ };
+
+ // inherit ID
+ if (!dom.o.id) {
+ dom.o.id = id;
+ } else {
+ id = dom.o.id;
+ }
+
+ }
+
+ function init() {
+
+ initDOM();
+
+ assignEvents();
+
+ // in a moment...
+ window.setTimeout(methods.powerToggle, 500);
+
+ }
+
+ init();
+
+ // public interface
+ api = {
+ id: id,
+ // css: css,
+ data: data,
+ methods: methods,
+ on: {} // per-turntable event overrides you can specify; see turntables.on for examples
+ };
+
+ return api;
+
+ }
+
+ // common JS helpers
+
+ utils = {
+
+ array: (function() {
+
+ function compare(property) {
+
+ var result;
+
+ return function(a, b) {
+
+ if (a[property] < b[property]) {
+ result = -1;
+ } else if (a[property] > b[property]) {
+ result = 1;
+ } else {
+ result = 0;
+ }
+ return result;
+ };
+
+ }
+
+ function shuffle(array) {
+
+ // Fisher-Yates shuffle algo
+
+ var i, j, temp;
+
+ for (i = array.length - 1; i > 0; i--) {
+ j = Math.floor(Math.random() * (i+1));
+ temp = array[i];
+ array[i] = array[j];
+ array[j] = temp;
+ }
+
+ return array;
+
+ }
+
+ return {
+ compare: compare,
+ shuffle: shuffle
+ };
+
+ }()),
+
+ css: (function() {
+
+ function hasClass(o, cStr) {
+
+ return (o.className !== undefined ? new RegExp('(^|\\s)' + cStr + '(\\s|$)').test(o.className) : false);
+
+ }
+
+ function addClass(o, cStr) {
+
+ if (!o || !cStr || hasClass(o, cStr)) {
+ return false; // safety net
+ }
+ o.className = (o.className ? o.className + ' ' : '') + cStr;
+
+ }
+
+ function removeClass(o, cStr) {
+
+ if (!o || !cStr || !hasClass(o, cStr)) {
+ return false;
+ }
+ o.className = o.className.replace(new RegExp('( ' + cStr + ')|(' + cStr + ')', 'g'), '');
+
+ }
+
+ function swapClass(o, cStr1, cStr2) {
+
+ var tmpClass = {
+ className: o.className
+ };
+
+ removeClass(tmpClass, cStr1);
+ addClass(tmpClass, cStr2);
+
+ o.className = tmpClass.className;
+
+ }
+
+ function toggleClass(o, cStr) {
+
+ var found,
+ method;
+
+ found = hasClass(o, cStr);
+
+ method = (found ? removeClass : addClass);
+
+ method(o, cStr);
+
+ // indicate the new state...
+ return !found;
+
+ }
+
+ return {
+ has: hasClass,
+ add: addClass,
+ remove: removeClass,
+ swap: swapClass,
+ toggle: toggleClass
+ };
+
+ }()),
+
+ dom: (function() {
+
+ function getAll(param1, param2) {
+
+ var node,
+ selector,
+ results;
+
+ if (arguments.length === 1) {
+
+ // .selector case
+ node = document.documentElement;
+ // first param is actually the selector
+ selector = param1;
+
+ } else {
+
+ // node, .selector
+ node = param1;
+ selector = param2;
+
+ }
+
+ // sorry, IE 7 users; IE 8+ required.
+ if (node && node.querySelectorAll) {
+
+ results = node.querySelectorAll(selector);
+
+ }
+
+ return results;
+
+ }
+
+ function get(/* parentNode, selector */) {
+
+ var results = getAll.apply(this, arguments);
+
+ // hackish: if an array, return the last item.
+ if (results && results.length) {
+ return results[results.length-1];
+ }
+
+ // handle "not found" case
+ return results && results.length === 0 ? null : results;
+
+ }
+
+ return {
+ get: get,
+ getAll: getAll
+ };
+
+ }()),
+
+ position: (function() {
+
+ function getOffX(o) {
+
+ // http://www.xs4all.nl/~ppk/js/findpos.html
+ var curleft = 0;
+
+ if (o.offsetParent) {
+
+ while (o.offsetParent) {
+
+ curleft += o.offsetLeft;
+
+ o = o.offsetParent;
+
+ }
+
+ } else if (o.x) {
+
+ curleft += o.x;
+
+ }
+
+ return curleft;
+
+ }
+
+ function getOffY(o) {
+
+ // http://www.xs4all.nl/~ppk/js/findpos.html
+ var curtop = 0;
+
+ if (o.offsetParent) {
+
+ while (o.offsetParent) {
+
+ curtop += o.offsetTop;
+
+ o = o.offsetParent;
+
+ }
+
+ } else if (o.y) {
+
+ curtop += o.y;
+
+ }
+
+ return curtop;
+
+ }
+
+ return {
+ getOffX: getOffX,
+ getOffY: getOffY
+ };
+
+ }()),
+
+ style: (function() {
+
+ function get(node, styleProp) {
+
+ // http://www.quirksmode.org/dom/getstyles.html
+ var value;
+
+ if (node.currentStyle) {
+
+ value = node.currentStyle[styleProp];
+
+ } else if (window.getComputedStyle) {
+
+ value = document.defaultView.getComputedStyle(node, null).getPropertyValue(styleProp);
+
+ }
+
+ return value;
+
+ }
+
+ return {
+ get: get
+ };
+
+ }()),
+
+ events: (function() {
+
+ var add, remove, preventDefault;
+
+ add = function(o, evtName, evtHandler) {
+ // return an object with a convenient detach method.
+ var eventObject = {
+ detach: function() {
+ return remove(o, evtName, evtHandler);
+ }
+ };
+ if (window.addEventListener) {
+ o.addEventListener(evtName, evtHandler, false);
+ } else {
+ o.attachEvent('on' + evtName, evtHandler);
+ }
+ return eventObject;
+ };
+
+ remove = (window.removeEventListener !== undefined ? function(o, evtName, evtHandler) {
+ return o.removeEventListener(evtName, evtHandler, false);
+ } : function(o, evtName, evtHandler) {
+ return o.detachEvent('on' + evtName, evtHandler);
+ });
+
+ preventDefault = function(e) {
+ if (e.preventDefault) {
+ e.preventDefault();
+ } else {
+ e.returnValue = false;
+ e.cancelBubble = true;
+ }
+ return false;
+ };
+
+ return {
+ add: add,
+ preventDefault: preventDefault,
+ remove: remove
+ };
+
+ }()),
+
+ features: (function() {
+
+ var getAnimationFrame,
+ localAnimationFrame,
+ localFeatures,
+ prop,
+ styles,
+ testDiv,
+ transform;
+
+ testDiv = document.createElement('div');
+
+ /**
+ * hat tip: paul irish
+ * http://paulirish.com/2011/requestanimationframe-for-smart-animating/
+ * https://gist.github.com/838785
+ */
+
+ localAnimationFrame = (window.requestAnimationFrame
+ || window.webkitRequestAnimationFrame
+ || window.mozRequestAnimationFrame
+ || window.oRequestAnimationFrame
+ || window.msRequestAnimationFrame
+ || null);
+
+ // apply to window, avoid "illegal invocation" errors in Chrome
+ getAnimationFrame = localAnimationFrame ? function() {
+ return localAnimationFrame.apply(window, arguments);
+ } : null;
+
+ function has(prop) {
+
+ // test for feature support
+ var result = testDiv.style[prop];
+
+ return (result !== undefined ? prop : null);
+
+ }
+
+ // note local scope.
+ localFeatures = {
+
+ transform: {
+ ie: has('-ms-transform'),
+ moz: has('MozTransform'),
+ opera: has('OTransform'),
+ webkit: has('webkitTransform'),
+ w3: has('transform'),
+ prop: null // the normalized property value
+ },
+
+ rotate: {
+ has3D: false,
+ prop: null
+ },
+
+ getAnimationFrame: getAnimationFrame
+
+ };
+
+ localFeatures.transform.prop = (
+ localFeatures.transform.w3 ||
+ localFeatures.transform.moz ||
+ localFeatures.transform.webkit ||
+ localFeatures.transform.ie ||
+ localFeatures.transform.opera
+ );
+
+ function attempt(style) {
+
+ try {
+ testDiv.style[transform] = style;
+ } catch(e) {
+ // that *definitely* didn't work.
+ return false;
+ }
+ // if we can read back the style, it should be cool.
+ return !!testDiv.style[transform];
+
+ }
+
+ if (localFeatures.transform.prop) {
+
+ // try to derive the rotate/3D support.
+ transform = localFeatures.transform.prop;
+ styles = {
+ css_2d: 'rotate(0deg)',
+ css_3d: 'rotate3d(0,0,0,0deg)'
+ };
+
+ if (attempt(styles.css_3d)) {
+ localFeatures.rotate.has3D = true;
+ prop = 'rotate3d';
+ } else if (attempt(styles.css_2d)) {
+ prop = 'rotate';
+ }
+
+ localFeatures.rotate.prop = prop;
+
+ }
+
+ testDiv = null;
+
+ return localFeatures;
+
+ }())
+
+ };
+
+ soundManager.setup({
+ // Trade-off: higher UI responsiveness (play/progress bar), but may use more CPU.
+ html5PollingInterval: 50,
+ flashVersion: 9
+ });
+
+ soundManager.onready(function() {
+
+ var nodes, i, j, tt;
+
+ nodes = utils.dom.getAll(turntableSelector);
+
+ if (nodes && nodes.length) {
+ for (i=0, j=nodes.length; i<j; i++) {
+ tt = new Turntable(nodes[i]);
+ turntables.push(tt);
+ turntablesById[tt.id] = tt;
+ }
+ }
+
+ });
+
+ window.turntables = turntables;
+ window.turntablesById = turntablesById;
+
+ // for external reference by demos, etc.
+ window.turntables.utils = utils;
+
+}(window));
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Revision History (Archived)</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Old and archived SoundManager 2 release information." />\r
+<meta name="keywords" content="download, javascript sound, javascript audio api" />\r
+<meta name="robots" content="all" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta name="copyright" content="Copyright (C) 1997 onwards Scott Schiller" />\r
+<meta name="language" content="en-us" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="../../demo/index.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="../../demo/index.js"></script>\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ url: '../../swf/',\r
+ debugMode: false\r
+});\r
+</script>\r
+</head>\r
+\r
+<body>\r
+ \r
+<div id="content">\r
+\r
+ <div id="top">\r
+\r
+ <h1>SoundManager 2: Download</h1>\r
+\r
+ <div id="nav">\r
+ <ul>\r
+\r
+ <li>\r
+ <a href="../../">Home</a>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="#">Demos</a>\r
+ <ul>\r
+ <li><a href="../../demo/template/">Basic Template</a></li>\r
+ <li><a href="../../demo/api/">API Examples</a></li>\r
+ <li><a href="../../demo/bar-ui/">Bar UI</a></li>\r
+ <li><a href="../../demo/play-mp3-links/" class="exclude">Playable MP3 links</a></li>\r
+ <li><a href="../../demo/mp3-player-button/" class="exclude">Basic MP3 Play Button</a></li>\r
+ <li><a href="../../demo/page-player/">Muxtape-style UI</a></li>\r
+ <li><a href="../../demo/360-player/">360° Player UI</a></li>\r
+ <li><a href="../../demo/mpc/">Drum Machine (MPC)</a></li>\r
+ <li><a href="../../demo/animation/">DOM/Animation Demos</a></li>\r
+ <li><a href="../../demo/flashblock/">FlashBlock Handling</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="../getstarted/">Getting Started</a>\r
+ <ul>\r
+ <li><a href="../getstarted/#how-sm2-works">How SoundManager 2 works</a></li>\r
+ <li><a href="../getstarted/#basic-inclusion">Including SM2 on your site</a></li>\r
+ <li><a href="../getstarted/#troubleshooting">Troubleshooting</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="..">Documentation</a>\r
+ <ul>\r
+ <li><a href="../#sm-config">SoundManager Properties</a></li>\r
+ <li><a href="../#sound-object-properties">Sound Object Properties</a></li>\r
+ <li><a href="../#smdefaults">Global Sound Defaults</a></li>\r
+ <li><a href="../#api">SoundManager Core API</a></li>\r
+ <li><a href="../#smsoundmethods">Sound Object (SMSound) API</a></li>\r
+ <li><a href="../generated/soundmanager2.html">Generated Documentation</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <strong><a href="#">Download</a></strong>\r
+ <ul>\r
+ <li><a href="#latest">Get SoundManager 2</a></li>\r
+ <li><a href="#revision-history">Revision History</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <a href="../technotes/">Technical Notes</a>\r
+ <ul>\r
+ <li><a href="../technotes/#requirements">System Requirements</a></li>\r
+ <li><a href="../technotes/#serving-audio">Serving To HTML5 + Flash Clients</a></li>\r
+ <li><a href="../technotes/#client-requests">How Clients Download Audio</a></li>\r
+ <li><a href="../technotes/#mobile-device-limitations">Mobile Device Limitations</a></li>\r
+ <li><a href="../technotes/#debug-output">Debug + Console Output</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="../resources/">Resources</a>\r
+ <ul>\r
+ <li><a href="../resources/#licensing">Licensing</a></li>\r
+ <li><a href="../resources/#related">Related Projects</a></li>\r
+ <li><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/">SM2 support / discussion</a></li>\r
+ <li><a href="http://www.schillmania.com/content/react/contact/">Contact Info @ Schillmania.com</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ <div class="clear"></div>\r
+ </div>\r
+ \r
+ </div>\r
+\r
+<div id="main-wrapper">\r
+\r
+ <div id="main" class="triple">\r
+\r
+\r
+ <div id="filter-box" class="columnar">\r
+\r
+ <div class="c1">\r
+ <div id="reset-filter"></div>\r
+ </div>\r
+\r
+ <div class="c2">\r
+ <div id="search-results"><!-- search results for %s --></div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ \r
+ <div id="history" class="columnar">\r
+ \r
+ <div class="c1">\r
+\r
+ <h2>Revision History</h2>\r
+ <p>Archived versions of SM2 releases</p>\r
+\r
+ </div>\r
+\r
+ <div class="c2">\r
+\r
+ <div class="f-block c-revision-history">\r
+\r
+ <h3 id="revision-history">Revision History (Archives)</h3>\r
+ \r
+ <p>A changelog of sorts.</p>\r
+\r
+ <ul id="revision-list" class="standard">\r
+\r
+ <!-- previously... -->\r
+\r
+ <li id="sm2-20111220" class="in">\r
+\r
+ <h3><b>V2.97a.20111220</b> - HTML5 <code>src</code>/<code>onload()</code>/<code>onstop()</code> fixes, new HTML5 polling, <code>onPosition()</code> updates, "audio sprites" (<code>from</code>/<code>to</code>) and multiple URL support. (Also: New homepage design!) (<a href="../../download/soundmanagerv297a-20111220.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <p>Fixes for HTML5 audio including redundant <code>src</code> assignment, <code>onload</code> and <code>onstop</code>. New <code>html5PollingInterval</code> property, <code>onPosition()</code> and <code>clearOnPosition()</code> methods, "audio sprites" support via <code>from</code> and <code>to</code> parameters. Updated <code>onposition()</code> sound method, added new <code>onposition</code> sound parameter, and multiple URLs / URL formats now allowed for a sound. Also: Version checking between JS and SWF, brand-new optimized homepage design and demo UI tweaks + optimizations.</p>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Fixed <code>Audio()</code> <code>src</code> attribute re-assignment bug seen in <code>createSound()</code>-><code>play()</code> use case.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: <code>mySound.load({onload:function(){}})</code> callback fixed so it works.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5 + Flash: <code>onload()</code> now called immediately when <code>load({onload:function(){}})</code> is used on a sound with the same URL which has already loaded.\r
+ </p>\r
+ </li>\r
+ \r
+ <li>\r
+ <p>\r
+ <code>onstop()</code> now mimics <code>onfinish()</code> in terms of sequence. HTML5 sets <code>position</code> to 0, but retains pre-<code>stop()</code> position property value (like Flash does.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Amazon Kindle Fire UA looks like Safari on OS X 10.6.3, but does not have broken HTML5 audio (i.e., intermittent playback failure) like the "isBadSafari" case.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ MovieStar/NetStream (non-RTMP) edge case: Correct <code>onfinish()</code> after <code>play()</code> and a seek so that it always fires. Remove <code>metadata()</code> after first call (as it was) for non-RTMP. Reduce buffer-near-end logic to 3 seconds from 5.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Flash 9 MovieStar/RTMP: Only fire <code>onconnect()</code> for RTMP (was firing for flash 9/NetStream, too, breaking MovieStar <code>createSound({autoLoad:true,onload:function(){this.play()}})</code> case.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ RTMP: Exclude RTMP from 30-second <code>resume()</code> reposition hack (streaming does not have this issue.) May have been breaking buffer due to seek on resume.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix edge case where <code>soundManager.waitForWindowLoad = true</code> (non-async startup case), but <code>_initComplete()</code> may fire after <code>window.onload()</code> and thus <code>onready()</code> never fired.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Added <code>soundManager.html5PollingInterval</code> property, for increased <code>whileplaying()</code> callback frequency (higher UI framerates) similar to <code>flashPollingInterval</code>. (By default, null/off.) Also excludes mobile (eg., iOS) by default.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>soundManager.onPosition()</code>: Queues a callback that will be fired each time a sound reaches a given position during playback. Applies for the life of the sound object.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>soundManager.clearOnPosition()</code>: Removes <code>onPosition()</code> callback(s) from a sound, by position and/or callback. (If no position or callback are specified, then all callbacks are cleared for the given sound.)\r
+ </p>\r
+ <p>\r
+ Optionally, an <code>onstop: function(){}</code> handler can be passed to capture the moment when "to" is reached. When using Flash, sound is preloaded 100% in order to guarantee playback can start at the "from" position.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added support for "audio sprites." New sound options, <code>from</code> and <code>to</code> allow segments, samples or slices of sound to be played. eg., <code>mySound.play({ from: 5000, to: 10000});</code>\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ New sound option, <code>onposition</code>, defines times and related callbacks for positions of interest within a sound. Applies on a per-play basis. eg. <code>onposition: {500: function(p) { console.log('position ' + p + ' was reached.') } }</code>\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Experimental: Multiple formats/encodings support in the sound <code>url</code> parameter; now accepts an array as an alternate to a single string. eg. <code>soundManager.createSound({id:'foo', url:['bar.ogg','bar.mp3']});</code> - SM2 will use the first playable URL it finds and the URL property will then reflect the one URL after that point. Note that this means the original array data will be lost.\r
+ </p>\r
+ <p>\r
+ Also accepts <code>type</code> attributes, eg. <code>url:[{type:'audio/mp3',url:'/path/to/play.php?song=123'},...]</code> - useful for URLs without obvious filetype extensions.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Flash 9 + MovieStar (NetStream) / RTMP: <code>onmetadata</code> (sound parameter) callback, allows capturing of metadata events from flash (eg., streaming song / title updates) similar to <code>onid3()</code>. Can now fire multiple times, eg., when RTMP streaming and new song / artist info is provided.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added JS version + Flash SWF build/version check to SM2 during start-up. (Finally! :D) ... Will now throw <code>new Error()</code> if soundmanager.js version reports V2.97a.20111030 and SWF version is V2.97a.20110918, for example. (Happens when upgrading/replacing old versions of SM2, you may forget to update one of the SWFs etc.)\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Homepage: Brand-new, shinier design, improved three-column layout; looks better even in IE 6. Small UI tweaks on inline demos. Combined demo JS + CSS files for performance; cut HTTP requests by over 50% (now down to 14 HTTP requests in most cases) via concatenation and data: URIs for some background images and sprites.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ 360 player demos: Updated UI with more circles and a few gradients, border-radius etc. Small 50x50 UI is now clickable over entire area, rather than small circular button.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Demos: Some data: URIs added to inline player and 360 player for performance (reduced HTTP requests.) Christmas lights demo now uses YUI 3 seed + animation.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>soundManager.useConsoleOnly = true</code> by default, was previously false. New "true" default means no HTML debug output if <code>console.log()</code> is available.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ soundmanager2.js: Micro-optimizations, further -nodebug-jsmin optimizations and minor comment formatting. Eliminated last Google Closure Compiler warning (caused by an empty "if" block.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Debug output no longer shows "loops: 1" (redundant), only interesting values eg. 2+ are reported.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Documentation: Small theme tweaks, textured background and re-organization of properties (left menu) for easier navigation. Fixed "onsuspend" event labeling, clarify SMSound events as properties and not methods. Re-sorted property lists, tidied up code formatting. Added missing <code>soundManager.onPosition()</code> documentation (side note: previously named onposition(), old lower-case method name maintained for backward compatibility.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Page player / Muxtape demos: Removed <code>useMovieStar</code> sound option - no longer exists, redundant.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+<!-- previously... -->\r
+\r
+ <li id="sm2-20111030" class="in">\r
+\r
+ <h3><b>V2.97a.20111030</b> - HTML5 <code>unload()</code> improvements, Android 2.3 fix and new <code>onsuspend()</code> event (<a href="../../download/soundmanagerv297a-20111030.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <p>Fixes for HTML5 <code>unload()</code> on Webkit (connection was not closing), playback on Android 2.3, and IE 9 "not implemented" / unsupported HTML5 case. Addition of <code>onsuspend()</code> HTML5 event, possibly applicable to iOS where stalled events suggest that user action is needed to play or resume audio playback.</p>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>HTML5 <code>unload()</code>: Correctly apply <code>about:blank</code> (_emptyURL default) to everyone except Firefox, which allegedly likes <code>''</code>. Webkit was not actually closing the connection of loading streams, in this case.</p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>HTML5 audio playback fix for Android 2.3 (Honeycomb), which doesn't seem to like <code>new Audio('foo.mp3')</code> followed by <code>load()</code> -> <code>play()</code>; first request/attempt stalls and eventually fires <code>ended</code> event. Rather odd. (<a href="http://getsatisfaction.com/schillmania/topics/soundmanager2_on_android">Related discussion</a>.)</p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>Added <code>try...catch</code> for dumb IE 9 <code>Audio()</code> "not implemented" error in Windows server case without "desktop experience" installed, means no HTML5 audio/video support. Hat tip: <a href="https://github.com/Modernizr/Modernizr/issues/224">Modernizr issue 224</a></p>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>Added <code>soundManager.noSWFCache</code> (boolean) for easy cache busting - good for dev/testing. SWFs tend to be aggressively cached by browsers, especially in offline cases.</p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+ <p>HTML5 <code>suspend</code> events are now listened for and fired via SMSound option <code>onsuspend()</code>. This event may be the best way to detect when mobile Safari (eg. iOS) is blocking autoplay-style behaviour, and user interaction is required to start or resume playback.</p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>Fix "playable MP3 links" demo for iOS, playing 2nd+ sound now works. Due to single sound object reuse, "old" sound must be paused before new one is created. Previously, playing sound 1 -> sound 2 -> sound 1 would fail.</p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>Tweaked 360player behaviour to support being initialized multiple times (for dynamic content, "decorating" new MP3 links etc.)</p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>Modified soundManager core property documentation to be multi-line, allowing longer comments</p>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li id="sm2-20110918" class="in">\r
+\r
+ <h3><b>V2.97a.20110918</b> - Code clean-up, improved comments and formatting, generated documentation, polling and <code>onbefore-</code> removal, HTML5 <code>stop()</code>/<code>unload()</code> fixes (<a href="../../download/soundmanagerv297a-20110918.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <p>Added block comments above major SM2 methods (and Docco-generated documentation), more line breaks for consistent vertical spacing and readability, removal of <code>onbefore</code>-related SMSound options, <code>allowPolling</code> + <code>useFastPolling</code> features. Improved build task optimizing of -nodebug JS build, removing comments, extra line breaks and debug code blocks which were previously only commented out.</p>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>HTML5 unload: Gecko can use url = '' to cancel request etc., others seem to need <code>about:blank</code> or similar empty URL (matching Flash 8.)</li>\r
+\r
+ <li>HTML5 <code>stop()</code>: Don't call <code>unload()</code> here (file under "durrr." This fixes a few state-related bugs.)</li>\r
+\r
+ <li>Fire the <code>onposition</code> callback after setting item.fired, instead of before. This allows looping in the form of <code>mySound.onposition(200, function(){ mySound.setposition(100); });</code></li>\r
+\r
+ <li>Fix movieStar (MPEG-4) handling for URLs without MIME hints (eg. a URL ending in .php) if <code>type: 'audio/mp4'</code> is passed, for example. (Possible regression introduced with V2.97a.20110801, one report was received.)</li>\r
+\r
+ <li>Fire <code>onposition()</code> <i>after</i> increasing the internal "onPositionFired" counter.</li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>Clean-up time! The following soundManager properties have been removed as they're ineffective and/or have modern replacements:</p>\r
+\r
+ <p>\r
+ <code>soundManager.nullURL = 'about:blank';</code> (internalized; search for 'about:blank' in the source if you want to customize it.)\r
+ </p>\r
+\r
+ <p>\r
+ <code>soundManager.allowPolling = true;</code> (ignored, always true now. <code>whileloading()</code> / <code>whileplaying()</code> calls rely on it.)\r
+ </p>\r
+\r
+ <p>\r
+ <code>soundManager.useFastPolling = false;</code> (redundant, now determined by flashPollingInterval now being specified as a number eg., 20, instead of the default of null.)\r
+ </p>\r
+\r
+ <p>\r
+ The following SMSound (sound options) have been removed, in favour of modern replacements (and also didn't work with HTML5 sounds.)\r
+ </p>\r
+\r
+ <pre class="block"><code>soundManager.defaultOptions.onbeforefinish = null;\r
+soundManager.defaultOptions.onbeforefinishtime = 5000;\r
+soundManager.defaultOptions.onbeforefinishcomplete = null;\r
+soundManager.defaultOptions.onjustbeforefinish = null;\r
+soundManager.defaultOptions.onjustbeforefinishtime: 200;</code></pre>\r
+\r
+ <p>\r
+ As a replacement, use the <code>SMSound.onposition()</code> method to assign an event callback handler to fire at the relevant time.\r
+ </p>\r
+\r
+<pre class="block"><code>mySound.onposition(10000, function() {\r
+ console.log('the sound ' + this.id + ' is now at position ' + this.position);\r
+});</code></pre>\r
+\r
+ <p>\r
+ If you need to fire an event relative to the true end of the sound, reference its duration once the sound has fully-loaded - ie., at or after the <code>onload()</code> event - as the duration will not be completely accurate until that time. <code>durationEstimate</code> may be referenced before <code>onload()</code>, but it should not be relied on when "precise" timings of say, < 1 second are desired.\r
+ </p>\r
+\r
+<pre class="block"><code>mySound.load({\r
+ onload: function() {\r
+ this.onposition(this.duration - 5000, function() {\r
+ console.log('the sound ' + this.id + ' is now at position ' + this.position);\r
+ }\r
+ }\r
+});</code></pre>\r
+\r
+ <p>\r
+ Again, note that due to the interval / polling-based methods of both HTML5 and flash audio, sound status updates and thus precision can vary between 20 msec to perhaps 0.5 seconds and the sound's position property will reflect this delta when the onposition() callback fires.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>Added <code>soundManager.onposition()</code> (forgot to mirror the SMSound method)</p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>\r
+ Privatize <code>soundManager.netStreamMimeTypes</code>, etc. <code>soundManager.mimePattern</code>, the resulting one applied to <code>canPlayMIME()</code> etc., is still exposed.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>\r
+ Simplify getMovie() to use _id(smID) || _doc[smID] || _win[smID] rather than IE / Safari special checks. Sometimes (old?) IE and Safari would return null on getElementById(), but window[id] or document[id] would work. Presumably related to Flash + ExternalInterface wackiness.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>Reviewed soundmanager2.js code for readability and comments. Added linebreaks, spacing and block-style comments around main functions.</li>\r
+\r
+ <li>Added generated documentation via "Rocco" (ruby port of Docco.)</li>\r
+\r
+ <li>Added build.xml notes re: Closure compiler, MTASC and where to find working builds</li>\r
+\r
+ <li>Modified soundmanager-nodebug.js build so comments and debug blocks are removed entirely from the code. Double-spaced linebreaks are also removed.</li>\r
+\r
+ <li>Removed executable permissions from almost all files</li>\r
+\r
+ <li>parseInt() on soundManager.flashVersion, invalidate strings like "9"</li>\r
+\r
+ <li>Use 10 / 50 msec polling interval for high performance mode vs. regular mode</li>\r
+\r
+ <li>Page cache/unload/restore (back button case): Only apply window unload event if using flash, since plugin is more likely to break (ie., state won't be recalled correctly.)</li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li id="sm2-20110801" class="in">\r
+\r
+ <h3><b>V2.97a.20110801</b> - "100% HTML5 mode" desktop browser (+no flash) fix, <code>useHTML5Audio</code> enabled by default, flash 9 end-of-sound correction, ClickToFlash improvements (<a href="../../download/soundmanagerv297a-20110801.zip" class="norewrite">Download archived version</a>)</h3>\r
+ \r
+ <p>Last release introduced a regression with HTML5-only mode on desktops when flash was not installed/present, now fixed; HTM5 audio support is enabled by default, although flash is still preferred for MP3/MP4 by default. <code>probably|maybe</code> is now the default when testing HTML5 format support. Flash 9 now <i>does not</i> reset sound position to 0 at <code>onfinish()</code>, matching flash 8 and HTML5 behaviour. Better ClickToPlugin / ClickToFlash compatibility (CSS tweaks for display of blocked SWF.) Minor internal flash polling loop improvements. soundManager <code>onload</code>, <code>onerror</code> and <code>oninitmovie</code> events have been deprecated in favour of <code>onready()</code> and <code>ontimeout()</code>, but remain functional.</p>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>A regression was introduced in V2.97.20110706 where SM2 would fail to start in HTML5-only mode on supported desktop browsers when flash was disabled or not installed, eg., Safari on new Macs or IE 9 without flash. (iOS was not affected.) This has been fixed with the 2.97.20110801 release.</li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p><code>soundManager.useHTML5Audio</code> is now <code>true</code> by default; however, <code>soundManager.preferFlash</code> is also <code>true</code> and HTML5 browsers will still attempt to use flash for playing MP3/MP4 by default, if those formats are marked as "required".</p>\r
+ <p>If you wish to have 100% HTML5 mode in more cases, set <code>soundManager.preferFlash = false</code>. Presently, the MP3 links and MP3 button SM2 demos are more HTML5-friendly and will serve as a test for exposing bugs that may be in the wild.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p><code>soundManager.html5Test</code> has been relaxed to use <code>(probably|maybe)</code> for Audio's <code>canPlayType()</code> test (previously, was only "probably") - so formats will be more likely to work on HTML5-only devices that conservatively report "maybe" for MIME types like <code>audio/mpeg; codecs="mp3"</code> at this point.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Certain mobile and tablet-like devices are special-cased as preferring HTML5, and will ignore checking for flash altogether; this presently includes the iPad, iPhone and iPod, Palm Pre and Motorola Xoom.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>The HTML5 audio "loadeddata" event triggers an SMSound <code>onload()</code> event, which now fires <code>whileplaying()</code> and tries to pass identical <code>bytesLoaded, bytesTotal</code> parameters so that UIs will correctly show the sound as fully-"loaded" - even if in truth, not all bytes have actually been fetched (depending on the browser and server, etc.) because of the ability to do arbitrary seeking.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Updated Flash 9 <code>onfinish()</code> / end-of-sound behaviour: Sound objects' <code>position</code> property no longer resets to 0 when a sound ends (and when <code>onfinish()</code> fires.) This now matches both HTML5 and flash 8's existing behaviour; therefore, a sound's <code>position</code> will equal its <code>duration</code> at <code>onfinish()</code> in all cases now. In the event <code>play()</code> is called from the end of a sound at or after <code>onfinish()</code>, the sound's position will be set to 0 before playback begins if using flash 9.</p>\r
+ <p>Edge case covered: if at internal SOUND_COMPLETE the SMSound.position is < its duration, flash will match position to duration and fire <code>whileplaying()</code> one last time so "100%" is always reached before <code>onfinish()</code> is called.</p>\r
+ <p><code>multiShot</code> + <code>multiShotEvent</code> case has been verified as working (eg. <code>onfinish()</code> fires 5x if <code>play()</code> called 5x.)</p>\r
+ </li>\r
+ \r
+ <li>\r
+ <p><a href="../#soundmanager-oninitmovie" onclick="if (!document.domain && !this.href.match(/index/i)) this.href=this.href+'index.html'">soundManager.onload</a>, <a href="../#soundmanager-onerror" onclick="checkDomain(this)">soundManager.onerror</a> and <a href="../#soundmanager-oninitmovie" onclick="if (!document.domain && !this.href.match(/index/i)) this.href=this.href+'index.html'">soundManager.oninitmovie</a> have been deprecated in favour of <a href="../#soundmanager-onready" onclick="if (!document.domain && !this.href.match(/index/i)) this.href=this.href+'index.html'">soundManager.onready()</a> and <a href="../#soundmanager-ontimeout" onclick="if (!document.domain && !this.href.match(/index/i)) this.href=this.href+'index.html'">soundManager.ontimeout()</a>. The deprecated methods are still present and work with this release, but you should migrate to their modern replacements.</p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>Flash 8 + 9 internal <code>whileplaying()</code> + <code>whileloading()</code> polling improvements: Internal check previously looped through all sounds from onLoad(), registerOnComplete(), _load() and _setPosition(). Now only the relevant sound is checked.</p>\r
+ </li>\r
+ \r
+ <li>\r
+ <p>Improved HTML5 support debug ouput/messaging, now right up top. Better messaging and error handling when Flash isn't present, yet required case (Flash plugin either not installed or disabled, but needed in some cases) - eg., Firefox and <code>audioFormats.mp3.required = true;</code> ... Also, only one _detectFlash() call now made.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Playable MP3 links and MP3 button demos use <code>soundManager.preferFlash = false</code>, so they should be able to run in 100% HTML5 mode. Some HTML5 bugs are anticipated, and these may help to reveal issues via a smaller audience.</p>\r
+ </li>\r
+ \r
+ <li>\r
+ <p>Initialization code reorganized, minor edits and clean-up, removal of some unused objects and ternary optimizations per jslint</p>\r
+ </li>\r
+ \r
+ <li>\r
+ <p>Cleaned up IE <<code>object></code> code, added <a href="http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-8000.html#WS4bebcd66a74275c36cfb8137124318eebc6-7ffd">highPriority</a> flash param (affects flash 10.1+, if at all.)</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Improved flashblock handling / compatibility (CSS layout tweaks) with newer <a href="hoyois.github.com/safariextensions/clicktoplugin/">ClickToPlugin</a>/ClickToFlash Safari (5.0.6 / 5.1+) extensions.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>SM2 homepage demos try HTML5 + Flash if available, with "safe" reboot + fallback to HTML5-only mode (if supported - eg., Safari with flashBlock/ClickToFlash.)</p>\r
+ </li>\r
+ \r
+ <li>\r
+ <p>Basic MP3 player demo: Fix event JS error when manually calling things like <code>basicMP3Player.handleClick({target:document.getElementById('foo')});</code></p>\r
+ </li>\r
+ \r
+ <li>\r
+ <p>Flash SWFs, debug versions: Mention right-click -> security panel options when troubleshooting security errors</p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+ \r
+ </li>\r
+\r
+\r
+\r
+ <li id="sm2-20110706" class="in">\r
+\r
+ <h3><b>V2.97a.20110706</b> - improved HTML5/flash "mixed mode" via <code>preferFlash</code>, Safari + Snow Leopard HTML5 audio bug update, better ClickToFlash compatibility, minor demo tweaks (<a href="../../download/soundmanagerv297a-20110706.zip" class="norewrite">Download archived version</a>)</h3>\r
+ \r
+ <p class="note">Special note: This <i>was</i> <b>V2.97a.20110705</b>, but the latest Flex SDK (4.5.1.21328) was downloaded and used for this build, and it compiled a Flash 9 SWF that wouldn't fully-start on <i>some</i> Windows machines running Firefox and IE 7, possibly others - thus, SM2 would fail to start up. The Flash 9 SWFs are now compiled with an older, working SDK version 4.1.0.16076, used in previous working releases. See <a href="http://getsatisfaction.com/schillmania/topics/flashversion_9_fails_to_initialize_but_only_on_windows">discussion</a> for more details.</p>\r
+\r
+ <p>Improved "mixed mode" HTML5/flash handling via new (experimental) <code>preferFlash</code> option, enabled by default. (If present, MP3/MP4 get flash for stability; HTML5 is used for other formats.) OS X 10.6.8 (finally?) fixes HTML5 audio in Safari. SoundManager 2 SWF adjusted to fall under ClickToFlash's "invisible" rules, may lower chance of blocking.</p>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>ClickToFlash (Safari/Mac flashblock-style extension) compatibility improvement: Use <code>width/height: auto</code> on SWF instead of 100%. The latter is not recognized as being within ClickToFlash's <= 8x8px "invisible flash" rules, almost guaranteed to be blocked. (When considered "invisible", SWF is allowed to load normally if user has the invisibles option enabled.)</li>\r
+\r
+ <li>Flash blocking/handling improvements: Default <code>#sm2-container</code> size now always 8x8px to fall under "invisible" flash rules, better chance of load being allowed. If blocked and using flashblock.css, <code>#sm2-container</code> reverts to 48x48px at <code>ontimeout()</code> for visibility (so user can see, and unblock the flash bit.)</li>\r
+\r
+ <li>OS X 10.6.8 "pre-Lion release" update <i>finally</i> appears to have fixed the broken Safari HTML5 audio issue. Thus, audio was broken from OS X 10.6.3 to 10.6.7 and SM2 will use Flash for these known cases. Related: <a href="http://isflashdeadyet.com/tests/safari-html5/">Testcase</a> and Webkit bug <a href="https://bugs.webkit.org/show_bug.cgi?id=32159">#32159</a>.</li>\r
+\r
+ <li>HTML5 audio: Playback now does not start after a <code>setPosition()</code> call (if the sound was not already playing), or if it was paused - matching the existing Flash API behaviour.</li>\r
+\r
+ <li>Fix <code>ontimeout()</code> queue incorrectly processing after <code>onload()</code> and successful startup.</li>\r
+\r
+ <li>Debug output: extraneous "%s" fixes for <code>onready()</code> / <code>ontimeout()</code></li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>Added experimental <code>soundManager.preferFlash</code> (default:<code>true</code>) for a more consistent MP3/MP4 playback option in certain HTML5 cases. If using <code>soundManager.useHTML5Audio</code> + <code>preferFlash</code> and flash is available, flash will be used for MP3/MP4.</p>\r
+ <p> HTML5 is still new and relatively unstable, and bugs are yet to be found and fixed across a growing number of browsers/platforms etc. (consider that it was broken on Safari between OS X 10.6.3 and 10.6.7.) If flash is not installed or <code>preferFlash = false</code>, 100% HTML5 mode can still apply. In any event, HTML5 will still be used (if enabled) for all other formats.</p>\r
+ </li>\r
+\r
+ <li>Moved internal html5Only to (experimental) <code>soundManager.html5Only</code>, for detecting "HTML5-only mode" - eg., iOS, Safari without <code>preferFlash</code> or other environments where SM2 is operating without the flash portion of SM2.</li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>Improved "can play" detection (<code>canPlayURL()</code> + <code>canPlayMIME()</code>) for HTML5 + flash cases. Increased "getting impatient, waiting for flash" message to 1 second.</li>\r
+\r
+ <li>360°, inline, MP3 button players: Event add/remove: use addEventListener based on typeof attachEvent === null (old IE behaviour)</li>\r
+\r
+ <li>MP3 player button demo: Fix IE 6/7 display issue on button (d'oh!)</li>\r
+\r
+ <li>Muxtape-style demo: Added <code>pagePlayer.playPrevious()</code>, to match <code>pagePlayer.playNext()</code> (call when a sound is currently playing.)</li>\r
+\r
+ <li>Fixed 360° player basic visualization demo (missing class in HTML), clarified canvas support (no eq/spectrum) re: IE <9.</li>\r
+\r
+ <li>360° UI: Old "empty element doesn't catch mouse events" bug apparently still applies to IE 9. Fix with invisible background image.</li>\r
+\r
+ <li>Minor homepage stylistic updates, source code order change for API docs (CTRL-F search now hits left column first)</li>\r
+ <li>Small debug output clean-up in SM2, object/embed, init etc.</li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+ \r
+ </li>\r
+ \r
+ <li id="sm2-20110424" class="in">\r
+\r
+ <h3><b>V2.97a.20110424</b> - Minor HTML5 tweaks, option inheritance fixes, improved build.xml file (<a href="../../download/soundmanagerv297a-20110424.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <p>HTML5 bulletproofing, <code>Audio(null)</code> argument fix for iOS + Opera, <code>load()</code> vs. <code>createSound()</code> and <code>setVolume()</code>/<code>setPan()</code> options/inheritance correction</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+ <li>HTML5: <code>new Audio(null)</code> fix for differences between iOS (which would try to load <code>null</code>) and Opera 9.64, which would throw a WRONG_ARGUMENTS_ERR if <code>null</code> was not passed.</li>\r
+ <li>HTML5: Restrict internal volume value range to 0..1, avoid DOM exceptions.</li>\r
+ <li>HTML5: <code>load{url:x})</code> improvements for desktop, better old vs. new URL comparison.</li>\r
+ <li>HTML5, iOS 4.2/4.3+, SM2 Muxtape/inline/link demos: <code>onfinish()</code>-><code>unload()</code>-><code>playNext()</code> was breaking on newer iOS versions, "play through" affected. Removing <code>unload()</code> for iOS fixed issue.</li>\r
+ <li>Flash <code>object</code>/<code>embed</code> <code>pluginspage</code>/<code>codebase</code> attribute now uses http:// when being used from file:// (offline), and http/https-agnostic //macromedia.com syntax to avoid SSL mixed-content warnings.</li>\r
+ <li>Fix <code>setVolume()</code> / <code>setPan()</code> to properly update <code>SMSound.options</code> (when not "instance-only"), so settings are retained for future <code>play()</code> calls. Bug was that original volume/pan were incorrectly restored after the first instance completed.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+ <li>\r
+<p class="compact">New and improved (nearly platform-independent) build.xml file, thanks to github user "dolmen". A <code>.build.properties</code> file is now needed, defining "mxmlc", "mtasc", and "closure-compiler.jar" paths. e.g.:</p>\r
+<pre class="compact block"><code><span><!-- .build.properties file in SM2 root --></span>\r
+mxmlc=/Applications/flexsdk/bin/mxmlc\r
+mtasc=/Applications/mtasc/mtasc\r
+closure-compiler.jar=${user.home}/compiler.jar</code></pre>\r
+\r
+<p>Running <code>ant</code> from the SM2 root will build the no-debug and minified versions of the script, as well as the SWF files.</p>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+\r
+\r
+<!-- 20110306 -->\r
+\r
+ <li id="sm2-20110306" class="in">\r
+ <h3><b>V2.97a.20110306</b> - HTML5 audio updates, Flash/HTML5 mode detection, IE flash init tweaks, reuse and instance options fixes (<a href="../../download/soundmanagerv297a-20110306.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <p>Bug fixes and improvements for HTML5 audio (object reuse on iOS), improved URL comparison. <code>onfinish()</code> -> <code>this.play()</code> instance option fix. IE flash wmode initialization tweak. Flash/NetStream (MP4) unpause()/resume() hack now applies to everyone. If no flash found (eg., new Mac desktops), HTML5 audio will now be tried. Make <code>hasPriority</code> actually work (d'oh!)</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>HTML5: <code>_resetProperties()</code> when setting Audio().src, fix sound1.play() -> sound2.play() -> sound1.play() case on iOS 4.1 not correctly re-assigning original sound URL (related to global audio object.)</li>\r
+ <li>HTML5 audio: If no flash, try forcing <code>useHTML5Audio = true</code> (eg. desktop safari on new Macs which don't come with Flash.) Related: flash detection code tweak.</li>\r
+ <li>Improved _iO vs. old _iO URL comparison, rather than .src which gets translated from local paths to file:// etc.</li>\r
+ <li>Correctly trash instanceOptions (and _iO) before calling onfinish(), but maintain local copy of onfinish() so it still works. Fix play({onfinish:this.play}) bug where _iO was being incorrectly remembered.</li>\r
+ <li>Flash 9/movieStar: <code>setPosition()</code> unpause hack for everyone, not just Webkit (via 8tracks dudes, reported now in Firefox? Should not cause regressions.)</li>\r
+ <li>Special wmode tweak for <a href="http://getsatisfaction.com/schillmania/topics/internet_explorer_security_error_preventing_soundmanager2_from_running">reports</a> of SM2 start-up failures, may be admin/non-admin account related, IE 8-only on Windows 7 (possibly Vista, too?) as of late January, 2011.</li>\r
+ <li>Apply <code>hasPriority</code> to object/embed, not its style. D'oh. :P</li>\r
+ <li>HTML5: use new Audio(null) vs new Audio(), Opera 9.64 expects URL argument; throws WRONG_ARGUMENTS_ERR otherwise. Doesn't implement canPlayType() either, but both are fixed in future releases.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Don't actually apply new value in <code>setPosition()</code> if a sound has not yet loaded (and if so, hasn't errored out.)</li>\r
+ <li>isNaN() check for HTML5 loading (saw one under Safari, in testing).</li>\r
+ <li>Added CLSID and codebase attributes for IE <code><object></code> (same as used in SWFObject), just to be safe.</li>\r
+ <li>Removed some HTML5 debug bits, unused _HTML5_states/codes block.</li>\r
+ <li>Flashblock CSS: Correctly hide the SWF via left/top:-9999em when it hits <code>.swf_loaded {}</code>, ie., never blocked in the first place. Minor flashblock regression fixes after .swf_loaded / .swf_unblocked changes with last release.</li>\r
+ <li>Ant build script parameter change, now uses .build.properties file (<a href="https://github.com/scottschiller/SoundManager2/pull/8">related pull request</a>)</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+\r
+ <li id="sm2-20110123" class="in">\r
+ <h3><b>V2.97a.20110123</b> - HTML5 audio improvements for desktop + mobile (iOS), 360° UI demo tweaks (<a href="../../download/soundmanagerv297a-20110123.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <p>Tweaks to HTML5 features, "mixed-mode" HTML5 + flash cases, desktop and iOS tweaks. Improved sound re-use and "play-through" on iOS (believed previously working, may have regressed with iOS 4.2.1.) Code clean-up and shuffling of homepage, 360° demo (jslinted and improved functionality), <code>load({options})</code> fix, better handling of broken Safari/Snow Leopard audio case.</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>Fix for <code>soundManager.load({options})</code> / <code>SMSound.load({options})</code>-specific case (regular <code>load()</code> sans-parameters was fine), where <code>load({onload:...})</code> would fail if a URL parameter was not specified. <code>load({url:...,onload:...})</code> was OK. If unspecified, load now takes URL from SMSound.url.</li>\r
+ <li>Fixed unload/replay case on iOS: play sound #1, interrupt it by starting sound #2, then play sound #1 again - previously, #1 would fail on replay due to interrupted state since iOS only allows one sound at a time. Should now restart OK. (This applies to the new <code>soundManager.useGlobalHTML5Audio</code> stuff.) Playlist auto-advance looks to be OK as well.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li id="sm2-20110123-api" class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>New (experimental) <code>soundManager.useGlobalHTML5Audio</code> property - if true (default for iOS/mobile), reuses a single <code>Audio()</code> object for loading sound. Helps make playlist / <code>onfinish()</code>-><code>play()</code> work on iOS without user interaction.</li>\r
+ <li>New (experimental) <code>soundManager.requireFlash</code> property (default: false.) If true, prevents HTML5-only mode on devices with both HTML5 and Flash. May be useful when HTML5 is enabled (and can play MP3), but Flash is desired to play RTMP content etc. As of this version, will only use Flash for RTMP.</li>\r
+ <li>HTML5: Fix for <code>type:'audio/mp3'</code> returning false on <code>canPlay()</code>. Timer update-while-paused tweak.</li>\r
+ <li>HTML5: More event listeners, ignore events on destroyed sounds, improved event clean-up, "seek before load" fix</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Improved broken Safari/Snow Leopard HTML5 audio situation: HTML5 mode is no longer disabled - and if available, Flash is used to play MP3/MP4 content to work around known playback issues with native HTML5 audio.</li>\r
+ <li>(Finally) report "true" position of MovieStar (MPEG4/AAC) content while scrubbing a playing/paused sound. Previously did not fire updates while scrubbing. Imperfect on resume due to buffer, but should be negligible and an improvement vs. old behaviour.</li>\r
+ <li>360° player refresh, works with multiple types (eg. small 48x48 square vs. large 256x256 square w/spectrum + EQ visualizations) on the same page now. Can play and seek simultaneously, as well. More configurable. Removed old empty.gif + imageRoot junk. Core JS now appeases the jslint gods.</li>\r
+ <li>Code clean-up, removed undocumented/experimental <code>playOnSeek</code> and related methods from a prior fork.</li>\r
+ <li>Fresh homepage demo design/layout, should be nicer for new users.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+\r
+ <li id="sm2-20110101" class="in">\r
+ <h3><b>V2.97a.20110101</b> - Simplified <code>onready()</code> behaviour (see <a href="#sm2-20110101-api" class="warning">potential <code>onready()</code> regression note</a>), new <code>ontimeout()</code> handler, Webkit + MovieStar 30-second-pause fix (<a href="../../download/soundmanagerv297a-20110101.zip" class="norewrite">Download archived version</a>)</h3>\r
+ <p><code>onready()</code> is now called only for SM2 init success (makes default case easier, no need for "supported" check) - new <code>ontimeout()</code> is called only for failure case, ie., flash blocked/missing. Special Webkit/MovieStar won't-resume-after-30-seconds-paused fix. <code>soundManager.supported()</code> renamed to <code>soundManager.ok()</code> (old method aliased for the time being.)</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>Special bad case, Webkit/Flash+MovieStar (AAC/MPEG4/RTMP-only, not MP3): sounds don't resume after being paused for 30+ seconds(?), but <code>setPosition()</code> with current position gets things going again after a <code>resume()</code> attempt. Reported via <a href="http://8tracks.com/">8tracks</a> dudes.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li id="sm2-20110101-api" class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>\r
+ <p>In previous releases, the <a href="../#soundmanager-onready" title="soundManager.onready() documentation">soundManager.onready()</a> queue would be processed for both OK and failure cases. The <code>onready()</code> queue is now processed only if successful initialisation occurs, making old "supported" checks within the <code>onready()</code> handlers redundant.</p>\r
+ <p><span class="warning">Potential regression note</span>: Old error case handling within <code>onready()</code> will never execute as a result of this change. Update your code to use the new explicit <a href="../#soundmanager-ontimeout" title="soundManager.ontimeout() documentation">soundManager.ontimeout()</a> handler instead.</p>\r
+\r
+<div style="display:inline-block;vertical-align:top;margin-right:2em">\r
+ <p class="compact"><b>Old <code>onready()</code> method</b></p>\r
+<pre class="block"><code>soundManager.onready(function(){\r
+ if (soundManager.supported()) {\r
+ <span>// OK, play sound etc.</span>\r
+ } else {\r
+ <span>// SM2 could not start; message user?</span>\r
+ }\r
+});</code></pre>\r
+</div>\r
+\r
+<div style="display:inline-block;vertical-align:top">\r
+ <p class="compact"><b>New <code>onready()</code> / <code>ontimeout()</code> method</b></p>\r
+<pre class="block"><code>soundManager.onready(function(){\r
+ <span>// OK, play sound etc.</span>\r
+});\r
+\r
+soundManager.ontimeout(function(){\r
+ <span>// SM2 could not start; message user?</span>\r
+});</code></pre>\r
+</div>\r
+\r
+ </li>\r
+ <li>New <a href="../#soundmanager-ontimeout" title="soundManager.ontimeout()">soundManager.ontimeout(myFunction)</a> method, for asynchronous queueing of init failure handlers. Fired only when SoundManager 2 is unable to initialise (usually due to blocked/missing flash, or flash security error.) Queue behaviour is the same style as <code>onready()</code>.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Code cleanup: Took the unsupported "jsAMP" demo (2007 prototype) out back and shot it.</li>\r
+ <li>360° UI demo: New "allowMultiple" config option, let 2+ sounds play at once etc. (Default: false, one at a time.)</li>\r
+ <li>360° UI, canvas visualization demo: Minor layout, UI, code tweaks</li>\r
+ <li>API/docs/demos reference and use updated onready()/ontimeout() methods.</li> \r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.97a.20101221</b> - HTML5 loading/progress and RTMP tweaks, <code>onready()</code> double-firing fix, <code>hasPriority</code> for mobile flash, Muxtape-style player now AJAX-friendly (<a href="../../download/soundmanagerv297a-20101221.zip" class="norewrite">Download archived version</a>)</h3>\r
+ <p>Improved HTML5 <code>whileloading()</code> / <code>whileplaying()</code>, <code>unload</code> and event handling. <code>hasPriority</code> for off-screen SWF loading on mobile, replaces old mobileFlash positioning tricks. Effectively re-wrote page player (Muxtape-style) demo to use event delegation + read live DOM, so should not break in AJAX cases. RTMP <code>onplay()</code> / <code>play()</code> / <code>buffering</code> fixes, <code>setPosition()</code> regression fix.</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>Double <code>onready()</code>-firing bug (HTML5 and non-flashblock case) fixed.</li>\r
+ <li>HTML5: Don't request null/about:blank URL with <code>unload()</code>, may hang/JS error in Chrome and IE 9 preview 7.</li>\r
+ <li>RTMP: Ensure <code>onplay()</code> is called for auto-loading streams when resumed. Don't call <code>play()</code> until connected. <code>play()</code> sets flash pauseOnBufferFull = false (fix for reported "<a href="http://getsatisfaction.com/schillmania/topics/rtmp_not_playing_audio#reply_3956421">RTMP not playing audio</a>" issue.)</li>\r
+ <li>overHTTP was likely returning incorrect values previously - now fixed.</li>\r
+ <li><code>unload()</code> tweak: Ensure <code>position</code> is reset to 0 if <code>unload()</code> fails</li>\r
+ <li>Flash audio: Log metaDataHandler info if debug enabled, possible <code>duration</code> metaData fix</li>\r
+ <li>No HTML5 audio for <i>any</i> Safari on OS X Snow Leopard 10.6.[3|4|5] due to underlying bugs causing intermittent audio playback failure; ongoing Apple issue, on their radar. Amusingly, Safari on Windows appears to be fine.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>Revised HTML5 <code>Audio()</code> events, improved <code>whileloading()</code> / <code>whileplaying()</code> / <code>onload()</code> for Webkit and Firefox 4. Progress/onload are still a bit quirky as HTML5 audio is more about "non-linear" loading including range and partial requests, where supported. See <a href="http://getsatisfaction.com/schillmania/topics/html5_chrome_ogg_problems">related discussion</a>.</li>\r
+ <li>New <code>soundManager.ok()</code> method, nicer alias for <code>soundManager.supported()</code>.</li>\r
+ <li>Took <code>soundmanager.loadFromXML()</code> (SM1 legacy method) out back and shot it. Last tweak was in 2008, nobody uses it.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Flash <code><object></code> / <code><embed></code>: <a href="http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html">hasPriority</a> attribute, enables off-screen SWF loading with Flash 10.1+. Removed mobileFlash positioning/repositioning tricks in lieu of this.</li>\r
+ <li>Effectively re-wrote page-player (Muxtape-style) demo, now traverses live DOM for next item(s). Should be more AJAX-friendly. Event delegation now handles any links added at any time. Externalised experimental features, too.</li>\r
+ <li>HTML5: If URL lacks <code>type</code> attribute and extension such as <code>.mp3</code> (worst-case scenario, you shouldn't be doing this anyway) just try dumbly loading it - imitating Flash behaviour.</li>\r
+ <li>Improved <code>dataerror</code> (wave/spectrum) exception handling, should result in lowered CPU use if playback continues with access exceptions (eg. YouTube video going in another tab.)</li>\r
+ <li>Start-up debug output/messaging clean-up (no movieStar in flash 8, minimal output in HTML5-only mode, etc.)</li>\r
+ <li>Add window unload handler if Flash being used, so back button will cause a page refresh (vs. the browser showing "previous state") to reinstate Flash in good browsers. Previously, the "previous state" was be shown but Flash audio would be broken.</li>\r
+ <li>ipod (ipod touch) gets HTML5 now, too.</li>\r
+ <li>Microsoft have added <code>Audio()</code> to Internet Explorer 9 as of "Platform Preview 7" - previous pre-releases of IE 9 only implemented <code><audio></code>, which SM2 does not use.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.97a.20101010</b> - Code cleanup, HTML5 audio tweaks, RTMP features, removal of experimental video, optional usePolicyFile crossdomain.xml feature (<a href="../../download/soundmanagerv297a-20101010.zip">Download archived version</a>)</h3>\r
+ <p>Shuffling of SoundManager 2 core, approximately 5% shaved off full debug-enabled file size after bug fixes, additional comments, new features and so on. Internal event handling code cleaned up. .SWF builds optimized, Flash 9 non-debug version now under 10 KB. Debug version now flash debugger-enabled. RTMP improvements for Red5 + Flash Media Server streaming cases - buffering, event and state handling. Experimental video feature is toast, createVideo() no longer implemented. iPhone + iPad touch events on page player + 360° player UI demos; tap and drag to seek, etc.</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>No HTML5 audio for *any* Safari on OS X Snow Leopard 10.6.[3|4] due to underlying bugs causing intermittent audio playback failure; ongoing Apple issue, on their radar. (See <a href="http://github.com/scottschiller/SoundManager2/commit/707697685408ef4aafd23811eeaa61a2d2ec120a">related GitHub commit</a>)</li>\r
+ <li>Don't <code>unload()</code> at <code>onfinish()</code> for HTML5 audio (was originally done to be conservative, but results in additional HTTP requests despite caching expectations?)</li>\r
+ <li><code>onload()</code> for HTML5 now using proper boolean values</li>\r
+ <li>Fix NetStream-specific <code>autoLoad</code>/<code>autoPlay</code>/<code>volume</code> <code>createSound()</code> call, specific null flash sound object error scenario. (Related <a href="http://github.com/scottschiller/SoundManager2/commit/0867fd641e83fda4e99665567a62f3398651fac4">changes on GitHub</a>.)</li>\r
+ <li>Fix for "<code>onbufferchange(1)</code> followed immediately by <code>onbufferchange(0)</code>" case when audio was actually still buffering.</li>\r
+ <li>Removed <code>setPosition()</code> within <code>unload()</code>, cleaner exit when destroying a sound</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li><b>Removed</b> experimental video feature (originally added late 2008, never developed further.) <code>createVideo()</code>, <code>allowFullScreen</code> and related video methods are now gone. Other dedicated HTML5/flash video player projects have since solved this problem.</li>\r
+ <li>New SMSound option: <a href="../#smsound-usepolicyfile" title="SoundManager sound option: usePolicyFile">usePolicyFile</a> - (boolean, default: <code>false</code>) - enables Flash to request /crossdomain.xml file for content on third-party domains, if access to ID3/metadata such as wave/peak/spectrum is needed. Will automagically enable if <code>onid3()</code> or peak/wave/spectrum features are being used.</li>\r
+ <li><code>console.warn()</code>-style messaging (instead of throwing exceptions) if <code>createSound()</code> etc. are called before SM2 init has fired. Now calls similar warning and exits if called after a failed, unsuccessful startup (ie., timeout or not-supported case.)</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>SoundManager 2 core code cleanup, ~5% shaved off soundmanager2.js code size after new features, bug fixes and comments etc. Internal event handling (DOM-related events for init, IE 6 vs. everybody else) improved.</li>\r
+ <li>Flash builds optimized; Flash 9 SWF build now under 10 KB. Debug-enabled Flash 9 SWF now hooks into Flash debug player/IDE debugging tools (compiled with <code>-debug=true</code>)</li>\r
+ <li>Attempt to detect RTL documents, position Flash accordingly if so to avoid long horizontal scrollbar issue (<a href="http://getsatisfaction.com/schillmania/topics/rtl_window_scroll_bar_issues_with_container_position" rel="nofollow">related discussion</a>)</li>\r
+ <li>iPhone + iPad <code>touchmove()</code> and related events added to page player + 360° player UI demos; tap and drag to seek should now work.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.96a.20100822</b> - HTML5 audio support no longer alpha, Safari 5.0.1/SL HTML5 audio issues continue, iPad/iPhone "play through", Flash tweak for Android (<a href="../../download/soundmanagerv296a-20100822.zip">Download archived version</a>)</h3>\r
+ <p><code>useHTML5Audio</code> feature now considered beta-worthy, though disabled by default to be safe (with the exception of iPhone + iPad.) iPhone/iPad will now play a sequence of sounds, user interaction only required to start first one. Flash on-screen positioning tweak for Android devices that run Flash. Safari 5.0.1 on Snow Leopard exhibits same buggy HTML5 audio issue, disabled by default; Apple have been notified. IE 9 "Platform Preview 4" has <code><audio></code> but no <code>Audio()</code> support (yet?) See <a href="https://connect.microsoft.com/IE/feedback/details/586311/audio-but-no-audio-support">bug #586311</a> (may require connect.microsoft.com / Windows Live ID, login first etc.)</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>HTML5 <code>Audio()</code> still broken in Safari 5.0.1 on Snow Leopard (10.6.3, 10.6.4), where sounds intermittently fail to load and play. Apple are aware of the regression. Related bug: <a href="https://bugs.webkit.org/show_bug.cgi?id=32159#c14">#32519</a>. Include <code>sm2-ignorebadua</code> in URL on SM2 pages to ignore this check and verify broken behaviour, etc.</li>\r
+ <li>Tweaks for experimental RTMP feature re: handling of paused state, tracking of position and <code>onfinish()</code> firing early.</li>\r
+ <li>Bumped SWF z-index to 5000 for Safari 5, SoundCloud-reported bug-and-fix for Safari 5-specific bad redraw issues, and occasional crash case referencing WebCore::RenderLayer::paintLayer</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>iPhone/iOS 4 and iPad can now play a sequence of sounds (once the user starts sound initially), provided <code>onfinish()</code> is used to create/play the next sound. Example: Muxtape-style UI on homepage will play through list without further interaction once a user plays something in the list.</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Special case for getting SM2 working more reliably on HTC Android + Flash 10.1, where flash does not load until on-screen (ie., in view.) If off-screen, Flash is repositioned at left/top 0px in order to load (including scroll/resize if needed), then events released and movie is repositioned off-screen. If movie is in the DOM already eg. as in <code>useFlashBlock</code> cases, <code>flashLoadTimeout</code> is set to 0 to allow infinite wait (eg., SM2 will not timeout with an error, and will simply load when the flash is scrolled into view.)</li>\r
+ <li>Documentation: Clarified <code>createSound()</code> behaviour if an existing sound ID is given (returns sound object "as-is", ignores any options passed.)</li>\r
+ <li>Page-player demo updated to use <code>canPlayLink()</code> instead of <code>canPlayURL</code>, more flexible link/type handling.</li>\r
+ <li>Homepage and documentation UI/layout and language tweaks, a few new "as seen on the internets" icons etc.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.96a.20100624</b> - Safari 5/Snow Leopard 10.6.3/10.6.4 HTML5 Audio() issue, X-domain SWF build fixes (<a href="../../download/soundmanagerv296a-20100624.zip">Download archived version</a>)</h3>\r
+ \r
+ <p>Disabling HTML5 Audio for Safari 5 on Snow Leopard 10.6.3 + 10.6.4 (current release) only, as it is broken similar to Safari 4.x (also on Snow Leopard only.) Related bug: <a href="https://bugs.webkit.org/show_bug.cgi?id=32159#c14">#32519</a>. Also, version info in SWFs and fixed X-domain SWF build.</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>HTML5 Audio() still broken in Safari 5 on Snow Leopard (10.6.3, 10.6.4) - disabling for now, falling back to Flash as with Safari 4.x on Snow Leopard. Include <code>sm2-ignorebadua</code> in URL to ignore this check and verify broken behaviour, etc.</li>\r
+ <li>Fixed X-domain SWF builds to actually work cross-domain.</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Added version info string to SWFs in Flash right-click / context menu, helpful when troubleshooting SWFs.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.96a.20100606</b> - RTMP (Flash Media Server) Support, HTML5 Updates (<a href="../../download/soundmanagerv295b-20100606.zip">Download archived version</a>)</h3>\r
+ \r
+ <p>HTML5 update, new RTMP feature: Experimental Flash Media Server support, <code>onposition()</code> event listener, SMSound <code>type</code> option and code cleanup.</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>New experimental <a href="../#smsound-serverurl" title="SMSound serverURL property">RTMP support</a> while maintaining existing NetStream-based behaviour for non-RTMP MPEG4 audio, etc. Uses new <code>serverURL</code> parameter for FMS (I used Red5 for dev/testing,) eg. <code>soundManager.createSound({id:'rtmpTest',serverURL:'rtmp://localhost/oflaDemo',url:'oh-alberta.mp3'}).play();</code></li>\r
+ <li>New SMSound option for createSound(), load(), play(): '<a href="../#smsound-type" title="SMSound type option">type</a>', for specifying MIME type alongside URL to help with detecting playability. eg. \r
+<code>soundManager.createSound({id:'foo', url:'/player.php?stream=1', type:'audio/mp3'}).play();</code> and so on. Hat tip: <a href="http://sylvinus.org">sylvinus.org</a></li>\r
+ <li>New SMSound event: <a href="../#smsound-onposition" title="SMSound onposition() event">onposition()</a>, for attaching listeners to specific times within a sound.</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>Flash sound unload/destroy ActionScript "could not close stream" exception/warning (finally?) fixed.</li>\r
+ <li>Sound looping updated for Flash 8, working (albeit with a quirk - requires preloading.)</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Removed Base64 HTML5 Audio() tests, redundant as numerous MIME (audio/mpeg, audio/mp3 etc.) checks seem to cover it.</li>\r
+ <li>Updated MPC (drum machine) demo from 2006-era design, modernizing the CSS a bit.</li>\r
+ <li><code>nullURL = 'about:blank'</code> tweak for unloading (flash 8.) May have finally fixed that dumb stream closing error on unload/destroy.</li>\r
+ <li>set <code>soundManager.didFlashBlock</code> *before* firing <code>onready()</code>/<code>onerror()</code> listeners</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.96a.20100520</b> - HTML5 Edition (<a href="../../download/soundmanagerv295b-20100520.zip">Download archived version</a>)</h3>\r
+ \r
+ <p>Experimental HTML5 support, lots of code shuffling and performance tweaks.</p>\r
+ \r
+ <ul class="double">\r
+ \r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>New <a href="../#soundmanager-usehtml5audio" title="SoundManager: useHTML5Audio feature">soundManager.useHTML5Audio</a> (disabled by default except for iPad, Palm Pre) - adds experimental HTML5 Audio support, with Flash fallback for MP3/MP4 formats as needed.</li>\r
+ <li>Sound looping now works in Flash! eg. <code>mySound.play({loops:3});</code> - for an example + discussion of how to get near-seamless looping, see <a href="http://www.flickr.com/photos/schill/4499319436/" title="SoundManager 2: Seamless Looping MP3s in Flash (Demo)">Seamless Looping MP3s in Flash</a> (demo video) on Flickr.</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li><code>beginDelayedInit()</code> is always used in lazy loading case (eg. via dynamic script tag/XHR etc.,) as some cases where SM2 won't auto-start eg. document.readyState empty for Firefox 3.5.5 (seen on Win32) with an HTML5 DOCTYPE.</li>\r
+ <li>SWF is now 8x8 pixels by default, vs. 6x6 pixels (odd fix for HTML5 Doctype on Firefox 3.6/win32)</li>\r
+ <li>Fixed dumb IE undefined ID bug</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>soundmanager2.swf and soundmanager2_flash9.swf are now "non-debug" versions; with debugMode enabled, soundmanager2_debug.swf and soundmanager2_flash9_debug.swf are loaded instead.</li>\r
+ <li>New build script for JS + SWFs, see <a href="../getstarted/#basic-inclusion" title="Including SoundManager 2, file size options">file size table</a>. JS compression now done via Google Closure compiler; new soundmanager-jsmin.js build, debug-enabled but compressed, in addition to build-script-optimized, no-debug, compressed JS (~9 KB with gzip vs. ~90 KB for raw, commented, debug-enabled version.)</li>\r
+ <li>Null check fix for unavailable eq/waveform data</li>\r
+ <li>Experimental video (flash 9-only) change: Use stage width/height instead of 0/0 when lacking metadata</li>\r
+ <li>Page player whileloading() calls now being throttled</li>\r
+ <li>Better page player click handling for IE 7</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.95b.20100323</b> (<a href="../../download/soundmanagerv295b-20100323.zip">Download archived version</a>)</h3>\r
+ <p><code>useFlashBlock</code>, better handling of time-out/errors (CSS-based SWF repositioning options for unblocking on time-out), "play MP3 button" demo, <code>canPlayLink()</code>, <code>canPlayMIME()</code>, <code>eqData</code> + <code>waveformData</code> for AAC/H.264 (movieStar) content, missing documentation and miscellaneous bug fixes.</p>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>New <code>soundManager.useFlashBlock</code> (disabled by default) - enables CSS classes assigned to SWF container indicate start-up state (ok/error/blocked), allowing positioning/display of SWF for unblock cases and successful recovery from unblocking. Built into homepage + (most) demos. Updated flashblock demo as well.</li>\r
+ <li>playableClass attribute eg. <code><a href="foo.php" class="inline-playable"></code>, allowing URLs without .mp3 to be picked up</li>\r
+ <li>New <code>soundManager.canPlayLink()</code> + <code>canPlayMIME()</code>, ability to check <a href="foo.php" type="audio/mp3"> for example</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li><code>soundManager.play()</code> type check fix, instanceof Object vs. typeof x === 'Object' (typo)</li>\r
+ <li><code>computeSpectrum()</code> can access waveform and eq (spectrum) data for movieStar (AAC/MP4, netstream-based) objects, too.</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Moved old demo code using <code>$()</code> to <code>_id()</code>, <code>_$</code> in <code>soundManager2</code> to <code>_id()</code> to avoid potential jQuery (and other $-based library) collisions</li>\r
+ <li>Make <code>new SoundManager('/path/to/swfs/');</code> actually work.</li>\r
+ <li>Flash time-out (flash blockers) vs. security failure detection/other error cases is smarter on the SM2 homepage now</li>\r
+ <li>New "MP3 player button" demo</li>\r
+ <li>Removed old IE onclick handler fix in several demos for non-MP3 links</li>\r
+ <li><code>eqeqeq = true</code> for jslint, why not.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+\r
+ \r
+ <li class="in">\r
+ <h3><b>V2.95b.20100101</b> (<a href="../../download/soundmanagerv295b-20100101.zip">Download archived version</a>)</h3>\r
+ <p>New features: Flash movie debugging in SWF via <code>debugFlash</code> (default:false), <code>SMSound.eqData = { left:[], right:[] }</code>, code tidying and debug output clean-up</p>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>New <code>soundManager.debugFlash</code> property, enables debug messages from within flash (output to flash movie). Useful for troubleshooting start-up, security issues etc. <a href="../getstarted/#flashdebug">Flash debug output example</a></li>\r
+ <li><code>SMSound.eqData</code> now has left and right channels - e.g. <code>eqData = { left: [], right: [] }</code> - was previously a single array: <code>eqData = [];</code> Backwards-compatibility is maintained for now as <code>eqData[i]</code> still works with the new structure.</li>\r
+ </ul>\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li><code>stream = true</code> is no longer automatically set when <code>SMSound.play()</code> is called and <code>readyState == 0</code>, as it was breaking the <code>stream:false</code> case where playback should not start until the sound has fully-loaded.</li>\r
+ <li><code>soundManager.reboot()</code> forces recreation of object/embed rather than old method of node remove/re-append (in case other options changed, eg. debugFlash was false, but assigned to true after an error during start-up.)</li>\r
+ </ul>\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Review of all SM2 debug output, more concise and informative messaging - especially around start-up troubleshooting/error debugging, security sandbox errors, SWF 404 case etc.</li>\r
+ <li>Code formatting clean-up (via jsbeautifier.org)\r
+ soundmanager2.js tested and passes JSLint, Edition 2009-11-22 + options: /*jslint undef: true, bitwise: true, newcap: true, immed: true */</li>\r
+ <li>Better organization/use of strings for debug output</li>\r
+ <li>New canvas-based favicon VU meter demo for home page, 360 player and muxtape-style player demos where supported (Firefox and Opera, currently.) Firefox 3.6 is disappearing support for XBM images, which were previously used.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+ \r
+ <li class="in">\r
+ <h3><b>V2.95a.20090717</b> (<a href="../../download/soundmanagerv295a-20090717.zip">Download archived version</a>)</h3>\r
+ <p>New features: onready(), fast polling, flash blocking demos etc.</p>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>New <code>soundManager.onready(myFunction[,scope])</code> method, for asynchronous queueing of <code>onload()</code>-style handlers. Fires when SM2 has finished initialising. Accepts an <i>optional</i> scope parameter to apply to handler; if none given, window object is used. A "status" object is passed to your handler (can be ignored) which includes a <code>success</code> boolean indicating whether SM2 loaded OK or not. Handlers added via onready() after successful initialisation will fire immediately.</li>\r
+ <li>New <code>soundManager.oninitmovie()</code> event callback, single assignment similar to <code>onload()</code>. Fires when the flash movie has first been written to (or read from) the DOM. Used internally for a flashblock-handler-related example, custom timeout condition.</li>\r
+ <li>New <code>soundManager.useFastPolling</code> property (false by default), enables 1 msec Flash 9+ timer for highest-possible <code>whileplaying()</code> and related JS callback frequency (default is 20 msec.) Use with <code>soundManager.useHighPerformance = true</code> for best performance, frame rates while updating the UI via whileplaying() etc.</li>\r
+ <li>New sound option (soundManager.defaultOptions): <code>multiShotEvents</code> (default:false) - enable support for multiShot-style events (currently <code>onfinish()</code> only). Eg. When <code>mySound.play()</code> is called three times, <code>onfinish()</code> will subsequently fire three times.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li><code>createSound</code> now writes a warning to debug output if the sound ID is a number, or is a string starting with a numeric character. Because SMSound objects are stored in <code>soundManager.sounds[]</code>, while not syntactically invalid, numeric IDs will be treated as array indices and are likely to break things.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>New flashblock / "click to flash" demo, example of handling blocked conditions and graceful recovery when flash is initially blocked until user chooses to allow it.</li>\r
+ <li>Cross-domain-scripting enabled SWF (using <code>allowDomain("*")</code>) included in swf/ directory (in its own .zip file.) Use when you must have domain A loading SM2 .SWF from domain B, or for testing etc and can't compile your own custom x-domain SWF from source.</li>\r
+ <li>Documentation, layout and menu tweaks</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+ \r
+ <li class="in">\r
+ <h3><b>V2.95a.20090501</b> (<a href="../../download/soundmanagerv295a-20090501.zip">Download archived version</a>)</h3>\r
+ <p>Lots of updates.</p>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>Added <code class="in">soundManager.allowFullVideo</code> for full-screen video playback, triggered by double-clicking. Also, related <code>soundManager.onfullscreenchange</code> event handler.</li>\r
+ <li>Updated <code>waveformData</code> to include stereo channels. Now an object literal instead of a single array. New format: <code>SMSound.waveformData = { left: [], right: [] }</code></li>\r
+ <li>New <code>SMSound.ondataerror()</code> (flash 9+) handler for cases where waveform/eq data is inaccessible due to other flash movies in the current browser which have loaded sound. (Flash must have security permissions to "read" all data currently being output, long story short. Having a YouTube tab open can cause this, for example.)</li>\r
+ <li>New <code class="in">isBuffering</code> property for MovieStar (MP4 audio/video) content, related <code class="in">onbufferchange()</code> event handler (sound object)</li>\r
+ <li>New <code>bufferTime</code> property for MovieStream content. Defines seconds of data to buffer before playback begins (null = flash default of 0.1 seconds; if AAC playback is gappy, try up to 3 seconds.)</li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>Off-screen flash with <code class="in">wmode</code> set to non-default value (transparent/opaque) will break SM2 for non-IE on Windows, time-out error style. SM2 will now revert wmode to default for this case (losing transparency/layering of movie) - <i>or</i> set <code>soundManager.flashLoadTimeout</code> to 0 and SM2 will retain wmode, but must now wait potentially infinitely for flash to load (until user scrolls it into view.) <code>soundManager.specialWmodeCase</code> reflects if this fix has been applied after init time. </li>\r
+ <li>Calling <code>soundObject.load()</code> after directly assigning a value to <code>soundObject.url</code> should now work as expected.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Shiny new "360° UI" canvas + visualization demos (Warning: Beta-ish code.)</li>\r
+ <li>Experimental SM2 exception/error handling + stack trace reporting added, an attempt to make custom errors thrown from SM2 more meaningful (ideally showing the user's call to SM2 where things went wrong in the stack.)</li>\r
+ <li>Calling <code>soundObject.load()</code> after directly assigning a value to <code>soundObject.url</code> should now work as expected.</li>\r
+ <li><code class="in">soundManager.useHighPerformance</code> update: Now false/disabled by default. Strange bug with JS/flash communication breaking with wmode=opaque on flash, specific (?) to Firefox on windows. SM2 does not normally set wmode. When <code class="in">useHighPerformance = true</code>, wmode=transparent will be used on the flash movie by default.</li>\r
+ <li>Tweaks related to position, whileplaying(), playState, buffering and state resetting when sound has finished playing (fixes for a few edge cases if replaying or reusing the same sound or video.)</li>\r
+ <li>Better code/feature separation and clean-up on inline player, Muxtape-style demos</li>\r
+ </ul>\r
+ </li>\r
+ \r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.94a.20090206</b> (<a href="../../download/soundmanagerv294a-20090206.zip">Download archived version</a>)</h3>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">API Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>New <code class="in">isBuffering</code> property, related <code class="in">onbufferchange()</code> event handler (sound object)</li>\r
+ <li>New <code class="in">soundManager.reboot()</code> method (<i>experimental</i>): Shut down and re-initialise SoundManager, remove and recreate flash movie (possibly handy for cases where you want to restart after flashblock-type whitelisting, etc.)</li>\r
+ <li>New <code class="in">soundManager.flashLoadTimeout</code> property, milliseconds SM2 will wait for flash movie callback before failing and calling soundManager.onerror() during start-up/init. If set to 0, SM2 will wait indefinitely for flash (good for reboot/flashblock-type scenarios.)</li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>Reverted Firebug 1.3 console.log().apply() hack, was breaking console.log() under IE 8 RC1 (as used with debug mode.) Firebug 1.3 seems to have a bug, occasional "console undefined" error.</li>\r
+ <li>Fixed a dumb flash 9/AS3 bug with setVolume() passing an extra parameter to flash.</li>\r
+ <li><code class="in">soundManager.useHighPerformance</code> update: Now false/disabled by default. Strange bug with JS/flash communication breaking with wmode=opaque on flash, specific (?) to Firefox on windows. SM2 does not normally set wmode. When <code class="in">useHighPerformance = true</code>, wmode=transparent will be used on the flash movie by default.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Tweaked project page / documentation UI, nicer code/debug formatting</li>\r
+ <li>Misc. API documentation fixes, improvements</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ \r
+ </li>\r
+\r
+\r
+ <li class="in">\r
+ <h3><b>V2.93a.20090117</b> (<a href="../../download/soundmanagerv293a-20090117.zip">Download archived version</a>)</h3>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">General Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>New SoundManager 2 start-up debugger / troubleshooting tool, built into project home (see <a href="../getstarted/#troubleshooting" title="SM2 troubleshooting">troubleshooting</a>, and a standalone version - see "<a href="../../troubleshoot/" title="SoundManager 2 standalone troubleshooting tool" class="norewrite">troubleshoot/</a>" directory of download package)</li>\r
+ <li>New soundManager.getMemoryUse() method (flash 9+.) Returns RAM use for flash plugin (appears to be browser-wide, possibly system-wide by design.) <a href="../../demo/video/" title="SM2 javascript video demo">Video demo</a> includes an example RAM use monitor.</li>\r
+ <li>highPerformance disabled by default for Firefox on Windows due to reports of bugs preventing SM2 start-up in some cases. To override the disabling safety check, set <code class="in">soundManager.useHighPerformance = 'always';</code></li>\r
+ <li>Updated API demo testcases (<a href="../../demo/api/">API Demo page</a>)</li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Fixed Flash 8 bug with <code class="in">autoLoad</code>/<code class="in">autoPlay</code> and <code class="in">playState</code> not being correctly set.</li>\r
+ <li class="in">Fixed a bug with <code class="in">onfinish()</code> not firing when <code class="in">autoPlay</code> is used.</li>\r
+ <li class="in">Fixed a bug with pan and volume defaults not being correctly inherited and handled</li>\r
+ <li class="in">console[method]() now uses apply(), preventing possible Firebug 1.3-related scope issue where this != console</li>\r
+ <li class="in">IE now appends (vs. destructive .innerHTML write) SWF movie to target element, appends DIV with className "sm2-object-box"</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ \r
+ </li>\r
+\r
+\r
+ <li class="in">\r
+ <h3><b>V2.92a.20081224</b> (<a href="../../download/soundmanagerv292a-20081224.zip">Download archived version</a>)</h3>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">General Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>Note: Flash (SWF) assets moved to swf/ subdirectory, starting with this version.</li>\r
+ <li>Updated design on API demo page, new <a href="../../demo/api/#looping">looping example</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Improved regular-expression-based URL detection for <code>canPlayURL()</code>, flash 8/9 and MovieStar (video) formats</li>\r
+ <li class="in">Improved <code>soundManager.url</code>-related <code>normalizeURL()</code> handling. If GET parameters are in the URL including the SWF, it will be left alone.</li>\r
+ <li class="in">Fixed out-of-bounds issue with <code>setPosition()</code>.</li>\r
+ <li class="in">Fixed a <code>setPosition(0)</code> and <i>before</i> <code>onfinish()</code>-related issue, so it is possible to nicely loop sounds from within <code>onfinish()</code> - see <a href="../../demo/api/#looping">looping a sound</a> (API demo)</li>\r
+ <li class="in">Fixed an error condition where destroying a loading sound would not terminate the HTTP request, relating to error cases involving <code>netStream.close()</code>.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ \r
+ </li>\r
+\r
+ \r
+ <li class="in">\r
+ <h3><b>V2.91a.20081205</b> (<a href="../../download/soundmanagerv291a-20081205.zip">Download archived version</a>)</h3>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">General Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>Completely-redesigned project page, multiple pages/sections, more-legible grid-based documentation layout</li>\r
+ <li>Code verified with <a href="http://jslint.com">jslint</a>. 0 errors reported with default settings, Edition 2008-11-26</li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <p class="compact">Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">True XHTML DOM compatibility. Rewrote <code>createMovie()</code> to use standard DOM <code>createElement()</code> methods, vs. previous writing to .innerHTML method which caused exceptions with XHTML documents.</li>\r
+ <li class="in">Special-cased <code>useHighPerformance</code> for Firefox 2 only, disabling it as it seems to be problematic. Further research pending.</li>\r
+ <li class="in">Removed try .. catch error handling within <code>soundManager.onload()</code>, catching exceptions when calling user-defined onload handler. Errors should now fall through as normally expected.</li>\r
+ <li class="in">Fixed several <code>setPosition()</code>-related bugs (NaN/undefined error, seeking to invalid position, position inconsistencies with pause/resume)</li>\r
+ </ul>\r
+ </li>\r
+ </ul>\r
+ \r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.90a.20081028 (Old documentation theme) - <a href="http://schillmania.com/projects/soundmanager2/download/soundmanagerv290a-20081028.zip">Download archived version</a></b></h3>\r
+\r
+ <ul class="double">\r
+ <li class="in">\r
+ <p class="compact">API: Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li>Fixed numerous Flash AS3 exceptions for Flash 10 plugin users of SM2 with Flash 9 .SWF</li>\r
+ <li class="in">Fixed a <code>setPosition()</code> bug where position > duration would stop sounds playing in other tabs</li>\r
+ <li class="in">Fixed <code>createSound(); play(); destruct();</code> sequence to correctly stop sound under Flash 9</li>\r
+ <li class="in">Changed Flash 9 <code>onload()</code> to properly pass boolean "false" on load failure, same as Flash 8</li>\r
+ <li class="in">Fixed <code>autoLoad</code>=true bug with Flash 9 movieStar (MPEG4) content, now pauses after creating</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">API: New shiny!</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in"><code>soundManager.useHighPerformance</code>: Minimize JS/Flash lag, ~3x <code>whileplaying()</code> frequency! (Most noticeable on Mac OS X, and Safari on Windows? Investigating IE cases.)</li>\r
+ <li class="in"><code>soundManager.pauseAll()</code> / <code>soundManager.resumeAll()</code>: Global pause/resume</li>\r
+ <li class="in"><code>soundManager.muteAll()</code> / <code>soundManager.unmuteAll()</code>: Global mute/unmute</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <p class="compact">MovieStar MPEG4 video support! <em>(experimental)</em></p>\r
+ <ul class="nested compact flat">\r
+ <li class="in"><code>soundManager.createVideo()</code> / <code>soundManager.destroyVideo()</code> for MovieStar MPEG4 formats!</li>\r
+ <li>Uses same SMSound instance object and API methods/options as regular sounds, with a few extra parameters</li>\r
+ <li class="in"><code>soundManager.useVideo</code> will show video when applicable (false/disabled by default)</li>\r
+ <li class="in"><code>SMSound.onmetadata</code>: Meta data handler for MPEG4 video files - provides dimensions (w/h)</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li><b>Removed</b> experimental flashBlock support. Considering eliminating SM2 timeout-based onerror() behaviour in favour of asynchronous loading (eg. user may initially block, notice flash movie and take action to unblock many seconds after loading - thus, flash movie eventually loads and can eventually trigger successful SM2 init.)</li>\r
+ <li class="in">Modified <code>pause()</code> and <code>resume()</code> to only affect playing sounds (eg. <code>playState != 0</code>).</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <!-- not newest -->\r
+\r
+ <li class="in">\r
+ <h3><b>V2.80a.20081005</b></h3>\r
+\r
+ <ul class="double">\r
+ <li class="in">\r
+ <p class="compact">API: Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Changed Flash 8 <code>onload()</code> boolean "loaded" to be based on sound duration being >0, better test of load success.</li>\r
+ <li class="in">Modified Flash 9 <code>onload()</code> to include boolean result for success/fail, parity with Flash 8</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">API: New shiny!</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">\r
+ <p style="font-weight:normal;padding-top:0px">Added <em>experimental</em> Flash 9.0r115+ (flash codename "<a href="http://www.adobe.com/support/documentation/en/flashplayer/9/releasenotes.html#fixes_90115">MovieStar</a>", Flash 9 Update 3) MPEG4 / HE-AAC support (audio only.) A subset of MPEG4 should be supported including FLV, MP4, M4A, MOV, MP4V, 3GP and 3G2 files. Feature is disabled by default.</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">New soundManager <code>useMovieStar</code> property, controls feature availability (currently disabled by default.)</li>\r
+ <li>New SMSound option, <code>isMovieStar</code>, configures feature behaviour on a per-sound basis. Default (null) is to auto-detect .mp4, .mov etc. in URL and enable if found, but can also be forced on or off (true / false).</li>\r
+ <li class="in">Video-based formats use the Flash 9 <code>NetStream</code> and <code>NetConnection</code> objects, whose API differs slightly from the Sound object. Seeking is limited to video key frames and is not as smooth as an MP3.</li>\r
+ <li class="in">Audio playback has been seen to pause during certain events (window scrolling, etc.) while playing MovieStar formats. It doesn't appear to be from CPU overload. More investigation is needed.</li>\r
+ <li class="in">Basic load, progress, onload, whileplaying API support is provided (page player demo includes MP4 and FLV formats). Not all methods (eg. setVolume) have been tested.</li>\r
+ <li class="in">.AVI is not included by default, but may work if the format is actually MPEG4-based.</li>\r
+ <li>Format limitation note: EQ, peak and spectrumData are not available with MovieStar content. This may be a Flash 9/AS3 limitation.</li>\r
+ </ul>\r
+ </li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <ul class="double">\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li>Added CSS checks to page player: "exclude" and "playable" to override default URL matching behaviour.</li>\r
+ </ul>\r
+ </li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.78a.20080920</b></h3>\r
+\r
+ <ul class="double">\r
+ <li class="in">\r
+ <p class="compact">API: Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Added <code>SoundLoaderContext</code> parameter to <code>load()</code>, Flash should now check policy-related (crossdomain.xml) files when loading resources from remote domains. Should fix previous security exception warnings when trying to access ID3 and/or waveform/EQ data. See related <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundLoaderContext.html">SoundLoaderContext documentation</a> (ActionScript 3)</li>\r
+ <li class="in">Fixed a bug with <code>load()</code>, was improperly expecting an options object - now works properly.</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">API: New shiny!</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Added <code>soundManager.altURL</code> property (and <code>useAltURL</code> conditional) for convenient offline and other URL switching cases (dev vs. production environments, etc.)</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Renamed internal soundManager and SMSound <code>self</code> closure references to <code>_s</code> and <code>_t</code>, respectively, to avoid potential conflicts with others' code</li>\r
+ <li class="in">Moved self-destruct to use <code>window.onunload</code> instead of <code>onbeforeunload</code>, given the latter event can be caught and canceled if desired by the user</li>\r
+ <li class="in">Inline player demo: Added <code>autoPlay</code> option</li>\r
+ <li class="in">"Basic" demo directory (demo/basic/) moved to demo/api/, added <code>load()</code>-related testcase</li>\r
+ </ul>\r
+ </li>\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+ <h3><b>V2.78a.20080920</b></h3>\r
+\r
+ <ul class="double">\r
+ <li class="in">\r
+ <p class="compact">API: Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Added <code>SoundLoaderContext</code> parameter to <code>load()</code>, Flash should now check policy-related (crossdomain.xml) files when loading resources from remote domains. Should fix previous security exception warnings when trying to access ID3 and/or waveform/EQ data. See related <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundLoaderContext.html">SoundLoaderContext documentation</a> (ActionScript 3)</li>\r
+ <li class="in">Fixed a bug with <code>load()</code>, was improperly expecting an options object - now works properly.</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">API: New shiny!</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Added <code>soundManager.altURL</code> property (and <code>useAltURL</code> conditional) for convenient offline and other URL switching cases (dev vs. production environments, etc.)</li>\r
+ </ul>\r
+ </li>\r
+ <li class="in">\r
+ <p class="compact">Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Renamed internal soundManager and SMSound <code>self</code> closure references to <code>_s</code> and <code>_t</code>, respectively, to avoid potential conflicts with others' code</li>\r
+ <li class="in">Moved self-destruct to use <code>window.onunload</code> instead of <code>onbeforeunload</code>, given the latter event can be caught and canceled if desired by the user</li>\r
+ <li class="in">Inline player demo: Added <code>autoPlay</code> option</li>\r
+ <li class="in">"Basic" demo directory (demo/basic/) moved to demo/api/, added <code>load()</code>-related testcase</li>\r
+ </ul>\r
+ </li>\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="old">\r
+ <h3><b>V2.77a.20080901</b></h3>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">API: Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Fixed some <code>mute()</code> / <code>unmute()</code>-related bugs, global muting should now work properly. Added some related demo page examples.</li>\r
+ <li class="in">Removed comment on flash9Options merging code, was previously new and didn't actually work as it was commented out. Oops. :D</li>\r
+ <li class="in">Added <i>experimental</i> Flashblock exception handling (mozilla/firefox extension), "notification bar"-style UI which can message and assist users in unblocking SM2 .swf. Configured via <code>soundManager.flashBlockHelper</code> object, currently disabled by default.</li>\r
+ <li class="in">Modified <code>soundManager.destroySound()</code> and <code>sound.destruct()</code>, fixed a bug with these methods and flash's unloading of sounds which was breaking things. Hopefully fixes destroying sounds within whileplaying() and related event handlers, too.</li>\r
+ <li class="in">Modified flash 9 "peak data" code to only set the data if the feature is actually enabled.</li>\r
+ <li class="in">Modified <code>soundManager._debug()</code> to list all sound object details, instead of just ID/URL.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="old">\r
+ <h3><b>V2.76a.20080808</b></h3>\r
+\r
+ <ul class="double">\r
+\r
+ <li class="in">\r
+ <p class="compact">API: Bug fixes</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">Fixed some memory "leaks" / garbage collection issues. RAM allocated to load sounds previously wasn't freed until page unload; now memory should be garbage collected some time after <code>sound.unload()</code> and/or <code>soundManager.destroySound()</code>/<code>sound.destruct()</code> methods are called. In certain cases, Flash sound objects may be destroyed and re-created (transparent to the JS-side) to release memory. Note that garbage collection is not instantaneous, and is affected by CPU/system load and other variables.</li>\r
+ <li class="in">Fixed an issue with <code>play()</code> not working on sounds created with <code>autoPlay</code>.</li>\r
+ <li class="in">Fixed SM2 to work under proper XHTML (served as <code>application/xhtml+xml</code> MIME type). Rewrote object/embed code <em>again</em>, now version-agnostic for IE (no CLSID parameters.)</li>\r
+ <li class="in">Corrected reported <code>loadFromXML()</code> bug, multiple loadFromXML() calls should work.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">API: New shiny!</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">New <code>useWaveformData</code> and <code>useEQData</code> sound options, providing access to raw waveform and sound frequency/EQ spectrum data via sound.waveformData and sound.eqData.</li>\r
+ <li class="in">Renamed <code>useSpectrumData</code> to <code>useWaveformData</code> - if using waveform stuff currently, make sure you update your code!</li>\r
+ <li class="in">Added <code>soundManager.features</code> object, which reflects the "support" state for <code>peakData</code>, <code>waveformData</code> and <code>eqData</code>. Handy for current and future version/support branching.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">API: Miscellaneous</p>\r
+ <ul class="nested compact flat">\r
+ <li class="in">New <code>flash9Options</code> configuration object for logical separation. When Flash 9+ is used, these options are merged into the <code>defaultOptions</code> object.</li>\r
+ <li class="in">Added <code>allowDomain()</code> stubs and documentation to .as source for allowing .swf on external domains to work (recompile of .swf required)</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">"Page As Playlist" demo: Updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>Added "favicon" VU meter display option (Flash 9+ only, experimental, currently Firefox/Opera only)</li>\r
+ <li class="in">More-efficient RAM use via <code>unload()</code> and <code>destruct()</code> sound methods, discarding inactive sounds and freeing RAM as appropriate.</li>\r
+ <li class="in">Added <code>useEQData</code>, showing sound spectrum (frequency range) instead of raw waveform</li>\r
+ <li class="in">Added <code>fillGraph</code> config option, allowing solid waveform graphs instead of only peak points</li>\r
+ <li class="in">Fixed <code>playNext</code> bug where same track couldn't be played twice in a row.</li>\r
+ <li>Fixed duplicate URL bug; items with identical MP3 URLs will now work. (Previously, URL was the ID for items and thus had to be unique. Lookup is now done by object.)</li>\r
+ <li>Modified MP3 URL search to include URL parameters, characters after ".mp3"</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="in">\r
+ <p class="compact">Other updates</p>\r
+ <ul class="nested compact flat">\r
+ <li>Demo code clean-up, externalised CSS, prettier demo layout and code color highlighting</li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="old">\r
+ <h3><b>V2.75a.20080707</b></h3>\r
+ <ul class="nested">\r
+ <li class="in">Flash 9 support! (soundmanager2_flash9.swf) - <code>multiShot</code> now actually works (layering/"chorus" effects on sounds), new <code>spectrumData</code> and <code>peakData</code> API features. All existing API features should have parity.</li>\r
+ <li class="in">Added <code>soundManager.flashVersion</code> property. Flash 8 is the supplied default.</li>\r
+ <li class="in">Modified <code>soundManager.url</code> to require only a path, eg. <code>/path/to/soundmanager-swfs/</code> to allow loading of varying .SWF versions.</li>\r
+ <li class="in">Basic (API) demo: Updated multiShot/Flash 9 behaviour documentation</li>\r
+ <li class="in">Page player demo: Added optional spectrum and VU (spectrumData/peakData) features</li>\r
+ <li class="in">MPC + animation demos: Modified to use Flash 9 (demo improved multiShot feature)</li>\r
+ <li>Flash 9 behaviour differences:\r
+ <ul>\r
+ <li class="in"><code>multiShot</code> properly allows <code>play()</code> to be called multiple times on a sound object, creating desired "chorus" effect. Will call <code>onfinish()</code> multiple times, but <code>whileplaying()</code> etc. are called only for the first "play instance" to avoid complications.</li>\r
+ <li class="in">New <code>soundSpectrum</code> and <code>peakData</code> sound features (spectrum graph / "VU" meter-style data) available</li>\r
+ <li>Sounds can be actually unloaded ("null" MP3 no longer needed to cancel loading of an MP3), but URL cannot be changed without destroying and recreating the related Flash sound object. The Flash 9 version does this to maintain API consistency.</li>\r
+ </ul>\r
+ </li>\r
+ <li>New + improved documentation/project page, updated 2-column layout with content filters, "Get Satisfaction" integration and self-update checks (and a light-switch-related easter egg.)</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="old">\r
+ <h3>V2.5b.20080525</h3>\r
+ <ul class="nested">\r
+ <li class="in">Added <code>waitForWindowLoad</code> for delayed init</li>\r
+ <li class="in">Added <code>onpause()</code> and <code>onresume()</code> event handlers</li>\r
+ <li class="in">Added <code>mute()</code> and <code>unmute()</code></li>\r
+ <li class="in">Updated demos, revised documentation</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="old">\r
+ <h3>V2.5b.20080505</h3>\r
+ <ul class="nested">\r
+ <li class="in">To improve startup time, <code>soundManager.go()</code> (<code>createMovie()</code> alias) now fires at <code>onDOMContentLoaded()</code> by default if supported. (Otherwise, falls back to <code>window.onload()</code>.)</li>\r
+ <li class="in">Improved initialisation routine - <code>soundManager.onerror()</code> is called when the Flash init "times out." Specifically, <code>onerror()</code> is called when Flash fails to make an ExternalInterface (Flash-> JS) call to SM2 within 1 second of <code>window.onload()</code> firing.</li>\r
+ <li>Added logic to handle special Safari delayed init case (Flash not loading when in a new, unfocused tab until focused) as a exception to the above.</li>\r
+ <li>Added better exception handling + debug messaging for initialisation failure cases (Flash security restrictions due to loading from local file system, no flash support, no ExternalInterface support etc.)</li>\r
+ <li class="in">Updated .swf appendChild() target to use best-to-worst options: <code>(document.body || document.documentElement || document.getElementsByTagName('div')[0])</code></li>\r
+ <li>Safari console[log|warn|error]-style messages are now properly formatted.</li>\r
+ <li class="in">Added tons of semicolons to closing braces, eg. <code>};</code></li>\r
+ <li>"No-debug", minified version of SM2 included: <a href="script/soundmanager2-nodebug-jsmin.js" title="No-debug, minified version of SoundManager 2 script">soundmanager2-nodebug-jsmin.js</a> (17.4 KB, down from full size of 35 KB.) With Gzip compression, file size is ~6 KB. (Commented, debug-enabled version compresses to 10 KB with Gzip.)</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="old">\r
+\r
+ <h3>V2.5b.20080501</h3>\r
+ <p class="compact"><b>Warning:</b> A little experimental too, read details below.</p>\r
+ <p><em>Changelog</em>:</p>\r
+ <ul class="nested">\r
+ <li class="in">Rewrote SoundManager initialisation: "Way faster." Communication now initiated from Flash, verification callback then performed by JS; far faster, hopefully more-reliable (TBD.) Init time drastically reduced from seconds to milliseconds in most cases, dependent primarily on Flash movie load rather than <code>window.onload()</code>.</li>\r
+ <li>Above change also fixes Safari "loading SM2 in background tab" issue, where Safari does not init Flash until background tab comes into focus (when a link is opened in a new, non-focused tab.)</li>\r
+ <li class="in">Current drawback: Difficult to determine, save for falling back to <code>window.onload()</code> plus focus methods due to above issue, whether SM2 is actually available or not (ie., <code>soundManager.onerror()</code> will not likely be called as in past.) However, the <code>supported()</code> method will correctly reflect if SM2 has successfully initialised, for example.</li>\r
+ <li class="in">Added sandbox/security model code; SM2 can now tell if it is restricted to either local or internet access only, for example. Helpful in potential debugging errors, plus viewing demos off the local filesystem should no longer throw init errors requiring whitelisting (seemingly due to the new initialisation method.) Win!</li>\r
+ <li class="in">Opera 9.27 has been noted to have some bugs relating to ExternalInterface, seems to be unable to make calls from ActionScript-level methods using <code>setTimeout()</code> or <code>setInterval()</code>. As a reulst, SoundManager 2 events like <code>onfinish()</code>, <code>whileplaying()</code> and <code>onfinish()</code> can be sporadically called or missed altogether. No known workaround at this time, but Opera 9.5 (beta 2) does not have this issue. Popular MP3 "mix tape" site muxtape.com uses similar techniques for JS-Flash communication and appears to suffer from the same problem.</li>\r
+ <li class="in"><strong>Warning</strong>: Random crash issue noticed when using IE 6 + 7 and this demo page, calling <code>createSound()</code> when <code>soundManager.defaultOptions.autoLoad = true;</code> from within <code>soundManager.onload()</code>, for creating + preloading the tab/theme switch sounds. Removing autoLoad=true (leaving the default of false) fixed the crash. Exact reason not determined, perhaps recursive calls or pre-onload issue (?), seems to be isolated to the home page. MPC demo uses autoLoad also, but did not crash. Mentioning just in case.</li>\r
+ <li>Updated Muxtape-style demo: More themes, load/security debugging info etc.</li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li class="old">\r
+\r
+ <h3>V2.2.20080420</h3>\r
+ <p><em>Changelog</em>:</p>\r
+ <ul class="nested">\r
+ <li>More demos! "<a href="../demo/page-player/" title="Muxtape.com-style playable page of MP3 links">Page as a playlist</a>" (muxtape.com-style) example, "<a href="../demo/play-mp3-links/" title="Play MP3 links in a web page using SoundManager 2">Make MP3 links playable inline</a>" demo</li>\r
+ <li class="in">Corrected <code>onStop()</code> handler inheritance/overriding behaviour (was incorrectly checking defaultOptions)</li>\r
+ <li class="in">Added debug output of options object for <code>createSound()</code> calls. Full options (result of merging global default + sound-instance-specific options) displayed, helpful in troubleshooting. Event handler function code is intelligently (hopefully) displayed, truncated at 64 characters of first block or end of line, whichever comes first.</li>\r
+ <li class="in">Removed most HTML markup from non-HTML (eg. console) <code>_writeDebug()</code> calls</li>\r
+ <li class="in"><code>soundManager.destruct()</code> writes to console, to be consistent</li>\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="old">\r
+\r
+ <h3>V2.1.20080331</h3>\r
+ <p><em>Changelog</em>:</p>\r
+ <ul class="nested">\r
+ <li class="in">Modified <code>createSound()</code> to return a sound object if successful (more logical)</li>\r
+ <li class="in">Updated <code>setPosition()</code> method and added <code>position</code> option parameter, documentation + demo (bugfix)</li>\r
+ <li class="in">Corrected <code>createSound()</code> and <code>play()</code> sound option inheritance/overriding behaviour (eg. <code>position</code>) to work as expected (most to least important: Method call options -> sound object instance options -> SM2 global options)</li>\r
+ <li class="in">Updated <code>deleteSound()</code> so Array.splice() is used instead of delete, the latter doesn't cause Array.length to update (bugfix)</li>\r
+ <li>Modified debug=alert to only work when debug mode is enabled (potential annoyance aversion)</li>\r
+ <li class="in">Modified <code>togglePause()</code> to use <code>position</code> option parameter rather than undocumented <code>offset</code> (oops :D)</li>\r
+ <li class="in">Added <code>supported()</code> convenience method (indicates pass/fail after SM2 has initialised.)</li>\r
+ <li>Added disabling debug calls from Flash (performance)</li>\r
+ <li>Added URL hash updating/bookmarking and page title updating to jsAMP demo app</li>\r
+ <li>Updated project page layout</li>\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="old">\r
+\r
+ <h3>V2.0b.20070415</h3>\r
+ <p><em>Changelog</em>:</p>\r
+ <ul class="nested">\r
+ <li class="in">Added <code>destroySound()</code> method</li>\r
+ <li>Made debug output slightly less-verbose (commented out)</li>\r
+ <li>Safety tweak for position-related Flash bug when loading new sounds</li>\r
+ <li class="in">Highly-expanded documentation (<code>SMSound</code> events + properties, examples, caveats, FAQs etc.)</li>\r
+ <li>Added time-sensitive light/dark theme for documentation</li>\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="old">\r
+\r
+ <h3>V2.0b.20070201</h3>\r
+ <p class="compact">Second beta?</p>\r
+ <p><em>Changelog</em>:</p>\r
+ <ul class="nested">\r
+ <li>Fixed stopAll() bug (previously broken)</li>\r
+ <li>Added <code class="in">nullURL</code> parameter</li>\r
+ <li>Updated documentation</li>\r
+ </ul>\r
+ <h3>V2.0b.20070123</h3>\r
+ <h3>V2.0b.20070118</h3>\r
+ <h3>V2.0b.20070115</h3>\r
+ </li>\r
+\r
+ <li class="old">\r
+ <h3>V2.0b.20070107</h3>\r
+ <p class="compact">First beta</p>\r
+ </li>\r
+\r
+ <li class="old">\r
+ <h3>V2.0a.20060904</h3>\r
+ <p class="compact">Prerelease alpha</p>\r
+ </li>\r
+\r
+ </ul>\r
+ \r
+ <!-- <script type="text/javascript">document.getElementById('revision-list').className += ' hide-old';</script> -->\r
+\r
+\r
+ <div id="html5-audio-notes">\r
+\r
+ <h5>HTML5 Audio: Support updates, technical notes, quirks, bugs and annoyances</h5>\r
+\r
+ <p class="note">Note: This section is archived content and has been rolled into <a href="#revision-history">Revision History</a>.</p>\r
+\r
+ <p><b>As of the V2.97.20111220 release of SM2:</b></p>\r
+\r
+ <ul>\r
+\r
+ <li>\r
+ <p>Multiple URLs (and/or multiple MIME types) can be specified when creating a sound, thus allowing for better native HTML5 support between OGG, MP3 and others. See <a href="#smsound-url">SMSound.url</a> for details.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Support for "audio sprites" has been added in the form of <code>from</code> and <code>to</code> sound options. See the <a href="../demo/api/#fitter-happier" title="SoundManager 2 audio sprite demo">audio sprite demo</a> for a live example.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Added <code>soundManager.html5PollingInterval</code>, for increased <code>whileplaying()</code> callback frequency (higher framerates.) Excludes mobile (eg., iOS) by default.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Fixed <code>Audio()</code> object <code>src</code> property re-assignment bug seen in <code>createSound()</code>-><code>play()</code>.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p><code>mySound.load({onload:function(){}})</code> callback fixed so it works.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p><code>onload()</code> now called immediately when <code>load({onload:function(){}})</code> is used on a sound with the same URL which has already loaded.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p><code>onstop()</code> now mimics <code>onfinish()</code> in terms of sequence. HTML5 sets position to 0, but retains pre-<code>stop()</code> position property value (like Flash does.)</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Amazon Kindle Fire UA looks like Safari on OS X 10.6.3, but does not have broken HTML5 audio (i.e., intermittent playback failure) like the "isBadSafari" case.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Side note: iOS ignores volume, always returns value of "1" (at least, on iOS 4 and present iOS 5 releases.) See <a href="http://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/AddingSoundtoCanvasAnimations/AddingSoundtoCanvasAnimations.html">related notes</a>.</p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ <p><b>As of the V2.97.20111030 release of SM2:</b></p>\r
+\r
+ <ul>\r
+\r
+ <li>\r
+ <p>Fixes for HTML5 <code>unload()</code> on Webkit (connection was not closing) due to src being set to <code>''</code> (OK only in Firefox, presently?) vs. an "empty" URL.</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>HTML5 <code>suspend</code> events are now listened for and fired via SMSound option <code>onsuspend()</code>. This event may be the best way to detect when mobile Safari (eg. iOS) is blocking autoplay-style behaviour, and user interaction is required to start or resume playback. (iOS does not allow auto-play of audio; user interaction is required for audio playback to start.)</p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>Added try...catch for dumb IE 9 <code>Audio()</code> "not implemented" error in Windows server case without "desktop experience" installed, means no HTML5 audio/video support. Hat tip: Modernizr issue 224.</p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ <p><b>As of the V2.97.20110801 release of SM2:</b></p>\r
+\r
+ <ul>\r
+ <li><p>A regression was introduced in V2.97.20110706 where SM2 would fail to start in HTML5-only mode on supported desktop browsers when flash was disabled or not installed, eg., Safari on new Macs or IE 9 without flash. (iOS was not affected.) This has been fixed with the 2.97.20110801 release.</p></li>\r
+ <li>\r
+ <p><code>soundManager.useHTML5Audio</code> is now <code>true</code> by default; however, <code>soundManager.preferFlash</code> is also <code>true</code> and HTML5 browsers will still attempt to use flash for playing MP3/MP4 by default, if those formats are marked as "required".</p>\r
+ <p>If you wish to have 100% HTML5 mode in more cases, set <code>soundManager.preferFlash = false</code>. Presently, the MP3 links and MP3 button SM2 demos are more HTML5-friendly and will serve as a test for exposing bugs that may be in the wild.</p>\r
+ </li>\r
+ <li>\r
+ <p><code>soundManager.html5Test</code> has been relaxed to use <code>(probably|maybe)</code> for Audio's <code>canPlayType()</code> test (previously, was only "probably") - so formats will be more likely to work on HTML5-only devices that conservatively report "maybe" for MIME types like <code>audio/mpeg; codecs="mp3"</code> at this point.</p>\r
+ </li>\r
+ <li>\r
+ <p>Certain mobile and tablet-like devices are special-cased as preferring HTML5, and will ignore checking for flash altogether; this presently includes the iPad, iPhone and iPod, Palm Pre and Motorola Xoom.</p>\r
+ </li>\r
+ <li>\r
+ <p>The HTML5 audio "loadeddata" event triggers an SMSound <code>onload()</code> event, which now fires <code>whileplaying()</code> and tries to pass identical <code>bytesLoaded, bytesTotal</code> parameters so that UIs will correctly show the sound as fully-"loaded" - even if in truth, not all bytes have actually been fetched (depending on the browser and server, etc.) because of the ability to do arbitrary seeking.</p>\r
+ </li>\r
+ <li>\r
+ <p>The experimental <code>soundManager.useGlobalHTML5Audio</code> and <code>soundManager.requireFlash</code> properties were removed. Internally the global HTML5 audio logic still applies to iOS, but it does not seem to be necessary for other devices at this time.</p>\r
+ </li>\r
+ </ul>\r
+\r
+ <p><b>As of the V2.97.20110706 release of SM2:</b></p>\r
+\r
+ <ul>\r
+ <li><p>HTML5 audio appears to have been <i>fixed</i> in Safari with Snow Leopard 10.6.8, the "pre-Lion release", from 06/2011. SM2 will now only blacklist Safari + OS X 10.6.3 through 10.6.7 as having broken HTML5 audio (intermittent load/playback failures), and falling back to Flash where available.</p></li>\r
+ <li>\r
+ <p>New, experimental <code>soundManager.preferFlash</code> for handling "mixed-mode" HTML5 + flash cases. In the event HTML5 supports MP3/MP4 and <code>preferFlash</code> is true (and flash is installed), flash will be used for MP3/MP4 content while allowing HTML5 to play OGG, WAV and other formats etc.</p>\r
+ <p><em>Important note:</em> Because HTML5 audio is still quirky and has bugs, <code>preferFlash</code> is <code>true</code> by default to help ensure MP3/MP4 play consistently. If set to <code>false</code> or flash is not available, "HTML5-only" mode will kick in and will apply to all formats.</p>\r
+ </li>\r
+ </ul>\r
+\r
+ <p><b>As of the V2.97.20110424 release of SM2:</b></p>\r
+\r
+ <ul>\r
+ <li><p>HTML5 audio in Safari on Snow Leopard 10.6.3 through 10.6.9 (10.6.7 was released 03/2011) are blacklisted and will fall back to Flash. 10.6.8 and 10.6.9 are preemptive guesses. According to beta testers, OS X 10.7 ("Lion") has fixed the intermittent <a href="https://bugs.webkit.org/show_bug.cgi?id=32159">HTML5 audio load/playback issue</a>.</p></li>\r
+ <li><p><code>new Audio(null)</code> is no longer used for iOS, as iOS would attempt to load a URL called "null".</p></li>\r
+ <li><p>iOS 4.2 or 4.3 may have introduced new security restrictions around <code>onfinish()</code>-><code>unload()</code>-><code>play()</code> that prevents the "play-through" behaviour previously allowed in certain cases. The <code>unload()</code> attempts to nullify the audio's <code>src</code> attribute, breaking the future <code>play()</code> request. The Muxtape/button/link demos were affected by this, and have been fixed with this release. To prevent this issue in your own apps, avoid <code>unload()</code> and simply use <code>onfinish()</code>-><code>play()</code> for iOS.</p></li>\r
+ </ul>\r
+\r
+ <p><b>As of the V2.97.20110306 release of SM2:</b></p>\r
+\r
+ <ul>\r
+ <li><p>Testing suggests that auto-play ("auto-annoy?") does work on iOS 4.1, but are aggressively blocked as of iOS 4.2.</p></li>\r
+ <li><p><code>_resetProperties()</code> when setting Audio().src, fix sound1.play() -> sound2.play() -> sound1.play() case on iOS 4.1 not correctly re-assigning original sound URL (related to global audio object.)</p></li>\r
+ <li><p>If no flash is detected, try forcing <code>useHTML5Audio = true</code> (eg. desktop safari on new Macs which don't come with Flash.) Related: flash detection code tweak.</p></li>\r
+ <li><p>isNaN() check for HTML5 loading (saw one under Safari, in testing).</p></li>\r
+ <li><p>Use new Audio(null) vs (), Opera 9.64 expects URL argument; throws WRONG_ARGUMENTS_ERR otherwise. Doesn't implement canPlayType() either, but both are fixed in future releases.</p></li>\r
+ </ul>\r
+\r
+ <p><b>As of the V2.97.20110123 release of SM2:</b></p>\r
+ \r
+ <ul>\r
+ <li><p>New (experimental) <code>soundManager.useGlobalHTML5Audio</code> attribute, enabled by default for mobile + iOS. Enables use of a single audio object, re-used for loading and playing all sounds. iOS currently can only play one sound at a time, so this limitation is safe for now. The global object fixes previous regression of play-through/playNext()-style behaviours.</p></li>\r
+ <li><p>Sound recycling with new global audio feature should work better than in prior (development) versions.</p></li>\r
+ <li><p>Improved broken Safari/Snow Leopard HTML5 audio situation: HTML5 mode is no longer disabled - and if available, Flash is used to play MP3/MP4 content to work around known playback issues with native HTML5 audio.</p></li>\r
+ <li><p>New (experimental) <code>soundManager.requireFlash</code> property (default: false.) If true, prevents HTML5-only mode on devices with both HTML5 and Flash. May be useful when HTML5 is enabled (and can play MP3), but Flash is desired to play RTMP content etc. As of this version, will only use Flash for RTMP.</p></li>\r
+ <li><p>Fix for <code>type:'audio/mp3'</code> returning false on <code>canPlay()</code>. Timer update-while-paused tweak.</p></li>\r
+ <li><p>More event listeners, ignore events on destroyed sounds, improved event clean-up, "seek before load" fix</p></li>\r
+ </ul>\r
+\r
+ <p><b>As of the January 1, 2011 (V2.97a.20110101) and December, 2010 releases of SM2 (V2.97a.20101221):</b></p>\r
+ <ul>\r
+ <li><p>The <code>bytesLoaded</code> and <code>bytesTotal</code> properties may become less-relevant under HTML5 due to non-linear HTTP downloading (using ranges and partials), but they are still provided under Firefox at this time.</p></li>\r
+ <li><p>Related to bytes loading/total, a sound's <code>onload</code> event may not always be fired (Mozilla currently discourage use of the DOM <code>loaded</code> event), again because of range requests and the ability to arbitrarily seek within a file.</p></li>\r
+ <li><p>Basic support for the W3 <code>TimeRanges</code> implementation of sound buffering (ie., loaded data) has been implemented. This gives an idea of "total time loaded", but again, is not necessarily sequential.</p></li>\r
+ <li><p>HTML5 audio is disabled for all versions of Safari (4 and 5) on Snow Leopard (OS X 10.6.3 - 10.6.5) until Apple fixes issues with audio loading and playback due to bugs in "underlying frameworks." See <a href="https://bugs.webkit.org/show_bug.cgi?id=32159#c9" title="Safari Snow Leopard HTML5 Audio Bug">Webkit #32159</a>. HTML5 audio in Safari on Windows (provided QuickTime is installed) does not have the same fatal bug.</p></li>\r
+ </ul>\r
+\r
+ <p><b>As of the October, 2010 release of SM2 (V2.97a.20101010):</b></p>\r
+ <ul>\r
+ <li><p>HTML5 audio is disabled for all versions of Safari (4 and 5) on Snow Leopard (OS X 10.6.3 and 10.6.4) until Apple fixes issues with audio loading and playback due to bugs in "underlying frameworks." See <a href="https://bugs.webkit.org/show_bug.cgi?id=32159#c9" title="Safari Snow Leopard HTML5 Audio Bug">Webkit #32159</a>.</p></li>\r
+ </ul>\r
+\r
+ <p><b>As of the August, 2010 release of SM2 (V2.96a.20100822):</b></p>\r
+ <ul>\r
+ <li><p>Safari 5.0.1 (533.17.18) on Snow Leopard (10.6.x) continues to show buggy HTML5 audio load/playback behaviour. Apple are aware of the regression, which began with Safari 4.0 on Snow Leopard (perhaps with the new QuickTime.) See <a href="https://bugs.webkit.org/show_bug.cgi?id=32159#c9" title="Safari Snow Leopard HTML5 Audio Bug">Webkit #32159</a>.</p></li>\r
+ <li><p>iPad/iPhone iOS4 will now play a sequence of sounds if using <code>onfinish()</code> to create/start the next (eg., the Muxtape-style playlist on the SM2 homepage will play through once the user starts it.) In any event, user interaction is always required to start the first sound.</p></li>\r
+ </ul>\r
+ \r
+ <p><b>As of the June, 2010 release of SM2 (V2.96a.20100624):</b></p>\r
+ <ul>\r
+ <li><p>Safari 5.0 (533.16) on OS X Snow Leopard (10.6.x) continues to show buggy HTML5 audio load/playback behaviour, same as with Safari 4.0.5 on Snow Leopard only - may be related to underlying QuickTime implementation (a guess, at this point.) SM2 will disable HTML5 audio support by default for this specific browser + OS combo. See <a href="https://bugs.webkit.org/show_bug.cgi?id=32159#c9" title="Safari Snow Leopard HTML5 Audio Bug">Webkit #32159</a> for discussion + testcases.</p></li>\r
+ </ul>\r
+ \r
+ <p><b>As of the May, 2010 release of SM2 (V2.96a.20100520):</b></p>\r
+ <ul>\r
+ <li><p>Safari 4.0.5 on OS X Snow Leopard (10.6.x) appears to have an annoying bug where audio inconsistently fails to load / play; SM2 will currently disable or ignore the HTML5 feature on this exact browser + OS version. See <a href="https://bugs.webkit.org/show_bug.cgi?id=32159#c9" title="Safari Snow Leopard HTML5 Audio Bug">Webkit #32159</a> for discussion + testcases. Note that Safari on OS X 10.5 "Leopard" and on Windows <i>do not</i> appear to have this bug; it seems to be limited to Snow Leopard, seen on OS X 10.6.3.</p></li>\r
+ <li><p>Some browsers (and iPad 3.2?) do not fire <code>progress</code> events, and/or do not implement bytesLoaded/bytesTotal-style attributes.</p></li>\r
+ <li><p>iPad 3.2 appears to be able to only play one sound at a time, and will terminate other sounds.</p></li>\r
+ <li><p>iPad 3.2 may also loop AAC+ (HE-AAC) and WAV sounds, perhaps not firing onfinish() and resetting the position to 0 each time, but is fine with MP3s. This has been observed, but not fully-tested.</p></li>\r
+ <li><p>Looping in HTML5 is either "infinite" or "none". A wrapper may be created for SM2 so that a number of loops can be specified, as with Flash. This is not yet implemented.</p></li>\r
+ <li><p>Panning (left/right channel balance) does not appear to be in HTML5.</p></li>\r
+ <li><p>Flash-only features such as ID3 tag reading, waveform and spectrum data will simply be ignored, and their related events will not fire on SMSound objects which are using HTML5.</p></li>\r
+ </ul>\r
+\r
+ </div>\r
+\r
+\r
+ \r
+ \r
+ </div>\r
+\r
+\r
+ </div>\r
+ \r
+\r
+ </div>\r
+\r
+\r
+ \r
+ <div id="col3" class="c3">\r
+\r
+ <div id="support-wrapper">\r
+ <div id="get-satisfaction" class="box">\r
+ <div id="gsfn_list_widget">\r
+ <h2><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/" title="User discussion, FAQs and support for SoundManager 2" rel="nofollow">Discussion / Support</a><span class="l"></span><span class="r"></span></h2>\r
+ <div id="gsfn_content"></div>\r
+ <div class="powered_by"><a href="http://getsatisfaction.com/" rel="nofollow">Get Satisfaction support network</a></div>\r
+ </div>\r
+ <!-- /.box -->\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="shortcuts">\r
+\r
+<!--\r
+ <div class="box">\r
+\r
+ <h2>Shortcuts<span class="l"></span><span class="r"></span></h2>\r
+\r
+ <ul class="first">\r
+ <li onclick="setFilter(event,'c-')" class="ignore">\r
+\r
+ <ul>\r
+\r
+ <li>Demos</li>\r
+ <li>Getting Started</li>\r
+ <li>Basic Use</li>\r
+ <li>Download</li>\r
+ <li>Requirements</li>\r
+ <li>Limitations</li>\r
+\r
+ <li>Debug Output</li>\r
+ <li>Revision History</li>\r
+ <li>About</li>\r
+ </ul>\r
+\r
+ </li>\r
+ </ul>\r
+\r
+ </div>\r
+-->\r
+\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ <div class="clear"></div>\r
+\r
+ <!-- /main -->\r
+ </div>\r
+\r
+ <!-- /main-wrapper -->\r
+ </div>\r
+\r
+ <!-- /content -->\r
+ </div>\r
+\r
+<script type="text/javascript">\r
+init();\r
+</script>\r
+ \r
+</body>\r
+\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Download</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Get the latest version of SoundManager 2 (BSD licensed.)" />\r
+<meta name="keywords" content="download, javascript sound, javascript audio api" />\r
+<meta name="robots" content="all" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta name="copyright" content="Copyright (C) 1997 onwards Scott Schiller" />\r
+<meta name="language" content="en-us" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="../../demo/index.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="../../demo/index.js"></script>\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ url: '../../swf/',\r
+ debugMode: false\r
+});\r
+</script>\r
+</head>\r
+\r
+<body>\r
+ \r
+<div id="content">\r
+\r
+ <div id="top">\r
+\r
+ <h1>SoundManager 2: Download</h1>\r
+\r
+ <div id="nav">\r
+ <ul>\r
+\r
+ <li>\r
+ <a href="../../">Home</a>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="#">Demos</a>\r
+ <ul>\r
+ <li><a href="../../demo/template/">Basic Template</a></li>\r
+ <li><a href="../../demo/api/">API Examples</a></li>\r
+ <li><a href="../../demo/bar-ui/">Bar UI</a></li>\r
+ <li><a href="../../demo/play-mp3-links/" class="exclude">Playable MP3 links</a></li>\r
+ <li><a href="../../demo/mp3-player-button/" class="exclude">Basic MP3 Play Button</a></li>\r
+ <li><a href="../../demo/page-player/">Muxtape-style UI</a></li>\r
+ <li><a href="../../demo/360-player/">360° Player UI</a></li>\r
+ <li><a href="../../demo/mpc/">Drum Machine (MPC)</a></li>\r
+ <li><a href="../../demo/animation/">DOM/Animation Demos</a></li>\r
+ <li><a href="../../demo/flashblock/">FlashBlock Handling</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="../getstarted/">Getting Started</a>\r
+ <ul>\r
+ <li><a href="../getstarted/#how-sm2-works">How SoundManager 2 works</a></li>\r
+ <li><a href="../getstarted/#basic-inclusion">Including SM2 on your site</a></li>\r
+ <li><a href="../getstarted/#troubleshooting">Troubleshooting</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="..">Documentation</a>\r
+ <ul>\r
+ <li><a href="../#sm-config">SoundManager Properties</a></li>\r
+ <li><a href="../#sound-object-properties">Sound Object Properties</a></li>\r
+ <li><a href="../#smdefaults">Global Sound Defaults</a></li>\r
+ <li><a href="../#api">SoundManager Core API</a></li>\r
+ <li><a href="../#smsoundmethods">Sound Object (SMSound) API</a></li>\r
+ <li><a href="../generated/soundmanager2.html">Generated Documentation</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <strong><a href="#">Download</a></strong>\r
+ <ul>\r
+ <li><a href="#latest">Get SoundManager 2</a></li>\r
+ <li><a href="#revision-history">Revision History</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <a href="../technotes/">Technical Notes</a>\r
+ <ul>\r
+ <li><a href="../technotes/#requirements">System Requirements</a></li>\r
+ <li><a href="../technotes/#serving-audio">Serving To HTML5 + Flash Clients</a></li>\r
+ <li><a href="../technotes/#client-requests">How Clients Download Audio</a></li>\r
+ <li><a href="../technotes/#mobile-device-limitations">Mobile Device Limitations</a></li>\r
+ <li><a href="../technotes/#debug-output">Debug + Console Output</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="../resources/">Resources</a>\r
+ <ul>\r
+ <li><a href="../resources/#licensing">Licensing</a></li>\r
+ <li><a href="../resources/#related">Related Projects</a></li>\r
+ <li><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/">SM2 support / discussion</a></li>\r
+ <li><a href="http://www.schillmania.com/content/react/contact/">Contact Info @ Schillmania.com</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ <div class="clear"></div>\r
+ </div>\r
+ \r
+ </div>\r
+\r
+<div id="main-wrapper">\r
+\r
+ <div id="main" class="triple">\r
+\r
+\r
+ <div id="filter-box" class="columnar">\r
+\r
+ <div class="c1">\r
+ <div id="reset-filter"></div>\r
+ </div>\r
+\r
+ <div class="c2">\r
+ <div id="search-results"><!-- search results for %s --></div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="newest" class="columnar">\r
+ \r
+ <div class="c1">\r
+ <h2>Get SoundManager 2</h2>\r
+ <p>Get the latest and greatest.</p>\r
+ </div>\r
+ \r
+ <div class="c2">\r
+\r
+ <h3>Download SoundManager 2</h3>\r
+\r
+ <p><b>Latest changes:</b> Minor tweaks for mobile and desktop Safari. Package/module (bower/npm) setup, "Bar UI" API update, Turntable UI demo and more. See <a href="#history">revision history</a> for details.</p>\r
+ \r
+ <p style="padding-top:0.5em"><a href="../../download/soundmanagerv297a-20150601.zip" title="Download SoundManager 2" class="norewrite feature">Download SoundManager 2.97a.20150601</a> or see <a href="https://github.com/scottschiller/SoundManager2/" title="SoundManager 2 on GitHub">on GitHub</a>, or <a href="https://www.npmjs.com/package/soundmanager2" title="SoundManager 2 on npm">on npm</a></p>\r
+\r
+ <p><b>Performance tip:</b> SM2's code size varies from over 150 KB (commented, debug-enabled) down to 12 KB (optimized) over HTTP; check the <a href="../getstarted/#basic-inclusion" title="Including SoundManager 2 on your site: Script build options">pre-optimized builds</a> for details.</p>\r
+\r
+ <p><b>Side reading + video talks, slides etc.</b></p>\r
+\r
+ <ul>\r
+ <li>Video, 02/2012: <a href="http://www.youtube.com/watch?v=C2Tw0BeZb8Q" title="Scott Schiller: Web Audio: HTML5 + Flash (in a tree)">Web Audio: HTML5 + Flash (in a tree)</a> (<a href="http://isflashdeadyet.com/talks/html5/bayjax_yahoo_sunnyvale_02-06-2012/" title=""Web Audio: HTML5 + Flash (in a tree)" presentation slides" class="cta">slides</a>.) Updated HTML5 content, demos and <a href="http://www.schillmania.com/content/entries/2012/survivor-c64-html-remake/" title="SURVIVOR: Remaking a Commodore 64 game in HTML">SURVIVOR</a> C64 game demo.</li>\r
+ <li>Video, 12/2011: <a href="http://www.youtube.com/watch?v=KjdPNtWV3Z0#t=56s" title="Scott Schiller: "Adding Sound To HTML"" class="cta">Adding Sound To HTML</a> (<a href="http://isflashdeadyet.com/talks/html5/cbs_san_francisco_12-07-2011/" title=""Adding Sound To HTML" presentation slides" class="cta">slides</a>.) Overview + updated content from 06/2011 talk.</li>\r
+ <li>Video, 06/2011: <a href="http://www.youtube.com/watch?v=ffk65q5Rl9I" title="Yahoo!/YUI video presentation: Scott Schiller on the State of HTML5 Audio">The State Of HTML5 Audio</a></li>\r
+ <li>Article: <a href="http://24ways.org/2010/the-state-of-html5-audio">"Probably, Maybe, No": The State of HTML5 Audio</a>.</li>\r
+ </ul>\r
+\r
+ </div>\r
+ \r
+ </div>\r
+\r
+ \r
+ <div id="history" class="columnar">\r
+ \r
+ <div class="c1">\r
+\r
+ <h2>Revision History</h2>\r
+ <p>Latest changes and archived notes from bug fixes, API updates, feature development etc.</p>\r
+\r
+ </div>\r
+\r
+ <div class="c2">\r
+\r
+ <div class="f-block c-revision-history">\r
+\r
+ <h3 id="revision-history">Revision History</h3>\r
+ \r
+ <p>A changelog of sorts.</p>\r
+\r
+ <ul id="revision-list" class="standard">\r
+\r
+ <li id="sm2-20150601" class="in">\r
+\r
+ <h3><b>V2.97a.20150601</b> - Minor tweaks for mobile and desktop Safari. Package/module (bower/npm) setup, "Bar UI" API update, Turntable UI demo and more. <a href="https://github.com/scottschiller/SoundManager2/compare/V2.97a.20140901...V2.97a.20150601">See GitHub commits</a>.</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>\r
+ At some point (perhaps iOS 7.1?), iOS devices began allowing multiple HTML5 <code>Audio()</code> instances to exist and play simultaneously. By default, SM2 will still apply the singleton pattern via <code>useGlobalHTML5Audio</code> for iOS because playlist-style behaviour may not work without it. If you aren't concerned with playlist-style behaviour and want to use multiple audio instances, see <code>ignoreMobileRestrictions</code>.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>\r
+ Added <code>forceUseGlobalHTML5Audio</code> setup option, to address desktop Safari breaking playlist-style playback when in a background tab (something with <code>new Audio()</code> prevents playback from starting automatically?)\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>\r
+ Improved RequireJS compatibility, correct <code>define()</code> usage and support for <code>SM2_DEFER</code>.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ API now fires <code>onstop()</code> when destroying a sound.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ New setup option: <code>ignoreMobileRestrictions</code>. Enable if you want to avoid the singleton HTML5 object pattern used for mobile devices. iOS WebView purportedly allows use of multiple HTML5 <code>Audio()</code> objects.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>soundManager.setVolume(33)</code> now applies to all sounds. (Overloaded form; standard is <code>soundManager.setVolume('mySound', 33)</code>.)\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bar UI Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Added <code>window.sm2BarPlayers</code> API including data and methods. Players are now scriptable / controllable from JS.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>on</code> object for event callbacks, global and per-instance - e.g., <code>window.sm2BarPlayers.on = { play: function() { ... }, stop: function() { ... } });</code> - or, per-instance: <code>window.sm2BarPlayers[0].on = { ... }</code>\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ New config option: <code>stopOtherSounds</code> (i.e., only one player active at a time)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ More config: <code>excludeClass</code> (default: <code>sm2-exclude</code>), prevents SM2 from playing link. Will fall through, download etc.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added support for additional links in playlist: shopping cart ("buy now"), and music note ("download") next to each playlist item.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Playlist now scrolls currently-playing item into view by default.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix timing issue when user switches tracks in error case.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Improved playlist open-by-default UI state. Added playlist toggle to demo.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Check for <code>defaultItem</code>, handle case when starting with an empty playlist.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Workaround for non-zero <code>scrollTop</code> offset the first time the playlist is opened.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Minor UI tweaks for alignment, polish.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ New 2015 <a href="../../demo/turntable/">Turntable UI</a> Demo. Based on the 2011 "<a href="http://www.schillmania.com/content/entries/2011/wheels-of-steel/" title="The Wheels of Steel: An Ode To Turntables (in HTML)">Wheels Of Steel</a>" browser-based turntable UI prototype. Basic UI, API and load/play ability with easily customizable slipmats, record and album artwork.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added <code>bower.json</code>, <code>component.json</code> and npm <code>package.json</code> definition files.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Improved RequireJS compatibility, correct <code>define()</code> usage and support for <code>SM2_DEFER</code>.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>soundmanager2.js</code> code style review (mostly for consistency.) Line breaks, quotes on strings, conditions and ternary statements, comment formatting etc.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Side note: The prior release's pre-emptive fix for iOS 8 ended up being a non-issue, as the official iOS 8 release did not use "OS 10" in the user-agent string. Nonetheless, SM2 will now correctly identify iOS 10+ vs. incorrectly flagging it as "iOS 1".\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li id="sm2-20140901" class="in">\r
+\r
+ <h3><b>V2.97a.20140901</b> - iOS 8 compatibility fix, "Bar UI" player demo, <code>durationchange</code>, buffering, edge case tweaks for HTML5 and RTMP, and browser environment checks. <a href="https://github.com/scottschiller/SoundManager2/compare/V2.97a.20131201...V2.97a.20140901">See GitHub commits</a>, or <a href="../../download/soundmanagerv297a-20140901.zip" class="norewrite">download archived version</a>.</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>\r
+ Why UA sniffing is generally bad, real-world example #1048577: "That time a missing <code>/s</code> on <code>navigator.userAgent</code> (based on single-digit UA version assumptions) broke SM2 on iOS 8+ devices."\r
+ </p>\r
+\r
+ <p>\r
+ The upside: The fix is adding <code>\s</code> to a UA <code>regex</code> check targeting legacy iOS devices with broken <code>HTML5 Audio()</code> support, so that the <code>"OS 10 "</code> portion of the UA string does not match the pattern <code>"OS 1 "</code>.\r
+ </p>\r
+\r
+ <p>\r
+ This is a pre-emptive fix for the pending iOS 8 release, which reportedly includes the string <code>"iPhone OS 10_10 like Mac OS X"</code>. Due to SM2 checking for <code>/os ([12|3_0|3_1])/i</code> which had broken <code>HTML5 Audio()</code> support, and not considering the far future possibility of <code>"iOS 10"</code> being included in the userAgent string at the time, HTML5 audio is incorrectly disabled on iOS 8 beta 3 and is likely to apply to the final iOS 8 release.\r
+ </p>\r
+\r
+ <p>\r
+ This is a good example and reminder of why UA checks are generally bad, and dangerous; similar issues hit other libraries doing UA and plugin checks both client and server-side when IE hit 10, and Flash hit version 10, so this iOS pattern change may affect some other libraries targeting iOS as well.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Listen to <code>durationchange</code> event, catch-all for duration update events. May help on mobile if duration is determined late. (<a href="https://getsatisfaction.com/schillmania/topics/soundmanager2_playing_songs_from_a_different_start_point_on_mobile_not_working#reply_13672624">Related discussion</a>.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Explicitly provide buffering status to <code>onbufferchange()</code>. Don't set <code>buffering(0)</code> when loading, since playback may still be paused.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Flash: Fix edge case where <code>play({ url: xxx, position: 0 });</code> on existing sound with assigned URL. New URL wouldn't take effect.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ SMSound <code>onwarning</code> and <code>onfailure</code> options for NetStream / RTMP error/exception handling. Removed additional sound param on <code>onfailure()</code> callback. Apologies if this breaks anyone's implementation (disclaimer: these options are still experimental, and undocumented. :D) "Unhandled" exceptions are now considered non-fatal, using <code>onwarning</code> instead of presuming playback has failed etc.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ "Bar UI" player demo added. SVG-based iconography, degrades nicely down to IE 8. See <a href="../../demo/bar-ui">live demo</a>.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Retina/hi-dpi updates for 360° canvas, small 360° player buttons and basic button player demo image assets.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ CommonJS + AMD (requireJS) <code>module.exports</code> / <code>define()</code> compatibility (see <a href="https://github.com/scottschiller/SoundManager2/commit/6e9b819ab9567492a9dab03261899a3002e04d60">commit</a> for details.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Check <code>window</code> && <code>window.document</code>, barf if loaded in server-side node environment vs. in a browser. (Even if Node.js etc. support <code>Audio()</code> at some point, SM2 was designed for a browser; this check is probably A Good Thing™ to have in place.) If you feel you have a use case that makes sense here, feedback is appreciated.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li id="sm2-20131201" class="in">\r
+\r
+ <h3><b>V2.97a.20131201</b> - 100% HTML5 mode by default. Duration fix for Adobe FMS/RTMP server-based streaming. HTML5 unload, <code>multiShot</code> and <code>autoPlay</code> tweaks. <a href="https://github.com/scottschiller/SoundManager2/compare/V2.97a.20130512...V2.97a.20131201">See GitHub commits</a>, or <a href="../../download/soundmanagerv297a-20131201.zip" class="norewrite">Download archived version</a>.</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Adobe FMS (RTMP Server) fix: Invoke server-side <code>getStreamLength()</code> call to determine duration. (Red5 and other free RTMP servers use NetStream <code>onMetaData()</code> to pass duration.) \r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix <code>html5Unload()</code> by loading a tiny base64-encoded data: URI WAVe file where supported. Elsewhere, use <code>about:blank</code>. This fixes errors in Chrome where the browser attempts to load the url "null" (a string.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ D'oh! Fix HTML5 sprite regression where <code>_oncanplay()</code> was not being picked up & fired, sound would not play on first click.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Fix double-play bug with <code>autoPlay: true</code>. Correct edge case where <code>onposition()</code> items would sometimes be cleared if called/assigned before <code>play()</code>.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>ontimeout: function(status) {}</code> callback parameter corrections. Fix missing error { <code>type: 'INIT_TIMEOUT'</code> } for missing/404 SWF case, and <code>INIT_FLASHBLOCK</code> for flashblock-specific case.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Apply volume to cloned sounds in HTML5 <code>multiShot</code> case.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fixed issue in <code>_processOnPosition</code> where the item in <code>onPositionItems[i]</code> can be undefined mid-loop if the callback that is triggered changes the length of the <code>onPositionItems</code> array, where <code>onPositionItems.length</code> becomes zero and there's an uncaught <code>TypeError</code> when trying to access <code>item.fired</code> the next time around.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fixed mute in HTML5.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix <code>onload</code> in Firefox 3.6 with no flash (and yes, Firefox 25 is the current release. :D)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Correct event removal (cloned HTML5 nodes) - <code>onended</code> → <code>ended</code>\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Use 100% HTML5 mode by default, where available. <code>preferFlash: false</code> is now the default setting. Firefox does MP3 on Vista (and newer) via HTML5, and recently (via Firefox Aurora builds) on OS X - the last major hold-out. The vast majority of browsers now support MP3 via HTML5, thus reducing the reliance on Flash.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Reboot into 100% HTML5 mode where supported if flash fails after loading, i.e., local/offline/file:// or other edge case.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Fixed <code>canPlayMIME()</code> documentation example.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <!-- previously ... -->\r
+\r
+ <li id="sm2-20130512" class="in">\r
+\r
+ <h3><b>V2.97a.20130512</b> - multiShot for polyphonic HTML5 clients. <code>createSound()</code> no longer requires an <code>id</code>. Auto-<code>reboot()</code> into 100% HTML5 mode where supported. HTML5 unload tweaks. (<a href="../../download/soundmanagerv297a-20130512.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Init enhancement: If <code>preferFlash: true</code> but <code>useFlashBlock: false</code> (the default SM2 config) and flash timeout / blocked case occurs, SM2 will reboot reboot into 100% HTML5 mode if available so init can succeed. If flash block handling is enabled, user interaction will be required to whitelist the flash movie and init will be delayed until the SWF loads.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Correct <code>reboot()</code> to allow 100% HTML5 mode when Flash was previously required due to <code>preferFlash: true</code>. Previously, <code>soundManager.audioFormats.mp3.required = false; soundManager.reboot()</code> did not result in 100% HTML5 mode under Firefox. Now works as expected.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5 unloading: Firefox was supposed to like assigning <code>''</code> to <code>Audio().url</code> for canceling requests, unloading and destroying the decoder (perhaps only on <code><audio></code>, in retrospect?) - similarly, <code>.src = null</code> did not seem to work, possible request to <code>./</code> - undesirable.\r
+ </p>\r
+\r
+ <p>\r
+ Now using more-conservative <code>null</code> URL for unload / destruct on webkit, iOS and others, and <code>emptyURL</code> for Firefox (user-customizable, <code>'about:blank'</code> by default.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ More HTML5 safety checks so that <code>buffered</code> can't go beyond 100%.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Improve Flash 9 <code>load()</code> -> <code>onload()</code> failure case, when loading a non-404 (eg., HTTP 301 -> 200) with non-audio content. Improved messaging for Flash 8, Flash 9 + HTML5 with zero-duration (invalid / unsupported sound) case.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix flash-only (no HTML5 / <code>useHTML5Audio: false</code>) init case, e.g., running under IE 8.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Fix legacy "overloaded" case when <code>soundManager.play('someID', 'some.mp3');</code> is called twice, second call would fail. This shortcut method is deprecated, and not recommended for use other than a conveience when in development / testing.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>\r
+ <code>createSound()</code> no longer requires an <code>id</code> property. If omitted, a unique <code>id</code> will automatically be generated for the new sound object with a prefix based on the SM2 setup option <code>idPrefix</code>.\r
+ </p>\r
+\r
+ <p>\r
+ Specifying an <code>id</code> is useful if you want to look up the sound via <code>getSoundById()</code> - otherwise, you can simply use the object returned by the <code>createSound()</code> call.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>\r
+ <code>multiShot</code> + <code>multiShotEvents</code> for HTML5 <code>Audio()</code>-based sounds, allowing layered / "chorused" playback if <code>play()</code> is called and <code>multiShot: true</code> has been specified to either <code>createSound()</code> or <code>play()</code>. Behaviour should mimic that of Flash 9. If <code>multiShotEvents: true</code> is specified, <code>onfinish()</code> will fire for each instance. Does not apply to mobile clients (e.g., iOS and Android) which only allow one sound to be played at a time.\r
+ </p>\r
+\r
+ <p>\r
+ Implementation summary: A <code>new Audio(src)</code> instance is created with an <code>onfinish</code> listener, and played immediately. It is unloaded and destroyed when playback finishes.\r
+ </p>\r
+\r
+ <p>\r
+ Caveat #1: If a position argument is provided eg., <code>play({ position: 1000 })</code>, the cloned <code>Audio()</code> instance must wait for a HTML5 <code>canplay</code> event before a seek and playback can begin. This may mean playback *could* have a slight delay vs. playing without the position offset.\r
+ </p>\r
+\r
+ <p>\r
+ Caveat #2: The from/to parameters used for "sound sprites", e.g., <code>{ from: 500, to: 1500 }</code>, are not presently supported under multiShot.\r
+ </p>\r
+\r
+ <p>\r
+ Caveat #3: multiShot is not supported where only a single audio instance can be playing at once, e.g., iOS (iPhone/iPad) and some Android devices.\r
+ </p>\r
+\r
+ <p>\r
+ Secondary instances are "fire-and-forget", similar to the Flash 9 implementation, and fire no events other than <code>onfinish()</code>. They do not respond to position, volume etc. after playback has begun.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <!-- not quite stable/finished yet. -->\r
+ <!--\r
+ <li>\r
+\r
+ <p>\r
+ <b>Experimental</b>: <code>createSound()</code> can be called without a <code>url</code> property, and will work in most cases (excluding old Flash 8-based edge cases of <code>.load({url:...}).play()</code> or <code>.play({url:...})</code>, which didn't work previously anyways.)\r
+ </p>\r
+\r
+ <p>\r
+ Currently, sounds determine their HTML5/Flash requirements at <code>createSound</code> time based on <code>url</code> or <code>type</code>. Some refactoring needs to be done to allow sound objects to dynamically switch between HTML5 + Flash, so omit <code>url</code> with caution. If you intend to play only a particular MIME type and the <code>url</code> is not known in advance, you can specify <code>type</code> to <code>createSound()</code> in the event mixed-mode HTML5/flash switching problems are encountered.\r
+ </p>\r
+\r
+ </li>\r
+ -->\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Remove debug-related <code>complain()</code> calls from -nodebug and minified script builds\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Force data: URLs over to HTML5. Catch unsupported case under 100% HTML5 mode, preventing attempt to use Flash fallback.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Edge case: Fix error case if <code>setup()</code> called without arguments inline, before DOMReady / init etc.\r
+ </p>\r
+ </li>\r
+ \r
+ <li>\r
+ <p>\r
+ Tweak <code>soundManager.getSoundById()</code> to not throw error if ID omitted. Improve language on "not found" messaging.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Warn on possible 32-sound channel Flash ceiling/limit, which can occur when Flash tries to begin playback and fails to start.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Documentation updates: <a href="../technotes/#client-requests">How Clients Download Audio</a> (Flash/HTML5 progressive download vs. byte streaming)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Improved <a href="../../demo/api/">API Examples</a> page design, two-column layout with navigation\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <!-- previously ... -->\r
+\r
+ <li id="sm2-20130324" class="in">\r
+\r
+ <h3><b>V2.97a.20130324</b> - Fix for playlist/event chaining when using <code>flashVersion = 8</code> with Flash Player 11.6.602.171. HTML5 iOS <code>load()</code> fix. Added Opus to audio formats. (<a href="../../download/soundmanagerv297a-20130324.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Flash Player 11.6.602.171, released by Adobe on 02/26/2013, introduced an issue with SM2's default Flash 8 (<code>flashVersion: 8</code>) API-based JS/Flash interaction, where SM2 methods called from callbacks such as <code>onfinish()</code> would not work. This primarily broke methods used for playing sounds in sequence, serially loading a series of sounds and so on. (See <a href="https://getsatisfaction.com/schillmania/topics/recent_chrome_update_seems_to_have_broken_my_sm2_audio_player">discussion</a> for more.)\r
+ </p>\r
+\r
+ <p>\r
+ Note that this does not affect cases where <code>soundManager.setup({ flashVersion: 9})</code> is being used; however, SM2 does use <code>flashVersion: 8</code> by default.\r
+ </p>\r
+\r
+ <p>\r
+ Specifically, Flash-initiated events (such as a sound finishing) make Flash -> JS calls to the SM2 API, which subsequently call user-specified event handlers. If the user-specified SM2 <code>onfinish()</code> handler immediately calls a SM2 method like <code>play()</code> that makes a JS -> Flash call, this call either silently fails or is blocked. Other JS + Flash libraries that use similar callback patterns may also be affected, if their SWF is built targeting the Flash 8 API.\r
+ </p>\r
+\r
+ <p>\r
+ Suspecting a timing or recursion/stack issue, it was found that introducing a <code>setTimeout(callback, 0)</code> to user-specified SM2 callbacks like <code>onfinish()</code> restored sequential/playlist functionality.\r
+ </p>\r
+\r
+ <p>\r
+ Flash Player 11.6.602.180, relased by Adobe on 3/12/2013, exhibits the same behaviour. To avoid additional hacks, SM2 applies this to all Flash 8-based API callbacks regardless of what version of Flash Player is installed. No regressions are anticipated as a result of this change.\r
+ </p>\r
+\r
+ <p>\r
+ Alternately, this issue can be avoided by using <code>soundManager.setup({ flashVersion: 9 })</code> as the Flash 9-based API does not appear to have this problem.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Fix for iOS <code>load()</code> case when using an auto-load and looping pattern (related <a href="https://getsatisfaction.com/schillmania/topics/autoload_on_ipad_loop_error">discussion</a>).\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Added check for Opus (OGG-based audio codec, <code>audio/opus</code>).\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>\r
+ Added documentation for <a href="../technotes/#serving-audio">Serving To Clients</a>, and <a href="../technotes/#mobile-device-limitations">Mobile Device Limitations</a>.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>\r
+ Minor SM2 homepage + documentation CSS tweaks (design)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+\r
+ <p>\r
+ This SM2 release is tagged "Mahalo Edition" to say thank-you, and because some SM2 work was done while on vacation in Hawai'i. Also, some new demo sound recordings from the beach on Kaua'i were added.\r
+ </p>\r
+\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <!-- previously ... -->\r
+\r
+ <li id="sm2-20130101" class="in">\r
+\r
+ <h3><b>V2.97a.20130101</b> - Strict Mode. Android 2.3 HTML5 fixes, cleaner debug output, improved default flashblock handling. Confirmed compatibility with Firefox WMF-based HTML5 MP3 support. New <code>reset()</code> method, <code>reboot()</code> tweaks (<a href="../../download/soundmanagerv297a-20130101.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Reset last URL and load state for "singleton" (global HTML5 audio) case, on iOS + Android <= 2.3 for specific use case - <code>createSound()</code> -> <code>play()</code> -> <code>destruct()</code> -> <code>createSound()</code> -> <code>play()</code> with same URL/parameters.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Fix for Android 2.3 / Nexus 7 - they work better with the singleton HTML5 <code>audio()</code> instance as well, same as iOS, for chained (i.e., playlist-style) playback cases.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>soundManager.setup()</code> now allows <code>html5Test</code> (regular expression, eg. <code>/probably|maybe/i</code>) to be passed. Was previously unrecognized/rejected.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ The SoundManager 2 core API (soundmanager2.js) now runs in Strict Mode, via <code>"use strict";</code>. This is scoped to a closure within soundmanager2.js, and should not cause issues when combined (rolled-up and/or minified) with other JavaScript code.\r
+ </p>\r
+ </li>\r
+\r
+\r
+ <li>\r
+ <p>\r
+ New <code>soundManager.reset()</code> method. Similar to <code>reboot()</code>, but also nukes any registered <code>onready()</code> and related callbacks. Based on pull request from Github user <a href="https://github.com/jabr/soundmanager-rails/commit/d25761145826b73cc0d1209e895699fce9ae8598">jabr</a>. Chaining is now possible too, e.g., <code>soundManager.reset().setup({onready:function(){console.log('reset() complete, reboot OK')}});</code>. Call <code>soundManager.beginDelayedInit()</code> to re-init after a <code>reset()</code>.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>soundManager.setup({url:...})</code> + lazy-loading (dynamically-loaded JS) case: If <code>setup()</code> given a <code>url</code> parameter after <code>DOMContentLoaded</code> has fired, assume we should start right away. (Helps reduce need for <code>beginDelayedInit()</code> + "just works" for most users).\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Don't init inline after <code>document.readyState === 'complete'</code> (improve lazy-loading case, wait for <code>setup()</code> with <code>url</code> instead).\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>\r
+ Prerelease Firefox builds can play MP3 audio via HTML5 in some cases, as part of a move to support H.264 video (see <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=799318">Bugzilla #799318</a> for details). Firefox 20 (nightlies, and Aurora channel builds in January 2013) can get native MP3 support via Windows Media Foundation (OS-level codec support) components on Windows 8, Windows 7, and <a href="http://news.ycombinator.com/item?id=4944080">soon</a>, Windows Vista. As of 12/2012, OS X support <a href="http://news.ycombinator.com/item?id=4945149">is planned</a>, and Windows XP support <a href="http://news.ycombinator.com/item?id=4944080">is not</a>. <span class="sidenote">(Disclaimer: Vista, OS X and XP notes sourced from comments on Hacker News; see links).</span>\r
+ </p>\r
+\r
+ <p>\r
+ When enabled with <code>media.windows-media-foundation.enabled = true</code> under <code>about:config</code>, Firefox may be able to play MP3s via HTML5 and thus get "100% HTML5 mode" when <code>soundManager.setup({preferFlash: false})</code> is used.\r
+ </p>\r
+\r
+ <p>\r
+ At time of writing (12/30/2012), Firefox 20 (nightly) returns <code>""</code> for <code>canPlayType('audio/mpeg; codecs="mp3"')</code>, a test commonly used to query for MP3 support under HTML5 and one which works in other modern browsers. Firefox's behaviour differs because it is trying to follow the MPEG spec, which does not include an explicit MP3 MIME type. Instead, <code>canPlayType('audio/mpeg')</code>, which is in-spec, presently returns a "maybe" when MP3 is supported under Firefox.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Improved SM2 <code>console.log()</code> debug output, aiming to be less "noisy". Core setup options are shown better at start-up, eg. "SoundManager V2.97a.20130101 (AS3/Flash 9) + HTML5 audio + preferFlash + html5PollingInterval (50ms) + flashBlock".\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Christmas light demo: Tweaks for iOS + Android touch devices.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ MP3 Player Button demo: Include HTML <code>type</code> (MIME hint) attribute, if specified.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li id="sm2-20121104" class="in">\r
+\r
+ <h3><b>V2.97a.20121104</b> - HTML5 + iOS load fixes, Windows 8 App Store compatibility tweak, code pattern improvements (<a href="../../download/soundmanagerv297a-20121104.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Fix HTML5 <code>unload()</code> -> <code>play()</code> case (re-use of same object without assigning new URL).\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ More global (iOS) HTML5 object <code>unload()</code> / <code>play()</code> re-use tweaks, improved handling of re-use and empty / <code>load()</code> cases\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Ensure <code>instanceOptions</code> are set after <code>play()</code> call results in <code>load()</code>. Noted <code>instanceOptions</code> not being set from within <code>whileplaying()</code>.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix call signature for Flash 8 load method, was tying <code>usePolicyFile</code> (enables remote crossdomain.xml request for ID3/waveform data on 3rd-party domains) to precence of <code>whileloading()</code> due to driver error. Derp. :D\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Windows 8 Store Apps (IE 10/"MSAppHost" in UA) don't support Flash or ActiveX, except for (at time of writing), three special ActiveX controls. Thus, <code>new window.ActiveXObject('ShockwaveFlash.ShockwaveFlash')</code> seems to work without error. However, an error is thrown if an <code><object></code> with a Flash ActiveX CLSID is appended to the DOM. http://msdn.microsoft.com/en-us/library/windows/apps/hh465143.aspx\r
+ </p>\r
+ </li>\r
+\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Death to underscores! Removed legacy pattern of <code>var _foo = ...</code> for most private internals.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Better <code>typeof x === 'undefined'</code> -> <code>x === undefined</code> pattern per newer jslint rules.\r
+ </p>\r
+ </li>\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li id="sm2-20120916" class="in">\r
+\r
+ <h3><b>V2.97a.20120916</b> - Inline, deferred and lazy-load init improvements, HTML5 format / detection improvements, "re-use" load/play URL fix. (<a href="../../download/soundmanagerv297a-20120916.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API Updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Init improvement: Don't fail if Flash URL is null in normal include + init case. Instead, show note in debug input and wait for <code>soundManager.setup()</code> with <code>url</code> param, then treat as delayed init case. Improved experience if including <code><script></code>, then trying to do <code>setup()</code> after DOM Ready (common jQuery case).\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>soundManager.setup({url:...})</code> + lazy-loading (dynamically-loaded JS) case: If <code>setup()</code> given url parameter after DOMContentLoaded has fired, assume we should start right away. (Helps reduce need for <code>beginDelayedInit()</code> + "just works" for most users)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Don't init inline after <code>document.readyState === 'complete'</code> (improve lazy-loading case, wait for setup() with url: instead)\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Fix <code>'audio/mpeg'</code> <code>canPlay()</code> checks, was incorrectly returning false due to <code>audio/mpeg; codecs="mp3"</code> working and preventing <code>audio/mpeg</code> from being checked.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ More paranoid <code>Audio()</code> handling for "bad" Opera (< 10) where <code>new Audio()</code> would throw not_enough_arguments (always required URL).\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Safer HTML5 duration checks - null now assigned instead of undefined.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Improve durationEstimate under HTML5 during <code>whileloading()</code>.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Flash 9/RTMP: Actually provide caption data to <code>oncaptiondata()</code>.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix <code>SMSound.play({url:...})</code> "re-use" case where new URL wasn't being assigned + loaded right away, and <code>SMSound.url</code> property was not being updated.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Correct <code>load()</code> and play() with new URL parameter, so that subsequent <code>play()</code> call uses new URL (and not URL assigned with original <code>createSound()</code> call).\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Use seconds for <code>SMSound.buffered</code> (time ranges) whether HTML5 or Flash, since SM2 API uses seconds for <code>setPosition()</code> etc.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Correct <code>play()</code> -> <code>pause()</code> -> <code>setPosition(0)</code> -> <code>play()</code> -> <code>pause()</code> case where the latter wasn't firing due to invalid state.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ New Cassette Tape UI Prototype/demo (experimental).\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Tweaked documentation layout for legibility. Webfont (deja vu sans mono) from <a href="http://dejavu-fonts.org/" title="Deja Vu Fonts">dejavu-fonts.org</a> for code examples.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Improved lazy-load / deferred example based on new <code>setup()</code> logic\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added SMSound.buffered documentation\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added m4b extension as an mp4 format\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Safer initial HTML5 support checks\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <!-- previously ... -->\r
+\r
+ <li id="sm2-20120624" class="in">\r
+\r
+ <h3><b>V2.97a.20120624</b> - New <code>soundManager.setup()</code> method, numerous HTML5 improvements for <code>createSound()</code>, <code>load()</code>, progress and reuse cases, and minor flash audio bug fixes (<a href="../../download/soundmanagerv297a-20120624.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API: New sugar-like stuff</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+\r
+ <p>\r
+ New <code>soundManager.setup()</code> mixin-style method for assigning properties and common start-up callbacks. Collects top-level soundManager configuration properties and object collections - <code>onready</code>, <code>ontimeout</code>, <code>defaultOptions</code>, <code>flash9Options</code> and <code>movieStarOptions</code> - under a single method call.\r
+ </p>\r
+ <p>\r
+ <b>Upgrade / legacy note:</b> This is a modern replacement for the direct property assignment method used in all previous versions - eg., <code>soundManager.url = '/swfs/'</code> - the old method continues to work for legacy support, but you should migrate to using the new method as it's much cleaner. All included demos use the new method where applicable.\r
+ </p>\r
+\r
+ <p>\r
+ <b>New <code>soundManager.setup()</code> method example</b>\r
+ </p>\r
+\r
+<pre class="block"><code>soundManager.setup({\r
+ <span><span>// required</span></span>\r
+ url: <span>'/path/to/swfs/'</span>,\r
+ <span><span>// optional</span></span>\r
+ flashVersion: <span>9</span>,\r
+ <span><span>// convenience</span></span>\r
+ onready: function() {\r
+ <span>console.log('Ready to play sound!');</span>\r
+ },\r
+ ontimeout: function() {\r
+ <span>console.log('SM2 start-up failed.');</span>\r
+ },\r
+ <span><span>// more custom parameters</span></span>\r
+ defaultOptions: {\r
+ <span>volume: 50</span>\r
+ }\r
+});</code></pre>\r
+\r
+ <p>\r
+ See <a href="../#soundmanager-setup" title="soundManager.setup() method documentation">soundManager.setup()</a> for details.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Improve HTML5 audio load/playback reliability + stability on iOS, and for object reuse cases (<code>play()</code> -> <code>load({url: ...})</code>. Prior behaviour was making initial HTTP request when object was created (meta/preload, not necessarily loading entire file.) Request now only happens with preload/load/play-related calls.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ HTML5: Firefox seems to have changed when unloading HTML5 audio, <code>url = ''</code> now loads hosting page HTML (boo) instead of <code>null</code> / no request. Changed to <code>about:blank</code> like everyone else. Also fixed boolean logic on <code>isMovieStar</code> assignment.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Add <code>audio/mp3</code> and related MIME checks for flash, correct edge case where <code>play({type:'audio/mp3'})</code> would use HTML5 when <code>preferFlash = true</code>, due to seeming lack of Flash support for the MIME type.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fixed old Flash 8 <code>onload()</code> edge case where loading from cache might return incorrect <code>didLoad: false</code> result - corrected by checking for a non-zero sound duration.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Properly reset <code>SMSound.id3 = {}</code> with internal resetProperty and public methods like <code>load()</code>.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Edge case fix: Don't attempt to remove flash unless reference exists (prevent false warning when <code>reboot()</code> called in 100% HTML5 mode.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Correct empty options JS error on internal <code>_setup_html5()</code> when reusing HTML5 audio object per <a href="https://getsatisfaction.com/schillmania/topics/possible_bug_when_html5_audio_tag_is_reused_20120527_release">V2.97a.20120527 bug report</a>\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix minor false positive (undocumented error handler case) with HTML5 <code>play()</code> falsely reporting 32-sound ceiling edge case and calling <code>SMSound.onplayerror()</code> (if assigned) when using flashVersion = 9. Should only apply when flash 9 is being used for playback, and ceiling hit.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Finally assign + use <code>SMSound.id</code> (instead of sID), matching <code>createSound({id: 'foo'})</code> pattern; maintain legacy sID property (ancient behaviour, originally intended to avoid potential namespace conflicts many years ago - now silly and not a concern.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Improved handling of <code>whileloading()</code> vs. HTML5 <code>onload</code> (when using HTTP range/partial requests).\r
+ </p>\r
+ <p>\r
+ HTML5 <code>onload()</code> (now triggered via native <code>canplaythrough</code> event) may fire early, followed by numerous HTML5 <code>progress</code> requests during playback as the audio object requests and buffers more audio ranges (eg., 0-10 seconds), eventually matching the total sound duration.\r
+ </p>\r
+ <p>\r
+ Bytes loaded / total are not available, so bytesLoaded instead reflects a fraction of "duration loaded", between 0 and 1 as data is buffered in. Previously, <code>whileloading</code> events would not fire once <code>onload</code> had fired under HTML5.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ New (undocumented, for now) <code>buffered</code> array on SMSound objects; list of objects following the pattern <code>SMSound.buffered = [{ start: 0, end: 706 }]</code> representing loaded time ranges (somewhat similar to HTML5 TimeRanges spec, but using static properties instead of method calls with an index parameter.) Array will initially be empty, zero-length. This can be looped through to show overlays of "loaded" time fragments on progress bars, for example.</p>\r
+ <p>SMSound <code>buffered</code> is updated during <code>whileloading()</code> calls, where values are provided by the browser. For flash, will always be one item with <code>{ start: 0, end: SMSound.duration }</code> assigned. Also stopped sending 1/1 values to <code>whileplaying()</code> at <code>onload()</code>, since HTML5 can fire <code>onload()</code> (via <code>canplaythrough</code>) very early followed by many progress (<code>whileloading()</code>) events.\r
+ </p>\r
+ <p>\r
+ <b>Support note:</b> Not all browsers (eg., Safari 5.1.7) appear to provide buffer / TimeRanges data for HTML5 audio objects. At time of writing (06/2012), Firefox, Chrome Canary, IE 9 and Opera provide TimeRanges alongside progress events.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Upgraded demos to use to <code>soundManager.setup({...})</code> for most configuration cases (vs. setting <code>soundManager.url</code>, <code>soundManager.defaultOptions.autoLoad</code> directly etc.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Warn if <code>soundManager.setup()</code> called with <code>url</code> or <code>flashVersion</code>, and init has already fired (ie., flash options already set + movie already loaded) where changes will not take effect until <code>soundManager.reboot()</code>.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Assign top-level soundManager properties (eg. <code>soundManager.url</code>) from <code>soundManager.setupOptions</code> at <code>DOMReady</code> time; this allows legacy <code>soundManager.url = ...</code> assignment to work, and helps to ensure legacy-style, directly-assigned top-level property values get written back to <code>soundManager.setupOptions</code>.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <!-- previously ... -->\r
+\r
+ <li id="sm2-20120527" class="in">\r
+\r
+ <h3><b>V2.97a.20120527</b> - Fix for <code>ontimeout()</code> regression. GWT/JSNI compatibility, slow connection and Safari "background tab" SWF load handling improvements (<a href="../../download/soundmanagerv297a-20120527.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Fix for <code>ontimeout()</code> regression seen when using lazy-loading / SM2_DEFER introduced with V2.97a.20120513; bug introduced when making edits to pass newer jslint rules regarding <code>return</code> within <code>if...else</code> blocks.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Replaced <code>instanceof Function</code> with "safer" <code>typeof x === 'function'</code> for <code>onready()</code>, <code>ontimeout()</code> and related callback argument checks as GWT + JSNI was passing arguments that failed the <code>instanceof</code> check. (Related <a href="https://getsatisfaction.com/schillmania/topics/gwt_jsni_problems_with_onready_and_ontimeout-ucvp8">bug report</a>.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Corrected another small regression for the <code>ontimeout()</code> -> <code>onready()</code> "recovery" edge case, ensuring "ready" does not fire after a timeout when init was unsuccessful.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+\r
+ <li>\r
+ <p>\r
+ Improved handling for special Safari page load case: When a new tab is opened that does not have focus, the Flash SWF does not load/init until the tab is brought to the foreground. SM2 now recognizes this special case and waits until <code>window.onfocus()</code> before attempting to do the JS/Flash part of init. Previously, it would fail with a timeout.\r
+ </p>\r
+ <p>\r
+ Code written to originally handle Safari 3.1, which did not support <code>document.hasFocus()</code>, was modified and updated for this purpose. The Safari 3.1 logic previously deferred SM2's start-up in a similar fashion. (The old Safari 3.1 <code>mousemove()</code> focus-detection hack has been removed as Safari 4 has been out since mid-2009, and Safari 5 since mid-2010.)\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ SM2 init process will now delay and retry if no Flash response, and SWF has loaded > 0 and < 100%. Timeout will now happen only after delay and when SWF has loaded 100%. Should help prevent first-visit (non-cached) failure on very slow or laggy connections.\r
+ </p>\r
+\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added note about potential Firefox regression: Offline JS/Flash start-up (viewing HTML pages via <code>file://</code> and/or <code>c:/</code> and so forth), possibly not working as of Firefox 9 and newer (at time of writing, also up to and including Firefox 12), even despite special security whitelisting under Flash Player "trusted locations" preferences / control panel.\r
+ </p>\r
+ <p>\r
+ After successful Flash -> JS call, SM2's "return" JS -> Flash call fails with unusual JS/Flash exception, "Error in ActionScript" error with no further detail. Offline viewing still works in other browsers.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+<!-- previously.. -->\r
+\r
+ <li id="sm2-20120513" class="in">\r
+\r
+ <h3><b>V2.97a.20120513</b> - Fixes for Android 2.3 playback, <code>onPosition()</code> in HTML5, Flash 9 double-play edge case. Minor new Flash 9-specific features (<a href="../../download/soundmanagerv297a-20120513.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Android 2.3 playback fix (some sounds started only after 2+ play attempts due to Android not liking <code>load()</code> immediately followed by <code>play()</code>?)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>onPosition()</code> fix for HTML5 playback, items were mistakenly being removed.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix RTMP stream duration reporting via <code>onmetadata()</code> (wrong value was being returned, previously.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix for Flash 9 <a href="https://getsatisfaction.com/schillmania/topics/sound_playing_double">double-play edge case</a> found with <code>pause()</code> + <code>setPosition()</code> calls.\r
+ </p>\r
+ </li>\r
+\r
+\r
+ <li>\r
+ <p>\r
+ JSLINT validation per 04-15-2012 edition rules, mostly removal of multiple return statements within <code>if ... else</code> blocks and inverted loop tricks.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">API updates</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Enabled waveform/eq/spectrum data features for MovieStar (H.264/NetStream content.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added <code>oncaptiondata()</code> callback for caption data from Flash 9 (NetStream/RTMP-only, similar to <code>onmetadata()</code>. Contributor: GitHub user <a href="https://github.com/scottschiller/SoundManager2/pull/19">karma</a>.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added <code>SMSound.onplayerror()</code>, presently for Flash 9 (non-MovieStar/NetStream) which can detect lack of available sound hardware or 32-channel ceiling as reasons for playback failure.\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Added <code>oncaptiondata()</code> callback for caption data from Flash 9 (NetStream/RTMP-only, similar to <code>onmetadata()</code>.)\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Scaling added to 360 UI (via GitHub user <a href="https://github.com/scottschiller/SoundManager2/commit/dbc6c46e4904e204add961c7f9fb127d66447242">tomasdev</a>)\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+<!-- previously.. -->\r
+\r
+ <li id="sm2-20120318" class="in">\r
+\r
+ <h3><b>V2.97a.20120318</b> - Minor updates. <code>from</code> / <code>to</code> and <code>onplay()</code> bug fixes, <code>canPlayMIME()</code> and <code>canPlayLink()</code> Flash-specific corrections. (<a href="../../download/soundmanagerv297a-20120318.zip" class="norewrite">Download archived version</a>)</h3>\r
+\r
+ <ul>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Bug fixes</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ Fix silly <code>undefined"soundID"</code> debug output message shown at <code>SMSound.onload</code> (now says <code>SMSound._onload()</code> as previously.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ <code>soundManager.sounds = {}</code> instead of <code>[]</code> on reboot (per <a href="http://getsatisfaction.com/schillmania/topics/possible_bug_in_reboot">bug report</a>)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix logic for calling <code>onplay()</code>, was always non-truthy. D'oh!\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Add missing <code>typeof</code> to fix html5 MIME check for playability tests\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Don't apply <code>width:auto</code> to SWF (invalid per HTML5, allegedly: Related <a href="https://github.com/grEvenX/SoundManager2/commit/6f30fb600598d8618efec2a010ba1a69c5b75694">patch</a>.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Make <code>soundManager.canPlayMIME()</code> and <code>canPlayLink()</code> check flash support before returning (check after <code>ontimeout()</code> was returning truthy when flash required under Firefox, for example, for <code>'audio/mp3'</code>)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Fix <code>play()</code> "<code>from</code>" + "<code>to</code>" sound sprite playback issue: In some cases, previously-fired "to" events were re-firing due to not being removed, because an equality check was comparing against a potential "to" value of a string rather than a number. (eg., 0-700 followed by 1500-2000; playback would stop in second case, saying 700 had been reached. (Related <a href="https://getsatisfaction.com/schillmania/topics/_from_to_problem_argument_for_to_is_not_updated">bug report</a>.)\r
+ </p>\r
+ </li>\r
+\r
+ <li>\r
+ <p>\r
+ Re-appeased the jslint gods, removed unused variables and two-statement reverse loop <code>(for i=x; i--;) { }</code> trickery.\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li class="in">\r
+\r
+ <p class="compact">Miscellaneous</p>\r
+\r
+ <ul class="nested compact flat">\r
+\r
+ <li>\r
+ <p>\r
+ The SoundManager project turned 10 years old, having originally launched in late 2001. Thanks for using it!\r
+ </p>\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+ </li>\r
+\r
+<!-- previously... -->\r
+\r
+ <li id="sm2-archives" class="in">\r
+\r
+ <h3>Older Release Info</h3>\r
+ <p>For release and changelog history going back to 2010, see the <a href="archive.html" title="SoundManager 2: Archived releases">archive</a> page.</p>\r
+\r
+ </li>\r
+\r
+ </ul>\r
+\r
+\r
+ </div>\r
+\r
+ \r
+ </div>\r
+\r
+\r
+ </div>\r
+ \r
+\r
+ </div>\r
+\r
+\r
+ \r
+ <div id="col3" class="c3">\r
+\r
+ <div id="support-wrapper">\r
+ <div id="get-satisfaction" class="box">\r
+ <div id="gsfn_list_widget">\r
+ <h2><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/" title="User discussion, FAQs and support for SoundManager 2" rel="nofollow">Discussion / Support</a><span class="l"></span><span class="r"></span></h2>\r
+ <div id="gsfn_content"></div>\r
+ <div class="powered_by"><a href="http://getsatisfaction.com/" rel="nofollow">Get Satisfaction support network</a></div>\r
+ </div>\r
+ <!-- /.box -->\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="shortcuts">\r
+\r
+<!--\r
+ <div class="box">\r
+\r
+ <h2>Shortcuts<span class="l"></span><span class="r"></span></h2>\r
+\r
+ <ul class="first">\r
+ <li onclick="setFilter(event,'c-')" class="ignore">\r
+\r
+ <ul>\r
+\r
+ <li>Demos</li>\r
+ <li>Getting Started</li>\r
+ <li>Basic Use</li>\r
+ <li>Download</li>\r
+ <li>Requirements</li>\r
+ <li>Limitations</li>\r
+\r
+ <li>Debug Output</li>\r
+ <li>Revision History</li>\r
+ <li>About</li>\r
+ </ul>\r
+\r
+ </li>\r
+ </ul>\r
+\r
+ </div>\r
+-->\r
+\r
+ </div>\r
+ \r
+ <div class="clear"></div>\r
+\r
+ <!-- /main -->\r
+ </div>\r
+\r
+ <!-- /main-wrapper -->\r
+ </div>\r
+\r
+ <!-- /content -->\r
+ </div>\r
+\r
+<script type="text/javascript">\r
+init();\r
+</script>\r
+ \r
+</body>\r
+\r
+</html>\r
--- /dev/null
+<!DOCTYPE html>
+
+<html>
+<head>
+ <title>SoundManager2_AS.as</title>
+<meta name="robots" content="noindex" />
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
+ <link rel="stylesheet" media="all" href="docco.css" />
+</head>
+<body>
+ <div id="container">
+ <div id="background"></div>
+
+ <ul id="jump_to">
+ <li>
+ <a class="large" href="javascript:void(0);">Jump To …</a>
+ <a class="small" href="javascript:void(0);">+</a>
+ <div id="jump_wrapper">
+ <div id="jump_page">
+
+
+ <a class="source" href="soundmanager2.html">
+ soundmanager2.js
+ </a>
+
+
+ <a class="source" href="SoundManager2_AS.html">
+ SoundManager2_AS.as
+ </a>
+
+
+ <a class="source" href="SoundManager2_AS3.html">
+ SoundManager2_AS3.as
+ </a>
+
+
+ <a class="source" href="SoundManager2_SMSound_AS3.html">
+ SoundManager2_SMSound_AS3.as
+ </a>
+
+ </div>
+ </li>
+ </ul>
+
+ <ul class="sections">
+
+ <li id="title">
+ <div class="annotation">
+ <h1>SoundManager2_AS.as</h1>
+ </div>
+ </li>
+
+
+
+ <li id="section-1">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-1">¶</a>
+ </div>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre><span class="comment">/**\r
+ * SoundManager 2: Javascript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code licensed under the BSD License:\r
+ * http://www.schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * Flash 8 / ActionScript 2 version\r
+ *\r
+ * Compiling AS to Flash 8 SWF using MTASC (free compiler - http://www.mtasc.org/):\r
+ * mtasc -swf soundmanager2.swf -main -header 16:16:30 SoundManager2.as -version 8\r
+ *\r
+ * ActionScript Sound class reference (Macromedia), documentation download:\r
+ * http://livedocs.macromedia.com/flash/8/\r
+ * Previously-live URL:\r
+ * http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002668.html\r
+ *\r
+ * *** NOTE ON LOCAL FILE SYSTEM ACCESS ***\r
+ *\r
+ * Flash security allows local OR network access, but not both\r
+ * unless explicitly whitelisted/allowed by the flash player's\r
+ * security settings.\r
+ *\r
+ * To enable in-flash messaging for troubleshooting, pass debug=1 in FlashVars (within object/embed code)\r
+ * SM2 will do this by default when soundManager.debugFlash = true.\r
+ *\r
+ */</span>\r
+\r
+<span class="preprocessor"><span class="keyword">import</span> flash.external.ExternalInterface;</span> <span class="comment">// woo</span>\r
+\r
+<span class="class"><span class="keyword">class</span> <span class="title">SoundManager2</span> {</span>\r
+\r
+ <span class="keyword">static</span> <span class="keyword">var</span> app: SoundManager2;\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">SoundManager2</span><span class="params">()</span> {</span>\r
+\r
+ <span class="keyword">var</span> version = <span class="string">"V2.97a.20150601"</span>;\r
+ <span class="keyword">var</span> version_as = <span class="string">"(AS2/Flash 8)"</span>;\r
+\r
+ <span class="comment">/**\r
+ * Cross-domain security options\r
+ * HTML on foo.com loading .swf hosted on bar.com? Define your "HTML domain" here to allow JS+Flash communication to work.\r
+ * // allow_xdomain_scripting = true;\r
+ * // xdomain = "foo.com";\r
+ * For all domains (possible security risk?), use xdomain = "*"; which ends up as System.security.allowDomain("*");\r
+ * When loading from HTTPS, use System.security.allowInsecureDomain();\r
+ * See "allowDomain (security.allowDomain method)" in Flash 8/AS2 liveDocs documentation (AS2 reference -> classes -> security)\r
+ * download from http://livedocs.macromedia.com/flash/8/\r
+ * Related AS3 documentation: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/Security.html#allowDomain%28%29\r
+ */</span>\r
+\r
+ <span class="keyword">var</span> allow_xdomain_scripting = <span class="literal">false</span>;\r
+ <span class="keyword">var</span> xdomain = <span class="string">"*"</span>;\r
+\r
+ <span class="keyword">if</span> (allow_xdomain_scripting && xdomain) {\r
+ System.security.allowDomain(xdomain);\r
+ version_as += <span class="string">' - cross-domain enabled'</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-2">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-2">¶</a>
+ </div>
+ <p>externalInterface references (for Javascript callbacks)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> baseJSController = <span class="string">"soundManager"</span>;\r
+ <span class="keyword">var</span> baseJSObject = baseJSController + <span class="string">".sounds"</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-3">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-3">¶</a>
+ </div>
+ <p>internal objects</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> sounds = []; <span class="comment">// indexed string array</span>\r
+ <span class="keyword">var</span> soundObjects = []; <span class="comment">// associative Sound() object array</span>\r
+ <span class="keyword">var</span> timer = <span class="literal">null</span>;\r
+ <span class="keyword">var</span> pollingEnabled = <span class="literal">false</span>; <span class="comment">// polling (timer) flag - disabled by default, enabled by JS->Flash call</span>\r
+ <span class="keyword">var</span> debugEnabled = <span class="literal">true</span>; <span class="comment">// Flash debug output enabled by default, disabled by JS call</span>\r
+ <span class="keyword">var</span> flashDebugEnabled = <span class="literal">false</span>; <span class="comment">// debug output to flash movie, off by default</span>\r
+ <span class="keyword">var</span> didSandboxMessage = <span class="literal">false</span>;\r
+ <span class="keyword">var</span> caughtFatal = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-4">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-4">¶</a>
+ </div>
+ <p>for flash text output, debugging etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> _messages = [];\r
+ <span class="keyword">var</span> _messageObj = <span class="literal">null</span>;\r
+ flashDebugEnabled = (_root.debug == <span class="number">1</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-5">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-5">¶</a>
+ </div>
+ <p>display stuffs</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> Stage.scaleMode = <span class="string">'noScale'</span>;\r
+ Stage.align = <span class="string">'TL'</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-6">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-6">¶</a>
+ </div>
+ <p>context menu item with version info</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> doNothing = <span class="keyword">function</span>() {}\r
+\r
+ <span class="keyword">var</span> sm2Menu:ContextMenu = <span class="keyword">new</span> ContextMenu();\r
+ <span class="keyword">var</span> sm2MenuItem:ContextMenuItem = <span class="keyword">new</span> ContextMenuItem(<span class="string">'SoundManager '</span> + version + <span class="string">' '</span> + version_as, doNothing);\r
+ sm2MenuItem.enabled = <span class="literal">false</span>;\r
+ sm2Menu.customItems.push(sm2MenuItem);\r
+ _root.menu = sm2Menu;\r
+\r
+ <span class="keyword">var</span> writeDebug = <span class="keyword">function</span>(s, logLevel) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-7">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-7">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!debugEnabled) <span class="keyword">return</span> <span class="literal">false</span>;\r
+ ExternalInterface.call(baseJSController + <span class="string">"['_writeDebug']"</span>, <span class="string">"(Flash): "</span> + s, (logLevel || <span class="number">0</span>));</pre></div></div>
+
+ </li>
+
+
+ <li id="section-8">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-8">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+\r
+ <span class="keyword">var</span> flashDebug = <span class="keyword">function</span>(messageText) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-9">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-9">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> _messages.push(messageText);\r
+ <span class="keyword">if</span> (!flashDebugEnabled) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">var</span> sans = <span class="keyword">new</span> TextFormat();\r
+ sans.size = <span class="number">12</span>;\r
+ sans.font = <span class="string">"Arial"</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-10">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-10">¶</a>
+ </div>
+ <p>320x240 if no stage dimensions (happens in IE, apparently 0 before stage resize event fires.)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> w = Stage.width?Stage.width:<span class="number">320</span>;\r
+ <span class="keyword">var</span> h = Stage.height?Stage.height:<span class="number">240</span>;\r
+ <span class="keyword">if</span> (!_messageObj) {\r
+ _messageObj = _root.createTextField(<span class="string">"_messageObj"</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, w, h);\r
+ _messageObj.x = <span class="number">0</span>;\r
+ _messageObj.y = <span class="number">0</span>;\r
+ _messageObj.multiline = <span class="literal">true</span>;\r
+ _messageObj.html = <span class="literal">true</span>;\r
+ _messageObj.wordWrap = <span class="literal">true</span>;\r
+ _messageObj.align = <span class="string">'left'</span>;\r
+ _messageObj.autoSize = <span class="literal">false</span>;\r
+ }\r
+ _messageObj.htmlText = _messages.join(<span class="string">'\n'</span>);\r
+ _messageObj.setTextFormat(sans);\r
+ _messageObj.width = w;\r
+ _messageObj.height = h;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-11">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-11">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+\r
+ <span class="keyword">var</span> _externalInterfaceTest = <span class="keyword">function</span>(isFirstCall) {\r
+ <span class="keyword">var</span> sandboxType = System.security[<span class="string">'sandboxType'</span>];\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">if</span> (isFirstCall) {\r
+ flashDebug(<span class="string">'Testing Flash -&gt; JS...'</span>)\r
+ <span class="keyword">if</span> (!didSandboxMessage && sandboxType != <span class="string">'remote'</span> && sandboxType != <span class="string">'localTrusted'</span>) {\r
+ didSandboxMessage = <span class="literal">true</span>;\r
+ flashDebug(<span class="string">'<br><b>Fatal: Security sandbox error: Got "'</span> + sandboxType + <span class="string">'", expected "remote" or "localTrusted".<br>Additional security permissions need to be granted.<br>See <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html">flash security settings panel</a> for non-HTTP, eg. file:// use.</b><br>http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html<br><br>You may also be able to right-click this movie and choose from the menu: <br>"Global Settings" -> "Advanced" tab -> "Trusted Location Settings"<br>'</span>);\r
+ }\r
+ ExternalInterface.call(baseJSController + <span class="string">"._externalInterfaceOK"</span>, version);\r
+ <span class="keyword">if</span> (!didSandboxMessage) {\r
+ flashDebug(<span class="string">'Flash -&gt; JS OK'</span>);\r
+ flashDebug(<span class="string">'Waiting for JS -&gt; Flash...'</span>);\r
+ }\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-12">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-12">¶</a>
+ </div>
+ <p>writeDebug('SM2 SWF ' + version + ' ' + version_as, 1);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSController + <span class="string">"._setSandboxType"</span>, sandboxType);\r
+ flashDebug(<span class="string">'JS -&gt; Flash OK'</span>);\r
+ }\r
+ } <span class="keyword">catch</span>(e) {\r
+ flashDebug(e.toString());\r
+ <span class="keyword">if</span> (!caughtFatal) {\r
+ caughtFatal = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> <span class="literal">true</span>; <span class="comment">// to verify that a call from JS to here, works. (eg. JS receives "true", thus OK.)</span>\r
+ }\r
+\r
+ <span class="keyword">var</span> _disableDebug = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-13">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-13">¶</a>
+ </div>
+ <p>prevent future debug calls from Flash going to client (maybe improve performance)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">'_disableDebug()'</span>);\r
+ debugEnabled = <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> checkProgress = <span class="keyword">function</span>() {\r
+ <span class="keyword">var</span> bL = <span class="number">0</span>;\r
+ <span class="keyword">var</span> bT = <span class="number">0</span>;\r
+ <span class="keyword">var</span> nD = <span class="number">0</span>;\r
+ <span class="keyword">var</span> nP = <span class="number">0</span>;\r
+ <span class="keyword">var</span> oSound = <span class="literal">null</span>;\r
+ <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, j = sounds.length; i < j; i++) {\r
+ oSound = soundObjects[sounds[i]];\r
+ bL = oSound.getBytesLoaded();\r
+ bT = oSound.getBytesTotal();\r
+ nD = oSound.duration || <span class="number">0</span>; <span class="comment">// can sometimes be null with short MP3s? Wack.</span>\r
+ nP = oSound.position;\r
+ <span class="keyword">if</span> (bL && bT && bL != oSound.lastValues.bytes) {\r
+ oSound.lastValues.bytes = bL;\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._whileloading"</span>, bL, bT, nD);\r
+ }\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> nP != <span class="string">'undefined'</span> && nP != oSound.lastValues.position) {\r
+ oSound.lastValues.position = nP;\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._whileplaying"</span>, nP);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-14">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-14">¶</a>
+ </div>
+ <p>if position changed, check for near-end</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+ }\r
+ }\r
+\r
+ <span class="keyword">var</span> onLoad = <span class="keyword">function</span>(bSuccess) {\r
+ checkProgress(); <span class="comment">// ensure progress stats are up-to-date</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-15">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-15">¶</a>
+ </div>
+ <p>force duration update (doesn't seem to be always accurate)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._whileloading"</span>, <span class="keyword">this</span>.getBytesLoaded(), <span class="keyword">this</span>.getBytesTotal(), <span class="keyword">this</span>.duration);\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onload"</span>, <span class="keyword">this</span>.duration > <span class="number">0</span> ? <span class="number">1</span> : <span class="number">0</span>); <span class="comment">// bSuccess doesn't always seem to work, so check MP3 duration instead.</span>\r
+ }\r
+\r
+ <span class="keyword">var</span> onID3 = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-16">
+ <div class="annotation">
+
+ <div class="pilwrap for-h2">
+ <a class="pilcrow" href="#section-16">¶</a>
+ </div>
+ <h2>--- NOTE: BUGGY? ---</h2>
+<p>TODO: Investigate holes in ID3 parsing - for some reason, Album will be populated with Date if empty and date is provided. (?)
+ID3V1 seem to parse OK, but "holes" / blanks in ID3V2 data seem to get messed up (eg. missing album gets filled with date.)
+iTunes issues: onID3 was not called with a test MP3 encoded with iTunes 7.01, and what appeared to be valid ID3V2 data.
+May be related to thumbnails for album art included in MP3 file by iTunes. See <a href="http://mabblog.com/blog/?p=33">http://mabblog.com/blog/?p=33</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> id3Data = [];\r
+ <span class="keyword">var</span> id3Props = [];\r
+ <span class="keyword">for</span> (<span class="keyword">var</span> prop <span class="keyword">in</span> <span class="keyword">this</span>.id3) {\r
+ id3Props.push(prop);\r
+ id3Data.push(<span class="keyword">this</span>.id3[prop]);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-17">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-17">¶</a>
+ </div>
+ <p>writeDebug('id3['+prop+']: '+this.id3[prop]);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onid3"</span>, id3Props, id3Data);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-18">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-18">¶</a>
+ </div>
+ <p>unhook own event handler, prevent second call (can fire twice as data is received - ID3V2 at beginning, ID3V1 at end.)
+Therefore if ID3V2 data is received, ID3V1 is ignored.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> soundObjects[<span class="keyword">this</span>.sID].onID3 = <span class="literal">null</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> registerOnComplete = <span class="keyword">function</span>(sID) {\r
+ soundObjects[sID].onSoundComplete = <span class="keyword">function</span>() {\r
+ checkProgress();\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + sID + <span class="string">"']._onfinish"</span>);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">var</span> _setPosition = <span class="keyword">function</span>(sID, nSecOffset, isPaused, _allowMultiShot) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-19">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-19">¶</a>
+ </div>
+ <p>note: multiShot is Flash 9-only; retained so JS/Flash function signatures are identical.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> s = soundObjects[sID];</pre></div></div>
+
+ </li>
+
+
+ <li id="section-20">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-20">¶</a>
+ </div>
+ <p>writeDebug('_setPosition()');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.lastValues.position = s.position;\r
+ <span class="keyword">if</span> (s.lastValues.loops > <span class="number">1</span> && nSecOffset != <span class="number">0</span>) {\r
+ writeDebug(<span class="string">'Warning: Looping functionality being disabled due to Flash limitation.'</span>, <span class="number">240</span>);\r
+ s.lastValues.loops = <span class="number">1</span>;\r
+ }\r
+ s.start(nSecOffset, s.lastValues.nLoops || <span class="number">1</span>); <span class="comment">// start playing at new position</span>\r
+ <span class="keyword">if</span> (isPaused) {\r
+ s.stop();\r
+ }\r
+ }\r
+\r
+ <span class="keyword">var</span> _load = <span class="keyword">function</span>(sID, sURL, bStream, bAutoPlay, bCheckPolicyFile) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-21">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-21">¶</a>
+ </div>
+ <p>writeDebug('_load(): '+sID+', '+sURL+', '+bStream+', '+bAutoPlay+', '+bCheckPolicyFile);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (<span class="keyword">typeof</span> bAutoPlay == <span class="string">'undefined'</span>) {\r
+ bAutoPlay = <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> bStream == <span class="string">'undefined'</span>) {\r
+ bStream = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> bCheckPolicyFile == <span class="string">'undefined'</span>) {\r
+ bCheckPolicyFile = <span class="literal">false</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-22">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-22">¶</a>
+ </div>
+ <p>writeDebug('bStream: '+bStream);
+writeDebug('bAutoPlay: '+bAutoPlay);
+checkProgress();</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> s = soundObjects[sID];\r
+ s.onID3 = onID3;\r
+ s.onLoad = onLoad;\r
+ s.loaded = <span class="literal">true</span>;\r
+ s.checkPolicyFile = bCheckPolicyFile;\r
+ s.loadSound(sURL, bStream);\r
+ <span class="keyword">if</span> (bAutoPlay != <span class="literal">true</span>) {\r
+ s.stop(); <span class="comment">// prevent default auto-play behaviour</span>\r
+ } <span class="keyword">else</span> {\r
+ writeDebug(<span class="string">'auto-play allowed'</span>);\r
+ }\r
+ registerOnComplete(sID);\r
+ }\r
+\r
+ <span class="keyword">var</span> _unload = <span class="keyword">function</span>(sID, sURL) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-23">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-23">¶</a>
+ </div>
+ <p>effectively "stop" loading by loading a tiny MP3</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> s = soundObjects[sID];\r
+ s.onID3 = <span class="literal">null</span>;\r
+ s.onLoad = <span class="literal">null</span>;\r
+ s.loaded = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-24">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-24">¶</a>
+ </div>
+ <p>ensure position is reset, if unload fails</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.start(<span class="number">0</span>,<span class="number">1</span>);\r
+ s.stop();\r
+ s.loadSound(sURL, <span class="literal">true</span>);\r
+ s.stop(); <span class="comment">// prevent auto-play</span>\r
+ }\r
+\r
+ <span class="keyword">var</span> _createSound = <span class="keyword">function</span>(sID, loops, checkPolicyFile) {\r
+ <span class="keyword">var</span> s = <span class="keyword">new</span> Sound();\r
+ <span class="keyword">if</span> (!soundObjects[sID]) {\r
+ sounds.push(sID);\r
+ }\r
+ soundObjects[sID] = s;\r
+ s.setVolume(<span class="number">100</span>);\r
+ s.sID = sID;\r
+ s.paused = <span class="literal">false</span>;\r
+ s.loaded = <span class="literal">false</span>;\r
+ s.checkPolicyFile = checkPolicyFile;\r
+ s.lastValues = {\r
+ bytes: <span class="number">0</span>,\r
+ position: <span class="number">0</span>,\r
+ nLoops: loops||<span class="number">1</span>\r
+ };\r
+ }\r
+\r
+ <span class="keyword">var</span> _destroySound = <span class="keyword">function</span>(sID) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-25">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-25">¶</a>
+ </div>
+ <p>for the power of garbage collection! .. er, Greyskull!</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> s = (soundObjects[sID] || <span class="literal">null</span>);\r
+ <span class="keyword">if</span> (!s) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < sounds.length; i++) {\r
+ <span class="keyword">if</span> (sounds[i] == sID) {\r
+ sounds.splice(i, <span class="number">1</span>);\r
+ <span class="keyword">break</span>;\r
+ }\r
+ }\r
+ s = <span class="literal">null</span>;\r
+ <span class="keyword">delete</span> soundObjects[sID];\r
+ }\r
+\r
+ <span class="keyword">var</span> _stop = <span class="keyword">function</span>(sID, bStopAll) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-26">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-26">¶</a>
+ </div>
+ <p>stop this particular instance (or "all", based on parameter)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (bStopAll) {\r
+ _root.stop();\r
+ } <span class="keyword">else</span> {\r
+ soundObjects[sID].stop();\r
+ soundObjects[sID].paused = <span class="literal">false</span>;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">var</span> _start = <span class="keyword">function</span>(sID, nLoops, nMsecOffset, _allowMultiShot) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-27">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-27">¶</a>
+ </div>
+ <p>note: multiShot is Flash 9-only; retained so JS/Flash function signatures are identical.
+writeDebug('_start: ' + sID + ', loops: ' + nLoops + ', nMsecOffset: ' + nMsecOffset);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> registerOnComplete();\r
+ <span class="keyword">var</span> s = soundObjects[sID];\r
+ s.lastValues.paused = <span class="literal">false</span>; <span class="comment">// reset pause if applicable</span>\r
+ s.lastValues.nLoops = (nLoops || <span class="number">1</span>);\r
+ s.start(nMsecOffset, nLoops);\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> _pause = <span class="keyword">function</span>(sID, _allowMultiShot) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-28">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-28">¶</a>
+ </div>
+ <p>note: multiShot is Flash 9-only; retained so JS/Flash function signatures are identical.
+writeDebug('_pause()');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> s = soundObjects[sID];\r
+ <span class="keyword">if</span> (!s.paused) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-29">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-29">¶</a>
+ </div>
+ <p>reference current position, stop sound</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.paused = <span class="literal">true</span>;\r
+ s.lastValues.position = s.position;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-30">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-30">¶</a>
+ </div>
+ <p>writeDebug('_pause(): position: '+s.lastValues.position);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.stop();\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-31">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-31">¶</a>
+ </div>
+ <p>resume playing from last position
+writeDebug('resuming - playing at '+s.lastValues.position+', '+s.lastValues.nLoops+' times');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.paused = <span class="literal">false</span>;\r
+ s.start(s.lastValues.position / <span class="number">1000</span>, s.lastValues.nLoops);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">var</span> _setPan = <span class="keyword">function</span>(sID, nPan) {\r
+ soundObjects[sID].setPan(nPan);\r
+ }\r
+\r
+ <span class="keyword">var</span> _setVolume = <span class="keyword">function</span>(sID, nVol) {\r
+ soundObjects[sID].setVolume(nVol);\r
+ }\r
+\r
+ <span class="keyword">var</span> _setPolling = <span class="keyword">function</span>(bPolling, timerInterval) {\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> timerInterval === <span class="string">'undefined'</span>) {\r
+ timerInterval = <span class="number">50</span>;\r
+ }\r
+ pollingEnabled = bPolling;\r
+ <span class="keyword">if</span> (timer == <span class="literal">null</span> && pollingEnabled) {\r
+ flashDebug(<span class="string">'Enabling polling, '</span> + timerInterval + <span class="string">' ms interval'</span>);\r
+ timer = setInterval(checkProgress, timerInterval);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (timer && !pollingEnabled) {\r
+ flashDebug(<span class="string">'Disabling polling'</span>);\r
+ clearInterval(timer);\r
+ timer = <span class="literal">null</span>;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">var</span> _init = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-32">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-32">¶</a>
+ </div>
+ <p>OK now stuff should be available</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">try</span> {\r
+ flashDebug(<span class="string">'Adding ExternalInterface callbacks...'</span>);\r
+ ExternalInterface.addCallback(<span class="string">'_load'</span>, <span class="keyword">this</span>, _load);\r
+ ExternalInterface.addCallback(<span class="string">'_unload'</span>, <span class="keyword">this</span>, _unload);\r
+ ExternalInterface.addCallback(<span class="string">'_stop'</span>, <span class="keyword">this</span>, _stop);\r
+ ExternalInterface.addCallback(<span class="string">'_start'</span>, <span class="keyword">this</span>, _start);\r
+ ExternalInterface.addCallback(<span class="string">'_pause'</span>, <span class="keyword">this</span>, _pause);\r
+ ExternalInterface.addCallback(<span class="string">'_setPosition'</span>, <span class="keyword">this</span>, _setPosition);\r
+ ExternalInterface.addCallback(<span class="string">'_setPan'</span>, <span class="keyword">this</span>, _setPan);\r
+ ExternalInterface.addCallback(<span class="string">'_setVolume'</span>, <span class="keyword">this</span>, _setVolume);\r
+ ExternalInterface.addCallback(<span class="string">'_setPolling'</span>, <span class="keyword">this</span>, _setPolling);\r
+ ExternalInterface.addCallback(<span class="string">'_externalInterfaceTest'</span>, <span class="keyword">this</span>, _externalInterfaceTest);\r
+ ExternalInterface.addCallback(<span class="string">'_disableDebug'</span>, <span class="keyword">this</span>, _disableDebug);\r
+ ExternalInterface.addCallback(<span class="string">'_createSound'</span>, <span class="keyword">this</span>, _createSound);\r
+ ExternalInterface.addCallback(<span class="string">'_destroySound'</span>, <span class="keyword">this</span>, _destroySound);\r
+ } <span class="keyword">catch</span>(e) {\r
+ flashDebug(<span class="string">'Fatal: ExternalInterface error: '</span> + e.toString());\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-33">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-33">¶</a>
+ </div>
+ <p>try to talk to JS, do init etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> _externalInterfaceTest(<span class="literal">true</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-34">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-34">¶</a>
+ </div>
+ <p>flashDebug('Init OK');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+\r
+ flashDebug(<span class="string">'SM2 SWF '</span> + version + <span class="string">' '</span> + version_as);\r
+\r
+ <span class="keyword">if</span> (ExternalInterface.available) {\r
+ flashDebug(<span class="string">'ExternalInterface available'</span>);\r
+ _init();\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-35">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-35">¶</a>
+ </div>
+ <p>d'oh! - may be from a corrupt install, ancient (pre-Netscape 6?) browser etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> flashDebug(<span class="string">'Fatal: ExternalInterface (Flash &lt;-&gt; JS) not available'</span>);\r
+ }\r
+\r
+\r
+ } <span class="comment">// SoundManager2()</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-36">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-36">¶</a>
+ </div>
+ <p>entry point</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">main</span><span class="params">(mc)</span> {</span>\r
+ app = <span class="keyword">new</span> SoundManager2();\r
+ }\r
+\r
+}</pre></div></div>
+
+ </li>
+
+ </ul>
+ </div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+
+<html>
+<head>
+ <title>SoundManager2_AS3.as</title>
+<meta name="robots" content="noindex" />
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
+ <link rel="stylesheet" media="all" href="docco.css" />
+</head>
+<body>
+ <div id="container">
+ <div id="background"></div>
+
+ <ul id="jump_to">
+ <li>
+ <a class="large" href="javascript:void(0);">Jump To …</a>
+ <a class="small" href="javascript:void(0);">+</a>
+ <div id="jump_wrapper">
+ <div id="jump_page">
+
+
+ <a class="source" href="soundmanager2.html">
+ soundmanager2.js
+ </a>
+
+
+ <a class="source" href="SoundManager2_AS.html">
+ SoundManager2_AS.as
+ </a>
+
+
+ <a class="source" href="SoundManager2_AS3.html">
+ SoundManager2_AS3.as
+ </a>
+
+
+ <a class="source" href="SoundManager2_SMSound_AS3.html">
+ SoundManager2_SMSound_AS3.as
+ </a>
+
+ </div>
+ </li>
+ </ul>
+
+ <ul class="sections">
+
+ <li id="title">
+ <div class="annotation">
+ <h1>SoundManager2_AS3.as</h1>
+ </div>
+ </li>
+
+
+
+ <li id="section-1">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-1">¶</a>
+ </div>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre><span class="comment">/**\r
+ * SoundManager 2: Javascript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code licensed under the BSD License:\r
+ * http://www.schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * Flash 9 / ActionScript 3 version\r
+ */</span>\r
+\r
+<span class="package"><span class="keyword">package</span> {</span>\r
+\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.display.Sprite;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.events.Event;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.events.IOErrorEvent;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.events.MouseEvent;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.events.SecurityErrorEvent;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.events.AsyncErrorEvent;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.events.NetStatusEvent;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.events.TimerEvent;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.external.ExternalInterface;</span> <span class="comment">// woo</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.media.Sound;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.media.SoundChannel;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.media.SoundMixer;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.net.URLLoader;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.net.URLRequest;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.system.Security;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.system.System;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.text.TextField;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.text.TextFormat;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.text.TextFieldAutoSize;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.ui.ContextMenu;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.ui.ContextMenuItem;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.utils.setInterval;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.utils.clearInterval;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.utils.Dictionary;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.utils.Timer;</span>\r
+\r
+ <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SoundManager2_AS3</span> <span class="keyword">extends</span> <span class="title">Sprite</span> {</span>\r
+\r
+ <span class="keyword">public</span> <span class="keyword">var</span> version:String = <span class="string">"V2.97a.20150601"</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> version_as:String = <span class="string">"(AS3/Flash 9)"</span>;\r
+\r
+ <span class="comment">/**\r
+ * Cross-domain security options\r
+ * HTML on foo.com loading .swf hosted on bar.com? Define your "HTML domain" here to allow JS+Flash communication to work.\r
+ * // allow_xdomain_scripting = true;\r
+ * // xdomain = "foo.com";\r
+ * For all domains (possible security risk?), use xdomain = "*"; which ends up as System.security.allowDomain("*");\r
+ * When loading from HTTPS, use System.security.allowInsecureDomain();\r
+ * See http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/Security.html#allowDomain()\r
+ */</span>\r
+ <span class="keyword">public</span> <span class="keyword">var</span> allow_xdomain_scripting:Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> xdomain:String = <span class="string">"*"</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-2">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-2">¶</a>
+ </div>
+ <p>externalInterface references (for Javascript callbacks)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">public</span> <span class="keyword">var</span> baseJSController:String = <span class="string">"soundManager"</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> baseJSObject:String = baseJSController + <span class="string">".sounds"</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-3">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-3">¶</a>
+ </div>
+ <p>internal objects</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">public</span> <span class="keyword">var</span> sounds:Array = []; <span class="comment">// indexed string array</span>\r
+ <span class="keyword">public</span> <span class="keyword">var</span> soundObjects: Dictionary = <span class="keyword">new</span> Dictionary(); <span class="comment">// associative Sound() object Dictionary type</span>\r
+ <span class="keyword">public</span> <span class="keyword">var</span> timer: Timer = <span class="literal">null</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> pollingEnabled: Boolean = <span class="literal">false</span>; <span class="comment">// polling (timer) flag - disabled by default, enabled by JS->Flash call</span>\r
+ <span class="keyword">public</span> <span class="keyword">var</span> debugEnabled: Boolean = <span class="literal">true</span>; <span class="comment">// Flash debug output enabled by default, disabled by JS call</span>\r
+ <span class="keyword">public</span> <span class="keyword">var</span> flashDebugEnabled: Boolean = <span class="literal">false</span>; <span class="comment">// Flash internal debug output (write to visible SWF in browser)</span>\r
+ <span class="keyword">public</span> <span class="keyword">var</span> loaded: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> currentObject: SoundManager2_SMSound_AS3 = <span class="literal">null</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> paramList:Object = <span class="literal">null</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> messages:Array = [];\r
+ <span class="keyword">public</span> <span class="keyword">var</span> textField: TextField = <span class="literal">null</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> textStyle: TextFormat = <span class="keyword">new</span> TextFormat();\r
+ <span class="keyword">public</span> <span class="keyword">var</span> didSandboxMessage: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> caughtFatal: Boolean = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">SoundManager2_AS3</span><span class="params">()</span> {</span>\r
+\r
+ <span class="keyword">if</span> (allow_xdomain_scripting && xdomain) {\r
+ Security.allowDomain(xdomain);\r
+ version_as += <span class="string">' - cross-domain enabled'</span>;\r
+ }\r
+\r
+ <span class="keyword">this</span>.paramList = <span class="keyword">this</span>.root.loaderInfo.parameters;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-4">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-4">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (<span class="keyword">this</span>.paramList[<span class="string">'debug'</span>] == <span class="number">1</span>) {\r
+ <span class="keyword">this</span>.flashDebugEnabled = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.flashDebugEnabled) {\r
+ <span class="keyword">var</span> canvas: Sprite = <span class="keyword">new</span> Sprite();\r
+ canvas.graphics.drawRect(<span class="number">0</span>, <span class="number">0</span>, stage.stageWidth, stage.stageHeight);\r
+ addChild(canvas);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-5">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-5">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ flashDebug(<span class="string">'SM2 SWF '</span> + version + <span class="string">' '</span> + version_as);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-6">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-6">¶</a>
+ </div>
+ <p>context menu item with version info</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> sm2Menu:ContextMenu = <span class="keyword">new</span> ContextMenu();\r
+ <span class="keyword">var</span> sm2MenuItem:ContextMenuItem = <span class="keyword">new</span> ContextMenuItem(<span class="string">'SoundManager '</span> + version + <span class="string">' '</span> + version_as);\r
+ sm2MenuItem.enabled = <span class="literal">false</span>;\r
+ sm2Menu.customItems.push(sm2MenuItem);\r
+ contextMenu = sm2Menu;\r
+\r
+ <span class="keyword">if</span> (ExternalInterface.available) {\r
+ flashDebug(<span class="string">'ExternalInterface available'</span>);\r
+ <span class="keyword">try</span> {\r
+ flashDebug(<span class="string">'Adding ExternalInterface callbacks...'</span>);\r
+ ExternalInterface.addCallback(<span class="string">'_load'</span>, _load);\r
+ ExternalInterface.addCallback(<span class="string">'_unload'</span>, _unload);\r
+ ExternalInterface.addCallback(<span class="string">'_stop'</span>, _stop);\r
+ ExternalInterface.addCallback(<span class="string">'_start'</span>, _start);\r
+ ExternalInterface.addCallback(<span class="string">'_pause'</span>, _pause);\r
+ ExternalInterface.addCallback(<span class="string">'_setPosition'</span>, _setPosition);\r
+ ExternalInterface.addCallback(<span class="string">'_setPan'</span>, _setPan);\r
+ ExternalInterface.addCallback(<span class="string">'_setVolume'</span>, _setVolume);\r
+ ExternalInterface.addCallback(<span class="string">'_setPolling'</span>, _setPolling);\r
+ ExternalInterface.addCallback(<span class="string">'_externalInterfaceTest'</span>, _externalInterfaceTest);\r
+ ExternalInterface.addCallback(<span class="string">'_disableDebug'</span>, _disableDebug);\r
+ ExternalInterface.addCallback(<span class="string">'_getMemoryUse'</span>, _getMemoryUse);\r
+ ExternalInterface.addCallback(<span class="string">'_createSound'</span>, _createSound);\r
+ ExternalInterface.addCallback(<span class="string">'_destroySound'</span>, _destroySound);\r
+ ExternalInterface.addCallback(<span class="string">'_setAutoPlay'</span>, _setAutoPlay);\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ flashDebug(<span class="string">'Fatal: ExternalInterface error: '</span> + e.toString());\r
+ }\r
+ } <span class="keyword">else</span> {\r
+ flashDebug(<span class="string">'Fatal: ExternalInterface (Flash &lt;-&gt; JS) not available'</span>);\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-7">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-7">¶</a>
+ </div>
+ <p>call after delay, to be safe (ensure callbacks are registered by the time JS is called below)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> timer: Timer = <span class="keyword">new</span> Timer(<span class="number">20</span>, <span class="number">0</span>);\r
+ timer.addEventListener(TimerEvent.TIMER, <span class="keyword">function</span>() : <span class="keyword">void</span> {\r
+ timer.reset();\r
+ _externalInterfaceTest(<span class="literal">true</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-8">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-8">¶</a>
+ </div>
+ <p>timer.reset();
+flashDebug('Init OK');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> });\r
+ timer.start();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-9">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-9">¶</a>
+ </div>
+ <p>delayed, see above
+_externalInterfaceTest(true);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> } <span class="comment">// SoundManager2()</span>\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">flashDebug</span> <span class="params">(txt:String)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-10">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-10">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> messages.push(txt);\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.flashDebugEnabled) {\r
+ <span class="keyword">var</span> didCreate: Boolean = <span class="literal">false</span>;\r
+ textStyle.font = <span class="string">'Arial'</span>;\r
+ textStyle.size = <span class="number">12</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-11">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-11">¶</a>
+ </div>
+ <p>320x240 if no stage dimensions (happens in IE, apparently 0 before stage resize event fires.)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> w:Number = <span class="keyword">this</span>.stage.width?<span class="keyword">this</span>.stage.width:<span class="number">320</span>;\r
+ <span class="keyword">var</span> h:Number = <span class="keyword">this</span>.stage.height?<span class="keyword">this</span>.stage.height:<span class="number">240</span>;\r
+ <span class="keyword">if</span> (textField == <span class="literal">null</span>) {\r
+ didCreate = <span class="literal">true</span>;\r
+ textField = <span class="keyword">new</span> TextField();\r
+ textField.autoSize = TextFieldAutoSize.LEFT;\r
+ textField.x = <span class="number">0</span>;\r
+ textField.y = <span class="number">0</span>;\r
+ textField.multiline = <span class="literal">true</span>;\r
+ textField.textColor = <span class="number">0</span>;\r
+ textField.wordWrap = <span class="literal">true</span>;\r
+ }\r
+ textField.htmlText = messages.join(<span class="string">'\n'</span>);\r
+ textField.setTextFormat(textStyle);\r
+ textField.width = w;\r
+ textField.height = h;\r
+ <span class="keyword">if</span> (didCreate) {\r
+ <span class="keyword">this</span>.addChild(textField);\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-12">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-12">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_setAutoPlay</span><span class="params">(sID:String, autoPlay:Boolean)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">var</span> s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ <span class="keyword">if</span> (s) {\r
+ s.setAutoPlay(autoPlay);\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-13">
+ <div class="annotation">
+
+ <div class="pilwrap for-h2">
+ <a class="pilcrow" href="#section-13">¶</a>
+ </div>
+ <h2>methods</h2>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">writeDebug</span> <span class="params">(s:String, logLevel:Number = 0)</span> <span class="type">: Boolean</span> {</span>\r
+ <span class="keyword">if</span> (!debugEnabled) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-14">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-14">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSController + <span class="string">"['_writeDebug']"</span>, <span class="string">"(Flash): "</span> + s, <span class="literal">null</span>, logLevel);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-15">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-15">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_externalInterfaceTest</span><span class="params">(isFirstCall: Boolean)</span> <span class="type">: Boolean</span> {</span>\r
+ <span class="keyword">var</span> sandboxType:String = flash.system.Security[<span class="string">'sandboxType'</span>];\r
+ <span class="keyword">if</span> (!didSandboxMessage && sandboxType != <span class="string">'localTrusted'</span> && sandboxType != <span class="string">'remote'</span>) {\r
+ didSandboxMessage = <span class="literal">true</span>;\r
+ flashDebug(<span class="string">'<br><b>Fatal: Security sandbox error: Got "'</span> + sandboxType + <span class="string">'", expected "remote" or "localTrusted".<br>Additional security permissions need to be granted.<br>See <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html">flash security settings panel</a> for non-HTTP, eg., file:// use.</b><br>http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html<br><br>You may also be able to right-click this movie and choose from the menu: <br>"Global Settings" -> "Advanced" tab -> "Trusted Location Settings"<br>'</span>);\r
+ }\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">if</span> (isFirstCall == <span class="literal">true</span>) {\r
+ flashDebug(<span class="string">'Testing Flash -&gt; JS...'</span>);\r
+ ExternalInterface.call(baseJSController + <span class="string">"._externalInterfaceOK"</span>, version);\r
+ flashDebug(<span class="string">'Flash -&gt; JS OK'</span>);\r
+ flashDebug(<span class="string">'Waiting for JS -&gt; Flash...'</span>);\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-16">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-16">¶</a>
+ </div>
+ <p>writeDebug('SM2 SWF ' + version + ' ' + version_as, 1);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSController + <span class="string">"._setSandboxType"</span>, sandboxType);\r
+ flashDebug(<span class="string">'JS -&gt; Flash OK'</span>);\r
+ }\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ flashDebug(<span class="string">'Fatal: Flash &lt;-&gt; JS error: '</span> + e.toString());\r
+ writeDebug(<span class="string">'_externalInterfaceTest: Error: '</span> + e.toString(), <span class="number">2</span>);\r
+ <span class="keyword">if</span> (!caughtFatal) {\r
+ caughtFatal = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> <span class="literal">true</span>; <span class="comment">// to verify that a call from JS to here, works. (eg. JS receives "true", thus OK.)</span>\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_disableDebug</span><span class="params">()</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-17">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-17">¶</a>
+ </div>
+ <p>prevent future debug calls from Flash going to client (maybe improve performance)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">'_disableDebug()'</span>);\r
+ debugEnabled = <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">checkLoadProgress</span><span class="params">(e: Event)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">var</span> oSound:Object = e.target;\r
+ <span class="keyword">var</span> bL: int = oSound.bytesLoaded;\r
+ <span class="keyword">var</span> bT: int = oSound.bytesTotal;\r
+ <span class="keyword">var</span> nD: int = oSound.length || oSound.duration || <span class="number">0</span>;\r
+ <span class="keyword">var</span> sMethod:String = baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._whileloading"</span>;\r
+ ExternalInterface.call(sMethod, bL, bT, nD);\r
+ <span class="keyword">if</span> (bL && bT && bL != oSound.lastValues.bytes) {\r
+ oSound.lastValues.bytes = bL;\r
+ ExternalInterface.call(sMethod, bL, bT, nD);\r
+ }\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'checkLoadProgress(): '</span> + e.toString());\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">checkSoundProgress</span><span class="params">(oSound:SoundManager2_SMSound_AS3, forceCheck:Boolean = false, forceEndCheck:Boolean = false)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">var</span> bL: int = <span class="number">0</span>;\r
+ <span class="keyword">var</span> bT: int = <span class="number">0</span>;\r
+ <span class="keyword">var</span> nD: int = <span class="number">0</span>;\r
+ <span class="keyword">var</span> nP: int = <span class="number">0</span>;\r
+ <span class="keyword">var</span> bufferLength: int = <span class="number">0</span>;\r
+ <span class="keyword">var</span> lP:Number = <span class="number">0</span>;\r
+ <span class="keyword">var</span> rP:Number = <span class="number">0</span>;\r
+ <span class="keyword">var</span> isBuffering:Object = <span class="literal">null</span>;\r
+ <span class="keyword">var</span> oSoundChannel: flash.media.SoundChannel = <span class="literal">null</span>;\r
+ <span class="keyword">var</span> sMethod:String = <span class="literal">null</span>;\r
+ <span class="keyword">var</span> newPeakData: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">var</span> newWaveformData: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">var</span> newEQData: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">var</span> areSoundsInaccessible: Boolean = SoundMixer.areSoundsInaccessible();\r
+ <span class="keyword">var</span> isPlaying: Boolean = <span class="literal">true</span>; <span class="comment">// special case for NetStream when ending</span>\r
+ <span class="keyword">var</span> hasNew:Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">var</span> hasNewLoaded:Boolean = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (!oSound || !oSound.useEvents || oSound.failed || !oSound.connected) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-18">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-18">¶</a>
+ </div>
+ <p>edge cases for ignoring: if sounds are destructed within event handlers while checkProgress() is running, may be null</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span>;\r
+ }\r
+\r
+ sMethod = baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._whileloading"</span>;\r
+\r
+ <span class="keyword">if</span> (oSound.useNetstream) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-19">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-19">¶</a>
+ </div>
+ <p>Don't do anything if there is no NetStream object yet</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!oSound.ns) {\r
+ <span class="keyword">return</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-20">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-20">¶</a>
+ </div>
+ <p>stream</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> bufferLength = oSound.ns.bufferLength;\r
+ bL = oSound.ns.bytesLoaded;\r
+ bT = oSound.ns.bytesTotal;\r
+ nD = int(oSound.duration || <span class="number">0</span>); <span class="comment">// can sometimes be null with short MP3s? Wack.</span>\r
+ nP = oSound.ns.time * <span class="number">1000</span>;\r
+\r
+ <span class="keyword">if</span> (oSound.paused) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-21">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-21">¶</a>
+ </div>
+ <p>special case: paused netStreams don't update if setPosition() is called while they are paused.
+instead, return lastValues.position which should reflect setPosition() call.
+writeDebug('paused case, setting nP of '+nP+' to -1');
+writeDebug('lastValues: '+oSound.lastValues.position);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> nP = oSound.lastValues.position;\r
+ }\r
+\r
+ <span class="keyword">if</span> (nP >= <span class="number">0</span> && nP != oSound.lastValues.position) {\r
+ oSound.lastValues.position = nP;\r
+ hasNew = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">if</span> (nD > oSound.lastValues.duration) {\r
+ oSound.lastValues.duration = nD;\r
+ hasNew = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">if</span> (bL > oSound.lastValues.bytesLoaded) {\r
+ oSound.lastValues.bytesLoaded = bL;\r
+ hasNew = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">if</span> (bT > oSound.lastValues.bytes) {\r
+ oSound.lastValues.bytes = bT;\r
+ hasNew = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">if</span> (bufferLength != oSound.lastValues.bufferLength) {\r
+ oSound.lastValues.bufferLength = bufferLength;\r
+ hasNew = <span class="literal">true</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-22">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-22">¶</a>
+ </div>
+ <p>Don't set loaded for streams because bytesLoaded and bytesTotal are always 0
+writeDebug('ns: time/duration, bytesloaded/total: '+nP+'/'+nD+', '+bL+'/'+bT);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (oSound.loaded != <span class="literal">true</span> && nD > <span class="number">0</span> && bL == bT && bL != <span class="number">0</span> && bT != <span class="number">0</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-23">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-23">¶</a>
+ </div>
+ <p>non-MP3 has loaded</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oSound.loaded = <span class="literal">true</span>;\r
+ <span class="keyword">try</span> {\r
+ ExternalInterface.call(sMethod, bL, bT, nD, bufferLength);\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._onload"</span>, oSound.duration > <span class="number">0</span> ? <span class="number">1</span> : <span class="number">0</span>);\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'_whileLoading/_onload error: '</span> + e.toString(), <span class="number">2</span>);\r
+ }\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (oSound.loaded != <span class="literal">true</span> && hasNew) {\r
+ ExternalInterface.call(sMethod, bL, bT, nD, bufferLength);\r
+ }\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-24">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-24">¶</a>
+ </div>
+ <p>MP3 sound</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oSoundChannel = oSound.soundChannel;\r
+ bL = oSound.bytesLoaded;\r
+ bT = oSound.bytesTotal;\r
+ nD = int(oSound.length || <span class="number">0</span>); <span class="comment">// can sometimes be null with short MP3s? Wack.</span>\r
+ isBuffering = oSound.isBuffering;\r
+\r
+ <span class="keyword">if</span> (oSoundChannel) {\r
+ nP = (oSoundChannel.position || <span class="number">0</span>);\r
+ <span class="keyword">if</span> (oSound.lastValues.loops > <span class="number">1</span> && nP > oSound.length) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-25">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-25">¶</a>
+ </div>
+ <p>round down to nearest loop</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> playedLoops:Number = Math.floor(nP/oSound.length);\r
+ nP = nP - (oSound.length*playedLoops);\r
+ }\r
+ <span class="keyword">if</span> (oSound.usePeakData) {\r
+ lP = int((oSoundChannel.leftPeak) * <span class="number">1000</span>) / <span class="number">1000</span>;\r
+ rP = int((oSoundChannel.rightPeak) * <span class="number">1000</span>) / <span class="number">1000</span>;\r
+ } <span class="keyword">else</span> {\r
+ lP = <span class="number">0</span>;\r
+ rP = <span class="number">0</span>;\r
+ }\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-26">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-26">¶</a>
+ </div>
+ <p>stopped, not loaded or feature not used</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> nP = <span class="number">0</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (forceEndCheck) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-27">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-27">¶</a>
+ </div>
+ <p>sound finish case: Ensure position is at end (sound duration), as flash 9 does not always correctly match the two.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (nP < nD) {\r
+ writeDebug(<span class="string">'correcting sound '</span> + oSound.sID + <span class="string">' end position ('</span>+nP+<span class="string">') to length: '</span>+ nD, <span class="number">2</span>);\r
+ nP = nD;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">if</span> (nP != oSound.lastValues.position && nP !== <span class="number">0</span> && !oSound.didFinish) { <span class="comment">// once "completed", sound is locked via didFinish so no more position-type events fire.</span>\r
+ oSound.lastValues.position = nP;\r
+ hasNew = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (nD > oSound.lastValues.duration) { <span class="comment">// original sound duration * number of sound loops</span>\r
+ oSound.lastValues.duration = nD;\r
+ hasNew = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (bL > oSound.lastValues.bytesLoaded) {\r
+ oSound.lastValues.bytesLoaded = bL;\r
+ hasNew = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (bT > oSound.lastValues.bytes) {\r
+ oSound.lastValues.bytes = bT;\r
+ hasNew = <span class="literal">true</span>;\r
+ hasNewLoaded = <span class="literal">true</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-28">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-28">¶</a>
+ </div>
+ <p>loading progress</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (hasNewLoaded) {\r
+ oSound.lastValues.bytes = bL;\r
+ ExternalInterface.call(sMethod, bL, bT, nD);\r
+ }\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-29">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-29">¶</a>
+ </div>
+ <p>peak data</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (oSoundChannel && oSound.usePeakData) {\r
+ <span class="keyword">if</span> (lP != oSound.lastValues.leftPeak) {\r
+ oSound.lastValues.leftPeak = lP;\r
+ newPeakData = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">if</span> (rP != oSound.lastValues.rightPeak) {\r
+ oSound.lastValues.rightPeak = rP;\r
+ newPeakData = <span class="literal">true</span>;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">var</span> newDataError:Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">var</span> dataError:String;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-30">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-30">¶</a>
+ </div>
+ <p>special case: Netstream may try to fire whileplaying() after finishing. check that stop hasn't fired.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> isPlaying = (oSound.didLoad && !oSound.paused && (!oSound.useNetstream || (oSound.useNetstream && oSound.lastNetStatus != <span class="string">"NetStream.Play.Stop"</span>))); <span class="comment">// don't update if stream has ended</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-31">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-31">¶</a>
+ </div>
+ <p>raw waveform + EQ spectrum data</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (isPlaying && (oSoundChannel || oSound.useNetstream)) {\r
+\r
+ <span class="keyword">if</span> (oSound.useWaveformData) {\r
+ <span class="keyword">if</span> (!areSoundsInaccessible && !oSound.handledDataError && !oSound.ignoreDataError) {\r
+ <span class="keyword">try</span> {\r
+ oSound.getWaveformData();\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ <span class="keyword">if</span> (!oSound.handledDataError) {\r
+ writeDebug(<span class="string">'getWaveformData() (waveform data) '</span>+e.toString());\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-32">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-32">¶</a>
+ </div>
+ <p>oSound.useWaveformData = false;</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> newDataError = <span class="literal">true</span>;\r
+ dataError = e.toString();\r
+ }\r
+ }\r
+ }\r
+\r
+ <span class="keyword">if</span> (oSound.useEQData) {\r
+ <span class="keyword">if</span> (!areSoundsInaccessible && !oSound.handledDataError && !oSound.ignoreDataError) {\r
+ <span class="keyword">try</span> {\r
+ oSound.getEQData();\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ <span class="keyword">if</span> (!oSound.handledDataError) {\r
+ writeDebug(<span class="string">'computeSpectrum() (EQ data) '</span>+e.toString());\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-33">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-33">¶</a>
+ </div>
+ <p>oSound.useEQData = false;</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> newDataError = <span class="literal">true</span>;\r
+ dataError = e.toString();\r
+ }\r
+ }\r
+ }\r
+\r
+ <span class="keyword">if</span> (oSound.waveformDataArray != oSound.lastValues.waveformDataArray) {\r
+ oSound.lastValues.waveformDataArray = oSound.waveformDataArray;\r
+ newWaveformData = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (oSound.eqDataArray != oSound.lastValues.eqDataArray) {\r
+ oSound.lastValues.eqDataArray = oSound.eqDataArray;\r
+ newEQData = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (newDataError && !oSound.handledDataError) {\r
+ sMethod = baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._ondataerror"</span>;\r
+ ExternalInterface.call(sMethod, <span class="string">'data unavailable: '</span> + dataError);\r
+ oSound.handledDataError = <span class="literal">true</span>;\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> nP != <span class="string">'undefined'</span> && (hasNew && (oSound.soundChannel || oSound.useNetstream || forceCheck || forceEndCheck))) { <span class="comment">// && isPlaying - removed to allow updates while paused, eg. from setPosition() calls. Also be more liberal if we're using netStream.</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-34">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-34">¶</a>
+ </div>
+ <p>oSound.lastValues.position = nP;</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sMethod = baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._whileplaying"</span>;\r
+ <span class="keyword">var</span> waveDataLeft:String = (newWaveformData ? oSound.waveformDataArray.slice(<span class="number">0</span>, <span class="number">256</span>).join(<span class="string">','</span>) : <span class="literal">null</span>);\r
+ <span class="keyword">var</span> waveDataRight:String = (newWaveformData ? oSound.waveformDataArray.slice(<span class="number">256</span>).join(<span class="string">','</span>) : <span class="literal">null</span>);\r
+ <span class="keyword">var</span> eqDataLeft:String = (newEQData ? oSound.eqDataArray.slice(<span class="number">0</span>, <span class="number">256</span>).join(<span class="string">','</span>) : <span class="literal">null</span>);\r
+ <span class="keyword">var</span> eqDataRight:String = (newEQData ? oSound.eqDataArray.slice(<span class="number">256</span>).join(<span class="string">','</span>) : <span class="literal">null</span>);\r
+ ExternalInterface.call(sMethod, nP, (newPeakData ? {\r
+ leftPeak: lP,\r
+ rightPeak: rP\r
+ } : <span class="literal">null</span>), waveDataLeft, waveDataRight, (newEQData ? {\r
+ leftEQ: eqDataLeft,\r
+ rightEQ: eqDataRight\r
+ } : <span class="literal">null</span>));\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-35">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-35">¶</a>
+ </div>
+ <p>check isBuffering</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!oSound.useNetstream && oSound.isBuffering != oSound.lastValues.isBuffering) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-36">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-36">¶</a>
+ </div>
+ <p>property has changed</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oSound.lastValues.isBuffering = oSound.isBuffering;\r
+ sMethod = baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._onbufferchange"</span>;\r
+ ExternalInterface.call(sMethod, oSound.isBuffering ? <span class="number">1</span> : <span class="number">0</span>);\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">checkProgress</span><span class="params">()</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">for</span> (<span class="keyword">var</span> i: int = <span class="number">0</span>, j: int = sounds.length; i < j; i++) {\r
+ checkSoundProgress(soundObjects[sounds[i]]);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">onLoadError</span><span class="params">(oSound:Object)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-37">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-37">¶</a>
+ </div>
+ <p>something went wrong. 404, bad format etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._onload"</span>, <span class="number">0</span>);\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">onLoad</span><span class="params">(e: Event)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">var</span> oSound:Object = e.target;\r
+ checkSoundProgress(soundObjects[oSound.sID]); <span class="comment">// ensure progress stats are up-to-date</span>\r
+ <span class="keyword">if</span> (!oSound.useNetstream) { <span class="comment">// FLV must also have metadata</span>\r
+ oSound.loaded = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-38">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-38">¶</a>
+ </div>
+ <p>force duration update (doesn't seem to be always accurate)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._whileloading"</span>, oSound.bytesLoaded, oSound.bytesTotal, oSound.length || oSound.duration);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-39">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-39">¶</a>
+ </div>
+ <p>duration > 0 means a valid sound was loaded.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._onload"</span>, (oSound.length || oSound.duration ? <span class="number">1</span> : <span class="number">0</span>));\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">onID3</span><span class="params">(e: Event)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-40">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-40">¶</a>
+ </div>
+ <p>--- NOTE: BUGGY (Flash 8 only? Haven't really checked 9 + 10.) ---
+TODO: Investigate holes in ID3 parsing - for some reason, Album will be populated with Date if empty and date is provided. (?)
+ID3V1 seem to parse OK, but "holes" / blanks in ID3V2 data seem to get messed up (eg. missing album gets filled with date.)
+iTunes issues: onID3 was not called with a test MP3 encoded with iTunes 7.01, and what appeared to be valid ID3V2 data.
+May be related to thumbnails for album art included in MP3 file by iTunes. See <a href="http://mabblog.com/blog/?p=33">http://mabblog.com/blog/?p=33</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">try</span> {\r
+ <span class="keyword">var</span> oSound:Object = e.target;\r
+\r
+ <span class="keyword">var</span> id3Data:Array = [];\r
+ <span class="keyword">var</span> id3Props:Array = [];\r
+ <span class="keyword">for</span> (<span class="keyword">var</span> prop:String <span class="keyword">in</span> oSound.id3) {\r
+ id3Props.push(prop);\r
+ id3Data.push(oSound.id3[prop]);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-41">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-41">¶</a>
+ </div>
+ <p>writeDebug('id3['+prop+']: '+oSound.id3[prop]);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + oSound.sID + <span class="string">"']._onid3"</span>, id3Props, id3Data);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-42">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-42">¶</a>
+ </div>
+ <p>unhook own event handler, prevent second call (can fire twice as data is received - ID3V2 at beginning, ID3V1 at end.)
+Therefore if ID3V2 data is received, ID3V1 is ignored.
+soundObjects[oSound.sID].onID3 = null;</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'onID3(): Unable to get ID3 info for '</span> + oSound.sID + <span class="string">'.'</span>);\r
+ }\r
+ oSound.removeEventListener(Event.ID3, onID3);\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">registerOnComplete</span><span class="params">(sID:String)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">var</span> oSound: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ <span class="keyword">if</span> (oSound && oSound.soundChannel) {\r
+ oSound.didFinish = <span class="literal">false</span>; <span class="comment">// reset this flag</span>\r
+ oSound.soundChannel.addEventListener(Event.SOUND_COMPLETE, <span class="keyword">function</span>() : <span class="keyword">void</span> {\r
+ <span class="keyword">if</span> (oSound) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-43">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-43">¶</a>
+ </div>
+ <p>force progress check, catching special end-of-sound case where position may not match duration.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> checkSoundProgress(oSound, <span class="literal">true</span>, <span class="literal">true</span>);\r
+ <span class="keyword">try</span> {\r
+ oSound.ignoreDataError = <span class="literal">true</span>; <span class="comment">// workaround: avoid data error handling for this manual step..</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-44">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-44">¶</a>
+ </div>
+ <p>oSound.soundChannel.stop();</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oSound.didFinish = <span class="literal">true</span>; <span class="comment">// "lock" sound, prevent extra whileplaying() position-type updates</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-45">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-45">¶</a>
+ </div>
+ <p>call onfinish first (with end position)...</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + sID + <span class="string">"']._onfinish"</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-46">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-46">¶</a>
+ </div>
+ <p>then reset sound so it can be played again.
+oSound.start(0, 1); // go back to 0</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'Could not set position on '</span> + sID + <span class="string">': '</span> + e.toString());\r
+ }\r
+ oSound.ignoreDataError = <span class="literal">false</span>; <span class="comment">// ..and reset</span>\r
+ oSound.handledDataError = <span class="literal">false</span>; <span class="comment">// reset this flag</span>\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-47">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-47">¶</a>
+ </div>
+ <p>safety net</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + sID + <span class="string">"']._onfinish"</span>);\r
+ }\r
+ });\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">doSecurityError</span><span class="params">(oSound: SoundManager2_SMSound_AS3, e: SecurityErrorEvent)</span> <span class="type">: void</span> {</span>\r
+ writeDebug(<span class="string">'securityError: '</span> + e.text);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-48">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-48">¶</a>
+ </div>
+ <p>when this happens, you don't have security rights on the server containing the FLV file
+a crossdomain.xml file would fix the problem easily</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_setPosition</span><span class="params">(sID:String, nSecOffset:Number, isPaused: Boolean, allowMultiShot: Boolean)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">var</span> s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ <span class="keyword">if</span> (!s) <span class="keyword">return</span> <span class="keyword">void</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-49">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-49">¶</a>
+ </div>
+ <p>writeDebug('_setPosition()');</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-50">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-50">¶</a>
+ </div>
+ <p>stop current channel, start new one.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.lastValues) {\r
+ s.lastValues.position = nSecOffset; <span class="comment">// s.soundChannel.position;</span>\r
+ }\r
+ <span class="keyword">if</span> (s.useNetstream) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-51">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-51">¶</a>
+ </div>
+ <p>Minimize the buffer so playback starts ASAP</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.ns.bufferTime = s.bufferTime;\r
+ writeDebug(<span class="string">'setPosition ('</span>+ sID + <span class="string">'): setting buffer to '</span>+s.ns.bufferTime+<span class="string">' secs'</span>);\r
+\r
+ nSecOffset = nSecOffset > <span class="number">0</span> ? nSecOffset / <span class="number">1000</span> : <span class="number">0</span>;\r
+ s.ns.seek(nSecOffset);\r
+ checkSoundProgress(s); <span class="comment">// force UI update</span>\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">if</span> (s.soundChannel) {\r
+ s.soundChannel.stop();\r
+ }\r
+ writeDebug(<span class="string">'setPosition ('</span>+ sID + <span class="string">'): '</span> + nSecOffset); <span class="comment">// +', '+(s.lastValues.loops?s.lastValues.loops:1));</span>\r
+ <span class="keyword">if</span> (s.lastValues.loops > <span class="number">1</span> && nSecOffset != <span class="number">0</span>) {\r
+ writeDebug(<span class="string">'Warning: Looping functionality being disabled due to Flash limitation.'</span>);\r
+ s.lastValues.loops = <span class="number">1</span>;\r
+ }\r
+ <span class="keyword">try</span> {\r
+ s.start(nSecOffset, s.lastValues.loops || <span class="number">1</span>, allowMultiShot); <span class="comment">// start playing at new position</span>\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'Warning: Could not set position on '</span> + sID + <span class="string">': '</span> + e.toString());\r
+ }\r
+ checkSoundProgress(s); <span class="comment">// force UI update</span>\r
+ <span class="keyword">try</span> {\r
+ registerOnComplete(sID);\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'_setPosition(): Could not register onComplete'</span>);\r
+ }\r
+ <span class="keyword">if</span> (isPaused && s.soundChannel) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-52">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-52">¶</a>
+ </div>
+ <p>writeDebug('_setPosition: stopping (paused) sound');
+writeDebug('last position: '+s.lastValues.position+' vs '+s.soundChannel.position);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.soundChannel.stop();\r
+ }\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_load</span><span class="params">(sID:String, sURL:String, bStream: Boolean, bAutoPlay: Boolean, nLoops: Number, bAutoLoad: Boolean, bCheckPolicyFile: Boolean)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-53">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-53">¶</a>
+ </div>
+ <p>writeDebug('_load()');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (<span class="keyword">typeof</span> bAutoPlay == <span class="string">'undefined'</span>) bAutoPlay = <span class="literal">false</span>;\r
+ <span class="keyword">var</span> s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ <span class="keyword">if</span> (!s) <span class="keyword">return</span> <span class="keyword">void</span>;\r
+ <span class="keyword">var</span> didRecreate: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">if</span> (s.didLoad == <span class="literal">true</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-54">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-54">¶</a>
+ </div>
+ <p>need to recreate sound</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> didRecreate = <span class="literal">true</span>;\r
+ writeDebug(<span class="string">'recreating sound '</span> + sID + <span class="string">' in order to load '</span> + sURL);\r
+ <span class="keyword">var</span> ns:Object = <span class="keyword">new</span> Object();\r
+ ns.sID = s.sID;\r
+ ns.loops = nLoops||<span class="number">1</span>;\r
+ ns.usePeakData = s.usePeakData;\r
+ ns.useWaveformData = s.useWaveformData;\r
+ ns.useEQData = s.useEQData;\r
+ ns.useNetstream = s.useNetstream;\r
+ ns.bufferTime = s.bufferTime;\r
+ ns.serverUrl = s.serverUrl;\r
+ ns.duration = s.duration;\r
+ ns.checkPolicyFile = s.checkPolicyFile;\r
+ ns.useEvents = <span class="literal">true</span>;\r
+ _destroySound(s.sID);\r
+ _createSound(ns.sID, sURL, ns.usePeakData, ns.useWaveformData, ns.useEQData, ns.useNetstream, ns.bufferTime, ns.loops, ns.serverUrl, ns.duration, bAutoPlay, ns.useEvents, bAutoLoad, ns.checkPolicyFile);\r
+ s = soundObjects[sID];</pre></div></div>
+
+ </li>
+
+
+ <li id="section-55">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-55">¶</a>
+ </div>
+ <p>writeDebug('Sound object replaced');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+ checkSoundProgress(s);\r
+\r
+ <span class="keyword">if</span> (!s.didLoad) {\r
+ <span class="keyword">try</span> {\r
+ s.addEventListener(Event.ID3, onID3);\r
+ s.addEventListener(Event.COMPLETE, onLoad);\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'_load(): could not assign ID3/complete event handlers'</span>);\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-56">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-56">¶</a>
+ </div>
+ <p>don't try to load if same request already made</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.sURL = sURL;\r
+\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">if</span> (!s.useNetstream) {\r
+ s.addEventListener(IOErrorEvent.IO_ERROR, <span class="keyword">function</span>(e: IOErrorEvent) : <span class="keyword">void</span> {\r
+ s.doIOError(e);\r
+ });\r
+ }\r
+ s.loadSound(sURL);\r
+ } <span class="keyword">catch</span>(e: Error) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-57">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-57">¶</a>
+ </div>
+ <p>oh well</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">'_load: Error loading '</span> + sURL + <span class="string">'. Flash error detail: '</span> + e.toString());\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_unload</span><span class="params">(sID:String)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">var</span> s: SoundManager2_SMSound_AS3 = (soundObjects[sID] || <span class="literal">null</span>);\r
+ <span class="keyword">if</span> (!s) <span class="keyword">return</span> <span class="keyword">void</span>;\r
+ <span class="keyword">var</span> sURL:String = s.sURL; <span class="comment">// save existing sound URL for object recreation</span>\r
+ <span class="keyword">try</span> {\r
+ removeEventListener(Event.ID3, onID3);\r
+ removeEventListener(Event.COMPLETE, onLoad);\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'_unload() warn: Could not remove ID3/complete events'</span>);\r
+ }\r
+ s.paused = <span class="literal">false</span>;\r
+ <span class="keyword">if</span> (s.soundChannel) {\r
+ s.soundChannel.stop();\r
+ }\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">if</span> (s.didLoad && !s.loaded && !s.useNetstream) {\r
+ s.close(); <span class="comment">// close stream only if still loading?</span>\r
+ }\r
+ } <span class="keyword">catch</span>(e: Error) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-58">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-58">¶</a>
+ </div>
+ <p>stream may already have closed if sound loaded, etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(sID + <span class="string">'._unload(): Note: Unable to close stream: '</span> + e.toString());</pre></div></div>
+
+ </li>
+
+
+ <li id="section-59">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-59">¶</a>
+ </div>
+ <p>oh well</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-60">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-60">¶</a>
+ </div>
+ <p>destroy and recreate Flash sound object, try to reclaim memory
+writeDebug('sound._unload(): recreating sound '+sID+' to free memory');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.useNetstream) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-61">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-61">¶</a>
+ </div>
+ <p>writeDebug('_unload(): closing netStream stuff');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">try</span> {\r
+ s.removeNetstreamEvents();\r
+ s.ns.close();\r
+ s.nc.close();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-62">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-62">¶</a>
+ </div>
+ <p>s.nc = null;
+s.ns = null;</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> } <span class="keyword">catch</span>(e: Error) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-63">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-63">¶</a>
+ </div>
+ <p>oh well</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">'_unload(): caught exception during netConnection/netStream close'</span>);\r
+ }\r
+ }\r
+ <span class="keyword">var</span> ns:Object = <span class="keyword">new</span> Object();\r
+ ns.sID = s.sID;\r
+ ns.loops = s.loops;\r
+ ns.usePeakData = s.usePeakData;\r
+ ns.useWaveformData = s.useWaveformData;\r
+ ns.useEQData = s.useEQData;\r
+ ns.useNetstream = s.useNetstream;\r
+ ns.bufferTime = s.bufferTime;\r
+ ns.serverUrl = s.serverUrl;\r
+ ns.duration = s.duration;\r
+ ns.autoPlay = s.autoPlay;\r
+ ns.autoLoad = s.autoLoad;\r
+ ns.checkPolicyFile = s.checkPolicyFile;\r
+ _destroySound(s.sID);\r
+ _createSound(ns.sID, sURL, ns.usePeakData, ns.useWaveformData, ns.useEQData, ns.useNetstream, ns.bufferTime, ns.loops, ns.serverUrl, ns.duration, ns.autoPlay, <span class="literal">false</span>, ns.autoLoad, ns.checkPolicyFile); <span class="comment">// false: don't allow events just yet</span>\r
+ soundObjects[sID].connected = <span class="literal">true</span>; <span class="comment">// fake it?</span>\r
+ writeDebug(s.sID + <span class="string">'.unload(): ok'</span>);\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_createSound</span><span class="params">(sID:String, sURL:String, usePeakData: Boolean, useWaveformData: Boolean, useEQData: Boolean, useNetstream: Boolean, bufferTime:Number, loops:Number, serverUrl:String, duration:Number, autoPlay:Boolean, useEvents:Boolean, autoLoad:Boolean, checkPolicyFile:Boolean)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">var</span> s: SoundManager2_SMSound_AS3 = <span class="keyword">new</span> SoundManager2_SMSound_AS3(<span class="keyword">this</span>, sID, sURL, usePeakData, useWaveformData, useEQData, useNetstream, bufferTime, serverUrl, duration, autoPlay, useEvents, autoLoad, checkPolicyFile);\r
+ <span class="keyword">if</span> (!soundObjects[sID]) {\r
+ sounds.push(sID);\r
+ }\r
+ soundObjects[sID] = s;\r
+ <span class="keyword">this</span>.currentObject = s;\r
+ s.sID = sID;\r
+ s.sURL = sURL;\r
+ s.paused = <span class="literal">false</span>;\r
+ s.loaded = <span class="literal">false</span>;\r
+ s.checkPolicyFile = checkPolicyFile;\r
+ s.lastValues = {\r
+ bytes: <span class="number">0</span>,\r
+ duration: <span class="number">0</span>,\r
+ position: <span class="number">0</span>,\r
+ loops: loops||<span class="number">1</span>,\r
+ leftPeak: <span class="number">0</span>,\r
+ rightPeak: <span class="number">0</span>,\r
+ bufferLength: <span class="number">0</span>\r
+ };\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_destroySound</span><span class="params">(sID:String)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-64">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-64">¶</a>
+ </div>
+ <p>for the power of garbage collection! .. er, Greyskull!</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> s: SoundManager2_SMSound_AS3 = (soundObjects[sID] || <span class="literal">null</span>);\r
+ <span class="keyword">if</span> (!s) <span class="keyword">return</span> <span class="keyword">void</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-65">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-65">¶</a>
+ </div>
+ <p>try to unload the sound</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">for</span> (<span class="keyword">var</span> i: int = <span class="number">0</span>, j: int = sounds.length; i < j; i++) {\r
+ <span class="keyword">if</span> (sounds[i] == sID) {\r
+ sounds.splice(i, <span class="number">1</span>);\r
+ <span class="keyword">break</span>;\r
+ }\r
+ }\r
+ <span class="keyword">if</span> (s.soundChannel) {\r
+ s.soundChannel.stop();\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-66">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-66">¶</a>
+ </div>
+ <p>if is a movie, remove that as well.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.useNetstream) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-67">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-67">¶</a>
+ </div>
+ <p>s.nc.client = null;</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">try</span> {\r
+ s.removeNetstreamEvents();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-68">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-68">¶</a>
+ </div>
+ <p>s.nc.removeEventListener(NetStatusEvent.NET_STATUS, s.doNetStatus);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'_destroySound(): Events already removed from netStream/netConnection?'</span>);\r
+ }\r
+ <span class="keyword">if</span> (s.didLoad) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-69">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-69">¶</a>
+ </div>
+ <p>TODO: figure out if stream is still open first, can't close an already-closed stream.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">try</span> {\r
+ s.ns.close();\r
+ s.nc.close();\r
+ } <span class="keyword">catch</span>(e: Error) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-70">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-70">¶</a>
+ </div>
+ <p>oh well</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">'_destroySound(): caught exception: '</span>+e.toString());\r
+ }\r
+ }\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s.didLoad) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-71">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-71">¶</a>
+ </div>
+ <p>non-netstream case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">try</span> {\r
+ s.close(); <span class="comment">// close stream only if still loading?</span>\r
+ } <span class="keyword">catch</span>(e: Error) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-72">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-72">¶</a>
+ </div>
+ <p>oh well</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+ }\r
+ s = <span class="literal">null</span>;\r
+ soundObjects[sID] = <span class="literal">null</span>;\r
+ <span class="keyword">delete</span> soundObjects[sID];\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_stop</span><span class="params">(sID:String, bStopAll: Boolean)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-73">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-73">¶</a>
+ </div>
+ <p>stop this particular instance (or "all", based on parameter)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (bStopAll) {\r
+ SoundMixer.stopAll();\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">var</span> s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ <span class="keyword">if</span> (!s) <span class="keyword">return</span> <span class="keyword">void</span>;\r
+ <span class="keyword">if</span> (s.useNetstream && s.ns) {\r
+ s.ns.pause();\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s.soundChannel) {\r
+ s.soundChannel.stop();\r
+ }\r
+ s.paused = <span class="literal">false</span>;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_start</span><span class="params">(sID:String, nLoops: int, nMsecOffset: int, allowMultiShot: Boolean)</span> <span class="type">: Boolean</span> {</span>\r
+ <span class="keyword">var</span> s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ <span class="keyword">var</span> result: Boolean;\r
+ <span class="keyword">if</span> (!s) <span class="keyword">return</span> <span class="literal">true</span>;\r
+ writeDebug(<span class="string">'start ('</span> + sID + <span class="string">'): '</span> + nMsecOffset + (nLoops > <span class="number">1</span> ? <span class="string">', loops: '</span> + nLoops : <span class="string">''</span>));\r
+ s.lastValues.paused = <span class="literal">false</span>; <span class="comment">// reset pause if applicable</span>\r
+ s.lastValues.loops = (nLoops || <span class="number">1</span>);\r
+ <span class="keyword">if</span> (!s.useNetstream) {\r
+ s.lastValues.position = nMsecOffset;\r
+ }\r
+ s.handledDataError = <span class="literal">false</span>; <span class="comment">// reset this flag</span>\r
+ <span class="keyword">try</span> {\r
+ result = s.start(nMsecOffset, nLoops, allowMultiShot);\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'Could not start '</span> + sID + <span class="string">': '</span> + e.toString());\r
+ }\r
+ <span class="keyword">try</span> {\r
+ registerOnComplete(sID);\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'_start(): registerOnComplete failed'</span>);\r
+ }\r
+ <span class="keyword">return</span> result;\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_pause</span><span class="params">(sID:String, allowMultiShot: Boolean)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-74">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-74">¶</a>
+ </div>
+ <p>writeDebug('_pause(): ' + sID);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ <span class="keyword">if</span> (!s) <span class="keyword">return</span> <span class="keyword">void</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-75">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-75">¶</a>
+ </div>
+ <p>writeDebug('s.paused: '+s.paused);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s.paused) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-76">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-76">¶</a>
+ </div>
+ <p>reference current position, stop sound</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.paused = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-77">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-77">¶</a>
+ </div>
+ <p>writeDebug('_pause(): position: '+s.lastValues.position);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.useNetstream) {\r
+ <span class="keyword">if</span> (s.ns) {\r
+ s.lastValues.position = s.ns.time*<span class="number">1000</span>;\r
+ s.ns.pause();\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s.autoPlay) {\r
+ s.setAutoPlay(<span class="literal">false</span>);\r
+ }\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">if</span> (s.soundChannel) {\r
+ s.lastValues.position = s.soundChannel.position;\r
+ s.soundChannel.stop();\r
+ }\r
+ }\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-78">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-78">¶</a>
+ </div>
+ <p>resume playing from last position
+writeDebug('resuming - playing at '+s.lastValues.position+', '+s.lastValues.loops+' times');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.paused = <span class="literal">false</span>;\r
+ <span class="keyword">if</span> (s.useNetstream) {\r
+ s.ns.resume();\r
+ } <span class="keyword">else</span> {\r
+ s.start(s.lastValues.position, s.lastValues.loops, allowMultiShot);\r
+ }\r
+ <span class="keyword">try</span> {\r
+ registerOnComplete(sID);\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'_pause(): registerOnComplete() failed'</span>);\r
+ }\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_setPan</span><span class="params">(sID:String, nPan:Number)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">if</span> (soundObjects[sID]) {\r
+ soundObjects[sID].setPan(nPan);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_setVolume</span><span class="params">(sID:String, nVol:Number)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-79">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-79">¶</a>
+ </div>
+ <p>writeDebug('_setVolume: '+nVol);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (soundObjects[sID]) {\r
+ soundObjects[sID].setVolume(nVol);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_setPolling</span><span class="params">(bPolling: Boolean = false, nTimerInterval: uint = 50)</span> <span class="type">: void</span> {</span>\r
+ pollingEnabled = bPolling;\r
+ <span class="keyword">if</span> (timer == <span class="literal">null</span> && pollingEnabled) {\r
+ flashDebug(<span class="string">'Enabling polling, '</span> + nTimerInterval + <span class="string">' ms interval'</span>);\r
+ timer = <span class="keyword">new</span> Timer(nTimerInterval, <span class="number">0</span>);\r
+ timer.addEventListener(TimerEvent.TIMER, <span class="keyword">function</span>() : <span class="keyword">void</span> {\r
+ checkProgress();\r
+ }); <span class="comment">// direct reference eg. checkProgress doesn't work? .. odd.</span>\r
+ timer.start();\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (timer && !pollingEnabled) {\r
+ flashDebug(<span class="string">'Disabling polling'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-80">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-80">¶</a>
+ </div>
+ <p>flash.utils.clearInterval(timer);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> timer.reset();\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">_getMemoryUse</span><span class="params">()</span> <span class="type">: String</span> {</span>\r
+ <span class="keyword">return</span> System.totalMemory.toString();\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-81">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-81">¶</a>
+ </div>
+ <hr>
+<p>end methods</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-82">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-82">¶</a>
+ </div>
+ <p>package</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+}</pre></div></div>
+
+ </li>
+
+ </ul>
+ </div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+
+<html>
+<head>
+ <title>SoundManager2_SMSound_AS3.as</title>
+<meta name="robots" content="noindex" />
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
+ <link rel="stylesheet" media="all" href="docco.css" />
+</head>
+<body>
+ <div id="container">
+ <div id="background"></div>
+
+ <ul id="jump_to">
+ <li>
+ <a class="large" href="javascript:void(0);">Jump To …</a>
+ <a class="small" href="javascript:void(0);">+</a>
+ <div id="jump_wrapper">
+ <div id="jump_page">
+
+
+ <a class="source" href="soundmanager2.html">
+ soundmanager2.js
+ </a>
+
+
+ <a class="source" href="SoundManager2_AS.html">
+ SoundManager2_AS.as
+ </a>
+
+
+ <a class="source" href="SoundManager2_AS3.html">
+ SoundManager2_AS3.as
+ </a>
+
+
+ <a class="source" href="SoundManager2_SMSound_AS3.html">
+ SoundManager2_SMSound_AS3.as
+ </a>
+
+ </div>
+ </li>
+ </ul>
+
+ <ul class="sections">
+
+ <li id="title">
+ <div class="annotation">
+ <h1>SoundManager2_SMSound_AS3.as</h1>
+ </div>
+ </li>
+
+
+
+ <li id="section-1">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-1">¶</a>
+ </div>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre><span class="comment">/**\r
+ * SoundManager 2: Javascript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code licensed under the BSD License:\r
+ * http://www.schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * Flash 9 / ActionScript 3 version\r
+ */</span>\r
+\r
+<span class="package"><span class="keyword">package</span> {</span>\r
+\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.external.*;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.events.*;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.media.Sound;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.media.SoundChannel;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.media.SoundLoaderContext;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.media.SoundTransform;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.media.SoundMixer;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.net.URLRequest;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.utils.ByteArray;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.utils.getTimer;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.net.NetConnection;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.net.NetStream;</span>\r
+ <span class="preprocessor"><span class="keyword">import</span> flash.net.Responder;</span>\r
+\r
+ <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">SoundManager2_SMSound_AS3</span> <span class="keyword">extends</span> <span class="title">Sound</span> {</span>\r
+\r
+ <span class="keyword">public</span> <span class="keyword">var</span> sm: SoundManager2_AS3 = <span class="literal">null</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-2">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-2">¶</a>
+ </div>
+ <p>externalInterface references (for Javascript callbacks)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">public</span> <span class="keyword">var</span> baseJSController: String = <span class="string">"soundManager"</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> baseJSObject: String = baseJSController + <span class="string">".sounds"</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> soundChannel: SoundChannel = <span class="keyword">new</span> SoundChannel();\r
+ <span class="keyword">public</span> <span class="keyword">var</span> urlRequest: URLRequest;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> soundLoaderContext: SoundLoaderContext;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> waveformData: ByteArray = <span class="keyword">new</span> ByteArray();\r
+ <span class="keyword">public</span> <span class="keyword">var</span> waveformDataArray: Array = [];\r
+ <span class="keyword">public</span> <span class="keyword">var</span> eqData: ByteArray = <span class="keyword">new</span> ByteArray();\r
+ <span class="keyword">public</span> <span class="keyword">var</span> eqDataArray: Array = [];\r
+ <span class="keyword">public</span> <span class="keyword">var</span> usePeakData: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> useWaveformData: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> useEQData: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> sID: String;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> sURL: String;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> didFinish: Boolean;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> loaded: Boolean;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> connected: Boolean;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> failed: Boolean;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> paused: Boolean;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> finished: Boolean;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> duration: Number;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> handledDataError: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> ignoreDataError: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> autoPlay: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> autoLoad: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> pauseOnBufferFull: Boolean = <span class="literal">false</span>; <span class="comment">// only applies to RTMP</span>\r
+ <span class="keyword">public</span> <span class="keyword">var</span> loops: Number = <span class="number">1</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> lastValues: Object = {\r
+ bytes: <span class="number">0</span>,\r
+ position: <span class="number">0</span>,\r
+ duration: <span class="number">0</span>,\r
+ volume: <span class="number">100</span>,\r
+ pan: <span class="number">0</span>,\r
+ loops: <span class="number">1</span>,\r
+ leftPeak: <span class="number">0</span>,\r
+ rightPeak: <span class="number">0</span>,\r
+ waveformDataArray: <span class="literal">null</span>,\r
+ eqDataArray: <span class="literal">null</span>,\r
+ isBuffering: <span class="literal">null</span>,\r
+ bufferLength: <span class="number">0</span>\r
+ };\r
+ <span class="keyword">public</span> <span class="keyword">var</span> didLoad: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> useEvents: Boolean = <span class="literal">false</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> sound: Sound = <span class="keyword">new</span> Sound();\r
+\r
+ <span class="keyword">public</span> <span class="keyword">var</span> cc: Object;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> nc: NetConnection;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> ns: NetStream = <span class="literal">null</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> st: SoundTransform;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> useNetstream: Boolean;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> bufferTime: Number = <span class="number">3</span>; <span class="comment">// previously 0.1</span>\r
+ <span class="keyword">public</span> <span class="keyword">var</span> lastNetStatus: String = <span class="literal">null</span>;\r
+ <span class="keyword">public</span> <span class="keyword">var</span> serverUrl: String = <span class="literal">null</span>;\r
+\r
+ <span class="keyword">public</span> <span class="keyword">var</span> checkPolicyFile:Boolean = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">SoundManager2_SMSound_AS3</span><span class="params">(oSoundManager: SoundManager2_AS3, sIDArg: String = null, sURLArg: String = null, usePeakData: Boolean = false, useWaveformData: Boolean = false, useEQData: Boolean = false, useNetstreamArg: Boolean = false, netStreamBufferTime: Number = 1, serverUrl: String = null, duration: Number = 0, autoPlay: Boolean = false, useEvents: Boolean = false, autoLoad: Boolean = false, checkPolicyFile: Boolean = false)</span> {</span>\r
+ <span class="keyword">this</span>.sm = oSoundManager;\r
+ <span class="keyword">this</span>.sID = sIDArg;\r
+ <span class="keyword">this</span>.sURL = sURLArg;\r
+ <span class="keyword">this</span>.usePeakData = usePeakData;\r
+ <span class="keyword">this</span>.useWaveformData = useWaveformData;\r
+ <span class="keyword">this</span>.useEQData = useEQData;\r
+ <span class="keyword">this</span>.urlRequest = <span class="keyword">new</span> URLRequest(sURLArg);\r
+ <span class="keyword">this</span>.didFinish = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.loaded = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.connected = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.failed = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.finished = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.soundChannel = <span class="literal">null</span>;\r
+ <span class="keyword">this</span>.lastNetStatus = <span class="literal">null</span>;\r
+ <span class="keyword">this</span>.useNetstream = useNetstreamArg;\r
+ <span class="keyword">this</span>.serverUrl = serverUrl;\r
+ <span class="keyword">this</span>.duration = duration;\r
+ <span class="keyword">this</span>.useEvents = useEvents;\r
+ <span class="keyword">this</span>.autoLoad = autoLoad;\r
+ <span class="keyword">if</span> (netStreamBufferTime) {\r
+ <span class="keyword">this</span>.bufferTime = netStreamBufferTime;\r
+ }\r
+ <span class="keyword">this</span>.checkPolicyFile = checkPolicyFile;\r
+\r
+ writeDebug(<span class="string">'SoundManager2_SMSound_AS3: Got duration: '</span>+duration+<span class="string">', autoPlay: '</span>+autoPlay);\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.useNetstream) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-3">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-3">¶</a>
+ </div>
+ <p>Pause on buffer full if auto-loading an RTMP stream</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (<span class="keyword">this</span>.serverUrl && <span class="keyword">this</span>.autoLoad) {\r
+ <span class="keyword">this</span>.pauseOnBufferFull = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">this</span>.cc = <span class="keyword">new</span> Object();\r
+ <span class="keyword">this</span>.nc = <span class="keyword">new</span> NetConnection();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-4">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-4">¶</a>
+ </div>
+ <p>Handle FMS bandwidth check callback.
+@see onBWDone
+@see <a href="http://www.adobe.com/devnet/flashmediaserver/articles/dynamic_stream_switching_04.html">http://www.adobe.com/devnet/flashmediaserver/articles/dynamic_stream_switching_04.html</a>
+@see <a href="http://www.johncblandii.com/index.php/2007/12/fms-a-quick-fix-for-missing-onbwdone-onfcsubscribe-etc.html">http://www.johncblandii.com/index.php/2007/12/fms-a-quick-fix-for-missing-onbwdone-onfcsubscribe-etc.html</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.nc.client = <span class="keyword">this</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-5">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-5">¶</a>
+ </div>
+ <p>TODO: security/IO error handling
+this.nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, doSecurityError);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.serverUrl != <span class="literal">null</span>) {\r
+ writeDebug(<span class="string">'SoundManager2_SMSound_AS3: NetConnection: connecting to server '</span> + <span class="keyword">this</span>.serverUrl + <span class="string">'...'</span>);\r
+ }\r
+ <span class="keyword">this</span>.nc.connect(serverUrl);\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">this</span>.connected = <span class="literal">true</span>;\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">rtmpResponder</span><span class="params">(result:Object)</span><span class="type">:void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-6">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-6">¶</a>
+ </div>
+ <p>callback from Flash Media Server (RTMP) for 'getStreamLength' server-side method - result should be a floating-point.
+<a href="http://help.adobe.com/en_US/FlashMediaServer/3.5_Deving/WS5b3ccc516d4fbf351e63e3d11a0773d117-7ffe.html">http://help.adobe.com/en_US/FlashMediaServer/3.5_Deving/WS5b3ccc516d4fbf351e63e3d11a0773d117-7ffe.html</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">'RTMP server getStreamLength() response: '</span> + result);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-7">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-7">¶</a>
+ </div>
+ <p>we now know the duration. type cast to floating-point - this will update JS-land during whileloading() / whileplaying().</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.duration = Number(result) * <span class="number">1000</span>;\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">netStatusHandler</span><span class="params">(event:NetStatusEvent)</span><span class="type">:void</span> {</span>\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.useEvents) {\r
+ writeDebug(<span class="string">'netStatusHandler: '</span>+event.info.code);\r
+ }\r
+\r
+ <span class="keyword">switch</span> (event.info.code) {\r
+\r
+ <span class="keyword">case</span> <span class="string">"NetConnection.Connect.Success"</span>:\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">this</span>.ns = <span class="keyword">new</span> NetStream(<span class="keyword">this</span>.nc);\r
+ <span class="keyword">this</span>.ns.checkPolicyFile = <span class="keyword">this</span>.checkPolicyFile;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-8">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-8">¶</a>
+ </div>
+ <p>bufferTime reference: <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/NetStream.html#bufferTime">http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/NetStream.html#bufferTime</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.ns.bufferTime = <span class="keyword">this</span>.bufferTime; <span class="comment">// set to 0.1 or higher. 0 is reported to cause playback issues with static files.</span>\r
+ <span class="keyword">this</span>.st = <span class="keyword">new</span> SoundTransform();\r
+ <span class="keyword">this</span>.cc.onMetaData = <span class="keyword">this</span>.onMetaData;\r
+ <span class="keyword">this</span>.cc.setCaption = <span class="keyword">this</span>.captionHandler;\r
+ <span class="keyword">this</span>.ns.client = <span class="keyword">this</span>.cc;\r
+ <span class="keyword">this</span>.ns.receiveAudio(<span class="literal">true</span>);\r
+ <span class="keyword">this</span>.addNetstreamEvents();\r
+ <span class="keyword">this</span>.connected = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-9">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-9">¶</a>
+ </div>
+ <p>RTMP-only</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (<span class="keyword">this</span>.serverUrl && <span class="keyword">this</span>.useEvents) {\r
+ <span class="keyword">var</span> responder:Responder = <span class="keyword">new</span> Responder(rtmpResponder);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-10">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-10">¶</a>
+ </div>
+ <p>call a method on server to get the length of the stream (like onMetaData, but Flash Media Server-specific)
+Red5 and other RTMP servers appear to provide duration via onMetaData event(s) in the stream.
+<a href="http://help.adobe.com/en_US/FlashMediaServer/3.5_Deving/WS5b3ccc516d4fbf351e63e3d11a0773d117-7ffe.html">http://help.adobe.com/en_US/FlashMediaServer/3.5_Deving/WS5b3ccc516d4fbf351e63e3d11a0773d117-7ffe.html</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> nc.call(<span class="string">'getStreamLength'</span>, responder, <span class="keyword">this</span>.sURL);\r
+ writeDebug(<span class="string">'NetConnection: connected'</span>);\r
+ writeDebug(<span class="string">'firing _onconnect for '</span>+<span class="keyword">this</span>.sID);\r
+ ExternalInterface.call(<span class="keyword">this</span>.sm.baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onconnect"</span>, <span class="number">1</span>);\r
+ }\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ <span class="keyword">this</span>.failed = <span class="literal">true</span>;\r
+ writeDebug(<span class="string">'netStream error: '</span> + e.toString());\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onfailure"</span>, <span class="string">'Connection failed!'</span>, event.info.level, event.info.code);\r
+ }\r
+ <span class="keyword">break</span>;\r
+\r
+ <span class="keyword">case</span> <span class="string">"NetStream.Play.StreamNotFound"</span>:\r
+ <span class="keyword">this</span>.failed = <span class="literal">true</span>;\r
+ writeDebug(<span class="string">"NetConnection: Stream not found!"</span>);\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onfailure"</span>, <span class="string">'Stream not found!'</span>, event.info.level, event.info.code);\r
+ <span class="keyword">break</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-11">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-11">¶</a>
+ </div>
+ <p>This is triggered when the sound loses the connection with the server.
+In some cases one could just try to reconnect to the server and resume playback.
+However for streams protected by expiring tokens, I don't think that will work.</p>
+<p>Flash says that this is not an error code, but a status code...
+should this call the onFailure handler?</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">case</span> <span class="string">"NetConnection.Connect.Closed"</span>:\r
+ <span class="keyword">this</span>.failed = <span class="literal">true</span>;\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onfailure"</span>, <span class="string">'Connection closed!'</span>, event.info.level, event.info.code);\r
+ writeDebug(<span class="string">"NetConnection: Connection closed!"</span>);\r
+ <span class="keyword">break</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-12">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-12">¶</a>
+ </div>
+ <p>Couldn't establish a connection with the server. Attempts to connect to the server
+can also fail if the permissible number of socket connections on either the client
+or the server computer is at its limit. This also happens when the internet
+connection is lost.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">case</span> <span class="string">"NetConnection.Connect.Failed"</span>:\r
+ <span class="keyword">this</span>.failed = <span class="literal">true</span>;\r
+ writeDebug(<span class="string">"NetConnection: Connection failed! Lost internet connection? Try again... Description: "</span> + event.info.description);\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onfailure"</span>, <span class="string">'Connection failed!'</span>, event.info.level, event.info.code);\r
+ <span class="keyword">break</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-13">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-13">¶</a>
+ </div>
+ <p>A change has occurred to the network status. This could mean that the network
+connection is back, or it could mean that it has been lost...just try to resume
+playback.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-14">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-14">¶</a>
+ </div>
+ <p>KJV: Can't use this yet because by the time you get your connection back the
+song has reached it's maximum retries, so it doesn't retry again. We need
+a new _ondisconnect handler.
+case "NetConnection.Connect.NetworkChange":
+ this.failed = true;
+ writeDebug("NetConnection: Network connection status changed");
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onfailure", 'Reconnecting...');
+ break;</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-15">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-15">¶</a>
+ </div>
+ <p>Consider everything else a warning...</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">default</span>:</pre></div></div>
+
+ </li>
+
+
+ <li id="section-16">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-16">¶</a>
+ </div>
+ <p>this.failed = true;</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">"NetConnection: got unhandled code '"</span> + event.info.code + <span class="string">"'. Description: "</span> + event.info.description);\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onwarning"</span>, event.info.description, event.info.level, event.info.code);\r
+ <span class="keyword">break</span>;\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">writeDebug</span> <span class="params">(s: String, logLevel: Number = 0)</span> <span class="type">: Boolean</span> {</span>\r
+ <span class="keyword">return</span> <span class="keyword">this</span>.sm.writeDebug (s,logLevel); <span class="comment">// defined in main SM object</span>\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">onMetaData</span><span class="params">(infoObject: Object)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">var</span> prop:String;\r
+ <span class="keyword">if</span> (sm.debugEnabled) {\r
+ <span class="keyword">var</span> data:String = <span class="keyword">new</span> String();\r
+ <span class="keyword">for</span> (prop <span class="keyword">in</span> infoObject) {\r
+ data += prop+<span class="string">': '</span>+infoObject[prop]+<span class="string">' \n'</span>;\r
+ }\r
+ writeDebug(<span class="string">'Metadata: '</span>+data);\r
+ }\r
+ <span class="keyword">this</span>.duration = infoObject.duration * <span class="number">1000</span>;\r
+ <span class="keyword">if</span> (!<span class="keyword">this</span>.loaded) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-17">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-17">¶</a>
+ </div>
+ <p>writeDebug('not loaded yet: '+this.ns.bytesLoaded+', '+this.ns.bytesTotal+', '+infoObject.duration<em>1000);
+TODO: investigate loaded/total values
+ExternalInterface.call(baseJSObject + "['" + this.sID + "']._whileloading", this.ns.bytesLoaded, this.ns.bytesTotal, infoObject.duration</em>1000);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._whileloading"</span>, <span class="keyword">this</span>.bytesLoaded, <span class="keyword">this</span>.bytesTotal, (<span class="keyword">this</span>.duration || infoObject.duration))\r
+ }\r
+ <span class="keyword">var</span> metaData:Array = [];\r
+ <span class="keyword">var</span> metaDataProps:Array = [];\r
+ <span class="keyword">for</span> (prop <span class="keyword">in</span> infoObject) {\r
+ metaData.push(prop);\r
+ metaDataProps.push(infoObject[prop]);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-18">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-18">¶</a>
+ </div>
+ <p>pass infoObject to _onmetadata, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onmetadata"</span>, metaData, metaDataProps);\r
+writeDebug(<span class="string">'waiting for next call...'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-19">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-19">¶</a>
+ </div>
+ <p>this handler may fire multiple times, eg., when a song changes while playing an RTMP stream.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!<span class="keyword">this</span>.serverUrl) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-20">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-20">¶</a>
+ </div>
+ <p>disconnect for non-RTMP cases, since multiple firings may mess up duration.
+this.cc.onMetaData = function(infoObject: Object) : void {}</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">captionHandler</span><span class="params">(infoObject: Object)</span> <span class="type">: void</span> {</span>\r
+\r
+ <span class="keyword">if</span> (sm.debugEnabled) {\r
+ <span class="keyword">var</span> data:String = <span class="keyword">new</span> String();\r
+ <span class="keyword">for</span> (<span class="keyword">var</span> prop:* <span class="keyword">in</span> infoObject) {\r
+ data += prop+<span class="string">': '</span>+infoObject[prop]+<span class="string">' \n'</span>;\r
+ }\r
+ writeDebug(<span class="string">'Caption: '</span>+data);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-21">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-21">¶</a>
+ </div>
+ <p>null this out for the duration of this object's existence.
+it may be called multiple times.
+this.cc.setCaption = function(infoObject: Object) : void {}</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-22">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-22">¶</a>
+ </div>
+ <p>writeDebug('Caption\n'+infoObject['dynamicMetadata']);
+writeDebug('firing _oncaptiondata for '+this.sID);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ ExternalInterface.call(<span class="keyword">this</span>.sm.baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._oncaptiondata"</span>, infoObject[<span class="string">'dynamicMetadata'</span>]);\r
+\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getWaveformData</span><span class="params">()</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-23">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-23">¶</a>
+ </div>
+ <p><a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum(">http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum(</a>)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> SoundMixer.computeSpectrum(<span class="keyword">this</span>.waveformData, <span class="literal">false</span>, <span class="number">0</span>); <span class="comment">// sample wave data at 44.1 KHz</span>\r
+ <span class="keyword">this</span>.waveformDataArray = [];\r
+ <span class="keyword">for</span> (<span class="keyword">var</span> i: int = <span class="number">0</span>, j: int = <span class="keyword">this</span>.waveformData.length / <span class="number">4</span>; i < j; i++) { <span class="comment">// get all 512 values (256 per channel)</span>\r
+ <span class="keyword">this</span>.waveformDataArray.push(int(<span class="keyword">this</span>.waveformData.readFloat() * <span class="number">1000</span>) / <span class="number">1000</span>);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getEQData</span><span class="params">()</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-24">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-24">¶</a>
+ </div>
+ <p><a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum(">http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum(</a>)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> SoundMixer.computeSpectrum(<span class="keyword">this</span>.eqData, <span class="literal">true</span>, <span class="number">0</span>); <span class="comment">// sample EQ data at 44.1 KHz</span>\r
+ <span class="keyword">this</span>.eqDataArray = [];\r
+ <span class="keyword">for</span> (<span class="keyword">var</span> i: int = <span class="number">0</span>, j: int = <span class="keyword">this</span>.eqData.length / <span class="number">4</span>; i < j; i++) { <span class="comment">// get all 512 values (256 per channel)</span>\r
+ <span class="keyword">this</span>.eqDataArray.push(int(<span class="keyword">this</span>.eqData.readFloat() * <span class="number">1000</span>) / <span class="number">1000</span>);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">start</span><span class="params">(nMsecOffset: int, nLoops: int, allowMultiShot:Boolean)</span> <span class="type">: Boolean</span> {</span>\r
+\r
+ <span class="keyword">this</span>.useEvents = <span class="literal">true</span>;\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.useNetstream) {\r
+\r
+ writeDebug(<span class="string">"SMSound::start nMsecOffset "</span>+ nMsecOffset+ <span class="string">' nLoops '</span>+nLoops + <span class="string">' current bufferTime '</span>+<span class="keyword">this</span>.ns.bufferTime+<span class="string">' current bufferLength '</span>+<span class="keyword">this</span>.ns.bufferLength+ <span class="string">' this.lastValues.position '</span>+<span class="keyword">this</span>.lastValues.position);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-25">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-25">¶</a>
+ </div>
+ <p>mark for later Netstream.Play.Stop / sound completion</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.finished = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">this</span>.cc.onMetaData = <span class="keyword">this</span>.onMetaData;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-26">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-26">¶</a>
+ </div>
+ <p>Don't seek if we don't have to because it destroys the buffer</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> set_position:Boolean = <span class="keyword">this</span>.lastValues.position != <span class="literal">null</span> && <span class="keyword">this</span>.lastValues.position != nMsecOffset;\r
+\r
+ <span class="keyword">if</span> (set_position) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-27">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-27">¶</a>
+ </div>
+ <p>Minimize the buffer so playback starts ASAP</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.ns.bufferTime = <span class="keyword">this</span>.bufferTime;\r
+ }\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.paused) {\r
+ writeDebug(<span class="string">'start: resuming from paused state'</span>);\r
+ <span class="keyword">this</span>.ns.resume(); <span class="comment">// get the sound going again</span>\r
+ <span class="keyword">if</span> (!<span class="keyword">this</span>.didLoad) {\r
+ <span class="keyword">this</span>.didLoad = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">this</span>.paused = <span class="literal">false</span>;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="keyword">this</span>.didLoad) {\r
+ writeDebug(<span class="string">'start: !didLoad - playing '</span>+<span class="keyword">this</span>.sURL);\r
+ <span class="keyword">this</span>.ns.play(<span class="keyword">this</span>.sURL);\r
+ <span class="keyword">this</span>.pauseOnBufferFull = <span class="literal">false</span>; <span class="comment">// SAS: playing behaviour overrides buffering behaviour</span>\r
+ <span class="keyword">this</span>.didLoad = <span class="literal">true</span>;\r
+ <span class="keyword">this</span>.paused = <span class="literal">false</span>;\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-28">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-28">¶</a>
+ </div>
+ <p>previously loaded, perhaps stopped/finished. play again?</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">'playing again (not paused, didLoad = true)'</span>);\r
+ <span class="keyword">this</span>.pauseOnBufferFull = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.ns.play(<span class="keyword">this</span>.sURL);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-29">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-29">¶</a>
+ </div>
+ <p>KJV seek after calling play otherwise some streams get a NetStream.Seek.Failed
+Should only apply to the !didLoad case, but do it for all for simplicity.
+nMsecOffset is in milliseconds for streams but in seconds for progressive
+download.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (set_position) {\r
+ <span class="keyword">this</span>.ns.seek(<span class="keyword">this</span>.serverUrl ? nMsecOffset / <span class="number">1000</span> : nMsecOffset);\r
+ <span class="keyword">this</span>.lastValues.position = nMsecOffset; <span class="comment">// https://gist.github.com/1de8a3113cf33d0cff67</span>\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-30">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-30">¶</a>
+ </div>
+ <p>this.ns.addEventListener(Event.SOUND_COMPLETE, _onfinish);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.applyTransform();\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-31">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-31">¶</a>
+ </div>
+ <p>writeDebug('start: seeking to '+nMsecOffset+', '+nLoops+(nLoops==1?' loop':' loops'));</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!<span class="keyword">this</span>.soundChannel || allowMultiShot) {\r
+ <span class="keyword">this</span>.soundChannel = <span class="keyword">this</span>.play(nMsecOffset, nLoops);\r
+ <span class="keyword">this</span>.addEventListener(Event.SOUND_COMPLETE, _onfinish);\r
+ <span class="keyword">this</span>.applyTransform();\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-32">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-32">¶</a>
+ </div>
+ <p>writeDebug('start: was already playing, no-multishot case. Seeking to '+nMsecOffset+', '+nLoops+(nLoops==1?' loop':' loops'));
+already playing and no multi-shot allowed, so re-start and set position</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (<span class="keyword">this</span>.soundChannel) {\r
+ <span class="keyword">this</span>.soundChannel.stop();\r
+ }\r
+ <span class="keyword">this</span>.soundChannel = <span class="keyword">this</span>.play(nMsecOffset, nLoops); <span class="comment">// start playing at new position</span>\r
+ <span class="keyword">this</span>.addEventListener(Event.SOUND_COMPLETE, _onfinish);\r
+ <span class="keyword">this</span>.applyTransform();\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-33">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-33">¶</a>
+ </div>
+ <p>if soundChannel is null (and not a netStream), there is no sound card (or 32-channel ceiling has been hit.)
+<a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29">http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> (!<span class="keyword">this</span>.useNetstream && <span class="keyword">this</span>.soundChannel === <span class="literal">null</span> ? <span class="literal">false</span> : <span class="literal">true</span>);\r
+\r
+ }\r
+\r
+ <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">_onfinish</span><span class="params">()</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">this</span>.removeEventListener(Event.SOUND_COMPLETE, _onfinish);\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">loadSound</span><span class="params">(sURL: String)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.useNetstream) {\r
+ <span class="keyword">this</span>.useEvents = <span class="literal">true</span>;\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.didLoad != <span class="literal">true</span>) {\r
+ <span class="keyword">this</span>.ns.play(<span class="keyword">this</span>.sURL); <span class="comment">// load streams by playing them</span>\r
+ <span class="keyword">if</span> (!<span class="keyword">this</span>.autoPlay) {\r
+ <span class="keyword">this</span>.pauseOnBufferFull = <span class="literal">true</span>;\r
+ }\r
+ <span class="keyword">this</span>.paused = <span class="literal">false</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-34">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-34">¶</a>
+ </div>
+ <p>this.addEventListener(Event.SOUND_COMPLETE, _onfinish);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.applyTransform();\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">this</span>.didLoad = <span class="literal">true</span>;\r
+ <span class="keyword">this</span>.urlRequest = <span class="keyword">new</span> URLRequest(sURL);\r
+ <span class="keyword">this</span>.soundLoaderContext = <span class="keyword">new</span> SoundLoaderContext(<span class="number">1000</span>, <span class="keyword">this</span>.checkPolicyFile); <span class="comment">// check for policy (crossdomain.xml) file on remote domains - http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundLoaderContext.html</span>\r
+ <span class="keyword">this</span>.load(<span class="keyword">this</span>.urlRequest, <span class="keyword">this</span>.soundLoaderContext);\r
+ } <span class="keyword">catch</span>(e: Error) {\r
+ writeDebug(<span class="string">'error during loadSound(): '</span> + e.toString());\r
+ }\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-35">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-35">¶</a>
+ </div>
+ <p>Set the value of autoPlay</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">setAutoPlay</span><span class="params">(autoPlay: Boolean)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">if</span> (!<span class="keyword">this</span>.serverUrl) {\r
+ <span class="keyword">this</span>.autoPlay = autoPlay;\r
+ } <span class="keyword">else</span> {\r
+ <span class="keyword">this</span>.autoPlay = autoPlay;\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.autoPlay) {\r
+ <span class="keyword">this</span>.pauseOnBufferFull = <span class="literal">false</span>;\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="keyword">this</span>.autoPlay) {\r
+ <span class="keyword">this</span>.pauseOnBufferFull = <span class="literal">true</span>;\r
+ }\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">setVolume</span><span class="params">(nVolume: Number)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">this</span>.lastValues.volume = nVolume / <span class="number">100</span>;\r
+ <span class="keyword">this</span>.applyTransform();\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">setPan</span><span class="params">(nPan: Number)</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">this</span>.lastValues.pan = nPan / <span class="number">100</span>;\r
+ <span class="keyword">this</span>.applyTransform();\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">applyTransform</span><span class="params">()</span> <span class="type">: void</span> {</span>\r
+ <span class="keyword">var</span> st: SoundTransform = <span class="keyword">new</span> SoundTransform(<span class="keyword">this</span>.lastValues.volume, <span class="keyword">this</span>.lastValues.pan);\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.useNetstream) {\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.ns) {\r
+ <span class="keyword">this</span>.ns.soundTransform = st;\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-36">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-36">¶</a>
+ </div>
+ <p>writeDebug('applyTransform(): Note: No active netStream');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">this</span>.soundChannel) {\r
+ <span class="keyword">this</span>.soundChannel.soundTransform = st; <span class="comment">// new SoundTransform(this.lastValues.volume, this.lastValues.pan);</span>\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-37">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-37">¶</a>
+ </div>
+ <p>Handle FMS bandwidth check callback.
+@see <a href="http://www.adobe.com/devnet/flashmediaserver/articles/dynamic_stream_switching_04.html">http://www.adobe.com/devnet/flashmediaserver/articles/dynamic_stream_switching_04.html</a>
+@see <a href="http://www.johncblandii.com/index.php/2007/12/fms-a-quick-fix-for-missing-onbwdone-onfcsubscribe-etc.html">http://www.johncblandii.com/index.php/2007/12/fms-a-quick-fix-for-missing-onbwdone-onfcsubscribe-etc.html</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">onBWDone</span><span class="params">()</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-38">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-38">¶</a>
+ </div>
+ <p>writeDebug('onBWDone: called and ignored');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-39">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-39">¶</a>
+ </div>
+ <p>NetStream client callback. Invoked when the song is complete.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">onPlayStatus</span><span class="params">(info:Object)</span><span class="type">:void</span> {</span>\r
+ writeDebug(<span class="string">'onPlayStatus called with '</span>+info);\r
+ <span class="keyword">switch</span>(info.code) {\r
+ <span class="keyword">case</span> <span class="string">"NetStream.Play.Complete"</span>:\r
+ writeDebug(<span class="string">'Song has finished!'</span>);\r
+ <span class="keyword">break</span>;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">doIOError</span><span class="params">(e: IOErrorEvent)</span> <span class="type">: void</span> {</span>\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onload"</span>, <span class="number">0</span>); <span class="comment">// call onload, assume it failed.</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-40">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-40">¶</a>
+ </div>
+ <p>there was a connection drop, a loss of internet connection, or something else wrong. 404 error too.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">doAsyncError</span><span class="params">(e: AsyncErrorEvent)</span> <span class="type">: void</span> {</span>\r
+ writeDebug(<span class="string">'asyncError: '</span> + e.text);\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">doNetStatus</span><span class="params">(e: NetStatusEvent)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-41">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-41">¶</a>
+ </div>
+ <p>Handle failures</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (e.info.code == <span class="string">"NetStream.Failed"</span>\r
+ || e.info.code == <span class="string">"NetStream.Play.FileStructureInvalid"</span>\r
+ || e.info.code == <span class="string">"NetStream.Play.StreamNotFound"</span>) {\r
+\r
+ <span class="keyword">this</span>.lastNetStatus = e.info.code;\r
+ writeDebug(<span class="string">'netStatusEvent: '</span> + e.info.code);\r
+ <span class="keyword">this</span>.failed = <span class="literal">true</span>;\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onfailure"</span>, <span class="string">''</span>, e.info.level, e.info.code);\r
+ <span class="keyword">return</span>;\r
+ }\r
+\r
+ writeDebug(<span class="string">'netStatusEvent: '</span> + e.info.code); <span class="comment">// KJV we like to see all events</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-42">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-42">¶</a>
+ </div>
+ <p>When streaming, Stop is called when buffering stops, not when the stream is actually finished.
+@see <a href="http://www.actionscript.org/forums/archive/index.php3/t-159194.html">http://www.actionscript.org/forums/archive/index.php3/t-159194.html</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (e.info.code == <span class="string">"NetStream.Play.Stop"</span>) {\r
+\r
+ <span class="keyword">if</span> (!<span class="keyword">this</span>.finished && (!<span class="keyword">this</span>.useNetstream || !<span class="keyword">this</span>.serverUrl)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-43">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-43">¶</a>
+ </div>
+ <p>finished playing, and not RTMP</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">'calling onfinish for a sound'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-44">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-44">¶</a>
+ </div>
+ <p>reset the sound? Move back to position 0?</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.sm.checkProgress();\r
+ <span class="keyword">this</span>.finished = <span class="literal">true</span>; <span class="comment">// will be reset via JS callback</span>\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onfinish"</span>);\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (e.info.code == <span class="string">"NetStream.Play.Start"</span> || e.info.code == <span class="string">"NetStream.Buffer.Empty"</span> || e.info.code == <span class="string">"NetStream.Buffer.Full"</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-45">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-45">¶</a>
+ </div>
+ <p>RTMP case..
+We wait for the buffer to fill up before pausing the just-loaded song because only if the
+buffer is full will the song continue to buffer until the user hits play.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (<span class="keyword">this</span>.serverUrl && e.info.code == <span class="string">"NetStream.Buffer.Full"</span> && <span class="keyword">this</span>.pauseOnBufferFull) {\r
+ <span class="keyword">this</span>.ns.pause();\r
+ <span class="keyword">this</span>.paused = <span class="literal">true</span>;\r
+ <span class="keyword">this</span>.pauseOnBufferFull = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-46">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-46">¶</a>
+ </div>
+ <p>Call pause in JS. This will call back to us to pause again, but
+that should be harmless.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> writeDebug(<span class="string">'Pausing on buffer full'</span>);\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"'].pause"</span>, <span class="literal">false</span>);\r
+ }\r
+\r
+ <span class="keyword">var</span> isNetstreamBuffering: Boolean = (e.info.code == <span class="string">"NetStream.Buffer.Empty"</span> || e.info.code == <span class="string">"NetStream.Play.Start"</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-47">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-47">¶</a>
+ </div>
+ <p>assume buffering when we start playing, eg. initial load.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (isNetstreamBuffering != <span class="keyword">this</span>.lastValues.isBuffering) {\r
+ <span class="keyword">this</span>.lastValues.isBuffering = isNetstreamBuffering;\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onbufferchange"</span>, <span class="keyword">this</span>.lastValues.isBuffering ? <span class="number">1</span> : <span class="number">0</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-48">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-48">¶</a>
+ </div>
+ <p>We can detect the end of the stream when Play.Stop is called followed by Buffer.Empty.
+However, if you pause and let the whole song buffer, Buffer.Flush is called followed by
+Buffer.Empty, so handle that case too.</p>
+<p>Ignore this event if we are more than 3 seconds from the end of the song.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (e.info.code == <span class="string">"NetStream.Buffer.Empty"</span> && (<span class="keyword">this</span>.lastNetStatus == <span class="string">'NetStream.Play.Stop'</span> || <span class="keyword">this</span>.lastNetStatus == <span class="string">'NetStream.Buffer.Flush'</span>)) {\r
+ <span class="keyword">if</span> (<span class="keyword">this</span>.duration && (<span class="keyword">this</span>.ns.time * <span class="number">1000</span>) < (<span class="keyword">this</span>.duration - <span class="number">3000</span>)) {\r
+ writeDebug(<span class="string">'Ignoring Buffer.Empty because this is too early to be the end of the stream! (sID: '</span>+<span class="keyword">this</span>.sID+<span class="string">', time: '</span>+(<span class="keyword">this</span>.ns.time*<span class="number">1000</span>)+<span class="string">', duration: '</span>+<span class="keyword">this</span>.duration+<span class="string">')'</span>);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (!<span class="keyword">this</span>.finished) {\r
+ <span class="keyword">this</span>.finished = <span class="literal">true</span>;\r
+ writeDebug(<span class="string">'calling onfinish for sound '</span>+<span class="keyword">this</span>.sID);\r
+ <span class="keyword">this</span>.sm.checkProgress();\r
+ ExternalInterface.call(baseJSObject + <span class="string">"['"</span> + <span class="keyword">this</span>.sID + <span class="string">"']._onfinish"</span>);\r
+ }\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (e.info.code == <span class="string">"NetStream.Buffer.Empty"</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-49">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-49">¶</a>
+ </div>
+ <p>The buffer is empty. Start from the smallest buffer again.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.ns.bufferTime = <span class="keyword">this</span>.bufferTime;\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-50">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-50">¶</a>
+ </div>
+ <p>Remember the last NetStatus event</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.lastNetStatus = e.info.code;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-51">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-51">¶</a>
+ </div>
+ <p>KJV The sound adds some of its own netstatus handlers so we don't need to do it here.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">addNetstreamEvents</span><span class="params">()</span> <span class="type">: void</span> {</span>\r
+ ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, doAsyncError);\r
+ ns.addEventListener(NetStatusEvent.NET_STATUS, doNetStatus);\r
+ ns.addEventListener(IOErrorEvent.IO_ERROR, doIOError);\r
+ }\r
+\r
+ <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">removeNetstreamEvents</span><span class="params">()</span> <span class="type">: void</span> {</span>\r
+ ns.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, doAsyncError);\r
+ ns.removeEventListener(NetStatusEvent.NET_STATUS, doNetStatus);\r
+ ns.addEventListener(NetStatusEvent.NET_STATUS, dummyNetStatusHandler);\r
+ ns.removeEventListener(IOErrorEvent.IO_ERROR, doIOError);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-52">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-52">¶</a>
+ </div>
+ <p>KJV Stop listening for NetConnection events on the sound</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> nc.removeEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-53">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-53">¶</a>
+ </div>
+ <p>Prevents possible 'Unhandled NetStatusEvent' condition if a sound is being
+destroyed and interacted with at the same time.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">dummyNetStatusHandler</span><span class="params">(e: NetStatusEvent)</span> <span class="type">: void</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-54">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-54">¶</a>
+ </div>
+ <p>Don't do anything</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+ }\r
+}</pre></div></div>
+
+ </li>
+
+ </ul>
+ </div>
+</body>
+</html>
--- /dev/null
+/*--------------------- Typography ----------------------------*/
+
+@font-face {
+ font-family: 'aller-light';
+ src: url('public/fonts/aller-light.eot');
+ src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'),
+ url('public/fonts/aller-light.woff') format('woff'),
+ url('public/fonts/aller-light.ttf') format('truetype');
+ font-weight: normal;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'aller-bold';
+ src: url('public/fonts/aller-bold.eot');
+ src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'),
+ url('public/fonts/aller-bold.woff') format('woff'),
+ url('public/fonts/aller-bold.ttf') format('truetype');
+ font-weight: normal;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: 'novecento-bold';
+ src: url('public/fonts/novecento-bold.eot');
+ src: url('public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'),
+ url('public/fonts/novecento-bold.woff') format('woff'),
+ url('public/fonts/novecento-bold.ttf') format('truetype');
+ font-weight: normal;
+ font-style: normal;
+}
+
+/*--------------------- Layout ----------------------------*/
+html { height: 100%; }
+body {
+ font-family: "aller-light";
+ font-size: 14px;
+ line-height: 18px;
+ color: #30404f;
+ margin: 0; padding: 0;
+ height:100%;
+}
+#container { min-height: 100%; }
+
+a {
+ color: #000;
+}
+
+b, strong {
+ font-weight: normal;
+ font-family: "aller-bold";
+}
+
+p {
+ margin: 15px 0 0px;
+}
+ .annotation ul, .annotation ol {
+ margin: 25px 0;
+ }
+ .annotation ul li, .annotation ol li {
+ font-size: 14px;
+ line-height: 18px;
+ margin: 10px 0;
+ }
+
+h1, h2, h3, h4, h5, h6 {
+ color: #112233;
+ line-height: 1em;
+ font-weight: normal;
+ font-family: "novecento-bold";
+ text-transform: uppercase;
+ margin: 30px 0 15px 0;
+}
+
+h1 {
+ margin-top: 40px;
+}
+
+hr {
+ border: 0;
+ background: 1px solid #ddd;
+ height: 1px;
+ margin: 20px 0;
+}
+
+pre, tt, code {
+ font-size: 12px; line-height: 16px;
+ font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace;
+ margin: 0; padding: 0;
+}
+ .annotation pre {
+ display: block;
+ margin: 0;
+ padding: 7px 10px;
+ background: #fcfcfc;
+ -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
+ -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
+ box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
+ overflow-x: auto;
+ }
+ .annotation pre code {
+ border: 0;
+ padding: 0;
+ background: transparent;
+ }
+
+
+blockquote {
+ border-left: 5px solid #ccc;
+ margin: 0;
+ padding: 1px 0 1px 1em;
+}
+ .sections blockquote p {
+ font-family: Menlo, Consolas, Monaco, monospace;
+ font-size: 12px; line-height: 16px;
+ color: #999;
+ margin: 10px 0 0;
+ white-space: pre-wrap;
+ }
+
+ul.sections {
+ list-style: none;
+ padding:0 0 5px 0;;
+ margin:0;
+}
+
+/*
+ Force border-box so that % widths fit the parent
+ container without overlap because of margin/padding.
+
+ More Info : http://www.quirksmode.org/css/box.html
+*/
+ul.sections > li > div {
+ -moz-box-sizing: border-box; /* firefox */
+ -ms-box-sizing: border-box; /* ie */
+ -webkit-box-sizing: border-box; /* webkit */
+ -khtml-box-sizing: border-box; /* konqueror */
+ box-sizing: border-box; /* css3 */
+}
+
+
+/*---------------------- Jump Page -----------------------------*/
+#jump_to, #jump_page {
+ margin: 0;
+ background: white;
+ -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
+ -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
+ font: 16px Arial;
+ cursor: pointer;
+ text-align: right;
+ list-style: none;
+}
+
+#jump_to a {
+ text-decoration: none;
+}
+
+#jump_to a.large {
+ display: none;
+}
+#jump_to a.small {
+ font-size: 22px;
+ font-weight: bold;
+ color: #676767;
+}
+
+#jump_to, #jump_wrapper {
+ position: fixed;
+ right: 0; top: 0;
+ padding: 10px 15px;
+ margin:0;
+}
+
+#jump_wrapper {
+ display: none;
+ padding:0;
+}
+
+#jump_to:hover #jump_wrapper {
+ display: block;
+}
+
+#jump_page {
+ padding: 5px 0 3px;
+ margin: 0 0 25px 25px;
+}
+
+#jump_page .source {
+ display: block;
+ padding: 15px;
+ text-decoration: none;
+ border-top: 1px solid #eee;
+}
+
+#jump_page .source:hover {
+ background: #F9FCFF;
+}
+
+#jump_page .source:first-child {
+}
+
+/*---------------------- Low resolutions (> 320px) ---------------------*/
+@media only screen and (min-width: 320px) {
+ .pilwrap { display: none; }
+
+ ul.sections > li > div {
+ display: block;
+ padding:5px 10px 0 10px;
+ }
+
+ ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol {
+ padding-left: 30px;
+ }
+
+ ul.sections > li > div.content {
+ background: #F9FCFF;
+ overflow-x:auto;
+ -webkit-box-shadow: inset 0 0 5px #e5e5ee;
+ box-shadow: inset 0 0 5px #e5e5ee;
+ border: 1px solid #dedede;
+ margin:5px 10px 5px 10px;
+ padding-bottom: 5px;
+ }
+
+ ul.sections > li > div.annotation pre {
+ margin: 7px 0 7px;
+ padding-left: 15px;
+ }
+
+ ul.sections > li > div.annotation p tt, .annotation code {
+ background: #f8f8ff;
+ border: 1px solid #dedede;
+ font-size: 12px;
+ padding: 0 0.2em;
+ }
+}
+
+/*---------------------- (> 481px) ---------------------*/
+@media only screen and (min-width: 481px) {
+ #container {
+ position: relative;
+ }
+ body {
+ background-color: #F9FCFF;
+ font-size: 15px;
+ line-height: 21px;
+ }
+ pre, tt, code {
+ line-height: 18px;
+ }
+ p, ul, ol {
+ margin: 0 0 15px;
+ }
+
+
+ #jump_to {
+ padding: 5px 10px;
+ }
+ #jump_wrapper {
+ padding: 0;
+ }
+ #jump_to, #jump_page {
+ font: 10px Arial;
+ text-transform: uppercase;
+ }
+ #jump_page .source {
+ padding: 5px 10px;
+ }
+ #jump_to a.large {
+ display: inline-block;
+ }
+ #jump_to a.small {
+ display: none;
+ }
+
+
+
+ #background {
+ position: absolute;
+ top: 0; bottom: 0;
+ width: 350px;
+ background: #fff;
+ border-right: 1px solid #e5e5ee;
+ z-index: -1;
+ }
+
+ ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol {
+ padding-left: 40px;
+ }
+
+ ul.sections > li {
+ white-space: nowrap;
+ }
+
+ ul.sections > li > div {
+ display: inline-block;
+ }
+
+ ul.sections > li > div.annotation {
+ max-width: 350px;
+ min-width: 350px;
+ min-height: 5px;
+ padding: 13px;
+ overflow-x: hidden;
+ white-space: normal;
+ vertical-align: top;
+ text-align: left;
+ }
+ ul.sections > li > div.annotation pre {
+ margin: 15px 0 15px;
+ padding-left: 15px;
+ }
+
+ ul.sections > li > div.content {
+ padding: 13px;
+ vertical-align: top;
+ background: #F9FCFF;
+ border: none;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+
+ .pilwrap {
+ position: relative;
+ display: inline;
+ }
+
+ .pilcrow {
+ font: 12px Arial;
+ text-decoration: none;
+ color: #454545;
+ position: absolute;
+ top: 3px; left: -20px;
+ padding: 1px 2px;
+ opacity: 0;
+ -webkit-transition: opacity 0.2s linear;
+ }
+ .for-h1 .pilcrow {
+ top: 47px;
+ }
+ .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow {
+ top: 35px;
+ }
+
+ ul.sections > li > div.annotation:hover .pilcrow {
+ opacity: 1;
+ }
+}
+
+/*---------------------- (> 1025px) ---------------------*/
+@media only screen and (min-width: 1025px) {
+
+ body {
+ font-size: 16px;
+ line-height: 24px;
+ }
+
+ #background {
+ width: 525px;
+ }
+ ul.sections > li > div.annotation {
+ max-width: 525px;
+ min-width: 525px;
+ padding: 10px 25px 1px 50px;
+ }
+ ul.sections > li > div.content {
+ padding: 9px 15px 16px 25px;
+ }
+}
+
+/*---------------------- Syntax Highlighting -----------------------------*/
+
+td.linenos { background-color: #f0f0f0; padding-right: 10px; }
+span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
+/*
+
+github.com style (c) Vasily Polovnyov <vast@whiteants.net>
+
+*/
+
+pre code {
+ display: block; padding: 0.5em;
+ color: #000;
+ background: #f8f8ff
+}
+
+pre .comment,
+pre .template_comment,
+pre .diff .header,
+pre .javadoc {
+ color: #408080;
+ font-style: italic
+}
+
+pre .keyword,
+pre .assignment,
+pre .literal,
+pre .css .rule .keyword,
+pre .winutils,
+pre .javascript .title,
+pre .lisp .title,
+pre .subst {
+ color: #954121;
+ /*font-weight: bold*/
+}
+
+pre .number,
+pre .hexcolor {
+ color: #40a070
+}
+
+pre .string,
+pre .tag .value,
+pre .phpdoc,
+pre .tex .formula {
+ color: #219161;
+}
+
+pre .title,
+pre .id {
+ color: #19469D;
+}
+pre .params {
+ color: #00F;
+}
+
+pre .javascript .title,
+pre .lisp .title,
+pre .subst {
+ font-weight: normal
+}
+
+pre .class .title,
+pre .haskell .label,
+pre .tex .command {
+ color: #458;
+ font-weight: bold
+}
+
+pre .tag,
+pre .tag .title,
+pre .rules .property,
+pre .django .tag .keyword {
+ color: #000080;
+ font-weight: normal
+}
+
+pre .attribute,
+pre .variable,
+pre .instancevar,
+pre .lisp .body {
+ color: #008080
+}
+
+pre .regexp {
+ color: #B68
+}
+
+pre .class {
+ color: #458;
+ font-weight: bold
+}
+
+pre .symbol,
+pre .ruby .symbol .string,
+pre .ruby .symbol .keyword,
+pre .ruby .symbol .keymethods,
+pre .lisp .keyword,
+pre .tex .special,
+pre .input_number {
+ color: #990073
+}
+
+pre .builtin,
+pre .constructor,
+pre .built_in,
+pre .lisp .title {
+ color: #0086b3
+}
+
+pre .preprocessor,
+pre .pi,
+pre .doctype,
+pre .shebang,
+pre .cdata {
+ color: #999;
+ font-weight: bold
+}
+
+pre .deletion {
+ background: #fdd
+}
+
+pre .addition {
+ background: #dfd
+}
+
+pre .diff .change {
+ background: #0086b3
+}
+
+pre .chunk {
+ color: #aaa
+}
+
+pre .tex .formula {
+ opacity: 0.5;
+}
--- /dev/null
+/*! normalize.css v2.0.1 | MIT License | git.io/normalize */
+
+/* ==========================================================================
+ HTML5 display definitions
+ ========================================================================== */
+
+/*
+ * Corrects `block` display not defined in IE 8/9.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+nav,
+section,
+summary {
+ display: block;
+}
+
+/*
+ * Corrects `inline-block` display not defined in IE 8/9.
+ */
+
+audio,
+canvas,
+video {
+ display: inline-block;
+}
+
+/*
+ * Prevents modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+/*
+ * Addresses styling for `hidden` attribute not present in IE 8/9.
+ */
+
+[hidden] {
+ display: none;
+}
+
+/* ==========================================================================
+ Base
+ ========================================================================== */
+
+/*
+ * 1. Sets default font family to sans-serif.
+ * 2. Prevents iOS text size adjust after orientation change, without disabling
+ * user zoom.
+ */
+
+html {
+ font-family: sans-serif; /* 1 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+ -ms-text-size-adjust: 100%; /* 2 */
+}
+
+/*
+ * Removes default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* ==========================================================================
+ Links
+ ========================================================================== */
+
+/*
+ * Addresses `outline` inconsistency between Chrome and other browsers.
+ */
+
+a:focus {
+ outline: thin dotted;
+}
+
+/*
+ * Improves readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/* ==========================================================================
+ Typography
+ ========================================================================== */
+
+/*
+ * Addresses `h1` font sizes within `section` and `article` in Firefox 4+,
+ * Safari 5, and Chrome.
+ */
+
+h1 {
+ font-size: 2em;
+}
+
+/*
+ * Addresses styling not present in IE 8/9, Safari 5, and Chrome.
+ */
+
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+/*
+ * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
+ */
+
+b,
+strong {
+ font-weight: bold;
+}
+
+/*
+ * Addresses styling not present in Safari 5 and Chrome.
+ */
+
+dfn {
+ font-style: italic;
+}
+
+/*
+ * Addresses styling not present in IE 8/9.
+ */
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+
+/*
+ * Corrects font family set oddly in Safari 5 and Chrome.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, serif;
+ font-size: 1em;
+}
+
+/*
+ * Improves readability of pre-formatted text in all browsers.
+ */
+
+pre {
+ white-space: pre;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
+
+/*
+ * Sets consistent quote types.
+ */
+
+q {
+ quotes: "\201C" "\201D" "\2018" "\2019";
+}
+
+/*
+ * Addresses inconsistent and variable font size in all browsers.
+ */
+
+small {
+ font-size: 80%;
+}
+
+/*
+ * Prevents `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/* ==========================================================================
+ Embedded content
+ ========================================================================== */
+
+/*
+ * Removes border when inside `a` element in IE 8/9.
+ */
+
+img {
+ border: 0;
+}
+
+/*
+ * Corrects overflow displayed oddly in IE 9.
+ */
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/* ==========================================================================
+ Figures
+ ========================================================================== */
+
+/*
+ * Addresses margin not present in IE 8/9 and Safari 5.
+ */
+
+figure {
+ margin: 0;
+}
+
+/* ==========================================================================
+ Forms
+ ========================================================================== */
+
+/*
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/*
+ * 1. Corrects color not being inherited in IE 8/9.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/*
+ * 1. Corrects font family not being inherited in all browsers.
+ * 2. Corrects font size not being inherited in all browsers.
+ * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome
+ */
+
+button,
+input,
+select,
+textarea {
+ font-family: inherit; /* 1 */
+ font-size: 100%; /* 2 */
+ margin: 0; /* 3 */
+}
+
+/*
+ * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+button,
+input {
+ line-height: normal;
+}
+
+/*
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Corrects inability to style clickable `input` types in iOS.
+ * 3. Improves usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
+}
+
+/*
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+input[disabled] {
+ cursor: default;
+}
+
+/*
+ * 1. Addresses box sizing set to `content-box` in IE 8/9.
+ * 2. Removes excess padding in IE 8/9.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/*
+ * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.
+ * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box; /* 2 */
+ box-sizing: content-box;
+}
+
+/*
+ * Removes inner padding and search cancel button in Safari 5 and Chrome
+ * on OS X.
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/*
+ * Removes inner padding and border in Firefox 4+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+/*
+ * 1. Removes default vertical scrollbar in IE 8/9.
+ * 2. Improves readability and alignment in all browsers.
+ */
+
+textarea {
+ overflow: auto; /* 1 */
+ vertical-align: top; /* 2 */
+}
+
+/* ==========================================================================
+ Tables
+ ========================================================================== */
+
+/*
+ * Remove most spacing between table cells.
+ */
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html>
+
+<html>
+<head>
+ <title>soundmanager2.js</title>
+<meta name="robots" content="noindex" />
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
+ <link rel="stylesheet" media="all" href="docco.css" />
+</head>
+<body>
+ <div id="container">
+ <div id="background"></div>
+
+ <ul id="jump_to">
+ <li>
+ <a class="large" href="javascript:void(0);">Jump To …</a>
+ <a class="small" href="javascript:void(0);">+</a>
+ <div id="jump_wrapper">
+ <div id="jump_page">
+
+
+ <a class="source" href="soundmanager2.html">
+ soundmanager2.js
+ </a>
+
+
+ <a class="source" href="SoundManager2_AS.html">
+ SoundManager2_AS.as
+ </a>
+
+
+ <a class="source" href="SoundManager2_AS3.html">
+ SoundManager2_AS3.as
+ </a>
+
+
+ <a class="source" href="SoundManager2_SMSound_AS3.html">
+ SoundManager2_SMSound_AS3.as
+ </a>
+
+ </div>
+ </li>
+ </ul>
+
+ <ul class="sections">
+
+ <li id="title">
+ <div class="annotation">
+ <h1>soundmanager2.js</h1>
+ </div>
+ </li>
+
+
+
+ <li id="section-1">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-1">¶</a>
+ </div>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre><span class="comment">/** @license\r
+ *\r
+ * SoundManager 2: JavaScript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code provided under the BSD License:\r
+ * http://schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * V2.97a.20150601\r
+ */</span>\r
+\r
+<span class="comment">/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio, opera, module, define */</span>\r
+<span class="comment">/*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true, todo: true */</span>\r
+\r
+<span class="comment">/**\r
+ * About this file\r
+ * -------------------------------------------------------------------------------------\r
+ * This is the fully-commented source version of the SoundManager 2 API,\r
+ * recommended for use during development and testing.\r
+ *\r
+ * See soundmanager2-nodebug-jsmin.js for an optimized build (~11KB with gzip.)\r
+ * http://schillmania.com/projects/soundmanager2/doc/getstarted/#basic-inclusion\r
+ * Alternately, serve this file with gzip for 75% compression savings (~30KB over HTTP.)\r
+ *\r
+ * You may notice <d> and </d> comments in this source; these are delimiters for\r
+ * debug blocks which are removed in the -nodebug builds, further optimizing code size.\r
+ *\r
+ * Also, as you may note: Whoa, reliable cross-platform/device audio support is hard! ;)\r
+ */</span>\r
+\r
+(<span class="keyword">function</span>(window, _<span class="literal">undefined</span>) {\r
+\r
+<span class="string">"use strict"</span>;\r
+\r
+<span class="keyword">if</span> (!window || !window.document) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-2">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-2">¶</a>
+ </div>
+ <p>Don't cross the [environment] streams. SM2 expects to be running in a browser, not under node.js etc.
+Additionally, if a browser somehow manages to fail this test, as Egon said: "It would be bad."</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> Error(<span class="string">'SoundManager requires a browser with window and document objects.'</span>);\r
+\r
+}\r
+\r
+<span class="keyword">var</span> soundManager = <span class="literal">null</span>;\r
+\r
+<span class="comment">/**\r
+ * The SoundManager constructor.\r
+ *\r
+ * @constructor\r
+ * @param {string} smURL Optional: Path to SWF files\r
+ * @param {string} smID Optional: The ID to use for the SWF container element\r
+ * @this {SoundManager}\r
+ * @return {SoundManager} The new SoundManager instance\r
+ */</span>\r
+\r
+<span class="function"><span class="keyword">function</span> <span class="title">SoundManager</span><span class="params">(smURL, smID)</span> {</span>\r
+\r
+ <span class="comment">/**\r
+ * soundManager configuration options list\r
+ * defines top-level configuration properties to be applied to the soundManager instance (eg. soundManager.flashVersion)\r
+ * to set these properties, use the setup() method - eg., soundManager.setup({url: '/swf/', flashVersion: 9})\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.setupOptions = {\r
+\r
+ <span class="string">'url'</span>: (smURL || <span class="literal">null</span>), <span class="comment">// path (directory) where SoundManager 2 SWFs exist, eg., /path/to/swfs/</span>\r
+ <span class="string">'flashVersion'</span>: <span class="number">8</span>, <span class="comment">// flash build to use (8 or 9.) Some API features require 9.</span>\r
+ <span class="string">'debugMode'</span>: <span class="literal">true</span>, <span class="comment">// enable debugging output (console.log() with HTML fallback)</span>\r
+ <span class="string">'debugFlash'</span>: <span class="literal">false</span>, <span class="comment">// enable debugging output inside SWF, troubleshoot Flash/browser issues</span>\r
+ <span class="string">'useConsole'</span>: <span class="literal">true</span>, <span class="comment">// use console.log() if available (otherwise, writes to #soundmanager-debug element)</span>\r
+ <span class="string">'consoleOnly'</span>: <span class="literal">true</span>, <span class="comment">// if console is being used, do not create/write to #soundmanager-debug</span>\r
+ <span class="string">'waitForWindowLoad'</span>: <span class="literal">false</span>, <span class="comment">// force SM2 to wait for window.onload() before trying to call soundManager.onload()</span>\r
+ <span class="string">'bgColor'</span>: <span class="string">'#ffffff'</span>, <span class="comment">// SWF background color. N/A when wmode = 'transparent'</span>\r
+ <span class="string">'useHighPerformance'</span>: <span class="literal">false</span>, <span class="comment">// position:fixed flash movie can help increase js/flash speed, minimize lag</span>\r
+ <span class="string">'flashPollingInterval'</span>: <span class="literal">null</span>, <span class="comment">// msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used.</span>\r
+ <span class="string">'html5PollingInterval'</span>: <span class="literal">null</span>, <span class="comment">// msec affecting whileplaying() for HTML5 audio, excluding mobile devices. If null, native HTML5 update events are used.</span>\r
+ <span class="string">'flashLoadTimeout'</span>: <span class="number">1000</span>, <span class="comment">// msec to wait for flash movie to load before failing (0 = infinity)</span>\r
+ <span class="string">'wmode'</span>: <span class="literal">null</span>, <span class="comment">// flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index to work)</span>\r
+ <span class="string">'allowScriptAccess'</span>: <span class="string">'always'</span>, <span class="comment">// for scripting the SWF (object/embed property), 'always' or 'sameDomain'</span>\r
+ <span class="string">'useFlashBlock'</span>: <span class="literal">false</span>, <span class="comment">// *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable.</span>\r
+ <span class="string">'useHTML5Audio'</span>: <span class="literal">true</span>, <span class="comment">// use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (MP3/MP4 support varies.) Ideally, transparent vs. Flash API where possible.</span>\r
+ <span class="string">'forceUseGlobalHTML5Audio'</span>: <span class="literal">false</span>, <span class="comment">// if true, a single Audio() object is used for all sounds - and only one can play at a time.</span>\r
+ <span class="string">'ignoreMobileRestrictions'</span>: <span class="literal">false</span>, <span class="comment">// if true, SM2 will not apply global HTML5 audio rules to mobile UAs. iOS > 7 and WebViews may allow multiple Audio() instances.</span>\r
+ <span class="string">'html5Test'</span>: <span class="regexp">/^(probably|maybe)$/i</span>, <span class="comment">// HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.</span>\r
+ <span class="string">'preferFlash'</span>: <span class="literal">false</span>, <span class="comment">// overrides useHTML5audio, will use Flash for MP3/MP4/AAC if present. Potential option if HTML5 playback with these formats is quirky.</span>\r
+ <span class="string">'noSWFCache'</span>: <span class="literal">false</span>, <span class="comment">// if true, appends ?ts={date} to break aggressive SWF caching.</span>\r
+ <span class="string">'idPrefix'</span>: <span class="string">'sound'</span> <span class="comment">// if an id is not provided to createSound(), this prefix is used for generated IDs - 'sound0', 'sound1' etc.</span>\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>.defaultOptions = {\r
+\r
+ <span class="comment">/**\r
+ * the default configuration for sound objects made with createSound() and related methods\r
+ * eg., volume, auto-load behaviour and so forth\r
+ */</span>\r
+\r
+ <span class="string">'autoLoad'</span>: <span class="literal">false</span>, <span class="comment">// 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)</span>\r
+ <span class="string">'autoPlay'</span>: <span class="literal">false</span>, <span class="comment">// enable playing of file as soon as possible (much faster if "stream" is true)</span>\r
+ <span class="string">'from'</span>: <span class="literal">null</span>, <span class="comment">// position to start playback within a sound (msec), default = beginning</span>\r
+ <span class="string">'loops'</span>: <span class="number">1</span>, <span class="comment">// how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0)</span>\r
+ <span class="string">'onid3'</span>: <span class="literal">null</span>, <span class="comment">// callback function for "ID3 data is added/available"</span>\r
+ <span class="string">'onload'</span>: <span class="literal">null</span>, <span class="comment">// callback function for "load finished"</span>\r
+ <span class="string">'whileloading'</span>: <span class="literal">null</span>, <span class="comment">// callback function for "download progress update" (X of Y bytes received)</span>\r
+ <span class="string">'onplay'</span>: <span class="literal">null</span>, <span class="comment">// callback for "play" start</span>\r
+ <span class="string">'onpause'</span>: <span class="literal">null</span>, <span class="comment">// callback for "pause"</span>\r
+ <span class="string">'onresume'</span>: <span class="literal">null</span>, <span class="comment">// callback for "resume" (pause toggle)</span>\r
+ <span class="string">'whileplaying'</span>: <span class="literal">null</span>, <span class="comment">// callback during play (position update)</span>\r
+ <span class="string">'onposition'</span>: <span class="literal">null</span>, <span class="comment">// object containing times and function callbacks for positions of interest</span>\r
+ <span class="string">'onstop'</span>: <span class="literal">null</span>, <span class="comment">// callback for "user stop"</span>\r
+ <span class="string">'onfailure'</span>: <span class="literal">null</span>, <span class="comment">// callback function for when playing fails</span>\r
+ <span class="string">'onfinish'</span>: <span class="literal">null</span>, <span class="comment">// callback function for "sound finished playing"</span>\r
+ <span class="string">'multiShot'</span>: <span class="literal">true</span>, <span class="comment">// let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time</span>\r
+ <span class="string">'multiShotEvents'</span>: <span class="literal">false</span>, <span class="comment">// fire multiple sound events (currently onfinish() only) when multiShot is enabled</span>\r
+ <span class="string">'position'</span>: <span class="literal">null</span>, <span class="comment">// offset (milliseconds) to seek to within loaded sound data.</span>\r
+ <span class="string">'pan'</span>: <span class="number">0</span>, <span class="comment">// "pan" settings, left-to-right, -100 to 100</span>\r
+ <span class="string">'stream'</span>: <span class="literal">true</span>, <span class="comment">// allows playing before entire file has loaded (recommended)</span>\r
+ <span class="string">'to'</span>: <span class="literal">null</span>, <span class="comment">// position to end playback within a sound (msec), default = end</span>\r
+ <span class="string">'type'</span>: <span class="literal">null</span>, <span class="comment">// MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3</span>\r
+ <span class="string">'usePolicyFile'</span>: <span class="literal">false</span>, <span class="comment">// enable crossdomain.xml request for audio on remote domains (for ID3/waveform access)</span>\r
+ <span class="string">'volume'</span>: <span class="number">100</span> <span class="comment">// self-explanatory. 0-100, the latter being the max.</span>\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>.flash9Options = {\r
+\r
+ <span class="comment">/**\r
+ * flash 9-only options,\r
+ * merged into defaultOptions if flash 9 is being used\r
+ */</span>\r
+\r
+ <span class="string">'isMovieStar'</span>: <span class="literal">null</span>, <span class="comment">// "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL</span>\r
+ <span class="string">'usePeakData'</span>: <span class="literal">false</span>, <span class="comment">// enable left/right channel peak (level) data</span>\r
+ <span class="string">'useWaveformData'</span>: <span class="literal">false</span>, <span class="comment">// enable sound spectrum (raw waveform data) - NOTE: May increase CPU load.</span>\r
+ <span class="string">'useEQData'</span>: <span class="literal">false</span>, <span class="comment">// enable sound EQ (frequency spectrum data) - NOTE: May increase CPU load.</span>\r
+ <span class="string">'onbufferchange'</span>: <span class="literal">null</span>, <span class="comment">// callback for "isBuffering" property change</span>\r
+ <span class="string">'ondataerror'</span>: <span class="literal">null</span> <span class="comment">// callback for waveform/eq data access error (flash playing audio in other tabs/domains)</span>\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>.movieStarOptions = {\r
+\r
+ <span class="comment">/**\r
+ * flash 9.0r115+ MPEG4 audio options,\r
+ * merged into defaultOptions if flash 9+movieStar mode is enabled\r
+ */</span>\r
+\r
+ <span class="string">'bufferTime'</span>: <span class="number">3</span>, <span class="comment">// seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.)</span>\r
+ <span class="string">'serverURL'</span>: <span class="literal">null</span>, <span class="comment">// rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants</span>\r
+ <span class="string">'onconnect'</span>: <span class="literal">null</span>, <span class="comment">// rtmp: callback for connection to flash media server</span>\r
+ <span class="string">'duration'</span>: <span class="literal">null</span> <span class="comment">// rtmp: song duration (msec)</span>\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>.audioFormats = {\r
+\r
+ <span class="comment">/**\r
+ * determines HTML5 support + flash requirements.\r
+ * if no support (via flash and/or HTML5) for a "required" format, SM2 will fail to start.\r
+ * flash fallback is used for MP3 or MP4 if HTML5 can't play it (or if preferFlash = true)\r
+ */</span>\r
+\r
+ <span class="string">'mp3'</span>: {\r
+ <span class="string">'type'</span>: [<span class="string">'audio/mpeg; codecs="mp3"'</span>, <span class="string">'audio/mpeg'</span>, <span class="string">'audio/mp3'</span>, <span class="string">'audio/MPA'</span>, <span class="string">'audio/mpa-robust'</span>],\r
+ <span class="string">'required'</span>: <span class="literal">true</span>\r
+ },\r
+\r
+ <span class="string">'mp4'</span>: {\r
+ <span class="string">'related'</span>: [<span class="string">'aac'</span>,<span class="string">'m4a'</span>,<span class="string">'m4b'</span>], <span class="comment">// additional formats under the MP4 container</span>\r
+ <span class="string">'type'</span>: [<span class="string">'audio/mp4; codecs="mp4a.40.2"'</span>, <span class="string">'audio/aac'</span>, <span class="string">'audio/x-m4a'</span>, <span class="string">'audio/MP4A-LATM'</span>, <span class="string">'audio/mpeg4-generic'</span>],\r
+ <span class="string">'required'</span>: <span class="literal">false</span>\r
+ },\r
+\r
+ <span class="string">'ogg'</span>: {\r
+ <span class="string">'type'</span>: [<span class="string">'audio/ogg; codecs=vorbis'</span>],\r
+ <span class="string">'required'</span>: <span class="literal">false</span>\r
+ },\r
+\r
+ <span class="string">'opus'</span>: {\r
+ <span class="string">'type'</span>: [<span class="string">'audio/ogg; codecs=opus'</span>, <span class="string">'audio/opus'</span>],\r
+ <span class="string">'required'</span>: <span class="literal">false</span>\r
+ },\r
+\r
+ <span class="string">'wav'</span>: {\r
+ <span class="string">'type'</span>: [<span class="string">'audio/wav; codecs="1"'</span>, <span class="string">'audio/wav'</span>, <span class="string">'audio/wave'</span>, <span class="string">'audio/x-wav'</span>],\r
+ <span class="string">'required'</span>: <span class="literal">false</span>\r
+ }\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-3">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-3">¶</a>
+ </div>
+ <p>HTML attributes (id + class names) for the SWF container</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">this</span>.movieID = <span class="string">'sm2-container'</span>;\r
+ <span class="keyword">this</span>.id = (smID || <span class="string">'sm2movie'</span>);\r
+\r
+ <span class="keyword">this</span>.debugID = <span class="string">'soundmanager-debug'</span>;\r
+ <span class="keyword">this</span>.debugURLParam = <span class="regexp">/([#?&])debug=1/i</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-4">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-4">¶</a>
+ </div>
+ <p>dynamic attributes</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">this</span>.versionNumber = <span class="string">'V2.97a.20150601'</span>;\r
+ <span class="keyword">this</span>.version = <span class="literal">null</span>;\r
+ <span class="keyword">this</span>.movieURL = <span class="literal">null</span>;\r
+ <span class="keyword">this</span>.altURL = <span class="literal">null</span>;\r
+ <span class="keyword">this</span>.swfLoaded = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.enabled = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.oMC = <span class="literal">null</span>;\r
+ <span class="keyword">this</span>.sounds = {};\r
+ <span class="keyword">this</span>.soundIDs = [];\r
+ <span class="keyword">this</span>.muted = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.didFlashBlock = <span class="literal">false</span>;\r
+ <span class="keyword">this</span>.filePattern = <span class="literal">null</span>;\r
+\r
+ <span class="keyword">this</span>.filePatterns = {\r
+ <span class="string">'flash8'</span>: <span class="regexp">/\.mp3(\?.*)?$/i</span>,\r
+ <span class="string">'flash9'</span>: <span class="regexp">/\.mp3(\?.*)?$/i</span>\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-5">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-5">¶</a>
+ </div>
+ <p>support indicators, set at init</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">this</span>.features = {\r
+ <span class="string">'buffering'</span>: <span class="literal">false</span>,\r
+ <span class="string">'peakData'</span>: <span class="literal">false</span>,\r
+ <span class="string">'waveformData'</span>: <span class="literal">false</span>,\r
+ <span class="string">'eqData'</span>: <span class="literal">false</span>,\r
+ <span class="string">'movieStar'</span>: <span class="literal">false</span>\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-6">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-6">¶</a>
+ </div>
+ <p>flash sandbox info, used primarily in troubleshooting</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">this</span>.sandbox = {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-7">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-7">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="string">'type'</span>: <span class="literal">null</span>,\r
+ <span class="string">'types'</span>: {\r
+ <span class="string">'remote'</span>: <span class="string">'remote (domain-based) rules'</span>,\r
+ <span class="string">'localWithFile'</span>: <span class="string">'local with file access (no internet access)'</span>,\r
+ <span class="string">'localWithNetwork'</span>: <span class="string">'local with network (internet access only, no local access)'</span>,\r
+ <span class="string">'localTrusted'</span>: <span class="string">'local, trusted (local+internet access)'</span>\r
+ },\r
+ <span class="string">'description'</span>: <span class="literal">null</span>,\r
+ <span class="string">'noRemote'</span>: <span class="literal">null</span>,\r
+ <span class="string">'noLocal'</span>: <span class="literal">null</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-8">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-8">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> };\r
+\r
+ <span class="comment">/**\r
+ * format support (html5/flash)\r
+ * stores canPlayType() results based on audioFormats.\r
+ * eg. { mp3: boolean, mp4: boolean }\r
+ * treat as read-only.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.html5 = {\r
+ <span class="string">'usingFlash'</span>: <span class="literal">null</span> <span class="comment">// set if/when flash fallback is needed</span>\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-9">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-9">¶</a>
+ </div>
+ <p>file type support hash</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.flash = {};</pre></div></div>
+
+ </li>
+
+
+ <li id="section-10">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-10">¶</a>
+ </div>
+ <p>determined at init time</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.html5Only = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-11">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-11">¶</a>
+ </div>
+ <p>used for special cases (eg. iPad/iPhone/palm OS?)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.ignoreFlash = <span class="literal">false</span>;\r
+\r
+ <span class="comment">/**\r
+ * a few private internals (OK, a lot. :D)\r
+ */</span>\r
+\r
+ <span class="keyword">var</span> SMSound,\r
+ sm2 = <span class="keyword">this</span>, globalHTML5Audio = <span class="literal">null</span>, flash = <span class="literal">null</span>, sm = <span class="string">'soundManager'</span>, smc = sm + <span class="string">': '</span>, h5 = <span class="string">'HTML5::'</span>, id, ua = navigator.userAgent, wl = window.location.href.toString(), doc = document, doNothing, setProperties, init, fV, on_queue = [], debugOpen = <span class="literal">true</span>, debugTS, didAppend = <span class="literal">false</span>, appendSuccess = <span class="literal">false</span>, didInit = <span class="literal">false</span>, disabled = <span class="literal">false</span>, windowLoaded = <span class="literal">false</span>, _wDS, wdCount = <span class="number">0</span>, initComplete, mixin, assign, extraOptions, addOnEvent, processOnEvents, initUserOnload, delayWaitForEI, waitForEI, rebootIntoHTML5, setVersionInfo, handleFocus, strings, initMovie, domContentLoaded, winOnLoad, didDCLoaded, getDocument, createMovie, catchError, setPolling, initDebug, debugLevels = [<span class="string">'log'</span>, <span class="string">'info'</span>, <span class="string">'warn'</span>, <span class="string">'error'</span>], defaultFlashVersion = <span class="number">8</span>, disableObject, failSafely, normalizeMovieURL, oRemoved = <span class="literal">null</span>, oRemovedHTML = <span class="literal">null</span>, str, flashBlockHandler, getSWFCSS, swfCSS, toggleDebug, loopFix, policyFix, complain, idCheck, waitingForEI = <span class="literal">false</span>, initPending = <span class="literal">false</span>, startTimer, stopTimer, timerExecute, h5TimerCount = <span class="number">0</span>, h5IntervalTimer = <span class="literal">null</span>, parseURL, messages = [],\r
+ canIgnoreFlash, needsFlash = <span class="literal">null</span>, featureCheck, html5OK, html5CanPlay, html5Ext, html5Unload, domContentLoadedIE, testHTML5, event, slice = Array.prototype.slice, useGlobalHTML5Audio = <span class="literal">false</span>, lastGlobalHTML5URL, hasFlash, detectFlash, badSafariFix, html5_events, showSupport, flushMessages, wrapCallback, idCounter = <span class="number">0</span>, didSetup, msecScale = <span class="number">1000</span>,\r
+ is_iDevice = ua.match(<span class="regexp">/(ipad|iphone|ipod)/i</span>), isAndroid = ua.match(<span class="regexp">/android/i</span>), isIE = ua.match(<span class="regexp">/msie/i</span>),\r
+ isWebkit = ua.match(<span class="regexp">/webkit/i</span>),\r
+ isSafari = (ua.match(<span class="regexp">/safari/i</span>) && !ua.match(<span class="regexp">/chrome/i</span>)),\r
+ isOpera = (ua.match(<span class="regexp">/opera/i</span>)),\r
+ mobileHTML5 = (ua.match(<span class="regexp">/(mobile|pre\/|xoom)/i</span>) || is_iDevice || isAndroid),\r
+ isBadSafari = (!wl.match(<span class="regexp">/usehtml5audio/i</span>) && !wl.match(<span class="regexp">/sm2\-ignorebadua/i</span>) && isSafari && !ua.match(<span class="regexp">/silk/i</span>) && ua.match(<span class="regexp">/OS X 10_6_([3-7])/i</span>)), <span class="comment">// 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</span>\r
+ hasConsole = (window.console !== _<span class="literal">undefined</span> && console.log !== _<span class="literal">undefined</span>),\r
+ isFocused = (doc.hasFocus !== _<span class="literal">undefined</span> ? doc.hasFocus() : <span class="literal">null</span>),\r
+ tryInitOnFocus = (isSafari && (doc.hasFocus === _<span class="literal">undefined</span> || !doc.hasFocus())),\r
+ okToDisable = !tryInitOnFocus,\r
+ flashMIME = <span class="regexp">/(mp3|mp4|mpa|m4a|m4b)/i</span>,\r
+ emptyURL = <span class="string">'about:blank'</span>, <span class="comment">// safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs)</span>\r
+ emptyWAV = <span class="string">'data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w=='</span>, <span class="comment">// tiny WAV for HTML5 unloading</span>\r
+ overHTTP = (doc.location ? doc.location.protocol.match(<span class="regexp">/http/i</span>) : <span class="literal">null</span>),\r
+ http = (!overHTTP ? <span class="string">'http:/'</span>+<span class="string">'/'</span> : <span class="string">''</span>),</pre></div></div>
+
+ </li>
+
+
+ <li id="section-12">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-12">¶</a>
+ </div>
+ <p>mp3, mp4, aac etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> netStreamMimeTypes = <span class="regexp">/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i</span>,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-13">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-13">¶</a>
+ </div>
+ <p>Flash v9.0r115+ "moviestar" formats</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> netStreamTypes = [<span class="string">'mpeg4'</span>, <span class="string">'aac'</span>, <span class="string">'flv'</span>, <span class="string">'mov'</span>, <span class="string">'mp4'</span>, <span class="string">'m4v'</span>, <span class="string">'f4v'</span>, <span class="string">'m4a'</span>, <span class="string">'m4b'</span>, <span class="string">'mp4v'</span>, <span class="string">'3gp'</span>, <span class="string">'3g2'</span>],\r
+ netStreamPattern = <span class="keyword">new</span> RegExp(<span class="string">'\\.('</span> + netStreamTypes.join(<span class="string">'|'</span>) + <span class="string">')(\\?.*)?$'</span>, <span class="string">'i'</span>);\r
+\r
+ <span class="keyword">this</span>.mimePattern = <span class="regexp">/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i</span>; <span class="comment">// default mp3 set</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-14">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-14">¶</a>
+ </div>
+ <p>use altURL if not "online"</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.useAltURL = !overHTTP;\r
+\r
+ swfCSS = {\r
+ <span class="string">'swfBox'</span>: <span class="string">'sm2-object-box'</span>,\r
+ <span class="string">'swfDefault'</span>: <span class="string">'movieContainer'</span>,\r
+ <span class="string">'swfError'</span>: <span class="string">'swf_error'</span>, <span class="comment">// SWF loaded, but SM2 couldn't start (other error)</span>\r
+ <span class="string">'swfTimedout'</span>: <span class="string">'swf_timedout'</span>,\r
+ <span class="string">'swfLoaded'</span>: <span class="string">'swf_loaded'</span>,\r
+ <span class="string">'swfUnblocked'</span>: <span class="string">'swf_unblocked'</span>, <span class="comment">// or loaded OK</span>\r
+ <span class="string">'sm2Debug'</span>: <span class="string">'sm2_debug'</span>,\r
+ <span class="string">'highPerf'</span>: <span class="string">'high_performance'</span>,\r
+ <span class="string">'flashDebug'</span>: <span class="string">'flash_debug'</span>\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * basic HTML5 Audio() support test\r
+ * try...catch because of IE 9 "not implemented" nonsense\r
+ * https://github.com/Modernizr/Modernizr/issues/224\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.hasHTML5 = (<span class="keyword">function</span>() {\r
+ <span class="keyword">try</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-15">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-15">¶</a>
+ </div>
+ <p>new Audio(null) for stupid Opera 9.64 case, which throws not_enough_arguments exception otherwise.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> (Audio !== _<span class="literal">undefined</span> && (isOpera && opera !== _<span class="literal">undefined</span> && opera.version() < <span class="number">10</span> ? <span class="keyword">new</span> Audio(<span class="literal">null</span>) : <span class="keyword">new</span> Audio()).canPlayType !== _<span class="literal">undefined</span>);\r
+ } <span class="keyword">catch</span>(e) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ }());\r
+\r
+ <span class="comment">/**\r
+ * Public SoundManager API\r
+ * -----------------------\r
+ */</span>\r
+\r
+ <span class="comment">/**\r
+ * Configures top-level soundManager properties.\r
+ *\r
+ * @param {object} options Option parameters, eg. { flashVersion: 9, url: '/path/to/swfs/' }\r
+ * onready and ontimeout are also accepted parameters. call soundManager.setup() to see the full list.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.setup = <span class="keyword">function</span>(options) {\r
+\r
+ <span class="keyword">var</span> noURL = (!sm2.url);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-16">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-16">¶</a>
+ </div>
+ <p>warn if flash options have already been applied</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (options !== _<span class="literal">undefined</span> && didInit && needsFlash && sm2.ok() && (options.flashVersion !== _<span class="literal">undefined</span> || options.url !== _<span class="literal">undefined</span> || options.html5Test !== _<span class="literal">undefined</span>)) {\r
+ complain(str(<span class="string">'setupLate'</span>));\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-17">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-17">¶</a>
+ </div>
+ <p>TODO: defer: true?</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ assign(options);\r
+\r
+ <span class="keyword">if</span> (!useGlobalHTML5Audio) {\r
+\r
+ <span class="keyword">if</span> (mobileHTML5) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-18">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-18">¶</a>
+ </div>
+ <p>force the singleton HTML5 pattern on mobile, by default.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!sm2.setupOptions.ignoreMobileRestrictions || sm2.setupOptions.forceUseGlobalHTML5Audio) {\r
+ messages.push(strings.globalHTML5);\r
+ useGlobalHTML5Audio = <span class="literal">true</span>;\r
+ }\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-19">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-19">¶</a>
+ </div>
+ <p>only apply singleton HTML5 on desktop if forced.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (sm2.setupOptions.forceUseGlobalHTML5Audio) {\r
+ messages.push(strings.globalHTML5);\r
+ useGlobalHTML5Audio = <span class="literal">true</span>;\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (!didSetup && mobileHTML5) {\r
+\r
+ <span class="keyword">if</span> (sm2.setupOptions.ignoreMobileRestrictions) {\r
+ \r
+ messages.push(strings.ignoreMobile);\r
+ \r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-20">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-20">¶</a>
+ </div>
+ <p>prefer HTML5 for mobile + tablet-like devices, probably more reliable vs. flash at this point.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-21">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-21">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!sm2.setupOptions.useHTML5Audio || sm2.setupOptions.preferFlash) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-22">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-22">¶</a>
+ </div>
+ <p>notify that defaults are being changed.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(strings.mobileUA);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-23">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-23">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ sm2.setupOptions.useHTML5Audio = <span class="literal">true</span>;\r
+ sm2.setupOptions.preferFlash = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (is_iDevice) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-24">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-24">¶</a>
+ </div>
+ <p>no flash here.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.ignoreFlash = <span class="literal">true</span>;\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> ((isAndroid && !ua.match(<span class="regexp">/android\s2\.3/i</span>)) || !isAndroid) {\r
+ \r
+ <span class="comment">/**\r
+ * Android devices tend to work better with a single audio instance, specifically for chained playback of sounds in sequence.\r
+ * Common use case: exiting sound onfinish() -> createSound() -> play()\r
+ * Presuming similar restrictions for other mobile, non-Android, non-iOS devices.\r
+ */</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-25">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-25">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(strings.globalHTML5);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-26">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-26">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ useGlobalHTML5Audio = <span class="literal">true</span>;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-27">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-27">¶</a>
+ </div>
+ <p>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.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (options) {\r
+\r
+ <span class="keyword">if</span> (noURL && didDCLoaded && options.url !== _<span class="literal">undefined</span>) {\r
+ sm2.beginDelayedInit();\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-28">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-28">¶</a>
+ </div>
+ <p>special case 2: If lazy-loading SM2 (DOMContentLoaded has already happened) and user calls setup() with url: parameter, try to init ASAP.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!didDCLoaded && options.url !== _<span class="literal">undefined</span> && doc.readyState === <span class="string">'complete'</span>) {\r
+ setTimeout(domContentLoaded, <span class="number">1</span>);\r
+ }\r
+\r
+ }\r
+\r
+ didSetup = <span class="literal">true</span>;\r
+\r
+ <span class="keyword">return</span> sm2;\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>.ok = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">return</span> (needsFlash ? (didInit && !disabled) : (sm2.useHTML5Audio && sm2.hasHTML5));\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>.supported = <span class="keyword">this</span>.ok; <span class="comment">// legacy</span>\r
+\r
+ <span class="keyword">this</span>.getMovie = <span class="keyword">function</span>(smID) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-29">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-29">¶</a>
+ </div>
+ <p>safety net: some old browsers differ on SWF references, possibly related to ExternalInterface / flash version</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> id(smID) || doc[smID] || window[smID];\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Creates a SMSound sound object instance. Can also be overloaded, e.g., createSound('mySound', '/some.mp3');\r
+ *\r
+ * @param {object} oOptions Sound options (at minimum, url parameter is required.)\r
+ * @return {object} SMSound The new SMSound object.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.createSound = <span class="keyword">function</span>(oOptions, _url) {\r
+\r
+ <span class="keyword">var</span> cs, cs_string, options, oSound = <span class="literal">null</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-30">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-30">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> cs = sm + <span class="string">'.createSound(): '</span>;\r
+ cs_string = cs + str(!didInit ? <span class="string">'notReady'</span> : <span class="string">'notOK'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-31">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-31">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!didInit || !sm2.ok()) {\r
+ complain(cs_string);\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (_url !== _<span class="literal">undefined</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-32">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-32">¶</a>
+ </div>
+ <p>function overloading in JS! :) ... assume simple createSound(id, url) use case.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oOptions = {\r
+ <span class="string">'id'</span>: oOptions,\r
+ <span class="string">'url'</span>: _url\r
+ };\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-33">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-33">¶</a>
+ </div>
+ <p>inherit from defaultOptions</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> options = mixin(oOptions);\r
+\r
+ options.url = parseURL(options.url);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-34">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-34">¶</a>
+ </div>
+ <p>generate an id, if needed.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (options.id === _<span class="literal">undefined</span>) {\r
+ options.id = sm2.setupOptions.idPrefix + (idCounter++);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-35">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-35">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (options.id.toString().charAt(<span class="number">0</span>).match(<span class="regexp">/^[0-9]$/</span>)) {\r
+ sm2._wD(cs + str(<span class="string">'badID'</span>, options.id), <span class="number">2</span>);\r
+ }\r
+\r
+ sm2._wD(cs + options.id + (options.url ? <span class="string">' ('</span> + options.url + <span class="string">')'</span> : <span class="string">''</span>), <span class="number">1</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-36">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-36">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (idCheck(options.id, <span class="literal">true</span>)) {\r
+ sm2._wD(cs + options.id + <span class="string">' exists'</span>, <span class="number">1</span>);\r
+ <span class="keyword">return</span> sm2.sounds[options.id];\r
+ }\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">make</span><span class="params">()</span> {</span>\r
+\r
+ options = loopFix(options);\r
+ sm2.sounds[options.id] = <span class="keyword">new</span> SMSound(options);\r
+ sm2.soundIDs.push(options.id);\r
+ <span class="keyword">return</span> sm2.sounds[options.id];\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (html5OK(options)) {\r
+\r
+ oSound = make();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-37">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-37">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!sm2.html5Only) {\r
+ sm2._wD(options.id + <span class="string">': Using HTML5'</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-38">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-38">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oSound._setup_html5(options);\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (sm2.html5Only) {\r
+ sm2._wD(options.id + <span class="string">': No HTML5 support for this sound, and no Flash. Exiting.'</span>);\r
+ <span class="keyword">return</span> make();\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-39">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-39">¶</a>
+ </div>
+ <p>TODO: Move HTML5/flash checks into generic URL parsing/handling function.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (sm2.html5.usingFlash && options.url && options.url.match(<span class="regexp">/data\:/i</span>)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-40">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-40">¶</a>
+ </div>
+ <p>data: URIs not supported by Flash, either.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(options.id + <span class="string">': data: URIs not supported via Flash. Exiting.'</span>);\r
+ <span class="keyword">return</span> make();\r
+ }\r
+\r
+ <span class="keyword">if</span> (fV > <span class="number">8</span>) {\r
+ <span class="keyword">if</span> (options.isMovieStar === <span class="literal">null</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-41">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-41">¶</a>
+ </div>
+ <p>attempt to detect MPEG-4 formats</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> options.isMovieStar = !!(options.serverURL || (options.type ? options.type.match(netStreamMimeTypes) : <span class="literal">false</span>) || (options.url && options.url.match(netStreamPattern)));\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-42">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-42">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (options.isMovieStar) {\r
+ sm2._wD(cs + <span class="string">'using MovieStar handling'</span>);\r
+ <span class="keyword">if</span> (options.loops > <span class="number">1</span>) {\r
+ _wDS(<span class="string">'noNSLoop'</span>);\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-43">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-43">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> }\r
+\r
+ options = policyFix(options, cs);\r
+ oSound = make();\r
+\r
+ <span class="keyword">if</span> (fV === <span class="number">8</span>) {\r
+ flash._createSound(options.id, options.loops || <span class="number">1</span>, options.usePolicyFile);\r
+ } <span class="keyword">else</span> {\r
+ flash._createSound(options.id, options.url, options.usePeakData, options.useWaveformData, options.useEQData, options.isMovieStar, (options.isMovieStar ? options.bufferTime : <span class="literal">false</span>), options.loops || <span class="number">1</span>, options.serverURL, options.duration || <span class="literal">null</span>, options.autoPlay, <span class="literal">true</span>, options.autoLoad, options.usePolicyFile);\r
+ <span class="keyword">if</span> (!options.serverURL) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-44">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-44">¶</a>
+ </div>
+ <p>We are connected immediately</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oSound.connected = <span class="literal">true</span>;\r
+ <span class="keyword">if</span> (options.onconnect) {\r
+ options.onconnect.apply(oSound);\r
+ }\r
+ }\r
+ }\r
+\r
+ <span class="keyword">if</span> (!options.serverURL && (options.autoLoad || options.autoPlay)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-45">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-45">¶</a>
+ </div>
+ <p>call load for non-rtmp streams</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oSound.load(options);\r
+ }\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-46">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-46">¶</a>
+ </div>
+ <p>rtmp will play in onconnect</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!options.serverURL && options.autoPlay) {\r
+ oSound.play();\r
+ }\r
+\r
+ <span class="keyword">return</span> oSound;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Destroys a SMSound sound object instance.\r
+ *\r
+ * @param {string} sID The ID of the sound to destroy\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.destroySound = <span class="keyword">function</span>(sID, _bFromSound) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-47">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-47">¶</a>
+ </div>
+ <p>explicitly destroy a sound before normal page unload, etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> oS = sm2.sounds[sID], i;\r
+\r
+ oS.stop();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-48">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-48">¶</a>
+ </div>
+ <p>Disable all callbacks after stop(), when the sound is being destroyed</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oS._iO = {};\r
+ \r
+ oS.unload();\r
+\r
+ <span class="keyword">for</span> (i = <span class="number">0</span>; i < sm2.soundIDs.length; i++) {\r
+ <span class="keyword">if</span> (sm2.soundIDs[i] === sID) {\r
+ sm2.soundIDs.splice(i, <span class="number">1</span>);\r
+ <span class="keyword">break</span>;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">if</span> (!_bFromSound) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-49">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-49">¶</a>
+ </div>
+ <p>ignore if being called from SMSound instance</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oS.destruct(<span class="literal">true</span>);\r
+ }\r
+\r
+ oS = <span class="literal">null</span>;\r
+ <span class="keyword">delete</span> sm2.sounds[sID];\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the load() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {object} oOptions Optional: Sound options\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.load = <span class="keyword">function</span>(sID, oOptions) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].load(oOptions);\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the unload() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.unload = <span class="keyword">function</span>(sID) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].unload();\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the onPosition() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nPosition The position to watch for\r
+ * @param {function} oMethod The relevant callback to fire\r
+ * @param {object} oScope Optional: The scope to apply the callback to\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.onPosition = <span class="keyword">function</span>(sID, nPosition, oMethod, oScope) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].onposition(nPosition, oMethod, oScope);\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-50">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-50">¶</a>
+ </div>
+ <p>legacy/backwards-compability: lower-case method name</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.onposition = <span class="keyword">this</span>.onPosition;\r
+\r
+ <span class="comment">/**\r
+ * Calls the clearOnPosition() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nPosition The position to watch for\r
+ * @param {function} oMethod Optional: The relevant callback to fire\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.clearOnPosition = <span class="keyword">function</span>(sID, nPosition, oMethod) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].clearOnPosition(nPosition, oMethod);\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the play() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {object} oOptions Optional: Sound options\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.play = <span class="keyword">function</span>(sID, oOptions) {\r
+\r
+ <span class="keyword">var</span> result = <span class="literal">null</span>,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-51">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-51">¶</a>
+ </div>
+ <p>legacy function-overloading use case: play('mySound', '/path/to/some.mp3');</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> overloaded = (oOptions && !(oOptions <span class="keyword">instanceof</span> Object));\r
+\r
+ <span class="keyword">if</span> (!didInit || !sm2.ok()) {\r
+ complain(sm + <span class="string">'.play(): '</span> + str(!didInit?<span class="string">'notReady'</span>:<span class="string">'notOK'</span>));\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID, overloaded)) {\r
+\r
+ <span class="keyword">if</span> (!overloaded) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-52">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-52">¶</a>
+ </div>
+ <p>no sound found for the given ID. Bail.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (overloaded) {\r
+ oOptions = {\r
+ url: oOptions\r
+ };\r
+ }\r
+\r
+ <span class="keyword">if</span> (oOptions && oOptions.url) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-53">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-53">¶</a>
+ </div>
+ <p>overloading use case, create+play: .play('someID', {url:'/path/to.mp3'});</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(sm + <span class="string">'.play(): Attempting to create "'</span> + sID + <span class="string">'"'</span>, <span class="number">1</span>);\r
+ oOptions.id = sID;\r
+ result = sm2.createSound(oOptions).play();\r
+ }\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (overloaded) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-54">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-54">¶</a>
+ </div>
+ <p>existing sound object case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oOptions = {\r
+ url: oOptions\r
+ };\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (result === <span class="literal">null</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-55">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-55">¶</a>
+ </div>
+ <p>default case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> result = sm2.sounds[sID].play(oOptions);\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-56">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-56">¶</a>
+ </div>
+ <p>just for convenience</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.start = <span class="keyword">this</span>.play;\r
+\r
+ <span class="comment">/**\r
+ * Calls the setPosition() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nMsecOffset Position (milliseconds)\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.setPosition = <span class="keyword">function</span>(sID, nMsecOffset) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].setPosition(nMsecOffset);\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the stop() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.stop = <span class="keyword">function</span>(sID) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ sm2._wD(sm + <span class="string">'.stop('</span> + sID + <span class="string">')'</span>, <span class="number">1</span>);\r
+ <span class="keyword">return</span> sm2.sounds[sID].stop();\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Stops all currently-playing sounds.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.stopAll = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> oSound;\r
+ sm2._wD(sm + <span class="string">'.stopAll()'</span>, <span class="number">1</span>);\r
+\r
+ <span class="keyword">for</span> (oSound <span class="keyword">in</span> sm2.sounds) {\r
+ <span class="keyword">if</span> (sm2.sounds.hasOwnProperty(oSound)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-57">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-57">¶</a>
+ </div>
+ <p>apply only to sound objects</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.sounds[oSound].stop();\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the pause() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.pause = <span class="keyword">function</span>(sID) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].pause();\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Pauses all currently-playing sounds.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.pauseAll = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> i;\r
+ <span class="keyword">for</span> (i = sm2.soundIDs.length - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].pause();\r
+ }\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the resume() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.resume = <span class="keyword">function</span>(sID) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].resume();\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Resumes all currently-paused sounds.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.resumeAll = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> i;\r
+ <span class="keyword">for</span> (i = sm2.soundIDs.length- <span class="number">1</span> ; i >= <span class="number">0</span>; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].resume();\r
+ }\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the togglePause() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.togglePause = <span class="keyword">function</span>(sID) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].togglePause();\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the setPan() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nPan The pan value (-100 to 100)\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.setPan = <span class="keyword">function</span>(sID, nPan) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].setPan(nPan);\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the setVolume() method of a SMSound object by ID\r
+ * Overloaded case: pass only volume argument eg., setVolume(50) to apply to all sounds.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nVol The volume value (0 to 100)\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.setVolume = <span class="keyword">function</span>(sID, nVol) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-58">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-58">¶</a>
+ </div>
+ <p>setVolume(50) function overloading case - apply to all sounds</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> i, j;\r
+\r
+ <span class="keyword">if</span> (sID !== _<span class="literal">undefined</span> && !isNaN(sID) && nVol === _<span class="literal">undefined</span>) {\r
+ <span class="keyword">for</span> (i = <span class="number">0</span>, j = sm2.soundIDs.length; i < j; i++) {\r
+ sm2.sounds[sm2.soundIDs[i]].setVolume(sID);\r
+ }\r
+ <span class="keyword">return</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-59">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-59">¶</a>
+ </div>
+ <p>setVolume('mySound', 50) case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">return</span> sm2.sounds[sID].setVolume(nVol);\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the mute() method of either a single SMSound object by ID, or all sound objects.\r
+ *\r
+ * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.)\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.mute = <span class="keyword">function</span>(sID) {\r
+\r
+ <span class="keyword">var</span> i = <span class="number">0</span>;\r
+\r
+ <span class="keyword">if</span> (sID <span class="keyword">instanceof</span> String) {\r
+ sID = <span class="literal">null</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!sID) {\r
+\r
+ sm2._wD(sm + <span class="string">'.mute(): Muting all sounds'</span>);\r
+ <span class="keyword">for</span> (i = sm2.soundIDs.length - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].mute();\r
+ }\r
+ sm2.muted = <span class="literal">true</span>;\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ sm2._wD(sm + <span class="string">'.mute(): Muting "'</span> + sID + <span class="string">'"'</span>);\r
+ <span class="keyword">return</span> sm2.sounds[sID].mute();\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Mutes all sounds.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.muteAll = <span class="keyword">function</span>() {\r
+\r
+ sm2.mute();\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the unmute() method of either a single SMSound object by ID, or all sound objects.\r
+ *\r
+ * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.)\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.unmute = <span class="keyword">function</span>(sID) {\r
+\r
+ <span class="keyword">var</span> i;\r
+\r
+ <span class="keyword">if</span> (sID <span class="keyword">instanceof</span> String) {\r
+ sID = <span class="literal">null</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!sID) {\r
+\r
+ sm2._wD(sm + <span class="string">'.unmute(): Unmuting all sounds'</span>);\r
+ <span class="keyword">for</span> (i = sm2.soundIDs.length - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].unmute();\r
+ }\r
+ sm2.muted = <span class="literal">false</span>;\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ sm2._wD(sm + <span class="string">'.unmute(): Unmuting "'</span> + sID + <span class="string">'"'</span>);\r
+ <span class="keyword">return</span> sm2.sounds[sID].unmute();\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Unmutes all sounds.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.unmuteAll = <span class="keyword">function</span>() {\r
+\r
+ sm2.unmute();\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Calls the toggleMute() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.toggleMute = <span class="keyword">function</span>(sID) {\r
+\r
+ <span class="keyword">if</span> (!idCheck(sID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ <span class="keyword">return</span> sm2.sounds[sID].toggleMute();\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Retrieves the memory used by the flash plugin.\r
+ *\r
+ * @return {number} The amount of memory in use\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.getMemoryUse = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-60">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-60">¶</a>
+ </div>
+ <p>flash-only</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> ram = <span class="number">0</span>;\r
+\r
+ <span class="keyword">if</span> (flash && fV !== <span class="number">8</span>) {\r
+ ram = parseInt(flash._getMemoryUse(), <span class="number">10</span>);\r
+ }\r
+\r
+ <span class="keyword">return</span> ram;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Undocumented: NOPs soundManager and all SMSound objects.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.disable = <span class="keyword">function</span>(bNoDisable) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-61">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-61">¶</a>
+ </div>
+ <p>destroy all functions</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> i;\r
+\r
+ <span class="keyword">if</span> (bNoDisable === _<span class="literal">undefined</span>) {\r
+ bNoDisable = <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (disabled) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ disabled = <span class="literal">true</span>;\r
+ _wDS(<span class="string">'shutdown'</span>, <span class="number">1</span>);\r
+\r
+ <span class="keyword">for</span> (i = sm2.soundIDs.length - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {\r
+ disableObject(sm2.sounds[sm2.soundIDs[i]]);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-62">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-62">¶</a>
+ </div>
+ <p>fire "complete", despite fail</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> initComplete(bNoDisable);\r
+ event.remove(window, <span class="string">'load'</span>, initUserOnload);\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Determines playability of a MIME type, eg. 'audio/mp3'.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.canPlayMIME = <span class="keyword">function</span>(sMIME) {\r
+\r
+ <span class="keyword">var</span> result;\r
+\r
+ <span class="keyword">if</span> (sm2.hasHTML5) {\r
+ result = html5CanPlay({\r
+ type: sMIME\r
+ });\r
+ }\r
+\r
+ <span class="keyword">if</span> (!result && needsFlash) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-63">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-63">¶</a>
+ </div>
+ <p>if flash 9, test netStream (movieStar) types as well.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> result = (sMIME && sm2.ok() ? !!((fV > <span class="number">8</span> ? sMIME.match(netStreamMimeTypes) : <span class="literal">null</span>) || sMIME.match(sm2.mimePattern)) : <span class="literal">null</span>); <span class="comment">// TODO: make less "weird" (per JSLint)</span>\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Determines playability of a URL based on audio support.\r
+ *\r
+ * @param {string} sURL The URL to test\r
+ * @return {boolean} URL playability\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.canPlayURL = <span class="keyword">function</span>(sURL) {\r
+\r
+ <span class="keyword">var</span> result;\r
+\r
+ <span class="keyword">if</span> (sm2.hasHTML5) {\r
+ result = html5CanPlay({\r
+ url: sURL\r
+ });\r
+ }\r
+\r
+ <span class="keyword">if</span> (!result && needsFlash) {\r
+ result = (sURL && sm2.ok() ? !!(sURL.match(sm2.filePattern)) : <span class="literal">null</span>);\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Determines playability of an HTML DOM &lt;a&gt; object (or similar object literal) based on audio support.\r
+ *\r
+ * @param {object} oLink an HTML DOM &lt;a&gt; object or object literal including href and/or type attributes\r
+ * @return {boolean} URL playability\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.canPlayLink = <span class="keyword">function</span>(oLink) {\r
+\r
+ <span class="keyword">if</span> (oLink.type !== _<span class="literal">undefined</span> && oLink.type) {\r
+ <span class="keyword">if</span> (sm2.canPlayMIME(oLink.type)) {\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">return</span> sm2.canPlayURL(oLink.href);\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Retrieves a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.getSoundById = <span class="keyword">function</span>(sID, _suppressDebug) {\r
+\r
+ <span class="keyword">if</span> (!sID) {\r
+ <span class="keyword">return</span> <span class="literal">null</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> result = sm2.sounds[sID];</pre></div></div>
+
+ </li>
+
+
+ <li id="section-64">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-64">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!result && !_suppressDebug) {\r
+ sm2._wD(sm + <span class="string">'.getSoundById(): Sound "'</span> + sID + <span class="string">'" not found.'</span>, <span class="number">2</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-65">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-65">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Queues a callback for execution when SoundManager has successfully initialized.\r
+ *\r
+ * @param {function} oMethod The callback method to fire\r
+ * @param {object} oScope Optional: The scope to apply to the callback\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.onready = <span class="keyword">function</span>(oMethod, oScope) {\r
+\r
+ <span class="keyword">var</span> sType = <span class="string">'onready'</span>,\r
+ result = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> oMethod === <span class="string">'function'</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-66">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-66">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (didInit) {\r
+ sm2._wD(str(<span class="string">'queue'</span>, sType));\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-67">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-67">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!oScope) {\r
+ oScope = window;\r
+ }\r
+\r
+ addOnEvent(sType, oMethod, oScope);\r
+ processOnEvents();\r
+\r
+ result = <span class="literal">true</span>;\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">throw</span> str(<span class="string">'needFunction'</span>, sType);\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Queues a callback for execution when SoundManager has failed to initialize.\r
+ *\r
+ * @param {function} oMethod The callback method to fire\r
+ * @param {object} oScope Optional: The scope to apply to the callback\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.ontimeout = <span class="keyword">function</span>(oMethod, oScope) {\r
+\r
+ <span class="keyword">var</span> sType = <span class="string">'ontimeout'</span>,\r
+ result = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> oMethod === <span class="string">'function'</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-68">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-68">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (didInit) {\r
+ sm2._wD(str(<span class="string">'queue'</span>, sType));\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-69">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-69">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!oScope) {\r
+ oScope = window;\r
+ }\r
+\r
+ addOnEvent(sType, oMethod, oScope);\r
+ processOnEvents({type:sType});\r
+\r
+ result = <span class="literal">true</span>;\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">throw</span> str(<span class="string">'needFunction'</span>, sType);\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Writes console.log()-style debug output to a console or in-browser element.\r
+ * Applies when debugMode = true\r
+ *\r
+ * @param {string} sText The console message\r
+ * @param {object} nType Optional log level (number), or object. Number case: Log type/style where 0 = 'info', 1 = 'warn', 2 = 'error'. Object case: Object to be dumped.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>._writeDebug = <span class="keyword">function</span>(sText, sTypeOrObject) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-70">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-70">¶</a>
+ </div>
+ <p>pseudo-private console.log()-style output</p>
+<d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> sDID = <span class="string">'soundmanager-debug'</span>, o, oItem;\r
+\r
+ <span class="keyword">if</span> (!sm2.setupOptions.debugMode) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (hasConsole && sm2.useConsole) {\r
+ <span class="keyword">if</span> (sTypeOrObject && <span class="keyword">typeof</span> sTypeOrObject === <span class="string">'object'</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-71">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-71">¶</a>
+ </div>
+ <p>object passed; dump to console.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> console.log(sText, sTypeOrObject);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (debugLevels[sTypeOrObject] !== _<span class="literal">undefined</span>) {\r
+ console[debugLevels[sTypeOrObject]](sText);\r
+ } <span class="keyword">else</span> {\r
+ console.log(sText);\r
+ }\r
+ <span class="keyword">if</span> (sm2.consoleOnly) {\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+ }\r
+ }\r
+\r
+ o = id(sDID);\r
+\r
+ <span class="keyword">if</span> (!o) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ oItem = doc.createElement(<span class="string">'div'</span>);\r
+\r
+ <span class="keyword">if</span> (++wdCount % <span class="number">2</span> === <span class="number">0</span>) {\r
+ oItem.className = <span class="string">'sm2-alt'</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (sTypeOrObject === _<span class="literal">undefined</span>) {\r
+ sTypeOrObject = <span class="number">0</span>;\r
+ } <span class="keyword">else</span> {\r
+ sTypeOrObject = parseInt(sTypeOrObject, <span class="number">10</span>);\r
+ }\r
+\r
+ oItem.appendChild(doc.createTextNode(sText));\r
+\r
+ <span class="keyword">if</span> (sTypeOrObject) {\r
+ <span class="keyword">if</span> (sTypeOrObject >= <span class="number">2</span>) {\r
+ oItem.style.fontWeight = <span class="string">'bold'</span>;\r
+ }\r
+ <span class="keyword">if</span> (sTypeOrObject === <span class="number">3</span>) {\r
+ oItem.style.color = <span class="string">'#ff3333'</span>;\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-72">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-72">¶</a>
+ </div>
+ <p>top-to-bottom
+o.appendChild(oItem);</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-73">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-73">¶</a>
+ </div>
+ <p>bottom-to-top</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> o.insertBefore(oItem, o.firstChild);\r
+\r
+ o = <span class="literal">null</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-74">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-74">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-75">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-75">¶</a>
+ </div>
+ <p><d>
+last-resort debugging option</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (wl.indexOf(<span class="string">'sm2-debug=alert'</span>) !== -<span class="number">1</span>) {\r
+ <span class="keyword">this</span>._writeDebug = <span class="keyword">function</span>(sText) {\r
+ window.alert(sText);\r
+ };\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-76">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-76">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-77">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-77">¶</a>
+ </div>
+ <p>alias</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>._wD = <span class="keyword">this</span>._writeDebug;\r
+\r
+ <span class="comment">/**\r
+ * Provides debug / state information on all SMSound objects.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>._debug = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-78">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-78">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> i, j;\r
+ _wDS(<span class="string">'currentObj'</span>, <span class="number">1</span>);\r
+\r
+ <span class="keyword">for</span> (i = <span class="number">0</span>, j = sm2.soundIDs.length; i < j; i++) {\r
+ sm2.sounds[sm2.soundIDs[i]]._debug();\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-79">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-79">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Restarts and re-initializes the SoundManager instance.\r
+ *\r
+ * @param {boolean} resetEvents Optional: When true, removes all registered onready and ontimeout event callbacks.\r
+ * @param {boolean} excludeInit Options: When true, does not call beginDelayedInit() (which would restart SM2).\r
+ * @return {object} soundManager The soundManager instance.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.reboot = <span class="keyword">function</span>(resetEvents, excludeInit) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-80">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-80">¶</a>
+ </div>
+ <p>reset some (or all) state, and re-init unless otherwise specified.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-81">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-81">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (sm2.soundIDs.length) {\r
+ sm2._wD(<span class="string">'Destroying '</span> + sm2.soundIDs.length + <span class="string">' SMSound object'</span> + (sm2.soundIDs.length !== <span class="number">1</span> ? <span class="string">'s'</span> : <span class="string">''</span>) + <span class="string">'...'</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-82">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-82">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> i, j, k;\r
+\r
+ <span class="keyword">for</span> (i = sm2.soundIDs.length- <span class="number">1</span> ; i >= <span class="number">0</span>; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].destruct();\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-83">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-83">¶</a>
+ </div>
+ <p>trash ze flash (remove from the DOM)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (flash) {\r
+\r
+ <span class="keyword">try</span> {\r
+\r
+ <span class="keyword">if</span> (isIE) {\r
+ oRemovedHTML = flash.innerHTML;\r
+ }\r
+\r
+ oRemoved = flash.parentNode.removeChild(flash);\r
+\r
+ } <span class="keyword">catch</span>(e) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-84">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-84">¶</a>
+ </div>
+ <p>Remove failed? May be due to flash blockers silently removing the SWF object/embed node from the DOM. Warn and continue.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ _wDS(<span class="string">'badRemove'</span>, <span class="number">2</span>);\r
+\r
+ }\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-85">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-85">¶</a>
+ </div>
+ <p>actually, force recreate of movie.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ oRemovedHTML = oRemoved = needsFlash = flash = <span class="literal">null</span>;\r
+\r
+ sm2.enabled = didDCLoaded = didInit = waitingForEI = initPending = didAppend = appendSuccess = disabled = useGlobalHTML5Audio = sm2.swfLoaded = <span class="literal">false</span>;\r
+\r
+ sm2.soundIDs = [];\r
+ sm2.sounds = {};\r
+\r
+ idCounter = <span class="number">0</span>;\r
+ didSetup = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (!resetEvents) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-86">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-86">¶</a>
+ </div>
+ <p>reset callbacks for onready, ontimeout etc. so that they will fire again on re-init</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">for</span> (i <span class="keyword">in</span> on_queue) {\r
+ <span class="keyword">if</span> (on_queue.hasOwnProperty(i)) {\r
+ <span class="keyword">for</span> (j = <span class="number">0</span>, k = on_queue[i].length; j < k; j++) {\r
+ on_queue[i][j].fired = <span class="literal">false</span>;\r
+ }\r
+ }\r
+ }\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-87">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-87">¶</a>
+ </div>
+ <p>remove all callbacks entirely</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> on_queue = [];\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-88">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-88">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!excludeInit) {\r
+ sm2._wD(sm + <span class="string">': Rebooting...'</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-89">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-89">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-90">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-90">¶</a>
+ </div>
+ <p>reset HTML5 and flash canPlay test results</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ sm2.html5 = {\r
+ <span class="string">'usingFlash'</span>: <span class="literal">null</span>\r
+ };\r
+\r
+ sm2.flash = {};</pre></div></div>
+
+ </li>
+
+
+ <li id="section-91">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-91">¶</a>
+ </div>
+ <p>reset device-specific HTML/flash mode switches</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ sm2.html5Only = <span class="literal">false</span>;\r
+ sm2.ignoreFlash = <span class="literal">false</span>;\r
+\r
+ window.setTimeout(<span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-92">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-92">¶</a>
+ </div>
+ <p>by default, re-init</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!excludeInit) {\r
+ sm2.beginDelayedInit();\r
+ }\r
+\r
+ }, <span class="number">20</span>);\r
+\r
+ <span class="keyword">return</span> sm2;\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>.reset = <span class="keyword">function</span>() {\r
+\r
+ <span class="comment">/**\r
+ * Shuts down and restores the SoundManager instance to its original loaded state, without an explicit reboot. All onready/ontimeout handlers are removed.\r
+ * After this call, SM2 may be re-initialized via soundManager.beginDelayedInit().\r
+ * @return {object} soundManager The soundManager instance.\r
+ */</span>\r
+\r
+ _wDS(<span class="string">'reset'</span>);\r
+ <span class="keyword">return</span> sm2.reboot(<span class="literal">true</span>, <span class="literal">true</span>);\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Undocumented: Determines the SM2 flash movie's load progress.\r
+ *\r
+ * @return {number or null} Percent loaded, or if invalid/unsupported, null.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.getMoviePercent = <span class="keyword">function</span>() {\r
+\r
+ <span class="comment">/**\r
+ * Interesting syntax notes...\r
+ * Flash/ExternalInterface (ActiveX/NPAPI) bridge methods are not typeof "function" nor instanceof Function, but are still valid.\r
+ * Additionally, JSLint dislikes ('PercentLoaded' in flash)-style syntax and recommends hasOwnProperty(), which does not work in this case.\r
+ * Furthermore, using (flash && flash.PercentLoaded) causes IE to throw "object doesn't support this property or method".\r
+ * Thus, 'in' syntax must be used.\r
+ */</span>\r
+\r
+ <span class="keyword">return</span> (flash && <span class="string">'PercentLoaded'</span> <span class="keyword">in</span> flash ? flash.PercentLoaded() : <span class="literal">null</span>); <span class="comment">// Yes, JSLint. See nearby comment in source for explanation.</span>\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Additional helper for manually invoking SM2's init process after DOM Ready / window.onload().\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.beginDelayedInit = <span class="keyword">function</span>() {\r
+\r
+ windowLoaded = <span class="literal">true</span>;\r
+ domContentLoaded();\r
+\r
+ setTimeout(<span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">if</span> (initPending) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ createMovie();\r
+ initMovie();\r
+ initPending = <span class="literal">true</span>;\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ }, <span class="number">20</span>);\r
+\r
+ delayWaitForEI();\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Destroys the SoundManager instance and all SMSound instances.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.destruct = <span class="keyword">function</span>() {\r
+\r
+ sm2._wD(sm + <span class="string">'.destruct()'</span>);\r
+ sm2.disable(<span class="literal">true</span>);\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * SMSound() (sound object) constructor\r
+ * ------------------------------------\r
+ *\r
+ * @param {object} oOptions Sound options (id and url are required attributes)\r
+ * @return {SMSound} The new SMSound object\r
+ */</span>\r
+\r
+ SMSound = <span class="keyword">function</span>(oOptions) {\r
+\r
+ <span class="keyword">var</span> s = <span class="keyword">this</span>, resetProperties, add_html5_events, remove_html5_events, stop_html5_timer, start_html5_timer, attachOnPosition, onplay_called = <span class="literal">false</span>, onPositionItems = [], onPositionFired = <span class="number">0</span>, detachOnPosition, applyFromTo, lastURL = <span class="literal">null</span>, lastHTML5State, urlOmitted;\r
+\r
+ lastHTML5State = {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-93">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-93">¶</a>
+ </div>
+ <p>tracks duration + position (time)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> duration: <span class="literal">null</span>,\r
+ time: <span class="literal">null</span>\r
+ };\r
+\r
+ <span class="keyword">this</span>.id = oOptions.id;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-94">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-94">¶</a>
+ </div>
+ <p>legacy</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.sID = <span class="keyword">this</span>.id;\r
+\r
+ <span class="keyword">this</span>.url = oOptions.url;\r
+ <span class="keyword">this</span>.options = mixin(oOptions);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-95">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-95">¶</a>
+ </div>
+ <p>per-play-instance-specific options</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.instanceOptions = <span class="keyword">this</span>.options;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-96">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-96">¶</a>
+ </div>
+ <p>short alias</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>._iO = <span class="keyword">this</span>.instanceOptions;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-97">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-97">¶</a>
+ </div>
+ <p>assign property defaults</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.pan = <span class="keyword">this</span>.options.pan;\r
+ <span class="keyword">this</span>.volume = <span class="keyword">this</span>.options.volume;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-98">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-98">¶</a>
+ </div>
+ <p>whether or not this object is using HTML5</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.isHTML5 = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-99">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-99">¶</a>
+ </div>
+ <p>internal HTML5 Audio() object reference</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>._a = <span class="literal">null</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-100">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-100">¶</a>
+ </div>
+ <p>for flash 8 special-case createSound() without url, followed by load/play with url case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> urlOmitted = (<span class="keyword">this</span>.url ? <span class="literal">false</span> : <span class="literal">true</span>);\r
+\r
+ <span class="comment">/**\r
+ * SMSound() public methods\r
+ * ------------------------\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.id3 = {};\r
+\r
+ <span class="comment">/**\r
+ * Writes SMSound object parameters to debug console\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>._debug = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-101">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-101">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(s.id + <span class="string">': Merged options:'</span>, s.options);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-102">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-102">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Begins loading a sound per its *url*.\r
+ *\r
+ * @param {object} oOptions Optional: Sound options\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.load = <span class="keyword">function</span>(oOptions) {\r
+\r
+ <span class="keyword">var</span> oSound = <span class="literal">null</span>, instanceOptions;\r
+\r
+ <span class="keyword">if</span> (oOptions !== _<span class="literal">undefined</span>) {\r
+ s._iO = mixin(oOptions, s.options);\r
+ } <span class="keyword">else</span> {\r
+ oOptions = s.options;\r
+ s._iO = oOptions;\r
+ <span class="keyword">if</span> (lastURL && lastURL !== s.url) {\r
+ _wDS(<span class="string">'manURL'</span>);\r
+ s._iO.url = s.url;\r
+ s.url = <span class="literal">null</span>;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">if</span> (!s._iO.url) {\r
+ s._iO.url = s.url;\r
+ }\r
+\r
+ s._iO.url = parseURL(s._iO.url);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-103">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-103">¶</a>
+ </div>
+ <p>ensure we're in sync</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.instanceOptions = s._iO;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-104">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-104">¶</a>
+ </div>
+ <p>local shortcut</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> instanceOptions = s._iO;\r
+\r
+ sm2._wD(s.id + <span class="string">': load ('</span> + instanceOptions.url + <span class="string">')'</span>);\r
+\r
+ <span class="keyword">if</span> (!instanceOptions.url && !s.url) {\r
+ sm2._wD(s.id + <span class="string">': load(): url is unassigned. Exiting.'</span>, <span class="number">2</span>);\r
+ <span class="keyword">return</span> s;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-105">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-105">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s.isHTML5 && fV === <span class="number">8</span> && !s.url && !instanceOptions.autoPlay) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-106">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-106">¶</a>
+ </div>
+ <p>flash 8 load() -> play() won't work before onload has fired.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(s.id + <span class="string">': Flash 8 load() limitation: Wait for onload() before calling play().'</span>, <span class="number">1</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-107">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-107">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (instanceOptions.url === s.url && s.readyState !== <span class="number">0</span> && s.readyState !== <span class="number">2</span>) {\r
+ _wDS(<span class="string">'onURL'</span>, <span class="number">1</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-108">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-108">¶</a>
+ </div>
+ <p>if loaded and an onload() exists, fire immediately.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.readyState === <span class="number">3</span> && instanceOptions.onload) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-109">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-109">¶</a>
+ </div>
+ <p>assume success based on truthy duration.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> wrapCallback(s, <span class="keyword">function</span>() {\r
+ instanceOptions.onload.apply(s, [(!!s.duration)]);\r
+ });\r
+ }\r
+ <span class="keyword">return</span> s;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-110">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-110">¶</a>
+ </div>
+ <p>reset a few state properties</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ s.loaded = <span class="literal">false</span>;\r
+ s.readyState = <span class="number">1</span>;\r
+ s.playState = <span class="number">0</span>;\r
+ s.id3 = {};</pre></div></div>
+
+ </li>
+
+
+ <li id="section-111">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-111">¶</a>
+ </div>
+ <p>TODO: If switching from HTML5 -> flash (or vice versa), stop currently-playing audio.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (html5OK(instanceOptions)) {\r
+\r
+ oSound = s._setup_html5(instanceOptions);\r
+\r
+ <span class="keyword">if</span> (!oSound._called_load) {\r
+\r
+ s._html5_canplay = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-112">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-112">¶</a>
+ </div>
+ <p>TODO: review called_load / html5_canplay logic</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-113">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-113">¶</a>
+ </div>
+ <p>if url provided directly to load(), assign it here.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (s.url !== instanceOptions.url) {\r
+\r
+ sm2._wD(_wDS(<span class="string">'manURL'</span>) + <span class="string">': '</span> + instanceOptions.url);\r
+\r
+ s._a.src = instanceOptions.url;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-114">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-114">¶</a>
+ </div>
+ <p>TODO: review / re-apply all relevant options (volume, loop, onposition etc.)</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-115">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-115">¶</a>
+ </div>
+ <p>reset position for new URL</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.setPosition(<span class="number">0</span>);\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-116">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-116">¶</a>
+ </div>
+ <p>given explicit load call, try to preload.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-117">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-117">¶</a>
+ </div>
+ <p>early HTML5 implementation (non-standard)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._a.autobuffer = <span class="string">'auto'</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-118">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-118">¶</a>
+ </div>
+ <p>standard property, values: none / metadata / auto
+reference: <a href="http://msdn.microsoft.com/en-us/library/ie/ff974759%28v=vs.85%29.aspx">http://msdn.microsoft.com/en-us/library/ie/ff974759%28v=vs.85%29.aspx</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._a.preload = <span class="string">'auto'</span>;\r
+\r
+ s._a._called_load = <span class="literal">true</span>;\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ sm2._wD(s.id + <span class="string">': Ignoring request to load again'</span>);\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (sm2.html5Only) {\r
+ sm2._wD(s.id + <span class="string">': No flash support. Exiting.'</span>);\r
+ <span class="keyword">return</span> s;\r
+ }\r
+\r
+ <span class="keyword">if</span> (s._iO.url && s._iO.url.match(<span class="regexp">/data\:/i</span>)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-119">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-119">¶</a>
+ </div>
+ <p>data: URIs not supported by Flash, either.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(s.id + <span class="string">': data: URIs not supported via Flash. Exiting.'</span>);\r
+ <span class="keyword">return</span> s;\r
+ }\r
+\r
+ <span class="keyword">try</span> {\r
+ s.isHTML5 = <span class="literal">false</span>;\r
+ s._iO = policyFix(loopFix(instanceOptions));</pre></div></div>
+
+ </li>
+
+
+ <li id="section-120">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-120">¶</a>
+ </div>
+ <p>if we have "position", disable auto-play as we'll be seeking to that position at onload().</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s._iO.autoPlay && (s._iO.position || s._iO.from)) {\r
+ sm2._wD(s.id + <span class="string">': Disabling autoPlay because of non-zero offset case'</span>);\r
+ s._iO.autoPlay = <span class="literal">false</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-121">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-121">¶</a>
+ </div>
+ <p>re-assign local shortcut</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> instanceOptions = s._iO;\r
+ <span class="keyword">if</span> (fV === <span class="number">8</span>) {\r
+ flash._load(s.id, instanceOptions.url, instanceOptions.stream, instanceOptions.autoPlay, instanceOptions.usePolicyFile);\r
+ } <span class="keyword">else</span> {\r
+ flash._load(s.id, instanceOptions.url, !!(instanceOptions.stream), !!(instanceOptions.autoPlay), instanceOptions.loops || <span class="number">1</span>, !!(instanceOptions.autoLoad), instanceOptions.usePolicyFile);\r
+ }\r
+ } <span class="keyword">catch</span>(e) {\r
+ _wDS(<span class="string">'smError'</span>, <span class="number">2</span>);\r
+ debugTS(<span class="string">'onload'</span>, <span class="literal">false</span>);\r
+ catchError({\r
+ type: <span class="string">'SMSOUND_LOAD_JS_EXCEPTION'</span>,\r
+ fatal: <span class="literal">true</span>\r
+ });\r
+ }\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-122">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-122">¶</a>
+ </div>
+ <p>after all of this, ensure sound url is up to date.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.url = instanceOptions.url;\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Unloads a sound, canceling any open HTTP requests.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.unload = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-123">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-123">¶</a>
+ </div>
+ <p>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</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (s.readyState !== <span class="number">0</span>) {\r
+\r
+ sm2._wD(s.id + <span class="string">': unload()'</span>);\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+\r
+ <span class="keyword">if</span> (fV === <span class="number">8</span>) {\r
+ flash._unload(s.id, emptyURL);\r
+ } <span class="keyword">else</span> {\r
+ flash._unload(s.id);\r
+ }\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ stop_html5_timer();\r
+\r
+ <span class="keyword">if</span> (s._a) {\r
+\r
+ s._a.pause();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-124">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-124">¶</a>
+ </div>
+ <p>update empty URL, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> lastURL = html5Unload(s._a);\r
+\r
+ }\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-125">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-125">¶</a>
+ </div>
+ <p>reset load/status flags</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> resetProperties();\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Unloads and destroys a sound.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.destruct = <span class="keyword">function</span>(_bFromSM) {\r
+\r
+ sm2._wD(s.id + <span class="string">': Destruct'</span>);\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-126">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-126">¶</a>
+ </div>
+ <p>kill sound within Flash
+Disable the onfailure handler</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._iO.onfailure = <span class="literal">null</span>;\r
+ flash._destroySound(s.id);\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ stop_html5_timer();\r
+\r
+ <span class="keyword">if</span> (s._a) {\r
+ s._a.pause();\r
+ html5Unload(s._a);\r
+ <span class="keyword">if</span> (!useGlobalHTML5Audio) {\r
+ remove_html5_events();\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-127">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-127">¶</a>
+ </div>
+ <p>break obvious circular reference</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._a._s = <span class="literal">null</span>;\r
+ s._a = <span class="literal">null</span>;\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (!_bFromSM) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-128">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-128">¶</a>
+ </div>
+ <p>ensure deletion from controller</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.destroySound(s.id, <span class="literal">true</span>);\r
+ }\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Begins playing a sound.\r
+ *\r
+ * @param {object} oOptions Optional: Sound options\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.play = <span class="keyword">function</span>(oOptions, _updatePlayState) {\r
+\r
+ <span class="keyword">var</span> fN, allowMulti, a, onready,\r
+ audioClone, onended, oncanplay,\r
+ startOK = <span class="literal">true</span>,\r
+ exit = <span class="literal">null</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-129">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-129">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> fN = s.id + <span class="string">': play(): '</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-130">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-130">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-131">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-131">¶</a>
+ </div>
+ <p>default to true</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> _updatePlayState = (_updatePlayState === _<span class="literal">undefined</span> ? <span class="literal">true</span> : _updatePlayState);\r
+\r
+ <span class="keyword">if</span> (!oOptions) {\r
+ oOptions = {};\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-132">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-132">¶</a>
+ </div>
+ <p>first, use local URL (if specified)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.url) {\r
+ s._iO.url = s.url;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-133">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-133">¶</a>
+ </div>
+ <p>mix in any options defined at createSound()</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._iO = mixin(s._iO, s.options);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-134">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-134">¶</a>
+ </div>
+ <p>mix in any options specific to this method</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._iO = mixin(oOptions, s._iO);\r
+\r
+ s._iO.url = parseURL(s._iO.url);\r
+\r
+ s.instanceOptions = s._iO;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-135">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-135">¶</a>
+ </div>
+ <p>RTMP-only</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s.isHTML5 && s._iO.serverURL && !s.connected) {\r
+ <span class="keyword">if</span> (!s.getAutoPlay()) {\r
+ sm2._wD(fN +<span class="string">' Netstream not connected yet - setting autoPlay'</span>);\r
+ s.setAutoPlay(<span class="literal">true</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-136">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-136">¶</a>
+ </div>
+ <p>play will be called in onconnect()</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> s;\r
+ }\r
+\r
+ <span class="keyword">if</span> (html5OK(s._iO)) {\r
+ s._setup_html5(s._iO);\r
+ start_html5_timer();\r
+ }\r
+\r
+ <span class="keyword">if</span> (s.playState === <span class="number">1</span> && !s.paused) {\r
+\r
+ allowMulti = s._iO.multiShot;\r
+\r
+ <span class="keyword">if</span> (!allowMulti) {\r
+\r
+ sm2._wD(fN + <span class="string">'Already playing (one-shot)'</span>, <span class="number">1</span>);\r
+\r
+ <span class="keyword">if</span> (s.isHTML5) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-137">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-137">¶</a>
+ </div>
+ <p>go back to original position.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.setPosition(s._iO.position);\r
+ }\r
+\r
+ exit = s;\r
+\r
+ } <span class="keyword">else</span> {\r
+ sm2._wD(fN + <span class="string">'Already playing (multi-shot)'</span>, <span class="number">1</span>);\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (exit !== <span class="literal">null</span>) {\r
+ <span class="keyword">return</span> exit;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-138">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-138">¶</a>
+ </div>
+ <p>edge case: play() with explicit URL parameter</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (oOptions.url && oOptions.url !== s.url) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-139">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-139">¶</a>
+ </div>
+ <p>special case for createSound() followed by load() / play() with url; avoid double-load case.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s.readyState && !s.isHTML5 && fV === <span class="number">8</span> && urlOmitted) {\r
+\r
+ urlOmitted = <span class="literal">false</span>;\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-140">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-140">¶</a>
+ </div>
+ <p>load using merged options</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.load(s._iO);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (!s.loaded) {\r
+\r
+ <span class="keyword">if</span> (s.readyState === <span class="number">0</span>) {\r
+\r
+ sm2._wD(fN + <span class="string">'Attempting to load'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-141">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-141">¶</a>
+ </div>
+ <p>try to get this sound playing ASAP</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s.isHTML5 && !sm2.html5Only) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-142">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-142">¶</a>
+ </div>
+ <p>flash: assign directly because setAutoPlay() increments the instanceCount</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._iO.autoPlay = <span class="literal">true</span>;\r
+ s.load(s._iO);\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s.isHTML5) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-143">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-143">¶</a>
+ </div>
+ <p>iOS needs this when recycling sounds, loading a new URL on an existing object.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.load(s._iO);\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ sm2._wD(fN + <span class="string">'Unsupported type. Exiting.'</span>);\r
+ exit = s;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-144">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-144">¶</a>
+ </div>
+ <p>HTML5 hack - re-set instanceOptions?</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.instanceOptions = s._iO;\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s.readyState === <span class="number">2</span>) {\r
+\r
+ sm2._wD(fN + <span class="string">'Could not load - exiting'</span>, <span class="number">2</span>);\r
+ exit = s;\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ sm2._wD(fN + <span class="string">'Loading - attempting to play...'</span>);\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-145">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-145">¶</a>
+ </div>
+ <p>"play()"</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(fN.substr(<span class="number">0</span>, fN.lastIndexOf(<span class="string">':'</span>)));\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (exit !== <span class="literal">null</span>) {\r
+ <span class="keyword">return</span> exit;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5 && fV === <span class="number">9</span> && s.position > <span class="number">0</span> && s.position === s.duration) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-146">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-146">¶</a>
+ </div>
+ <p>flash 9 needs a position reset if play() is called while at the end of a sound.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(fN + <span class="string">'Sound at end, resetting to position: 0'</span>);\r
+ oOptions.position = <span class="number">0</span>;\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Streams will pause when their buffer is full if they are being loaded.\r
+ * In this case paused is true, but the song hasn't started playing yet.\r
+ * If we just call resume() the onplay() callback will never be called.\r
+ * So only call resume() if the position is > 0.\r
+ * Another reason is because options like volume won't have been applied yet.\r
+ * For normal sounds, just resume.\r
+ */</span>\r
+\r
+ <span class="keyword">if</span> (s.paused && s.position >= <span class="number">0</span> && (!s._iO.serverURL || s.position > <span class="number">0</span>)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-147">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-147">¶</a>
+ </div>
+ <p><a href="https://gist.github.com/37b17df75cc4d7a90bf6">https://gist.github.com/37b17df75cc4d7a90bf6</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(fN + <span class="string">'Resuming from paused state'</span>, <span class="number">1</span>);\r
+ s.resume();\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ s._iO = mixin(oOptions, s._iO);\r
+\r
+ <span class="comment">/**\r
+ * Preload in the event of play() with position under Flash,\r
+ * or from/to parameters and non-RTMP case\r
+ */</span>\r
+ <span class="keyword">if</span> (((!s.isHTML5 && s._iO.position !== <span class="literal">null</span> && s._iO.position > <span class="number">0</span>) || (s._iO.from !== <span class="literal">null</span> && s._iO.from > <span class="number">0</span>) || s._iO.to !== <span class="literal">null</span>) && s.instanceCount === <span class="number">0</span> && s.playState === <span class="number">0</span> && !s._iO.serverURL) {\r
+\r
+ onready = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-148">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-148">¶</a>
+ </div>
+ <p>sound "canplay" or onload()
+re-apply position/from/to to instance options, and start playback</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._iO = mixin(oOptions, s._iO);\r
+ s.play(s._iO);\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-149">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-149">¶</a>
+ </div>
+ <p>HTML5 needs to at least have "canplay" fired before seeking.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.isHTML5 && !s._html5_canplay) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-150">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-150">¶</a>
+ </div>
+ <p>this hasn't been loaded yet. load it first, and then do this again.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(fN + <span class="string">'Beginning load for non-zero offset case'</span>);\r
+\r
+ s.load({</pre></div></div>
+
+ </li>
+
+
+ <li id="section-151">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-151">¶</a>
+ </div>
+ <p>note: custom HTML5-only event added for from/to implementation.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> _oncanplay: onready\r
+ });\r
+\r
+ exit = <span class="literal">false</span>;\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (!s.isHTML5 && !s.loaded && (!s.readyState || s.readyState !== <span class="number">2</span>)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-152">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-152">¶</a>
+ </div>
+ <p>to be safe, preload the whole thing in Flash.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ sm2._wD(fN + <span class="string">'Preloading for non-zero offset case'</span>);\r
+\r
+ s.load({\r
+ onload: onready\r
+ });\r
+\r
+ exit = <span class="literal">false</span>;\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (exit !== <span class="literal">null</span>) {\r
+ <span class="keyword">return</span> exit;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-153">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-153">¶</a>
+ </div>
+ <p>otherwise, we're ready to go. re-apply local options, and continue</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ s._iO = applyFromTo();\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-154">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-154">¶</a>
+ </div>
+ <p>sm2._wD(fN + 'Starting to play');</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-155">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-155">¶</a>
+ </div>
+ <p>increment instance counter, where enabled + supported</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s.instanceCount || s._iO.multiShotEvents || (s.isHTML5 && s._iO.multiShot && !useGlobalHTML5Audio) || (!s.isHTML5 && fV > <span class="number">8</span> && !s.getAutoPlay())) {\r
+ s.instanceCount++;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-156">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-156">¶</a>
+ </div>
+ <p>if first play and onposition parameters exist, apply them now</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s._iO.onposition && s.playState === <span class="number">0</span>) {\r
+ attachOnPosition(s);\r
+ }\r
+\r
+ s.playState = <span class="number">1</span>;\r
+ s.paused = <span class="literal">false</span>;\r
+\r
+ s.position = (s._iO.position !== _<span class="literal">undefined</span> && !isNaN(s._iO.position) ? s._iO.position : <span class="number">0</span>);\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+ s._iO = policyFix(loopFix(s._iO));\r
+ }\r
+\r
+ <span class="keyword">if</span> (s._iO.onplay && _updatePlayState) {\r
+ s._iO.onplay.apply(s);\r
+ onplay_called = <span class="literal">true</span>;\r
+ }\r
+\r
+ s.setVolume(s._iO.volume, <span class="literal">true</span>);\r
+ s.setPan(s._iO.pan, <span class="literal">true</span>);\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+\r
+ startOK = flash._start(s.id, s._iO.loops || <span class="number">1</span>, (fV === <span class="number">9</span> ? s.position : s.position / msecScale), s._iO.multiShot || <span class="literal">false</span>);\r
+\r
+ <span class="keyword">if</span> (fV === <span class="number">9</span> && !startOK) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-157">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-157">¶</a>
+ </div>
+ <p>edge case: no sound hardware, or 32-channel flash ceiling hit.
+applies only to Flash 9, non-NetStream/MovieStar sounds.
+<a href="http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29">http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(fN + <span class="string">'No sound hardware, or 32-sound ceiling hit'</span>, <span class="number">2</span>);\r
+ <span class="keyword">if</span> (s._iO.onplayerror) {\r
+ s._iO.onplayerror.apply(s);\r
+ }\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (s.instanceCount < <span class="number">2</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-158">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-158">¶</a>
+ </div>
+ <p>HTML5 single-instance case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ start_html5_timer();\r
+\r
+ a = s._setup_html5();\r
+\r
+ s.setPosition(s._iO.position);\r
+\r
+ a.play();\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-159">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-159">¶</a>
+ </div>
+ <p>HTML5 multi-shot case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ sm2._wD(s.id + <span class="string">': Cloning Audio() for instance #'</span> + s.instanceCount + <span class="string">'...'</span>);\r
+\r
+ audioClone = <span class="keyword">new</span> Audio(s._iO.url);\r
+\r
+ onended = <span class="keyword">function</span>() {\r
+ event.remove(audioClone, <span class="string">'ended'</span>, onended);\r
+ s._onfinish(s);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-160">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-160">¶</a>
+ </div>
+ <p>cleanup</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> html5Unload(audioClone);\r
+ audioClone = <span class="literal">null</span>;\r
+ };\r
+\r
+ oncanplay = <span class="keyword">function</span>() {\r
+ event.remove(audioClone, <span class="string">'canplay'</span>, oncanplay);\r
+ <span class="keyword">try</span> {\r
+ audioClone.currentTime = s._iO.position/msecScale;\r
+ } <span class="keyword">catch</span>(err) {\r
+ complain(s.id + <span class="string">': multiShot play() failed to apply position of '</span> + (s._iO.position/msecScale));\r
+ }\r
+ audioClone.play();\r
+ };\r
+\r
+ event.add(audioClone, <span class="string">'ended'</span>, onended);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-161">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-161">¶</a>
+ </div>
+ <p>apply volume to clones, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s._iO.volume !== _<span class="literal">undefined</span>) {\r
+ audioClone.volume = Math.max(<span class="number">0</span>, Math.min(<span class="number">1</span>, s._iO.volume/<span class="number">100</span>));\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-162">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-162">¶</a>
+ </div>
+ <p>playing multiple muted sounds? if you do this, you're weird ;) - but let's cover it.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.muted) {\r
+ audioClone.muted = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (s._iO.position) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-163">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-163">¶</a>
+ </div>
+ <p>HTML5 audio can't seek before onplay() event has fired.
+wait for canplay, then seek to position and start playback.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> event.add(audioClone, <span class="string">'canplay'</span>, oncanplay);\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-164">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-164">¶</a>
+ </div>
+ <p>begin playback at currentTime: 0</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> audioClone.play();\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-165">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-165">¶</a>
+ </div>
+ <p>just for convenience</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.start = <span class="keyword">this</span>.play;\r
+\r
+ <span class="comment">/**\r
+ * Stops playing a sound (and optionally, all sounds)\r
+ *\r
+ * @param {boolean} bAll Optional: Whether to stop all sounds\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.stop = <span class="keyword">function</span>(bAll) {\r
+\r
+ <span class="keyword">var</span> instanceOptions = s._iO,\r
+ originalPosition;\r
+\r
+ <span class="keyword">if</span> (s.playState === <span class="number">1</span>) {\r
+\r
+ sm2._wD(s.id + <span class="string">': stop()'</span>);\r
+\r
+ s._onbufferchange(<span class="number">0</span>);\r
+ s._resetOnPosition(<span class="number">0</span>);\r
+ s.paused = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+ s.playState = <span class="number">0</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-166">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-166">¶</a>
+ </div>
+ <p>remove onPosition listeners, if any</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> detachOnPosition();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-167">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-167">¶</a>
+ </div>
+ <p>and "to" position, if set</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (instanceOptions.to) {\r
+ s.clearOnPosition(instanceOptions.to);\r
+ }\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+\r
+ flash._stop(s.id, bAll);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-168">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-168">¶</a>
+ </div>
+ <p>hack for netStream: just unload</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (instanceOptions.serverURL) {\r
+ s.unload();\r
+ }\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (s._a) {\r
+\r
+ originalPosition = s.position;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-169">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-169">¶</a>
+ </div>
+ <p>act like Flash, though</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.setPosition(<span class="number">0</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-170">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-170">¶</a>
+ </div>
+ <p>hack: reflect old position for onstop() (also like Flash)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.position = originalPosition;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-171">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-171">¶</a>
+ </div>
+ <p>html5 has no stop()
+NOTE: pausing means iOS requires interaction to resume.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._a.pause();\r
+\r
+ s.playState = <span class="number">0</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-172">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-172">¶</a>
+ </div>
+ <p>and update UI</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._onTimer();\r
+\r
+ stop_html5_timer();\r
+\r
+ }\r
+\r
+ }\r
+\r
+ s.instanceCount = <span class="number">0</span>;\r
+ s._iO = {};\r
+\r
+ <span class="keyword">if</span> (instanceOptions.onstop) {\r
+ instanceOptions.onstop.apply(s);\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Undocumented/internal: Sets autoPlay for RTMP.\r
+ *\r
+ * @param {boolean} autoPlay state\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.setAutoPlay = <span class="keyword">function</span>(autoPlay) {\r
+\r
+ sm2._wD(s.id + <span class="string">': Autoplay turned '</span> + (autoPlay ? <span class="string">'on'</span> : <span class="string">'off'</span>));\r
+ s._iO.autoPlay = autoPlay;\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+ flash._setAutoPlay(s.id, autoPlay);\r
+ <span class="keyword">if</span> (autoPlay) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-173">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-173">¶</a>
+ </div>
+ <p>only increment the instanceCount if the sound isn't loaded (TODO: verify RTMP)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s.instanceCount && s.readyState === <span class="number">1</span>) {\r
+ s.instanceCount++;\r
+ sm2._wD(s.id + <span class="string">': Incremented instance count to '</span>+s.instanceCount);\r
+ }\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Undocumented/internal: Returns the autoPlay boolean.\r
+ *\r
+ * @return {boolean} The current autoPlay value\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.getAutoPlay = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">return</span> s._iO.autoPlay;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Sets the position of a sound.\r
+ *\r
+ * @param {number} nMsecOffset Position (milliseconds)\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.setPosition = <span class="keyword">function</span>(nMsecOffset) {\r
+\r
+ <span class="keyword">if</span> (nMsecOffset === _<span class="literal">undefined</span>) {\r
+ nMsecOffset = <span class="number">0</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> position, position1K,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-174">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-174">¶</a>
+ </div>
+ <p>Use the duration from the instance options, if we don't have a track duration yet.
+position >= 0 and <= current available (loaded) duration</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> offset = (s.isHTML5 ? Math.max(nMsecOffset, <span class="number">0</span>) : Math.min(s.duration || s._iO.duration, Math.max(nMsecOffset, <span class="number">0</span>)));\r
+\r
+ s.position = offset;\r
+ position1K = s.position/msecScale;\r
+ s._resetOnPosition(s.position);\r
+ s._iO.position = offset;\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+\r
+ position = (fV === <span class="number">9</span> ? s.position : position1K);\r
+\r
+ <span class="keyword">if</span> (s.readyState && s.readyState !== <span class="number">2</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-175">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-175">¶</a>
+ </div>
+ <p>if paused or not playing, will not resume (by playing)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> flash._setPosition(s.id, position, (s.paused || !s.playState), s._iO.multiShot);\r
+ }\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s._a) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-176">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-176">¶</a>
+ </div>
+ <p>Set the position in the canplay handler if the sound is not ready yet</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s._html5_canplay) {\r
+\r
+ <span class="keyword">if</span> (s._a.currentTime !== position1K) {\r
+\r
+ <span class="comment">/**\r
+ * DOM/JS errors/exceptions to watch out for:\r
+ * if seek is beyond (loaded?) position, "DOM exception 11"\r
+ * "INDEX_SIZE_ERR": DOM exception 1\r
+ */</span>\r
+ sm2._wD(s.id + <span class="string">': setPosition('</span> + position1K + <span class="string">')'</span>);\r
+\r
+ <span class="keyword">try</span> {\r
+ s._a.currentTime = position1K;\r
+ <span class="keyword">if</span> (s.playState === <span class="number">0</span> || s.paused) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-177">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-177">¶</a>
+ </div>
+ <p>allow seek without auto-play/resume</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._a.pause();\r
+ }\r
+ } <span class="keyword">catch</span>(e) {\r
+ sm2._wD(s.id + <span class="string">': setPosition('</span> + position1K + <span class="string">') failed: '</span> + e.message, <span class="number">2</span>);\r
+ }\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (position1K) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-178">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-178">¶</a>
+ </div>
+ <p>warn on non-zero seek attempts</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(s.id + <span class="string">': setPosition('</span> + position1K + <span class="string">'): Cannot seek yet, sound not ready'</span>, <span class="number">2</span>);\r
+ <span class="keyword">return</span> s;\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (s.paused) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-179">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-179">¶</a>
+ </div>
+ <p>if paused, refresh UI right away by forcing update</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._onTimer(<span class="literal">true</span>);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Pauses sound playback.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.pause = <span class="keyword">function</span>(_bCallFlash) {\r
+\r
+ <span class="keyword">if</span> (s.paused || (s.playState === <span class="number">0</span> && s.readyState !== <span class="number">1</span>)) {\r
+ <span class="keyword">return</span> s;\r
+ }\r
+\r
+ sm2._wD(s.id + <span class="string">': pause()'</span>);\r
+ s.paused = <span class="literal">true</span>;\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+ <span class="keyword">if</span> (_bCallFlash || _bCallFlash === _<span class="literal">undefined</span>) {\r
+ flash._pause(s.id, s._iO.multiShot);\r
+ }\r
+ } <span class="keyword">else</span> {\r
+ s._setup_html5().pause();\r
+ stop_html5_timer();\r
+ }\r
+\r
+ <span class="keyword">if</span> (s._iO.onpause) {\r
+ s._iO.onpause.apply(s);\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Resumes sound playback.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="comment">/**\r
+ * When auto-loaded streams pause on buffer full they have a playState of 0.\r
+ * We need to make sure that the playState is set to 1 when these streams "resume".\r
+ * When a paused stream is resumed, we need to trigger the onplay() callback if it\r
+ * hasn't been called already. In this case since the sound is being played for the\r
+ * first time, I think it's more appropriate to call onplay() rather than onresume().\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.resume = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> instanceOptions = s._iO;\r
+\r
+ <span class="keyword">if</span> (!s.paused) {\r
+ <span class="keyword">return</span> s;\r
+ }\r
+\r
+ sm2._wD(s.id + <span class="string">': resume()'</span>);\r
+ s.paused = <span class="literal">false</span>;\r
+ s.playState = <span class="number">1</span>;\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+\r
+ <span class="keyword">if</span> (instanceOptions.isMovieStar && !instanceOptions.serverURL) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-180">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-180">¶</a>
+ </div>
+ <p>Bizarre Webkit bug (Chrome reported via 8tracks.com dudes): AAC content paused for 30+ seconds(?) will not resume without a reposition.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.setPosition(s.position);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-181">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-181">¶</a>
+ </div>
+ <p>flash method is toggle-based (pause/resume)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> flash._pause(s.id, instanceOptions.multiShot);\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ s._setup_html5().play();\r
+ start_html5_timer();\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (!onplay_called && instanceOptions.onplay) {\r
+\r
+ instanceOptions.onplay.apply(s);\r
+ onplay_called = <span class="literal">true</span>;\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (instanceOptions.onresume) {\r
+\r
+ instanceOptions.onresume.apply(s);\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Toggles sound playback.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.togglePause = <span class="keyword">function</span>() {\r
+\r
+ sm2._wD(s.id + <span class="string">': togglePause()'</span>);\r
+\r
+ <span class="keyword">if</span> (s.playState === <span class="number">0</span>) {\r
+ s.play({\r
+ position: (fV === <span class="number">9</span> && !s.isHTML5 ? s.position : s.position / msecScale)\r
+ });\r
+ <span class="keyword">return</span> s;\r
+ }\r
+\r
+ <span class="keyword">if</span> (s.paused) {\r
+ s.resume();\r
+ } <span class="keyword">else</span> {\r
+ s.pause();\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Sets the panning (L-R) effect.\r
+ *\r
+ * @param {number} nPan The pan value (-100 to 100)\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.setPan = <span class="keyword">function</span>(nPan, bInstanceOnly) {\r
+\r
+ <span class="keyword">if</span> (nPan === _<span class="literal">undefined</span>) {\r
+ nPan = <span class="number">0</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (bInstanceOnly === _<span class="literal">undefined</span>) {\r
+ bInstanceOnly = <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+ flash._setPan(s.id, nPan);\r
+ } <span class="comment">// else { no HTML5 pan? }</span>\r
+\r
+ s._iO.pan = nPan;\r
+\r
+ <span class="keyword">if</span> (!bInstanceOnly) {\r
+ s.pan = nPan;\r
+ s.options.pan = nPan;\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Sets the volume.\r
+ *\r
+ * @param {number} nVol The volume value (0 to 100)\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.setVolume = <span class="keyword">function</span>(nVol, _bInstanceOnly) {\r
+\r
+ <span class="comment">/**\r
+ * Note: Setting volume has no effect on iOS "special snowflake" devices.\r
+ * Hardware volume control overrides software, and volume\r
+ * will always return 1 per Apple docs. (iOS 4 + 5.)\r
+ * http://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/AddingSoundtoCanvasAnimations/AddingSoundtoCanvasAnimations.html\r
+ */</span>\r
+\r
+ <span class="keyword">if</span> (nVol === _<span class="literal">undefined</span>) {\r
+ nVol = <span class="number">100</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (_bInstanceOnly === _<span class="literal">undefined</span>) {\r
+ _bInstanceOnly = <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+\r
+ flash._setVolume(s.id, (sm2.muted && !s.muted) || s.muted ? <span class="number">0</span> : nVol);\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s._a) {\r
+\r
+ <span class="keyword">if</span> (sm2.muted && !s.muted) {\r
+ s.muted = <span class="literal">true</span>;\r
+ s._a.muted = <span class="literal">true</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-182">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-182">¶</a>
+ </div>
+ <p>valid range for native HTML5 Audio(): 0-1</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._a.volume = Math.max(<span class="number">0</span>, Math.min(<span class="number">1</span>, nVol/<span class="number">100</span>));\r
+\r
+ }\r
+\r
+ s._iO.volume = nVol;\r
+\r
+ <span class="keyword">if</span> (!_bInstanceOnly) {\r
+ s.volume = nVol;\r
+ s.options.volume = nVol;\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Mutes the sound.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.mute = <span class="keyword">function</span>() {\r
+\r
+ s.muted = <span class="literal">true</span>;\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+ flash._setVolume(s.id, <span class="number">0</span>);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s._a) {\r
+ s._a.muted = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Unmutes the sound.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.unmute = <span class="keyword">function</span>() {\r
+\r
+ s.muted = <span class="literal">false</span>;\r
+ <span class="keyword">var</span> hasIO = (s._iO.volume !== _<span class="literal">undefined</span>);\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5) {\r
+ flash._setVolume(s.id, hasIO ? s._iO.volume : s.options.volume);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s._a) {\r
+ s._a.muted = <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Toggles the muted state of a sound.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.toggleMute = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">return</span> (s.muted ? s.unmute() : s.mute());\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Registers a callback to be fired when a sound reaches a given position during playback.\r
+ *\r
+ * @param {number} nPosition The position to watch for\r
+ * @param {function} oMethod The relevant callback to fire\r
+ * @param {object} oScope Optional: The scope to apply the callback to\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.onPosition = <span class="keyword">function</span>(nPosition, oMethod, oScope) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-183">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-183">¶</a>
+ </div>
+ <p>TODO: basic dupe checking?</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ onPositionItems.push({\r
+ position: parseInt(nPosition, <span class="number">10</span>),\r
+ method: oMethod,\r
+ scope: (oScope !== _<span class="literal">undefined</span> ? oScope : s),\r
+ fired: <span class="literal">false</span>\r
+ });\r
+\r
+ <span class="keyword">return</span> s;\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-184">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-184">¶</a>
+ </div>
+ <p>legacy/backwards-compability: lower-case method name</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>.onposition = <span class="keyword">this</span>.onPosition;\r
+\r
+ <span class="comment">/**\r
+ * Removes registered callback(s) from a sound, by position and/or callback.\r
+ *\r
+ * @param {number} nPosition The position to clear callback(s) for\r
+ * @param {function} oMethod Optional: Identify one callback to be removed when multiple listeners exist for one position\r
+ * @return {SMSound} The SMSound object\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>.clearOnPosition = <span class="keyword">function</span>(nPosition, oMethod) {\r
+\r
+ <span class="keyword">var</span> i;\r
+\r
+ nPosition = parseInt(nPosition, <span class="number">10</span>);\r
+\r
+ <span class="keyword">if</span> (isNaN(nPosition)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-185">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-185">¶</a>
+ </div>
+ <p>safety check</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">for</span> (i=<span class="number">0</span>; i < onPositionItems.length; i++) {\r
+\r
+ <span class="keyword">if</span> (nPosition === onPositionItems[i].position) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-186">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-186">¶</a>
+ </div>
+ <p>remove this item if no method was specified, or, if the method matches</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> \r
+ <span class="keyword">if</span> (!oMethod || (oMethod === onPositionItems[i].method)) {\r
+ \r
+ <span class="keyword">if</span> (onPositionItems[i].fired) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-187">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-187">¶</a>
+ </div>
+ <p>decrement "fired" counter, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> onPositionFired--;\r
+ }\r
+ \r
+ onPositionItems.splice(i, <span class="number">1</span>);\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._processOnPosition = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> i, item, j = onPositionItems.length;\r
+\r
+ <span class="keyword">if</span> (!j || !s.playState || onPositionFired >= j) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">for</span> (i = j - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {\r
+ \r
+ item = onPositionItems[i];\r
+ \r
+ <span class="keyword">if</span> (!item.fired && s.position >= item.position) {\r
+ \r
+ item.fired = <span class="literal">true</span>;\r
+ onPositionFired++;\r
+ item.method.apply(item.scope, [item.position]);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-188">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-188">¶</a>
+ </div>
+ <p> reset j -- onPositionItems.length can be changed in the item callback above... occasionally breaking the loop.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> j = onPositionItems.length;\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._resetOnPosition = <span class="keyword">function</span>(nPosition) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-189">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-189">¶</a>
+ </div>
+ <p>reset "fired" for items interested in this position</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> i, item, j = onPositionItems.length;\r
+\r
+ <span class="keyword">if</span> (!j) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">for</span> (i = j - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {\r
+ \r
+ item = onPositionItems[i];\r
+ \r
+ <span class="keyword">if</span> (item.fired && nPosition <= item.position) {\r
+ item.fired = <span class="literal">false</span>;\r
+ onPositionFired--;\r
+ }\r
+ \r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * SMSound() private internals\r
+ * --------------------------------\r
+ */</span>\r
+\r
+ applyFromTo = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> instanceOptions = s._iO,\r
+ f = instanceOptions.from,\r
+ t = instanceOptions.to,\r
+ start, end;\r
+\r
+ end = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-190">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-190">¶</a>
+ </div>
+ <p>end has been reached.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(s.id + <span class="string">': "To" time of '</span> + t + <span class="string">' reached.'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-191">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-191">¶</a>
+ </div>
+ <p>detach listener</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.clearOnPosition(t, end);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-192">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-192">¶</a>
+ </div>
+ <p>stop should clear this, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.stop();\r
+\r
+ };\r
+\r
+ start = <span class="keyword">function</span>() {\r
+\r
+ sm2._wD(s.id + <span class="string">': Playing "from" '</span> + f);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-193">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-193">¶</a>
+ </div>
+ <p>add listener for end</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (t !== <span class="literal">null</span> && !isNaN(t)) {\r
+ s.onPosition(t, end);\r
+ }\r
+\r
+ };\r
+\r
+ <span class="keyword">if</span> (f !== <span class="literal">null</span> && !isNaN(f)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-194">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-194">¶</a>
+ </div>
+ <p>apply to instance options, guaranteeing correct start position.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> instanceOptions.position = f;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-195">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-195">¶</a>
+ </div>
+ <p>multiShot timing can't be tracked, so prevent that.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> instanceOptions.multiShot = <span class="literal">false</span>;\r
+\r
+ start();\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-196">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-196">¶</a>
+ </div>
+ <p>return updated instanceOptions including starting position</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> instanceOptions;\r
+\r
+ };\r
+\r
+ attachOnPosition = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> item,\r
+ op = s._iO.onposition;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-197">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-197">¶</a>
+ </div>
+ <p>attach onposition things, if any, now.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (op) {\r
+\r
+ <span class="keyword">for</span> (item <span class="keyword">in</span> op) {\r
+ <span class="keyword">if</span> (op.hasOwnProperty(item)) {\r
+ s.onPosition(parseInt(item, <span class="number">10</span>), op[item]);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ detachOnPosition = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> item,\r
+ op = s._iO.onposition;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-198">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-198">¶</a>
+ </div>
+ <p>detach any onposition()-style listeners.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (op) {\r
+\r
+ <span class="keyword">for</span> (item <span class="keyword">in</span> op) {\r
+ <span class="keyword">if</span> (op.hasOwnProperty(item)) {\r
+ s.clearOnPosition(parseInt(item, <span class="number">10</span>));\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ start_html5_timer = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">if</span> (s.isHTML5) {\r
+ startTimer(s);\r
+ }\r
+\r
+ };\r
+\r
+ stop_html5_timer = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">if</span> (s.isHTML5) {\r
+ stopTimer(s);\r
+ }\r
+\r
+ };\r
+\r
+ resetProperties = <span class="keyword">function</span>(retainPosition) {\r
+\r
+ <span class="keyword">if</span> (!retainPosition) {\r
+ onPositionItems = [];\r
+ onPositionFired = <span class="number">0</span>;\r
+ }\r
+\r
+ onplay_called = <span class="literal">false</span>;\r
+\r
+ s._hasTimer = <span class="literal">null</span>;\r
+ s._a = <span class="literal">null</span>;\r
+ s._html5_canplay = <span class="literal">false</span>;\r
+ s.bytesLoaded = <span class="literal">null</span>;\r
+ s.bytesTotal = <span class="literal">null</span>;\r
+ s.duration = (s._iO && s._iO.duration ? s._iO.duration : <span class="literal">null</span>);\r
+ s.durationEstimate = <span class="literal">null</span>;\r
+ s.buffered = [];</pre></div></div>
+
+ </li>
+
+
+ <li id="section-199">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-199">¶</a>
+ </div>
+ <p>legacy: 1D array</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.eqData = [];\r
+\r
+ s.eqData.left = [];\r
+ s.eqData.right = [];\r
+\r
+ s.failures = <span class="number">0</span>;\r
+ s.isBuffering = <span class="literal">false</span>;\r
+ s.instanceOptions = {};\r
+ s.instanceCount = <span class="number">0</span>;\r
+ s.loaded = <span class="literal">false</span>;\r
+ s.metadata = {};</pre></div></div>
+
+ </li>
+
+
+ <li id="section-200">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-200">¶</a>
+ </div>
+ <p>0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.readyState = <span class="number">0</span>;\r
+\r
+ s.muted = <span class="literal">false</span>;\r
+ s.paused = <span class="literal">false</span>;\r
+\r
+ s.peakData = {\r
+ left: <span class="number">0</span>,\r
+ right: <span class="number">0</span>\r
+ };\r
+\r
+ s.waveformData = {\r
+ left: [],\r
+ right: []\r
+ };\r
+\r
+ s.playState = <span class="number">0</span>;\r
+ s.position = <span class="literal">null</span>;\r
+\r
+ s.id3 = {};\r
+\r
+ };\r
+\r
+ resetProperties();\r
+\r
+ <span class="comment">/**\r
+ * Pseudo-private SMSound internals\r
+ * --------------------------------\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>._onTimer = <span class="keyword">function</span>(bForce) {\r
+\r
+ <span class="comment">/**\r
+ * HTML5-only _whileplaying() etc.\r
+ * called from both HTML5 native events, and polling/interval-based timers\r
+ * mimics flash and fires only when time/duration change, so as to be polling-friendly\r
+ */</span>\r
+\r
+ <span class="keyword">var</span> duration, isNew = <span class="literal">false</span>, time, x = {};\r
+\r
+ <span class="keyword">if</span> (s._hasTimer || bForce) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-201">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-201">¶</a>
+ </div>
+ <p>TODO: May not need to track readyState (1 = loading)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (s._a && (bForce || ((s.playState > <span class="number">0</span> || s.readyState === <span class="number">1</span>) && !s.paused))) {\r
+\r
+ duration = s._get_html5_duration();\r
+\r
+ <span class="keyword">if</span> (duration !== lastHTML5State.duration) {\r
+\r
+ lastHTML5State.duration = duration;\r
+ s.duration = duration;\r
+ isNew = <span class="literal">true</span>;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-202">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-202">¶</a>
+ </div>
+ <p>TODO: investigate why this goes wack if not set/re-set each time.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.durationEstimate = s.duration;\r
+\r
+ time = (s._a.currentTime * msecScale || <span class="number">0</span>);\r
+\r
+ <span class="keyword">if</span> (time !== lastHTML5State.time) {\r
+\r
+ lastHTML5State.time = time;\r
+ isNew = <span class="literal">true</span>;\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (isNew || bForce) {\r
+\r
+ s._whileplaying(time, x, x, x, x);\r
+\r
+ }\r
+\r
+ }<span class="comment">/* else {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-203">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-203">¶</a>
+ </div>
+ <p>sm2._wD('_onTimer: Warn for "'+s.id+'": '+(!s._a?'Could not find element. ':'')+(s.playState === 0?'playState bad, 0?':'playState = '+s.playState+', OK'));</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ return false;\r
+\r
+ }*/\r
+\r
+ return isNew;\r
+\r
+ }\r
+\r
+ };\r
+\r
+ this._get_html5_duration = function() {\r
+\r
+ var instanceOptions = s._iO,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-204">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-204">¶</a>
+ </div>
+ <p>if audio object exists, use its duration - else, instance option duration (if provided - it's a hack, really, and should be retired) OR null</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> d = (s._a && s._a.duration ? s._a.duration * msecScale : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : <span class="literal">null</span>)),\r
+ result = (d && !isNaN(d) && d !== <span class="literal">Infinity</span> ? d : <span class="literal">null</span>);\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._apply_loop = <span class="keyword">function</span>(a, nLoops) {\r
+\r
+ <span class="comment">/**\r
+ * boolean instead of "loop", for webkit? - spec says string. http://www.w3.org/TR/html-markup/audio.html#audio.attrs.loop\r
+ * note that loop is either off or infinite under HTML5, unlike Flash which allows arbitrary loop counts to be specified.\r
+ */</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-205">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-205">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!a.loop && nLoops > <span class="number">1</span>) {\r
+ sm2._wD(<span class="string">'Note: Native HTML5 looping is infinite.'</span>, <span class="number">1</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-206">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-206">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ a.loop = (nLoops > <span class="number">1</span> ? <span class="string">'loop'</span> : <span class="string">''</span>);\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._setup_html5 = <span class="keyword">function</span>(oOptions) {\r
+\r
+ <span class="keyword">var</span> instanceOptions = mixin(s._iO, oOptions),\r
+ a = useGlobalHTML5Audio ? globalHTML5Audio : s._a,\r
+ dURL = decodeURI(instanceOptions.url),\r
+ sameURL;\r
+\r
+ <span class="comment">/**\r
+ * "First things first, I, Poppa..." (reset the previous state of the old sound, if playing)\r
+ * Fixes case with devices that can only play one sound at a time\r
+ * Otherwise, other sounds in mid-play will be terminated without warning and in a stuck state\r
+ */</span>\r
+\r
+ <span class="keyword">if</span> (useGlobalHTML5Audio) {\r
+\r
+ <span class="keyword">if</span> (dURL === decodeURI(lastGlobalHTML5URL)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-207">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-207">¶</a>
+ </div>
+ <p>global HTML5 audio: re-use of URL</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sameURL = <span class="literal">true</span>;\r
+ }\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (dURL === decodeURI(lastURL)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-208">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-208">¶</a>
+ </div>
+ <p>options URL is the same as the "last" URL, and we used (loaded) it</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sameURL = <span class="literal">true</span>;\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (a) {\r
+\r
+ <span class="keyword">if</span> (a._s) {\r
+\r
+ <span class="keyword">if</span> (useGlobalHTML5Audio) {\r
+\r
+ <span class="keyword">if</span> (a._s && a._s.playState && !sameURL) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-209">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-209">¶</a>
+ </div>
+ <p>global HTML5 audio case, and loading a new URL. stop the currently-playing one.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> a._s.stop();\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (!useGlobalHTML5Audio && dURL === decodeURI(lastURL)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-210">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-210">¶</a>
+ </div>
+ <p>non-global HTML5 reuse case: same url, ignore request</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._apply_loop(a, instanceOptions.loops);\r
+\r
+ <span class="keyword">return</span> a;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (!sameURL) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-211">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-211">¶</a>
+ </div>
+ <p>don't retain onPosition() stuff with new URLs.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (lastURL) {\r
+ resetProperties(<span class="literal">false</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-212">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-212">¶</a>
+ </div>
+ <p>assign new HTML5 URL</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ a.src = instanceOptions.url;\r
+\r
+ s.url = instanceOptions.url;\r
+\r
+ lastURL = instanceOptions.url;\r
+\r
+ lastGlobalHTML5URL = instanceOptions.url;\r
+\r
+ a._called_load = <span class="literal">false</span>;\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (instanceOptions.autoLoad || instanceOptions.autoPlay) {\r
+\r
+ s._a = <span class="keyword">new</span> Audio(instanceOptions.url);\r
+ s._a.load();\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-213">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-213">¶</a>
+ </div>
+ <p>null for stupid Opera 9.64 case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._a = (isOpera && opera.version() < <span class="number">10</span> ? <span class="keyword">new</span> Audio(<span class="literal">null</span>) : <span class="keyword">new</span> Audio());\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-214">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-214">¶</a>
+ </div>
+ <p>assign local reference</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> a = s._a;\r
+\r
+ a._called_load = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (useGlobalHTML5Audio) {\r
+\r
+ globalHTML5Audio = a;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ s.isHTML5 = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-215">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-215">¶</a>
+ </div>
+ <p>store a ref on the track</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._a = a;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-216">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-216">¶</a>
+ </div>
+ <p>store a ref on the audio</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> a._s = s;\r
+\r
+ add_html5_events();\r
+\r
+ s._apply_loop(a, instanceOptions.loops);\r
+\r
+ <span class="keyword">if</span> (instanceOptions.autoLoad || instanceOptions.autoPlay) {\r
+\r
+ s.load();\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-217">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-217">¶</a>
+ </div>
+ <p>early HTML5 implementation (non-standard)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> a.autobuffer = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-218">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-218">¶</a>
+ </div>
+ <p>standard ('none' is also an option.)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> a.preload = <span class="string">'auto'</span>;\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> a;\r
+\r
+ };\r
+\r
+ add_html5_events = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">if</span> (s._a._added_events) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> f;\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">add</span><span class="params">(oEvt, oFn, bCapture)</span> {</span>\r
+ <span class="keyword">return</span> s._a ? s._a.addEventListener(oEvt, oFn, bCapture || <span class="literal">false</span>) : <span class="literal">null</span>;\r
+ }\r
+\r
+ s._a._added_events = <span class="literal">true</span>;\r
+\r
+ <span class="keyword">for</span> (f <span class="keyword">in</span> html5_events) {\r
+ <span class="keyword">if</span> (html5_events.hasOwnProperty(f)) {\r
+ add(f, html5_events[f]);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ remove_html5_events = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-219">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-219">¶</a>
+ </div>
+ <p>Remove event listeners</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> f;\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">remove</span><span class="params">(oEvt, oFn, bCapture)</span> {</span>\r
+ <span class="keyword">return</span> (s._a ? s._a.removeEventListener(oEvt, oFn, bCapture || <span class="literal">false</span>) : <span class="literal">null</span>);\r
+ }\r
+\r
+ sm2._wD(s.id + <span class="string">': Removing event listeners'</span>);\r
+ s._a._added_events = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">for</span> (f <span class="keyword">in</span> html5_events) {\r
+ <span class="keyword">if</span> (html5_events.hasOwnProperty(f)) {\r
+ remove(f, html5_events[f]);\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Pseudo-private event internals\r
+ * ------------------------------\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>._onload = <span class="keyword">function</span>(nSuccess) {\r
+\r
+ <span class="keyword">var</span> fN,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-220">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-220">¶</a>
+ </div>
+ <p>check for duration to prevent false positives from flash 8 when loading from cache.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> loadOK = !!nSuccess || (!s.isHTML5 && fV === <span class="number">8</span> && s.duration);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-221">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-221">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> fN = s.id + <span class="string">': '</span>;\r
+ sm2._wD(fN + (loadOK ? <span class="string">'onload()'</span> : <span class="string">'Failed to load / invalid sound?'</span> + (!s.duration ? <span class="string">' Zero-length duration reported.'</span> : <span class="string">' -'</span>) + <span class="string">' ('</span> + s.url + <span class="string">')'</span>), (loadOK ? <span class="number">1</span> : <span class="number">2</span>));\r
+\r
+ <span class="keyword">if</span> (!loadOK && !s.isHTML5) {\r
+ <span class="keyword">if</span> (sm2.sandbox.noRemote === <span class="literal">true</span>) {\r
+ sm2._wD(fN + str(<span class="string">'noNet'</span>), <span class="number">1</span>);\r
+ }\r
+ <span class="keyword">if</span> (sm2.sandbox.noLocal === <span class="literal">true</span>) {\r
+ sm2._wD(fN + str(<span class="string">'noLocal'</span>), <span class="number">1</span>);\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-222">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-222">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ s.loaded = loadOK;\r
+ s.readyState = (loadOK ? <span class="number">3</span> : <span class="number">2</span>);\r
+ s._onbufferchange(<span class="number">0</span>);\r
+\r
+ <span class="keyword">if</span> (s._iO.onload) {\r
+ wrapCallback(s, <span class="keyword">function</span>() {\r
+ s._iO.onload.apply(s, [loadOK]);\r
+ });\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._onbufferchange = <span class="keyword">function</span>(nIsBuffering) {\r
+\r
+ <span class="keyword">if</span> (s.playState === <span class="number">0</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-223">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-223">¶</a>
+ </div>
+ <p>ignore if not playing</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> ((nIsBuffering && s.isBuffering) || (!nIsBuffering && !s.isBuffering)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ s.isBuffering = (nIsBuffering === <span class="number">1</span>);\r
+ \r
+ <span class="keyword">if</span> (s._iO.onbufferchange) {\r
+ sm2._wD(s.id + <span class="string">': Buffer state change: '</span> + nIsBuffering);\r
+ s._iO.onbufferchange.apply(s, [nIsBuffering]);\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Playback may have stopped due to buffering, or related reason.\r
+ * This state can be encountered on iOS < 6 when auto-play is blocked.\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>._onsuspend = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">if</span> (s._iO.onsuspend) {\r
+ sm2._wD(s.id + <span class="string">': Playback suspended'</span>);\r
+ s._iO.onsuspend.apply(s);\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * flash 9/movieStar + RTMP-only method, should fire only once at most\r
+ * at this point we just recreate failed sounds rather than trying to reconnect\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>._onfailure = <span class="keyword">function</span>(msg, level, code) {\r
+\r
+ s.failures++;\r
+ sm2._wD(s.id + <span class="string">': Failure ('</span> + s.failures + <span class="string">'): '</span> + msg);\r
+\r
+ <span class="keyword">if</span> (s._iO.onfailure && s.failures === <span class="number">1</span>) {\r
+ s._iO.onfailure(msg, level, code);\r
+ } <span class="keyword">else</span> {\r
+ sm2._wD(s.id + <span class="string">': Ignoring failure'</span>);\r
+ }\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * flash 9/movieStar + RTMP-only method for unhandled warnings/exceptions from Flash\r
+ * e.g., RTMP "method missing" warning (non-fatal) for getStreamLength on server\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>._onwarning = <span class="keyword">function</span>(msg, level, code) {\r
+\r
+ <span class="keyword">if</span> (s._iO.onwarning) {\r
+ s._iO.onwarning(msg, level, code);\r
+ }\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._onfinish = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-224">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-224">¶</a>
+ </div>
+ <p>store local copy before it gets trashed...</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> io_onfinish = s._iO.onfinish;\r
+\r
+ s._onbufferchange(<span class="number">0</span>);\r
+ s._resetOnPosition(<span class="number">0</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-225">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-225">¶</a>
+ </div>
+ <p>reset some state items</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.instanceCount) {\r
+\r
+ s.instanceCount--;\r
+\r
+ <span class="keyword">if</span> (!s.instanceCount) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-226">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-226">¶</a>
+ </div>
+ <p>remove onPosition listeners, if any</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> detachOnPosition();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-227">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-227">¶</a>
+ </div>
+ <p>reset instance options</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.playState = <span class="number">0</span>;\r
+ s.paused = <span class="literal">false</span>;\r
+ s.instanceCount = <span class="number">0</span>;\r
+ s.instanceOptions = {};\r
+ s._iO = {};\r
+ stop_html5_timer();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-228">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-228">¶</a>
+ </div>
+ <p>reset position, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.isHTML5) {\r
+ s.position = <span class="number">0</span>;\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (!s.instanceCount || s._iO.multiShotEvents) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-229">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-229">¶</a>
+ </div>
+ <p>fire onfinish for last, or every instance</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (io_onfinish) {\r
+ sm2._wD(s.id + <span class="string">': onfinish()'</span>);\r
+ wrapCallback(s, <span class="keyword">function</span>() {\r
+ io_onfinish.apply(s);\r
+ });\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._whileloading = <span class="keyword">function</span>(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) {\r
+\r
+ <span class="keyword">var</span> instanceOptions = s._iO;\r
+\r
+ s.bytesLoaded = nBytesLoaded;\r
+ s.bytesTotal = nBytesTotal;\r
+ s.duration = Math.floor(nDuration);\r
+ s.bufferLength = nBufferLength;\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5 && !instanceOptions.isMovieStar) {\r
+\r
+ <span class="keyword">if</span> (instanceOptions.duration) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-230">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-230">¶</a>
+ </div>
+ <p>use duration from options, if specified and larger. nobody should be specifying duration in options, actually, and it should be retired.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.durationEstimate = (s.duration > instanceOptions.duration) ? s.duration : instanceOptions.duration;\r
+ } <span class="keyword">else</span> {\r
+ s.durationEstimate = parseInt((s.bytesTotal / s.bytesLoaded) * s.duration, <span class="number">10</span>);\r
+ }\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ s.durationEstimate = s.duration;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-231">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-231">¶</a>
+ </div>
+ <p>for flash, reflect sequential-load-style buffering</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s.isHTML5) {\r
+ s.buffered = [{\r
+ <span class="string">'start'</span>: <span class="number">0</span>,\r
+ <span class="string">'end'</span>: s.duration\r
+ }];\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-232">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-232">¶</a>
+ </div>
+ <p>allow whileloading to fire even if "load" fired under HTML5, due to HTTP range/partials</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> ((s.readyState !== <span class="number">3</span> || s.isHTML5) && instanceOptions.whileloading) {\r
+ instanceOptions.whileloading.apply(s);\r
+ }\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._whileplaying = <span class="keyword">function</span>(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) {\r
+\r
+ <span class="keyword">var</span> instanceOptions = s._iO,\r
+ eqLeft;\r
+\r
+ <span class="keyword">if</span> (isNaN(nPosition) || nPosition === <span class="literal">null</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-233">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-233">¶</a>
+ </div>
+ <p>flash safety net</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-234">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-234">¶</a>
+ </div>
+ <p>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.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.position = Math.max(<span class="number">0</span>, nPosition);\r
+\r
+ s._processOnPosition();\r
+\r
+ <span class="keyword">if</span> (!s.isHTML5 && fV > <span class="number">8</span>) {\r
+\r
+ <span class="keyword">if</span> (instanceOptions.usePeakData && oPeakData !== _<span class="literal">undefined</span> && oPeakData) {\r
+ s.peakData = {\r
+ left: oPeakData.leftPeak,\r
+ right: oPeakData.rightPeak\r
+ };\r
+ }\r
+\r
+ <span class="keyword">if</span> (instanceOptions.useWaveformData && oWaveformDataLeft !== _<span class="literal">undefined</span> && oWaveformDataLeft) {\r
+ s.waveformData = {\r
+ left: oWaveformDataLeft.split(<span class="string">','</span>),\r
+ right: oWaveformDataRight.split(<span class="string">','</span>)\r
+ };\r
+ }\r
+\r
+ <span class="keyword">if</span> (instanceOptions.useEQData) {\r
+ <span class="keyword">if</span> (oEQData !== _<span class="literal">undefined</span> && oEQData && oEQData.leftEQ) {\r
+ eqLeft = oEQData.leftEQ.split(<span class="string">','</span>);\r
+ s.eqData = eqLeft;\r
+ s.eqData.left = eqLeft;\r
+ <span class="keyword">if</span> (oEQData.rightEQ !== _<span class="literal">undefined</span> && oEQData.rightEQ) {\r
+ s.eqData.right = oEQData.rightEQ.split(<span class="string">','</span>);\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (s.playState === <span class="number">1</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-235">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-235">¶</a>
+ </div>
+ <p>special case/hack: ensure buffering is false if loading from cache (and not yet started)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s.isHTML5 && fV === <span class="number">8</span> && !s.position && s.isBuffering) {\r
+ s._onbufferchange(<span class="number">0</span>);\r
+ }\r
+\r
+ <span class="keyword">if</span> (instanceOptions.whileplaying) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-236">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-236">¶</a>
+ </div>
+ <p>flash may call after actual finish</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> instanceOptions.whileplaying.apply(s);\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._oncaptiondata = <span class="keyword">function</span>(oData) {\r
+\r
+ <span class="comment">/**\r
+ * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature\r
+ *\r
+ * @param {object} oData\r
+ */</span>\r
+\r
+ sm2._wD(s.id + <span class="string">': Caption data received.'</span>);\r
+\r
+ s.captiondata = oData;\r
+\r
+ <span class="keyword">if</span> (s._iO.oncaptiondata) {\r
+ s._iO.oncaptiondata.apply(s, [oData]);\r
+ }\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._onmetadata = <span class="keyword">function</span>(oMDProps, oMDData) {\r
+\r
+ <span class="comment">/**\r
+ * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature\r
+ * RTMP may include song title, MovieStar content may include encoding info\r
+ *\r
+ * @param {array} oMDProps (names)\r
+ * @param {array} oMDData (values)\r
+ */</span>\r
+\r
+ sm2._wD(s.id + <span class="string">': Metadata received.'</span>);\r
+\r
+ <span class="keyword">var</span> oData = {}, i, j;\r
+\r
+ <span class="keyword">for</span> (i = <span class="number">0</span>, j = oMDProps.length; i < j; i++) {\r
+ oData[oMDProps[i]] = oMDData[i];\r
+ }\r
+\r
+ s.metadata = oData;\r
+\r
+ <span class="keyword">if</span> (s._iO.onmetadata) {\r
+ s._iO.onmetadata.call(s, s.metadata);\r
+ }\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._onid3 = <span class="keyword">function</span>(oID3Props, oID3Data) {\r
+\r
+ <span class="comment">/**\r
+ * internal: flash 8 + flash 9 ID3 feature\r
+ * may include artist, song title etc.\r
+ *\r
+ * @param {array} oID3Props (names)\r
+ * @param {array} oID3Data (values)\r
+ */</span>\r
+\r
+ sm2._wD(s.id + <span class="string">': ID3 data received.'</span>);\r
+\r
+ <span class="keyword">var</span> oData = [], i, j;\r
+\r
+ <span class="keyword">for</span> (i = <span class="number">0</span>, j = oID3Props.length; i < j; i++) {\r
+ oData[oID3Props[i]] = oID3Data[i];\r
+ }\r
+\r
+ s.id3 = mixin(s.id3, oData);\r
+\r
+ <span class="keyword">if</span> (s._iO.onid3) {\r
+ s._iO.onid3.apply(s);\r
+ }\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-237">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-237">¶</a>
+ </div>
+ <p>flash/RTMP-only</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">this</span>._onconnect = <span class="keyword">function</span>(bSuccess) {\r
+\r
+ bSuccess = (bSuccess === <span class="number">1</span>);\r
+ sm2._wD(s.id + <span class="string">': '</span> + (bSuccess ? <span class="string">'Connected.'</span> : <span class="string">'Failed to connect? - '</span> + s.url), (bSuccess ? <span class="number">1</span> : <span class="number">2</span>));\r
+ s.connected = bSuccess;\r
+\r
+ <span class="keyword">if</span> (bSuccess) {\r
+\r
+ s.failures = <span class="number">0</span>;\r
+\r
+ <span class="keyword">if</span> (idCheck(s.id)) {\r
+ <span class="keyword">if</span> (s.getAutoPlay()) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-238">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-238">¶</a>
+ </div>
+ <p>only update the play state if auto playing</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.play(_<span class="literal">undefined</span>, s.getAutoPlay());\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (s._iO.autoLoad) {\r
+ s.load();\r
+ }\r
+ }\r
+\r
+ <span class="keyword">if</span> (s._iO.onconnect) {\r
+ s._iO.onconnect.apply(s, [bSuccess]);\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ <span class="keyword">this</span>._ondataerror = <span class="keyword">function</span>(sError) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-239">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-239">¶</a>
+ </div>
+ <p>flash 9 wave/eq data handler
+hack: called at start, and end from flash at/after onfinish()</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s.playState > <span class="number">0</span>) {\r
+ sm2._wD(s.id + <span class="string">': Data error: '</span> + sError);\r
+ <span class="keyword">if</span> (s._iO.ondataerror) {\r
+ s._iO.ondataerror.apply(s);\r
+ }\r
+ }\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-240">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-240">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>._debug();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-241">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-241">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ }; <span class="comment">// SMSound()</span>\r
+\r
+ <span class="comment">/**\r
+ * Private SoundManager internals\r
+ * ------------------------------\r
+ */</span>\r
+\r
+ getDocument = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">return</span> (doc.body || doc.getElementsByTagName(<span class="string">'div'</span>)[<span class="number">0</span>]);\r
+\r
+ };\r
+\r
+ id = <span class="keyword">function</span>(sID) {\r
+\r
+ <span class="keyword">return</span> doc.getElementById(sID);\r
+\r
+ };\r
+\r
+ mixin = <span class="keyword">function</span>(oMain, oAdd) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-242">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-242">¶</a>
+ </div>
+ <p>non-destructive merge</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> o1 = (oMain || {}), o2, o;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-243">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-243">¶</a>
+ </div>
+ <p>if unspecified, o2 is the default options object</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> o2 = (oAdd === _<span class="literal">undefined</span> ? sm2.defaultOptions : oAdd);\r
+\r
+ <span class="keyword">for</span> (o <span class="keyword">in</span> o2) {\r
+\r
+ <span class="keyword">if</span> (o2.hasOwnProperty(o) && o1[o] === _<span class="literal">undefined</span>) {\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> o2[o] !== <span class="string">'object'</span> || o2[o] === <span class="literal">null</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-244">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-244">¶</a>
+ </div>
+ <p>assign directly</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> o1[o] = o2[o];\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-245">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-245">¶</a>
+ </div>
+ <p>recurse through o2</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> o1[o] = mixin(o1[o], o2[o]);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> o1;\r
+\r
+ };\r
+\r
+ wrapCallback = <span class="keyword">function</span>(oSound, callback) {\r
+\r
+ <span class="comment">/**\r
+ * 03/03/2013: Fix for Flash Player 11.6.602.171 + Flash 8 (flashVersion = 8) SWF issue\r
+ * setTimeout() fix for certain SMSound callbacks like onload() and onfinish(), where subsequent calls like play() and load() fail when Flash Player 11.6.602.171 is installed, and using soundManager with flashVersion = 8 (which is the default).\r
+ * Not sure of exact cause. Suspect race condition and/or invalid (NaN-style) position argument trickling down to the next JS -> Flash _start() call, in the play() case.\r
+ * Fix: setTimeout() to yield, plus safer null / NaN checking on position argument provided to Flash.\r
+ * https://getsatisfaction.com/schillmania/topics/recent_chrome_update_seems_to_have_broken_my_sm2_audio_player\r
+ */</span>\r
+ <span class="keyword">if</span> (!oSound.isHTML5 && fV === <span class="number">8</span>) {\r
+ window.setTimeout(callback, <span class="number">0</span>);\r
+ } <span class="keyword">else</span> {\r
+ callback();\r
+ }\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-246">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-246">¶</a>
+ </div>
+ <p>additional soundManager properties that soundManager.setup() will accept</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ extraOptions = {\r
+ <span class="string">'onready'</span>: <span class="number">1</span>,\r
+ <span class="string">'ontimeout'</span>: <span class="number">1</span>,\r
+ <span class="string">'defaultOptions'</span>: <span class="number">1</span>,\r
+ <span class="string">'flash9Options'</span>: <span class="number">1</span>,\r
+ <span class="string">'movieStarOptions'</span>: <span class="number">1</span>\r
+ };\r
+\r
+ assign = <span class="keyword">function</span>(o, oParent) {\r
+\r
+ <span class="comment">/**\r
+ * recursive assignment of properties, soundManager.setup() helper\r
+ * allows property assignment based on whitelist\r
+ */</span>\r
+\r
+ <span class="keyword">var</span> i,\r
+ result = <span class="literal">true</span>,\r
+ hasParent = (oParent !== _<span class="literal">undefined</span>),\r
+ setupOptions = sm2.setupOptions,\r
+ bonusOptions = extraOptions;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-247">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-247">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-248">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-248">¶</a>
+ </div>
+ <p>if soundManager.setup() called, show accepted parameters.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (o === _<span class="literal">undefined</span>) {\r
+\r
+ result = [];\r
+\r
+ <span class="keyword">for</span> (i <span class="keyword">in</span> setupOptions) {\r
+\r
+ <span class="keyword">if</span> (setupOptions.hasOwnProperty(i)) {\r
+ result.push(i);\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">for</span> (i <span class="keyword">in</span> bonusOptions) {\r
+\r
+ <span class="keyword">if</span> (bonusOptions.hasOwnProperty(i)) {\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> sm2[i] === <span class="string">'object'</span>) {\r
+ result.push(i + <span class="string">': {...}'</span>);\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (sm2[i] <span class="keyword">instanceof</span> Function) {\r
+ result.push(i + <span class="string">': function() {...}'</span>);\r
+ } <span class="keyword">else</span> {\r
+ result.push(i);\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ sm2._wD(str(<span class="string">'setup'</span>, result.join(<span class="string">', '</span>)));\r
+\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-249">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-249">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">for</span> (i <span class="keyword">in</span> o) {\r
+\r
+ <span class="keyword">if</span> (o.hasOwnProperty(i)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-250">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-250">¶</a>
+ </div>
+ <p>if not an {object} we want to recurse through...</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> o[i] !== <span class="string">'object'</span> || o[i] === <span class="literal">null</span> || o[i] <span class="keyword">instanceof</span> Array || o[i] <span class="keyword">instanceof</span> RegExp) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-251">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-251">¶</a>
+ </div>
+ <p>check "allowed" options</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (hasParent && bonusOptions[oParent] !== _<span class="literal">undefined</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-252">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-252">¶</a>
+ </div>
+ <p>valid recursive / nested object option, eg., { defaultOptions: { volume: 50 } }</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2[oParent][i] = o[i];\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (setupOptions[i] !== _<span class="literal">undefined</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-253">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-253">¶</a>
+ </div>
+ <p>special case: assign to setupOptions object, which soundManager property references</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.setupOptions[i] = o[i];</pre></div></div>
+
+ </li>
+
+
+ <li id="section-254">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-254">¶</a>
+ </div>
+ <p>assign directly to soundManager, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2[i] = o[i];\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (bonusOptions[i] === _<span class="literal">undefined</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-255">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-255">¶</a>
+ </div>
+ <p>invalid or disallowed parameter. complain.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> complain(str((sm2[i] === _<span class="literal">undefined</span> ? <span class="string">'setupUndef'</span> : <span class="string">'setupError'</span>), i), <span class="number">2</span>);\r
+\r
+ result = <span class="literal">false</span>;\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="comment">/**\r
+ * valid extraOptions (bonusOptions) parameter.\r
+ * is it a method, like onready/ontimeout? call it.\r
+ * multiple parameters should be in an array, eg. soundManager.setup({onready: [myHandler, myScope]});\r
+ */</span>\r
+\r
+ <span class="keyword">if</span> (sm2[i] <span class="keyword">instanceof</span> Function) {\r
+\r
+ sm2[i].apply(sm2, (o[i] <span class="keyword">instanceof</span> Array ? o[i] : [o[i]]));\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-256">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-256">¶</a>
+ </div>
+ <p>good old-fashioned direct assignment</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2[i] = o[i];\r
+\r
+ }\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-257">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-257">¶</a>
+ </div>
+ <p>recursion case, eg., { defaultOptions: { ... } }</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (bonusOptions[i] === _<span class="literal">undefined</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-258">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-258">¶</a>
+ </div>
+ <p>invalid or disallowed parameter. complain.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> complain(str((sm2[i] === _<span class="literal">undefined</span> ? <span class="string">'setupUndef'</span> : <span class="string">'setupError'</span>), i), <span class="number">2</span>);\r
+\r
+ result = <span class="literal">false</span>;\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-259">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-259">¶</a>
+ </div>
+ <p>recurse through object</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> assign(o[i], i);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">preferFlashCheck</span><span class="params">(kind)</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-260">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-260">¶</a>
+ </div>
+ <p>whether flash should play a given type</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> (sm2.preferFlash && hasFlash && !sm2.ignoreFlash && (sm2.flash[kind] !== _<span class="literal">undefined</span> && sm2.flash[kind]));\r
+\r
+ }\r
+\r
+ <span class="comment">/**\r
+ * Internal DOM2-level event helpers\r
+ * ---------------------------------\r
+ */</span>\r
+\r
+ event = (<span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-261">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-261">¶</a>
+ </div>
+ <p>normalize event methods</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> old = (window.attachEvent),\r
+ evt = {\r
+ add: (old ? <span class="string">'attachEvent'</span> : <span class="string">'addEventListener'</span>),\r
+ remove: (old ? <span class="string">'detachEvent'</span> : <span class="string">'removeEventListener'</span>)\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-262">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-262">¶</a>
+ </div>
+ <p>normalize "on" event prefix, optional capture argument</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="function"><span class="keyword">function</span> <span class="title">getArgs</span><span class="params">(oArgs)</span> {</span>\r
+\r
+ <span class="keyword">var</span> args = slice.call(oArgs),\r
+ len = args.length;\r
+\r
+ <span class="keyword">if</span> (old) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-263">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-263">¶</a>
+ </div>
+ <p>prefix</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> args[<span class="number">1</span>] = <span class="string">'on'</span> + args[<span class="number">1</span>];\r
+ <span class="keyword">if</span> (len > <span class="number">3</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-264">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-264">¶</a>
+ </div>
+ <p>no capture</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> args.pop();\r
+ }\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (len === <span class="number">3</span>) {\r
+ args.push(<span class="literal">false</span>);\r
+ }\r
+\r
+ <span class="keyword">return</span> args;\r
+\r
+ }\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">apply</span><span class="params">(args, sType)</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-265">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-265">¶</a>
+ </div>
+ <p>normalize and call the event method, with the proper arguments</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> element = args.shift(),\r
+ method = [evt[sType]];\r
+\r
+ <span class="keyword">if</span> (old) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-266">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-266">¶</a>
+ </div>
+ <p>old IE can't do apply().</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> element[method](args[<span class="number">0</span>], args[<span class="number">1</span>]);\r
+ } <span class="keyword">else</span> {\r
+ element[method].apply(element, args);\r
+ }\r
+\r
+ }\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">add</span><span class="params">()</span> {</span>\r
+ apply(getArgs(arguments), <span class="string">'add'</span>);\r
+ }\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">remove</span><span class="params">()</span> {</span>\r
+ apply(getArgs(arguments), <span class="string">'remove'</span>);\r
+ }\r
+\r
+ <span class="keyword">return</span> {\r
+ <span class="string">'add'</span>: add,\r
+ <span class="string">'remove'</span>: remove\r
+ };\r
+\r
+ }());\r
+\r
+ <span class="comment">/**\r
+ * Internal HTML5 event handling\r
+ * -----------------------------\r
+ */</span>\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">html5_event</span><span class="params">(oFn)</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-267">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-267">¶</a>
+ </div>
+ <p>wrap html5 event handlers so we don't call them on destroyed and/or unloaded sounds</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">return</span> <span class="keyword">function</span>(e) {\r
+\r
+ <span class="keyword">var</span> s = <span class="keyword">this</span>._s,\r
+ result;\r
+\r
+ <span class="keyword">if</span> (!s || !s._a) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-268">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-268">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s && s.id) {\r
+ sm2._wD(s.id + <span class="string">': Ignoring '</span> + e.type);\r
+ } <span class="keyword">else</span> {\r
+ sm2._wD(h5 + <span class="string">'Ignoring '</span> + e.type);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-269">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-269">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> result = <span class="literal">null</span>;\r
+ } <span class="keyword">else</span> {\r
+ result = oFn.call(<span class="keyword">this</span>, e);\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ }\r
+\r
+ html5_events = {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-270">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-270">¶</a>
+ </div>
+ <p>HTML5 event-name-to-handler map</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ abort: html5_event(<span class="keyword">function</span>() {\r
+\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': abort'</span>);\r
+\r
+ }),</pre></div></div>
+
+ </li>
+
+
+ <li id="section-271">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-271">¶</a>
+ </div>
+ <p>enough has loaded to play</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ canplay: html5_event(<span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> s = <span class="keyword">this</span>._s,\r
+ position1K;\r
+\r
+ <span class="keyword">if</span> (s._html5_canplay) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-272">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-272">¶</a>
+ </div>
+ <p>this event has already fired. ignore.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">true</span>;\r
+ }\r
+\r
+ s._html5_canplay = <span class="literal">true</span>;\r
+ sm2._wD(s.id + <span class="string">': canplay'</span>);\r
+ s._onbufferchange(<span class="number">0</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-273">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-273">¶</a>
+ </div>
+ <p>position according to instance options</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> position1K = (s._iO.position !== _<span class="literal">undefined</span> && !isNaN(s._iO.position) ? s._iO.position/msecScale : <span class="literal">null</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-274">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-274">¶</a>
+ </div>
+ <p>set the position if position was provided before the sound loaded</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (<span class="keyword">this</span>.currentTime !== position1K) {\r
+ sm2._wD(s.id + <span class="string">': canplay: Setting position to '</span> + position1K);\r
+ <span class="keyword">try</span> {\r
+ <span class="keyword">this</span>.currentTime = position1K;\r
+ } <span class="keyword">catch</span>(ee) {\r
+ sm2._wD(s.id + <span class="string">': canplay: Setting position of '</span> + position1K + <span class="string">' failed: '</span> + ee.message, <span class="number">2</span>);\r
+ }\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-275">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-275">¶</a>
+ </div>
+ <p>hack for HTML5 from/to case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (s._iO._oncanplay) {\r
+ s._iO._oncanplay();\r
+ }\r
+\r
+ }),\r
+\r
+ canplaythrough: html5_event(<span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> s = <span class="keyword">this</span>._s;\r
+\r
+ <span class="keyword">if</span> (!s.loaded) {\r
+ s._onbufferchange(<span class="number">0</span>);\r
+ s._whileloading(s.bytesLoaded, s.bytesTotal, s._get_html5_duration());\r
+ s._onload(<span class="literal">true</span>);\r
+ }\r
+\r
+ }),\r
+\r
+ durationchange: html5_event(<span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-276">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-276">¶</a>
+ </div>
+ <p>durationchange may fire at various times, probably the safest way to capture accurate/final duration.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> s = <span class="keyword">this</span>._s,\r
+ duration;\r
+\r
+ duration = s._get_html5_duration();\r
+\r
+ <span class="keyword">if</span> (!isNaN(duration) && duration !== s.duration) {\r
+\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': durationchange ('</span> + duration + <span class="string">')'</span> + (s.duration ? <span class="string">', previously '</span> + s.duration : <span class="string">''</span>));\r
+\r
+ s.durationEstimate = s.duration = duration;\r
+\r
+ }\r
+\r
+ }),</pre></div></div>
+
+ </li>
+
+
+ <li id="section-277">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-277">¶</a>
+ </div>
+ <p>TODO: Reserved for potential use</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="comment">/*\r
+ emptied: html5_event(function() {\r
+\r
+ sm2._wD(this._s.id + ': emptied');\r
+\r
+ }),\r
+ */</span>\r
+\r
+ ended: html5_event(<span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> s = <span class="keyword">this</span>._s;\r
+\r
+ sm2._wD(s.id + <span class="string">': ended'</span>);\r
+\r
+ s._onfinish();\r
+\r
+ }),\r
+\r
+ error: html5_event(<span class="keyword">function</span>() {\r
+\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': HTML5 error, code '</span> + <span class="keyword">this</span>.error.code);\r
+ <span class="comment">/**\r
+ * HTML5 error codes, per W3C\r
+ * Error 1: Client aborted download at user's request.\r
+ * Error 2: Network error after load started.\r
+ * Error 3: Decoding issue.\r
+ * Error 4: Media (audio file) not supported.\r
+ * Reference: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#error-codes\r
+ */</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-278">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-278">¶</a>
+ </div>
+ <p>call load with error state?</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>._s._onload(<span class="literal">false</span>);\r
+\r
+ }),\r
+\r
+ loadeddata: html5_event(<span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> s = <span class="keyword">this</span>._s;\r
+\r
+ sm2._wD(s.id + <span class="string">': loadeddata'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-279">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-279">¶</a>
+ </div>
+ <p>safari seems to nicely report progress events, eventually totalling 100%</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!s._loaded && !isSafari) {\r
+ s.duration = s._get_html5_duration();\r
+ }\r
+\r
+ }),\r
+\r
+ loadedmetadata: html5_event(<span class="keyword">function</span>() {\r
+\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': loadedmetadata'</span>);\r
+\r
+ }),\r
+\r
+ loadstart: html5_event(<span class="keyword">function</span>() {\r
+\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': loadstart'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-280">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-280">¶</a>
+ </div>
+ <p>assume buffering at first</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>._s._onbufferchange(<span class="number">1</span>);\r
+\r
+ }),\r
+\r
+ play: html5_event(<span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-281">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-281">¶</a>
+ </div>
+ <p>sm2._wD(this._s.id + ': play()');
+once play starts, no buffering</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>._s._onbufferchange(<span class="number">0</span>);\r
+\r
+ }),\r
+\r
+ playing: html5_event(<span class="keyword">function</span>() {\r
+\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': playing '</span> + String.fromCharCode(<span class="number">9835</span>));</pre></div></div>
+
+ </li>
+
+
+ <li id="section-282">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-282">¶</a>
+ </div>
+ <p>once play starts, no buffering</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">this</span>._s._onbufferchange(<span class="number">0</span>);\r
+\r
+ }),\r
+\r
+ progress: html5_event(<span class="keyword">function</span>(e) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-283">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-283">¶</a>
+ </div>
+ <p>note: can fire repeatedly after "loaded" event, due to use of HTTP range/partials</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> s = <span class="keyword">this</span>._s,\r
+ i, j, progStr, buffered = <span class="number">0</span>,\r
+ isProgress = (e.type === <span class="string">'progress'</span>),\r
+ ranges = e.target.buffered,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-284">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-284">¶</a>
+ </div>
+ <p>firefox 3.6 implements e.loaded/total (bytes)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> loaded = (e.loaded || <span class="number">0</span>),\r
+ total = (e.total || <span class="number">1</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-285">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-285">¶</a>
+ </div>
+ <p>reset the "buffered" (loaded byte ranges) array</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s.buffered = [];\r
+\r
+ <span class="keyword">if</span> (ranges && ranges.length) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-286">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-286">¶</a>
+ </div>
+ <p>if loaded is 0, try TimeRanges implementation as % of load
+<a href="https://developer.mozilla.org/en/DOM/TimeRanges">https://developer.mozilla.org/en/DOM/TimeRanges</a></p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-287">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-287">¶</a>
+ </div>
+ <p>re-build "buffered" array
+HTML5 returns seconds. SM2 API uses msec for setPosition() etc., whether Flash or HTML5.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">for</span> (i = <span class="number">0</span>, j = ranges.length; i < j; i++) {\r
+ s.buffered.push({\r
+ <span class="string">'start'</span>: ranges.start(i) * msecScale,\r
+ <span class="string">'end'</span>: ranges.end(i) * msecScale\r
+ });\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-288">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-288">¶</a>
+ </div>
+ <p>use the last value locally</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> buffered = (ranges.end(<span class="number">0</span>) - ranges.start(<span class="number">0</span>)) * msecScale;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-289">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-289">¶</a>
+ </div>
+ <p>linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> loaded = Math.min(<span class="number">1</span>, buffered / (e.target.duration * msecScale));</pre></div></div>
+
+ </li>
+
+
+ <li id="section-290">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-290">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (isProgress && ranges.length > <span class="number">1</span>) {\r
+ progStr = [];\r
+ j = ranges.length;\r
+ <span class="keyword">for</span> (i = <span class="number">0</span>; i < j; i++) {\r
+ progStr.push((e.target.buffered.start(i) * msecScale) + <span class="string">'-'</span> + (e.target.buffered.end(i) * msecScale));\r
+ }\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': progress, timeRanges: '</span> + progStr.join(<span class="string">', '</span>));\r
+ }\r
+\r
+ <span class="keyword">if</span> (isProgress && !isNaN(loaded)) {\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': progress, '</span> + Math.floor(loaded * <span class="number">100</span>) + <span class="string">'% loaded'</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-291">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-291">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ }\r
+\r
+ <span class="keyword">if</span> (!isNaN(loaded)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-292">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-292">¶</a>
+ </div>
+ <p>TODO: prevent calls with duplicate values.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._whileloading(loaded, total, s._get_html5_duration());\r
+ <span class="keyword">if</span> (loaded && total && loaded === total) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-293">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-293">¶</a>
+ </div>
+ <p>in case "onload" doesn't fire (eg. gecko 1.9.2)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> html5_events.canplaythrough.call(<span class="keyword">this</span>, e);\r
+ }\r
+\r
+ }\r
+\r
+ }),\r
+\r
+ ratechange: html5_event(<span class="keyword">function</span>() {\r
+\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': ratechange'</span>);\r
+\r
+ }),\r
+\r
+ suspend: html5_event(<span class="keyword">function</span>(e) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-294">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-294">¶</a>
+ </div>
+ <p>download paused/stopped, may have finished (eg. onload)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> s = <span class="keyword">this</span>._s;\r
+\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': suspend'</span>);\r
+ html5_events.progress.call(<span class="keyword">this</span>, e);\r
+ s._onsuspend();\r
+\r
+ }),\r
+\r
+ stalled: html5_event(<span class="keyword">function</span>() {\r
+\r
+ sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': stalled'</span>);\r
+\r
+ }),\r
+\r
+ timeupdate: html5_event(<span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">this</span>._s._onTimer();\r
+\r
+ }),\r
+\r
+ waiting: html5_event(<span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> s = <span class="keyword">this</span>._s;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-295">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-295">¶</a>
+ </div>
+ <p>see also: seeking</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(<span class="keyword">this</span>._s.id + <span class="string">': waiting'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-296">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-296">¶</a>
+ </div>
+ <p>playback faster than download rate, etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s._onbufferchange(<span class="number">1</span>);\r
+\r
+ })\r
+\r
+ };\r
+\r
+ html5OK = <span class="keyword">function</span>(iO) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-297">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-297">¶</a>
+ </div>
+ <p>playability test based on URL or MIME type</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> result;\r
+\r
+ <span class="keyword">if</span> (!iO || (!iO.type && !iO.url && !iO.serverURL)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-298">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-298">¶</a>
+ </div>
+ <p>nothing to check</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> result = <span class="literal">false</span>;\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (iO.serverURL || (iO.type && preferFlashCheck(iO.type))) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-299">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-299">¶</a>
+ </div>
+ <p>RTMP, or preferring flash</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> result = <span class="literal">false</span>;\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-300">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-300">¶</a>
+ </div>
+ <p>Use type, if specified. Pass data: URIs to HTML5. If HTML5-only mode, no other options, so just give 'er</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> result = ((iO.type ? html5CanPlay({type:iO.type}) : html5CanPlay({url:iO.url}) || sm2.html5Only || iO.url.match(<span class="regexp">/data\:/i</span>)));\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ html5Unload = <span class="keyword">function</span>(oAudio) {\r
+\r
+ <span class="comment">/**\r
+ * Internal method: Unload media, and cancel any current/pending network requests.\r
+ * Firefox can load an empty URL, which allegedly destroys the decoder and stops the download.\r
+ * https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media\r
+ * However, Firefox has been seen loading a relative URL from '' and thus requesting the hosting page on unload.\r
+ * Other UA behaviour is unclear, so everyone else gets an about:blank-style URL.\r
+ */</span>\r
+\r
+ <span class="keyword">var</span> url;\r
+\r
+ <span class="keyword">if</span> (oAudio) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-301">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-301">¶</a>
+ </div>
+ <p>Firefox and Chrome accept short WAVe data: URIs. Chome dislikes audio/wav, but accepts audio/wav for data: MIME.
+Desktop Safari complains / fails on data: URI, so it gets about:blank.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> url = (isSafari ? emptyURL : (sm2.html5.canPlayType(<span class="string">'audio/wav'</span>) ? emptyWAV : emptyURL));\r
+\r
+ oAudio.src = url;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-302">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-302">¶</a>
+ </div>
+ <p>reset some state, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (oAudio._called_unload !== _<span class="literal">undefined</span>) {\r
+ oAudio._called_load = <span class="literal">false</span>;\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (useGlobalHTML5Audio) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-303">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-303">¶</a>
+ </div>
+ <p>ensure URL state is trashed, also</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> lastGlobalHTML5URL = <span class="literal">null</span>;\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> url;\r
+\r
+ };\r
+\r
+ html5CanPlay = <span class="keyword">function</span>(o) {\r
+\r
+ <span class="comment">/**\r
+ * Try to find MIME, test and return truthiness\r
+ * o = {\r
+ * url: '/path/to/an.mp3',\r
+ * type: 'audio/mp3'\r
+ * }\r
+ */</span>\r
+\r
+ <span class="keyword">if</span> (!sm2.useHTML5Audio || !sm2.hasHTML5) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> url = (o.url || <span class="literal">null</span>),\r
+ mime = (o.type || <span class="literal">null</span>),\r
+ aF = sm2.audioFormats,\r
+ result,\r
+ offset,\r
+ fileExt,\r
+ item;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-304">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-304">¶</a>
+ </div>
+ <p>account for known cases like audio/mp3</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (mime && sm2.html5[mime] !== _<span class="literal">undefined</span>) {\r
+ <span class="keyword">return</span> (sm2.html5[mime] && !preferFlashCheck(mime));\r
+ }\r
+\r
+ <span class="keyword">if</span> (!html5Ext) {\r
+ \r
+ html5Ext = [];\r
+ \r
+ <span class="keyword">for</span> (item <span class="keyword">in</span> aF) {\r
+ \r
+ <span class="keyword">if</span> (aF.hasOwnProperty(item)) {\r
+ \r
+ html5Ext.push(item);\r
+ \r
+ <span class="keyword">if</span> (aF[item].related) {\r
+ html5Ext = html5Ext.concat(aF[item].related);\r
+ }\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ html5Ext = <span class="keyword">new</span> RegExp(<span class="string">'\\.('</span>+html5Ext.join(<span class="string">'|'</span>)+<span class="string">')(\\?.*)?$'</span>,<span class="string">'i'</span>);\r
+ \r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-305">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-305">¶</a>
+ </div>
+ <p>TODO: Strip URL queries, etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> fileExt = (url ? url.toLowerCase().match(html5Ext) : <span class="literal">null</span>);\r
+\r
+ <span class="keyword">if</span> (!fileExt || !fileExt.length) {\r
+ \r
+ <span class="keyword">if</span> (!mime) {\r
+ \r
+ result = <span class="literal">false</span>;\r
+ \r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-306">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-306">¶</a>
+ </div>
+ <p>audio/mp3 -> mp3, result should be known</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> offset = mime.indexOf(<span class="string">';'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-307">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-307">¶</a>
+ </div>
+ <p>strip "audio/X; codecs..."</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> fileExt = (offset !== -<span class="number">1</span> ? mime.substr(<span class="number">0</span>,offset) : mime).substr(<span class="number">6</span>);\r
+ \r
+ }\r
+ \r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-308">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-308">¶</a>
+ </div>
+ <p>match the raw extension name - "mp3", for example</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> fileExt = fileExt[<span class="number">1</span>];\r
+ \r
+ }\r
+\r
+ <span class="keyword">if</span> (fileExt && sm2.html5[fileExt] !== _<span class="literal">undefined</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-309">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-309">¶</a>
+ </div>
+ <p>result known</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> result = (sm2.html5[fileExt] && !preferFlashCheck(fileExt));\r
+ \r
+ } <span class="keyword">else</span> {\r
+ \r
+ mime = <span class="string">'audio/'</span> + fileExt;\r
+ result = sm2.html5.canPlayType({type:mime});\r
+ \r
+ sm2.html5[fileExt] = result;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-310">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-310">¶</a>
+ </div>
+ <p>sm2._wD('canPlayType, found result: ' + result);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> result = (result && sm2.html5[mime] && !preferFlashCheck(mime));\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ testHTML5 = <span class="keyword">function</span>() {\r
+\r
+ <span class="comment">/**\r
+ * Internal: Iterates over audioFormats, determining support eg. audio/mp3, audio/mpeg and so on\r
+ * assigns results to html5[] and flash[].\r
+ */</span>\r
+\r
+ <span class="keyword">if</span> (!sm2.useHTML5Audio || !sm2.hasHTML5) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-311">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-311">¶</a>
+ </div>
+ <p>without HTML5, we need Flash.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.html5.usingFlash = <span class="literal">true</span>;\r
+ needsFlash = <span class="literal">true</span>;\r
+ \r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ \r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-312">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-312">¶</a>
+ </div>
+ <p>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. :/</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> a = (Audio !== _<span class="literal">undefined</span> ? (isOpera && opera.version() < <span class="number">10</span> ? <span class="keyword">new</span> Audio(<span class="literal">null</span>) : <span class="keyword">new</span> Audio()) : <span class="literal">null</span>),\r
+ item, lookup, support = {}, aF, i;\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">cp</span><span class="params">(m)</span> {</span>\r
+\r
+ <span class="keyword">var</span> canPlay, j,\r
+ result = <span class="literal">false</span>,\r
+ isOK = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (!a || <span class="keyword">typeof</span> a.canPlayType !== <span class="string">'function'</span>) {\r
+ <span class="keyword">return</span> result;\r
+ }\r
+\r
+ <span class="keyword">if</span> (m <span class="keyword">instanceof</span> Array) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-313">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-313">¶</a>
+ </div>
+ <p>iterate through all mime types, return any successes</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> \r
+ <span class="keyword">for</span> (i = <span class="number">0</span>, j = m.length; i < j; i++) {\r
+ \r
+ <span class="keyword">if</span> (sm2.html5[m[i]] || a.canPlayType(m[i]).match(sm2.html5Test)) {\r
+ \r
+ isOK = <span class="literal">true</span>;\r
+ sm2.html5[m[i]] = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-314">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-314">¶</a>
+ </div>
+ <p>note flash support, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.flash[m[i]] = !!(m[i].match(flashMIME));\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ result = isOK;\r
+ \r
+ } <span class="keyword">else</span> {\r
+ \r
+ canPlay = (a && <span class="keyword">typeof</span> a.canPlayType === <span class="string">'function'</span> ? a.canPlayType(m) : <span class="literal">false</span>);\r
+ result = !!(canPlay && (canPlay.match(sm2.html5Test)));\r
+ \r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-315">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-315">¶</a>
+ </div>
+ <p>test all registered formats + codecs</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ aF = sm2.audioFormats;\r
+\r
+ <span class="keyword">for</span> (item <span class="keyword">in</span> aF) {\r
+\r
+ <span class="keyword">if</span> (aF.hasOwnProperty(item)) {\r
+\r
+ lookup = <span class="string">'audio/'</span> + item;\r
+\r
+ support[item] = cp(aF[item].type);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-316">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-316">¶</a>
+ </div>
+ <p>write back generic type too, eg. audio/mp3</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> support[lookup] = support[item];</pre></div></div>
+
+ </li>
+
+
+ <li id="section-317">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-317">¶</a>
+ </div>
+ <p>assign flash</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (item.match(flashMIME)) {\r
+\r
+ sm2.flash[item] = <span class="literal">true</span>;\r
+ sm2.flash[lookup] = <span class="literal">true</span>;\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ sm2.flash[item] = <span class="literal">false</span>;\r
+ sm2.flash[lookup] = <span class="literal">false</span>;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-318">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-318">¶</a>
+ </div>
+ <p>assign result to related formats, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (aF[item] && aF[item].related) {\r
+\r
+ <span class="keyword">for</span> (i = aF[item].related.length - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-319">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-319">¶</a>
+ </div>
+ <p>eg. audio/m4a</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> support[<span class="string">'audio/'</span> + aF[item].related[i]] = support[item];\r
+ sm2.html5[aF[item].related[i]] = support[item];\r
+ sm2.flash[aF[item].related[i]] = support[item];\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ support.canPlayType = (a ? cp : <span class="literal">null</span>);\r
+ sm2.html5 = mixin(sm2.html5, support);\r
+\r
+ sm2.html5.usingFlash = featureCheck();\r
+ needsFlash = sm2.html5.usingFlash;\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ strings = {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-320">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-320">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> notReady: <span class="string">'Unavailable - wait until onready() has fired.'</span>,\r
+ notOK: <span class="string">'Audio support is not available.'</span>,\r
+ domError: sm + <span class="string">'exception caught while appending SWF to DOM.'</span>,\r
+ spcWmode: <span class="string">'Removing wmode, preventing known SWF loading issue(s)'</span>,\r
+ swf404: smc + <span class="string">'Verify that %s is a valid path.'</span>,\r
+ tryDebug: <span class="string">'Try '</span> + sm + <span class="string">'.debugFlash = true for more security details (output goes to SWF.)'</span>,\r
+ checkSWF: <span class="string">'See SWF output for more debug info.'</span>,\r
+ localFail: smc + <span class="string">'Non-HTTP page ('</span> + doc.location.protocol + <span class="string">' 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/'</span>,\r
+ waitFocus: smc + <span class="string">'Special case: Waiting for SWF to load with window focus...'</span>,\r
+ waitForever: smc + <span class="string">'Waiting indefinitely for Flash (will recover if unblocked)...'</span>,\r
+ waitSWF: smc + <span class="string">'Waiting for 100% SWF load...'</span>,\r
+ needFunction: smc + <span class="string">'Function object expected for %s'</span>,\r
+ badID: <span class="string">'Sound ID "%s" should be a string, starting with a non-numeric character'</span>,\r
+ currentObj: smc + <span class="string">'_debug(): Current sound objects'</span>,\r
+ waitOnload: smc + <span class="string">'Waiting for window.onload()'</span>,\r
+ docLoaded: smc + <span class="string">'Document already loaded'</span>,\r
+ onload: smc + <span class="string">'initComplete(): calling soundManager.onload()'</span>,\r
+ onloadOK: sm + <span class="string">'.onload() complete'</span>,\r
+ didInit: smc + <span class="string">'init(): Already called?'</span>,\r
+ secNote: <span class="string">'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'</span>,\r
+ badRemove: smc + <span class="string">'Failed to remove Flash node.'</span>,\r
+ shutdown: sm + <span class="string">'.disable(): Shutting down'</span>,\r
+ queue: smc + <span class="string">'Queueing %s handler'</span>,\r
+ smError: <span class="string">'SMSound.load(): Exception: JS-Flash communication failed, or JS error.'</span>,\r
+ fbTimeout: <span class="string">'No flash response, applying .'</span> + swfCSS.swfTimedout + <span class="string">' CSS...'</span>,\r
+ fbLoaded: <span class="string">'Flash loaded'</span>,\r
+ fbHandler: smc + <span class="string">'flashBlockHandler()'</span>,\r
+ manURL: <span class="string">'SMSound.load(): Using manually-assigned URL'</span>,\r
+ onURL: sm + <span class="string">'.load(): current URL already assigned.'</span>,\r
+ badFV: sm + <span class="string">'.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.'</span>,\r
+ as2loop: <span class="string">'Note: Setting stream:false so looping can work (flash 8 limitation)'</span>,\r
+ noNSLoop: <span class="string">'Note: Looping not implemented for MovieStar formats'</span>,\r
+ needfl9: <span class="string">'Note: Switching to flash 9, required for MP4 formats.'</span>,\r
+ mfTimeout: <span class="string">'Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case'</span>,\r
+ needFlash: smc + <span class="string">'Fatal error: Flash is needed to play some required formats, but is not available.'</span>,\r
+ gotFocus: smc + <span class="string">'Got window focus.'</span>,\r
+ policy: <span class="string">'Enabling usePolicyFile for data access'</span>,\r
+ setup: sm + <span class="string">'.setup(): allowed parameters: %s'</span>,\r
+ setupError: sm + <span class="string">'.setup(): "%s" cannot be assigned with this method.'</span>,\r
+ setupUndef: sm + <span class="string">'.setup(): Could not find option "%s"'</span>,\r
+ setupLate: sm + <span class="string">'.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().'</span>,\r
+ noURL: smc + <span class="string">'Flash URL required. Call soundManager.setup({url:...}) to get started.'</span>,\r
+ sm2Loaded: <span class="string">'SoundManager 2: Ready. '</span> + String.fromCharCode(<span class="number">10003</span>),\r
+ reset: sm + <span class="string">'.reset(): Removing event callbacks'</span>,\r
+ mobileUA: <span class="string">'Mobile UA detected, preferring HTML5 by default.'</span>,\r
+ globalHTML5: <span class="string">'Using singleton HTML5 Audio() pattern for this device.'</span>,\r
+ ignoreMobile: <span class="string">'Ignoring mobile restrictions for this device.'</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-321">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-321">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ };\r
+\r
+ str = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-322">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-322">¶</a>
+ </div>
+ <p>internal string replace helper.
+arguments: o [,items to replace]</p>
+<d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> args,\r
+ i, j, o,\r
+ sstr;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-323">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-323">¶</a>
+ </div>
+ <p>real array, please</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> args = slice.call(arguments);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-324">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-324">¶</a>
+ </div>
+ <p>first argument</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> o = args.shift();\r
+\r
+ sstr = (strings && strings[o] ? strings[o] : <span class="string">''</span>);\r
+\r
+ <span class="keyword">if</span> (sstr && args && args.length) {\r
+ <span class="keyword">for</span> (i = <span class="number">0</span>, j = args.length; i < j; i++) {\r
+ sstr = sstr.replace(<span class="string">'%s'</span>, args[i]);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">return</span> sstr;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-325">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-325">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ };\r
+\r
+ loopFix = <span class="keyword">function</span>(sOpt) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-326">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-326">¶</a>
+ </div>
+ <p>flash 8 requires stream = false for looping to work</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (fV === <span class="number">8</span> && sOpt.loops > <span class="number">1</span> && sOpt.stream) {\r
+ _wDS(<span class="string">'as2loop'</span>);\r
+ sOpt.stream = <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">return</span> sOpt;\r
+\r
+ };\r
+\r
+ policyFix = <span class="keyword">function</span>(sOpt, sPre) {\r
+\r
+ <span class="keyword">if</span> (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) {\r
+ sm2._wD((sPre || <span class="string">''</span>) + str(<span class="string">'policy'</span>));\r
+ sOpt.usePolicyFile = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">return</span> sOpt;\r
+\r
+ };\r
+\r
+ complain = <span class="keyword">function</span>(sMsg) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-327">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-327">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (hasConsole && console.warn !== _<span class="literal">undefined</span>) {\r
+ console.warn(sMsg);\r
+ } <span class="keyword">else</span> {\r
+ sm2._wD(sMsg);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-328">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-328">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ };\r
+\r
+ doNothing = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+\r
+ };\r
+\r
+ disableObject = <span class="keyword">function</span>(o) {\r
+\r
+ <span class="keyword">var</span> oProp;\r
+\r
+ <span class="keyword">for</span> (oProp <span class="keyword">in</span> o) {\r
+ <span class="keyword">if</span> (o.hasOwnProperty(oProp) && <span class="keyword">typeof</span> o[oProp] === <span class="string">'function'</span>) {\r
+ o[oProp] = doNothing;\r
+ }\r
+ }\r
+\r
+ oProp = <span class="literal">null</span>;\r
+\r
+ };\r
+\r
+ failSafely = <span class="keyword">function</span>(bNoDisable) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-329">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-329">¶</a>
+ </div>
+ <p>general failure exception handler</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (bNoDisable === _<span class="literal">undefined</span>) {\r
+ bNoDisable = <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (disabled || bNoDisable) {\r
+ sm2.disable(bNoDisable);\r
+ }\r
+\r
+ };\r
+\r
+ normalizeMovieURL = <span class="keyword">function</span>(smURL) {\r
+\r
+ <span class="keyword">var</span> urlParams = <span class="literal">null</span>, url;\r
+\r
+ <span class="keyword">if</span> (smURL) {\r
+ \r
+ <span class="keyword">if</span> (smURL.match(<span class="regexp">/\.swf(\?.*)?$/i</span>)) {\r
+ \r
+ urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf(<span class="string">'.swf?'</span>) + <span class="number">4</span>);\r
+ \r
+ <span class="keyword">if</span> (urlParams) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-330">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-330">¶</a>
+ </div>
+ <p>assume user knows what they're doing</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> smURL;\r
+ }\r
+ \r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (smURL.lastIndexOf(<span class="string">'/'</span>) !== smURL.length - <span class="number">1</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-331">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-331">¶</a>
+ </div>
+ <p>append trailing slash, if needed</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> smURL += <span class="string">'/'</span>;\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ url = (smURL && smURL.lastIndexOf(<span class="string">'/'</span>) !== - <span class="number">1</span> ? smURL.substr(<span class="number">0</span>, smURL.lastIndexOf(<span class="string">'/'</span>) + <span class="number">1</span>) : <span class="string">'./'</span>) + sm2.movieURL;\r
+\r
+ <span class="keyword">if</span> (sm2.noSWFCache) {\r
+ url += (<span class="string">'?ts='</span> + <span class="keyword">new</span> Date().getTime());\r
+ }\r
+\r
+ <span class="keyword">return</span> url;\r
+\r
+ };\r
+\r
+ setVersionInfo = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-332">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-332">¶</a>
+ </div>
+ <p>short-hand for internal use</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ fV = parseInt(sm2.flashVersion, <span class="number">10</span>);\r
+\r
+ <span class="keyword">if</span> (fV !== <span class="number">8</span> && fV !== <span class="number">9</span>) {\r
+ sm2._wD(str(<span class="string">'badFV'</span>, fV, defaultFlashVersion));\r
+ sm2.flashVersion = fV = defaultFlashVersion;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-333">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-333">¶</a>
+ </div>
+ <p>debug flash movie, if applicable</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> isDebug = (sm2.debugMode || sm2.debugFlash ? <span class="string">'_debug.swf'</span> : <span class="string">'.swf'</span>);\r
+\r
+ <span class="keyword">if</span> (sm2.useHTML5Audio && !sm2.html5Only && sm2.audioFormats.mp4.required && fV < <span class="number">9</span>) {\r
+ sm2._wD(str(<span class="string">'needfl9'</span>));\r
+ sm2.flashVersion = fV = <span class="number">9</span>;\r
+ }\r
+\r
+ sm2.version = sm2.versionNumber + (sm2.html5Only ? <span class="string">' (HTML5-only mode)'</span> : (fV === <span class="number">9</span> ? <span class="string">' (AS3/Flash 9)'</span> : <span class="string">' (AS2/Flash 8)'</span>));</pre></div></div>
+
+ </li>
+
+
+ <li id="section-334">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-334">¶</a>
+ </div>
+ <p>set up default options</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (fV > <span class="number">8</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-335">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-335">¶</a>
+ </div>
+ <p>+flash 9 base options</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.flash9Options);\r
+ sm2.features.buffering = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-336">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-336">¶</a>
+ </div>
+ <p>+moviestar support</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.movieStarOptions);\r
+ sm2.filePatterns.flash9 = <span class="keyword">new</span> RegExp(<span class="string">'\\.(mp3|'</span> + netStreamTypes.join(<span class="string">'|'</span>) + <span class="string">')(\\?.*)?$'</span>, <span class="string">'i'</span>);\r
+ sm2.features.movieStar = <span class="literal">true</span>;\r
+ \r
+ } <span class="keyword">else</span> {\r
+ \r
+ sm2.features.movieStar = <span class="literal">false</span>;\r
+ \r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-337">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-337">¶</a>
+ </div>
+ <p>regExp for flash canPlay(), etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.filePattern = sm2.filePatterns[(fV !== <span class="number">8</span> ? <span class="string">'flash9'</span> : <span class="string">'flash8'</span>)];</pre></div></div>
+
+ </li>
+
+
+ <li id="section-338">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-338">¶</a>
+ </div>
+ <p>if applicable, use _debug versions of SWFs</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.movieURL = (fV === <span class="number">8</span> ? <span class="string">'soundmanager2.swf'</span> : <span class="string">'soundmanager2_flash9.swf'</span>).replace(<span class="string">'.swf'</span>, isDebug);\r
+\r
+ sm2.features.peakData = sm2.features.waveformData = sm2.features.eqData = (fV > <span class="number">8</span>);\r
+\r
+ };\r
+\r
+ setPolling = <span class="keyword">function</span>(bPolling, bHighPerformance) {\r
+\r
+ <span class="keyword">if</span> (!flash) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ flash._setPolling(bPolling, bHighPerformance);\r
+\r
+ };\r
+\r
+ initDebug = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-339">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-339">¶</a>
+ </div>
+ <p>starts debug mode, creating output <div> for UAs without console object</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-340">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-340">¶</a>
+ </div>
+ <p>allow force of debug mode via URL</p>
+<d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (sm2.debugURLParam.test(wl)) {\r
+ sm2.setupOptions.debugMode = sm2.debugMode = <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (id(sm2.debugID)) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> oD, oDebug, oTarget, oToggle, tmp;\r
+\r
+ <span class="keyword">if</span> (sm2.debugMode && !id(sm2.debugID) && (!hasConsole || !sm2.useConsole || !sm2.consoleOnly)) {\r
+\r
+ oD = doc.createElement(<span class="string">'div'</span>);\r
+ oD.id = sm2.debugID + <span class="string">'-toggle'</span>;\r
+\r
+ oToggle = {\r
+ <span class="string">'position'</span>: <span class="string">'fixed'</span>,\r
+ <span class="string">'bottom'</span>: <span class="string">'0px'</span>,\r
+ <span class="string">'right'</span>: <span class="string">'0px'</span>,\r
+ <span class="string">'width'</span>: <span class="string">'1.2em'</span>,\r
+ <span class="string">'height'</span>: <span class="string">'1.2em'</span>,\r
+ <span class="string">'lineHeight'</span>: <span class="string">'1.2em'</span>,\r
+ <span class="string">'margin'</span>: <span class="string">'2px'</span>,\r
+ <span class="string">'textAlign'</span>: <span class="string">'center'</span>,\r
+ <span class="string">'border'</span>: <span class="string">'1px solid #999'</span>,\r
+ <span class="string">'cursor'</span>: <span class="string">'pointer'</span>,\r
+ <span class="string">'background'</span>: <span class="string">'#fff'</span>,\r
+ <span class="string">'color'</span>: <span class="string">'#333'</span>,\r
+ <span class="string">'zIndex'</span>: <span class="number">10001</span>\r
+ };\r
+\r
+ oD.appendChild(doc.createTextNode(<span class="string">'-'</span>));\r
+ oD.onclick = toggleDebug;\r
+ oD.title = <span class="string">'Toggle SM2 debug console'</span>;\r
+\r
+ <span class="keyword">if</span> (ua.match(<span class="regexp">/msie 6/i</span>)) {\r
+ oD.style.position = <span class="string">'absolute'</span>;\r
+ oD.style.cursor = <span class="string">'hand'</span>;\r
+ }\r
+\r
+ <span class="keyword">for</span> (tmp <span class="keyword">in</span> oToggle) {\r
+ <span class="keyword">if</span> (oToggle.hasOwnProperty(tmp)) {\r
+ oD.style[tmp] = oToggle[tmp];\r
+ }\r
+ }\r
+\r
+ oDebug = doc.createElement(<span class="string">'div'</span>);\r
+ oDebug.id = sm2.debugID;\r
+ oDebug.style.display = (sm2.debugMode ? <span class="string">'block'</span> : <span class="string">'none'</span>);\r
+\r
+ <span class="keyword">if</span> (sm2.debugMode && !id(oD.id)) {\r
+ <span class="keyword">try</span> {\r
+ oTarget = getDocument();\r
+ oTarget.appendChild(oD);\r
+ } <span class="keyword">catch</span>(e2) {\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> Error(str(<span class="string">'domError'</span>) + <span class="string">' \n'</span> + e2.toString());\r
+ }\r
+ oTarget.appendChild(oDebug);\r
+ }\r
+\r
+ }\r
+\r
+ oTarget = <span class="literal">null</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-341">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-341">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ };\r
+\r
+ idCheck = <span class="keyword">this</span>.getSoundById;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-342">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-342">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> _wDS = <span class="keyword">function</span>(o, errorLevel) {\r
+\r
+ <span class="keyword">return</span> (!o ? <span class="string">''</span> : sm2._wD(str(o), errorLevel));\r
+\r
+ };\r
+\r
+ toggleDebug = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> o = id(sm2.debugID),\r
+ oT = id(sm2.debugID + <span class="string">'-toggle'</span>);\r
+\r
+ <span class="keyword">if</span> (!o) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (debugOpen) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-343">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-343">¶</a>
+ </div>
+ <p>minimize</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oT.innerHTML = <span class="string">'+'</span>;\r
+ o.style.display = <span class="string">'none'</span>;\r
+ } <span class="keyword">else</span> {\r
+ oT.innerHTML = <span class="string">'-'</span>;\r
+ o.style.display = <span class="string">'block'</span>;\r
+ }\r
+\r
+ debugOpen = !debugOpen;\r
+\r
+ };\r
+\r
+ debugTS = <span class="keyword">function</span>(sEventType, bSuccess, sMessage) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-344">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-344">¶</a>
+ </div>
+ <p>troubleshooter debug hooks</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (window.sm2Debugger !== _<span class="literal">undefined</span>) {\r
+ <span class="keyword">try</span> {\r
+ sm2Debugger.handleEvent(sEventType, bSuccess, sMessage);\r
+ } <span class="keyword">catch</span>(e) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-345">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-345">¶</a>
+ </div>
+ <p>oh well</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-346">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-346">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ getSWFCSS = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> css = [];\r
+\r
+ <span class="keyword">if</span> (sm2.debugMode) {\r
+ css.push(swfCSS.sm2Debug);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.debugFlash) {\r
+ css.push(swfCSS.flashDebug);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.useHighPerformance) {\r
+ css.push(swfCSS.highPerf);\r
+ }\r
+\r
+ <span class="keyword">return</span> css.join(<span class="string">' '</span>);\r
+\r
+ };\r
+\r
+ flashBlockHandler = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-347">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-347">¶</a>
+ </div>
+ <p><em>possible</em> flash block situation.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> name = str(<span class="string">'fbHandler'</span>),\r
+ p = sm2.getMoviePercent(),\r
+ css = swfCSS,\r
+ error = {\r
+ type:<span class="string">'FLASHBLOCK'</span>\r
+ };\r
+\r
+ <span class="keyword">if</span> (sm2.html5Only) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-348">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-348">¶</a>
+ </div>
+ <p>no flash, or unused</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!sm2.ok()) {\r
+\r
+ <span class="keyword">if</span> (needsFlash) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-349">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-349">¶</a>
+ </div>
+ <p>make the movie more visible, so user can fix</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.oMC.className = getSWFCSS() + <span class="string">' '</span> + css.swfDefault + <span class="string">' '</span> + (p === <span class="literal">null</span> ? css.swfTimedout : css.swfError);\r
+ sm2._wD(name + <span class="string">': '</span> + str(<span class="string">'fbTimeout'</span>) + (p ? <span class="string">' ('</span> + str(<span class="string">'fbLoaded'</span>) + <span class="string">')'</span> : <span class="string">''</span>));\r
+ }\r
+\r
+ sm2.didFlashBlock = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-350">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-350">¶</a>
+ </div>
+ <p>fire onready(), complain lightly</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> processOnEvents({\r
+ type: <span class="string">'ontimeout'</span>,\r
+ ignoreInit: <span class="literal">true</span>,\r
+ error: error\r
+ });\r
+\r
+ catchError(error);\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-351">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-351">¶</a>
+ </div>
+ <p>SM2 loaded OK (or recovered)</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-352">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-352">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (sm2.didFlashBlock) {\r
+ sm2._wD(name + <span class="string">': Unblocked'</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-353">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-353">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (sm2.oMC) {\r
+ sm2.oMC.className = [getSWFCSS(), css.swfDefault, css.swfLoaded + (sm2.didFlashBlock ? <span class="string">' '</span> + css.swfUnblocked : <span class="string">''</span>)].join(<span class="string">' '</span>);\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ addOnEvent = <span class="keyword">function</span>(sType, oMethod, oScope) {\r
+\r
+ <span class="keyword">if</span> (on_queue[sType] === _<span class="literal">undefined</span>) {\r
+ on_queue[sType] = [];\r
+ }\r
+\r
+ on_queue[sType].push({\r
+ <span class="string">'method'</span>: oMethod,\r
+ <span class="string">'scope'</span>: (oScope || <span class="literal">null</span>),\r
+ <span class="string">'fired'</span>: <span class="literal">false</span>\r
+ });\r
+\r
+ };\r
+\r
+ processOnEvents = <span class="keyword">function</span>(oOptions) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-354">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-354">¶</a>
+ </div>
+ <p>if unspecified, assume OK/error</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!oOptions) {\r
+ oOptions = {\r
+ type: (sm2.ok() ? <span class="string">'onready'</span> : <span class="string">'ontimeout'</span>)\r
+ };\r
+ }\r
+\r
+ <span class="keyword">if</span> (!didInit && oOptions && !oOptions.ignoreInit) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-355">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-355">¶</a>
+ </div>
+ <p>not ready yet.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (oOptions.type === <span class="string">'ontimeout'</span> && (sm2.ok() || (disabled && !oOptions.ignoreInit))) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-356">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-356">¶</a>
+ </div>
+ <p>invalid case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> status = {\r
+ success: (oOptions && oOptions.ignoreInit ? sm2.ok() : !disabled)\r
+ },</pre></div></div>
+
+ </li>
+
+
+ <li id="section-357">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-357">¶</a>
+ </div>
+ <p>queue specified by type, or none</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> srcQueue = (oOptions && oOptions.type ? on_queue[oOptions.type] || [] : []),\r
+\r
+ queue = [], i, j,\r
+ args = [status],\r
+ canRetry = (needsFlash && !sm2.ok());\r
+\r
+ <span class="keyword">if</span> (oOptions.error) {\r
+ args[<span class="number">0</span>].error = oOptions.error;\r
+ }\r
+\r
+ <span class="keyword">for</span> (i = <span class="number">0</span>, j = srcQueue.length; i < j; i++) {\r
+ <span class="keyword">if</span> (srcQueue[i].fired !== <span class="literal">true</span>) {\r
+ queue.push(srcQueue[i]);\r
+ }\r
+ }\r
+\r
+ <span class="keyword">if</span> (queue.length) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-358">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-358">¶</a>
+ </div>
+ <p>sm2._wD(sm + ': Firing ' + queue.length + ' ' + oOptions.type + '() item' + (queue.length === 1 ? '' : 's')); </p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">for</span> (i = <span class="number">0</span>, j = queue.length; i < j; i++) {\r
+ \r
+ <span class="keyword">if</span> (queue[i].scope) {\r
+ queue[i].method.apply(queue[i].scope, args);\r
+ } <span class="keyword">else</span> {\r
+ queue[i].method.apply(<span class="keyword">this</span>, args);\r
+ }\r
+ \r
+ <span class="keyword">if</span> (!canRetry) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-359">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-359">¶</a>
+ </div>
+ <p>useFlashBlock and SWF timeout case doesn't count here.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> queue[i].fired = <span class="literal">true</span>;\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ initUserOnload = <span class="keyword">function</span>() {\r
+\r
+ window.setTimeout(<span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">if</span> (sm2.useFlashBlock) {\r
+ flashBlockHandler();\r
+ }\r
+\r
+ processOnEvents();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-360">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-360">¶</a>
+ </div>
+ <p>call user-defined "onload", scoped to window</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> sm2.onload === <span class="string">'function'</span>) {\r
+ _wDS(<span class="string">'onload'</span>, <span class="number">1</span>);\r
+ sm2.onload.apply(window);\r
+ _wDS(<span class="string">'onloadOK'</span>, <span class="number">1</span>);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.waitForWindowLoad) {\r
+ event.add(window, <span class="string">'load'</span>, initUserOnload);\r
+ }\r
+\r
+ }, <span class="number">1</span>);\r
+\r
+ };\r
+\r
+ detectFlash = <span class="keyword">function</span>() {\r
+\r
+ <span class="comment">/**\r
+ * Hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau\r
+ * http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt\r
+ */</span>\r
+\r
+ <span class="keyword">if</span> (hasFlash !== _<span class="literal">undefined</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-361">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-361">¶</a>
+ </div>
+ <p>this work has already been done.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> hasFlash;\r
+ }\r
+\r
+ <span class="keyword">var</span> hasPlugin = <span class="literal">false</span>, n = navigator, nP = n.plugins, obj, type, types, AX = window.ActiveXObject;\r
+\r
+ <span class="keyword">if</span> (nP && nP.length) {\r
+ \r
+ type = <span class="string">'application/x-shockwave-flash'</span>;\r
+ types = n.mimeTypes;\r
+ \r
+ <span class="keyword">if</span> (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) {\r
+ hasPlugin = <span class="literal">true</span>;\r
+ }\r
+ \r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (AX !== _<span class="literal">undefined</span> && !ua.match(<span class="regexp">/MSAppHost/i</span>)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-362">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-362">¶</a>
+ </div>
+ <p>Windows 8 Store Apps (MSAppHost) are weird (compatibility?) and won't complain here, but will barf if Flash/ActiveX object is appended to the DOM.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">try</span> {\r
+ obj = <span class="keyword">new</span> AX(<span class="string">'ShockwaveFlash.ShockwaveFlash'</span>);\r
+ } <span class="keyword">catch</span>(e) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-363">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-363">¶</a>
+ </div>
+ <p>oh well</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> obj = <span class="literal">null</span>;\r
+ }\r
+ \r
+ hasPlugin = (!!obj);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-364">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-364">¶</a>
+ </div>
+ <p>cleanup, because it is ActiveX after all</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> obj = <span class="literal">null</span>;\r
+ \r
+ }\r
+\r
+ hasFlash = hasPlugin;\r
+\r
+ <span class="keyword">return</span> hasPlugin;\r
+\r
+ };\r
+\r
+featureCheck = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> flashNeeded,\r
+ item,\r
+ formats = sm2.audioFormats,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-365">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-365">¶</a>
+ </div>
+ <p>iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (original iPad) + iOS4 works.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> isSpecial = (is_iDevice && !!(ua.match(<span class="regexp">/os (1|2|3_0|3_1)\s/i</span>)));\r
+\r
+ <span class="keyword">if</span> (isSpecial) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-366">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-366">¶</a>
+ </div>
+ <p>has Audio(), but is broken; let it load links directly.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.hasHTML5 = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-367">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-367">¶</a>
+ </div>
+ <p>ignore flash case, however</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.html5Only = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-368">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-368">¶</a>
+ </div>
+ <p>hide the SWF, if present</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (sm2.oMC) {\r
+ sm2.oMC.style.display = <span class="string">'none'</span>;\r
+ }\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (sm2.useHTML5Audio) {\r
+\r
+ <span class="keyword">if</span> (!sm2.html5 || !sm2.html5.canPlayType) {\r
+ sm2._wD(<span class="string">'SoundManager: No HTML5 Audio() support detected.'</span>);\r
+ sm2.hasHTML5 = <span class="literal">false</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-369">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-369">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (isBadSafari) {\r
+ sm2._wD(smc + <span class="string">'Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - '</span> + (!hasFlash ? <span class="string">' would use flash fallback for MP3/MP4, but none detected.'</span> : <span class="string">'will use flash fallback for MP3/MP4, if available'</span>), <span class="number">1</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-370">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-370">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.useHTML5Audio && sm2.hasHTML5) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-371">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-371">¶</a>
+ </div>
+ <p>sort out whether flash is optional, required or can be ignored.</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-372">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-372">¶</a>
+ </div>
+ <p>innocent until proven guilty.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> canIgnoreFlash = <span class="literal">true</span>;\r
+\r
+ <span class="keyword">for</span> (item <span class="keyword">in</span> formats) {\r
+ \r
+ <span class="keyword">if</span> (formats.hasOwnProperty(item)) {\r
+ \r
+ <span class="keyword">if</span> (formats[item].required) {\r
+ \r
+ <span class="keyword">if</span> (!sm2.html5.canPlayType(formats[item].type)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-373">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-373">¶</a>
+ </div>
+ <p>100% HTML5 mode is not possible.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> canIgnoreFlash = <span class="literal">false</span>;\r
+ flashNeeded = <span class="literal">true</span>;\r
+ \r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (sm2.preferFlash && (sm2.flash[item] || sm2.flash[formats[item].type])) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-374">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-374">¶</a>
+ </div>
+ <p>flash may be required, or preferred for this format.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> flashNeeded = <span class="literal">true</span>;\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-375">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-375">¶</a>
+ </div>
+ <p>sanity check...</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (sm2.ignoreFlash) {\r
+ flashNeeded = <span class="literal">false</span>;\r
+ canIgnoreFlash = <span class="literal">true</span>;\r
+ }\r
+\r
+ sm2.html5Only = (sm2.hasHTML5 && sm2.useHTML5Audio && !flashNeeded);\r
+\r
+ <span class="keyword">return</span> (!sm2.html5Only);\r
+\r
+ };\r
+\r
+ parseURL = <span class="keyword">function</span>(url) {\r
+\r
+ <span class="comment">/**\r
+ * Internal: Finds and returns the first playable URL (or failing that, the first URL.)\r
+ * @param {string or array} url A single URL string, OR, an array of URL strings or {url:'/path/to/resource', type:'audio/mp3'} objects.\r
+ */</span>\r
+\r
+ <span class="keyword">var</span> i, j, urlResult = <span class="number">0</span>, result;\r
+\r
+ <span class="keyword">if</span> (url <span class="keyword">instanceof</span> Array) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-376">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-376">¶</a>
+ </div>
+ <p>find the first good one</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">for</span> (i = <span class="number">0</span>, j = url.length; i < j; i++) {\r
+\r
+ <span class="keyword">if</span> (url[i] <span class="keyword">instanceof</span> Object) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-377">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-377">¶</a>
+ </div>
+ <p>MIME check</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (sm2.canPlayMIME(url[i].type)) {\r
+ urlResult = i;\r
+ <span class="keyword">break</span>;\r
+ }\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (sm2.canPlayURL(url[i])) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-378">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-378">¶</a>
+ </div>
+ <p>URL string check</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> urlResult = i;\r
+ <span class="keyword">break</span>;\r
+\r
+ }\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-379">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-379">¶</a>
+ </div>
+ <p>normalize to string</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (url[urlResult].url) {\r
+ url[urlResult] = url[urlResult].url;\r
+ }\r
+\r
+ result = url[urlResult];\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-380">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-380">¶</a>
+ </div>
+ <p>single URL case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> result = url;\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+\r
+ startTimer = <span class="keyword">function</span>(oSound) {\r
+\r
+ <span class="comment">/**\r
+ * attach a timer to this sound, and start an interval if needed\r
+ */</span>\r
+\r
+ <span class="keyword">if</span> (!oSound._hasTimer) {\r
+\r
+ oSound._hasTimer = <span class="literal">true</span>;\r
+\r
+ <span class="keyword">if</span> (!mobileHTML5 && sm2.html5PollingInterval) {\r
+\r
+ <span class="keyword">if</span> (h5IntervalTimer === <span class="literal">null</span> && h5TimerCount === <span class="number">0</span>) {\r
+\r
+ h5IntervalTimer = setInterval(timerExecute, sm2.html5PollingInterval);\r
+\r
+ }\r
+\r
+ h5TimerCount++;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ stopTimer = <span class="keyword">function</span>(oSound) {\r
+\r
+ <span class="comment">/**\r
+ * detach a timer\r
+ */</span>\r
+\r
+ <span class="keyword">if</span> (oSound._hasTimer) {\r
+\r
+ oSound._hasTimer = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (!mobileHTML5 && sm2.html5PollingInterval) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-381">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-381">¶</a>
+ </div>
+ <p>interval will stop itself at next execution.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ h5TimerCount--;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ timerExecute = <span class="keyword">function</span>() {\r
+\r
+ <span class="comment">/**\r
+ * manual polling for HTML5 progress events, ie., whileplaying()\r
+ * (can achieve greater precision than conservative default HTML5 interval)\r
+ */</span>\r
+\r
+ <span class="keyword">var</span> i;\r
+\r
+ <span class="keyword">if</span> (h5IntervalTimer !== <span class="literal">null</span> && !h5TimerCount) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-382">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-382">¶</a>
+ </div>
+ <p>no active timers, stop polling interval.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ clearInterval(h5IntervalTimer);\r
+\r
+ h5IntervalTimer = <span class="literal">null</span>;\r
+\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-383">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-383">¶</a>
+ </div>
+ <p>check all HTML5 sounds with timers</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">for</span> (i = sm2.soundIDs.length - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {\r
+\r
+ <span class="keyword">if</span> (sm2.sounds[sm2.soundIDs[i]].isHTML5 && sm2.sounds[sm2.soundIDs[i]]._hasTimer) {\r
+ sm2.sounds[sm2.soundIDs[i]]._onTimer();\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ catchError = <span class="keyword">function</span>(options) {\r
+\r
+ options = (options !== _<span class="literal">undefined</span> ? options : {});\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> sm2.onerror === <span class="string">'function'</span>) {\r
+ sm2.onerror.apply(window, [{\r
+ type: (options.type !== _<span class="literal">undefined</span> ? options.type : <span class="literal">null</span>)\r
+ }]);\r
+ }\r
+\r
+ <span class="keyword">if</span> (options.fatal !== _<span class="literal">undefined</span> && options.fatal) {\r
+ sm2.disable();\r
+ }\r
+\r
+ };\r
+\r
+ badSafariFix = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-384">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-384">¶</a>
+ </div>
+ <p>special case: "bad" Safari (OS X 10.3 - 10.7) must fall back to flash for MP3/MP4</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!isBadSafari || !detectFlash()) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-385">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-385">¶</a>
+ </div>
+ <p>doesn't apply</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> aF = sm2.audioFormats, i, item;\r
+\r
+ <span class="keyword">for</span> (item <span class="keyword">in</span> aF) {\r
+\r
+ <span class="keyword">if</span> (aF.hasOwnProperty(item)) {\r
+\r
+ <span class="keyword">if</span> (item === <span class="string">'mp3'</span> || item === <span class="string">'mp4'</span>) {\r
+\r
+ sm2._wD(sm + <span class="string">': Using flash fallback for '</span> + item + <span class="string">' format'</span>);\r
+ sm2.html5[item] = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-386">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-386">¶</a>
+ </div>
+ <p>assign result to related formats, too</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (aF[item] && aF[item].related) {\r
+ <span class="keyword">for</span> (i = aF[item].related.length - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {\r
+ sm2.html5[aF[item].related[i]] = <span class="literal">false</span>;\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Pseudo-private flash/ExternalInterface methods\r
+ * ----------------------------------------------\r
+ */</span>\r
+\r
+ <span class="keyword">this</span>._setSandboxType = <span class="keyword">function</span>(sandboxType) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-387">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-387">¶</a>
+ </div>
+ <p><d>
+Security sandbox according to Flash plugin</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> sb = sm2.sandbox;\r
+\r
+ sb.type = sandboxType;\r
+ sb.description = sb.types[(sb.types[sandboxType] !== _<span class="literal">undefined</span>?sandboxType : <span class="string">'unknown'</span>)];\r
+\r
+ <span class="keyword">if</span> (sb.type === <span class="string">'localWithFile'</span>) {\r
+\r
+ sb.noRemote = <span class="literal">true</span>;\r
+ sb.noLocal = <span class="literal">false</span>;\r
+ _wDS(<span class="string">'secNote'</span>, <span class="number">2</span>);\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (sb.type === <span class="string">'localWithNetwork'</span>) {\r
+\r
+ sb.noRemote = <span class="literal">false</span>;\r
+ sb.noLocal = <span class="literal">true</span>;\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (sb.type === <span class="string">'localTrusted'</span>) {\r
+\r
+ sb.noRemote = <span class="literal">false</span>;\r
+ sb.noLocal = <span class="literal">false</span>;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-388">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-388">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ };\r
+\r
+ <span class="keyword">this</span>._externalInterfaceOK = <span class="keyword">function</span>(swfVersion) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-389">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-389">¶</a>
+ </div>
+ <p>flash callback confirming flash loaded, EI working etc.
+swfVersion: SWF build string</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (sm2.swfLoaded) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> e;\r
+\r
+ debugTS(<span class="string">'swf'</span>, <span class="literal">true</span>);\r
+ debugTS(<span class="string">'flashtojs'</span>, <span class="literal">true</span>);\r
+ sm2.swfLoaded = <span class="literal">true</span>;\r
+ tryInitOnFocus = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (isBadSafari) {\r
+ badSafariFix();\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-390">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-390">¶</a>
+ </div>
+ <p>complain if JS + SWF build/version strings don't match, excluding +DEV builds</p>
+<d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!swfVersion || swfVersion.replace(<span class="regexp">/\+dev/i</span>,<span class="string">''</span>) !== sm2.versionNumber.replace(<span class="regexp">/\+dev/i</span>, <span class="string">''</span>)) {\r
+\r
+ e = sm + <span class="string">': Fatal: JavaScript file build "'</span> + sm2.versionNumber + <span class="string">'" does not match Flash SWF build "'</span> + swfVersion + <span class="string">'" at '</span> + sm2.url + <span class="string">'. Ensure both are up-to-date.'</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-391">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-391">¶</a>
+ </div>
+ <p>escape flash -> JS stack so this error fires in window.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> setTimeout(<span class="function"><span class="keyword">function</span> <span class="title">versionMismatch</span><span class="params">()</span> {</span>\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> Error(e);\r
+ }, <span class="number">0</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-392">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-392">¶</a>
+ </div>
+ <p>exit, init will fail with timeout</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-393">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-393">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-394">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-394">¶</a>
+ </div>
+ <p>IE needs a larger timeout</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> setTimeout(init, isIE ? <span class="number">100</span> : <span class="number">1</span>);\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * Private initialization helpers\r
+ * ------------------------------\r
+ */</span>\r
+\r
+ createMovie = <span class="keyword">function</span>(smID, smURL) {\r
+\r
+ <span class="keyword">if</span> (didAppend && appendSuccess) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-395">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-395">¶</a>
+ </div>
+ <p>ignore if already succeeded</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">initMsg</span><span class="params">()</span> {</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-396">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-396">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">var</span> options = [],\r
+ title,\r
+ msg = [],\r
+ delimiter = <span class="string">' + '</span>;\r
+\r
+ title = <span class="string">'SoundManager '</span> + sm2.version + (!sm2.html5Only && sm2.useHTML5Audio ? (sm2.hasHTML5 ? <span class="string">' + HTML5 audio'</span> : <span class="string">', no HTML5 audio support'</span>) : <span class="string">''</span>);\r
+\r
+ <span class="keyword">if</span> (!sm2.html5Only) {\r
+\r
+ <span class="keyword">if</span> (sm2.preferFlash) {\r
+ options.push(<span class="string">'preferFlash'</span>);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.useHighPerformance) {\r
+ options.push(<span class="string">'useHighPerformance'</span>);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.flashPollingInterval) {\r
+ options.push(<span class="string">'flashPollingInterval ('</span> + sm2.flashPollingInterval + <span class="string">'ms)'</span>);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.html5PollingInterval) {\r
+ options.push(<span class="string">'html5PollingInterval ('</span> + sm2.html5PollingInterval + <span class="string">'ms)'</span>);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.wmode) {\r
+ options.push(<span class="string">'wmode ('</span> + sm2.wmode + <span class="string">')'</span>);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.debugFlash) {\r
+ options.push(<span class="string">'debugFlash'</span>);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.useFlashBlock) {\r
+ options.push(<span class="string">'flashBlock'</span>);\r
+ }\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (sm2.html5PollingInterval) {\r
+ options.push(<span class="string">'html5PollingInterval ('</span> + sm2.html5PollingInterval + <span class="string">'ms)'</span>);\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (options.length) {\r
+ msg = msg.concat([options.join(delimiter)]);\r
+ }\r
+\r
+ sm2._wD(title + (msg.length ? delimiter + msg.join(<span class="string">', '</span>) : <span class="string">''</span>), <span class="number">1</span>);\r
+\r
+ showSupport();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-397">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-397">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.html5Only) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-398">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-398">¶</a>
+ </div>
+ <p>100% HTML5 mode</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> setVersionInfo();\r
+\r
+ initMsg();\r
+ sm2.oMC = id(sm2.movieID);\r
+ init();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-399">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-399">¶</a>
+ </div>
+ <p>prevent multiple init attempts</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> didAppend = <span class="literal">true</span>;\r
+\r
+ appendSuccess = <span class="literal">true</span>;\r
+\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-400">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-400">¶</a>
+ </div>
+ <p>flash path</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">var</span> remoteURL = (smURL || sm2.url),\r
+ localURL = (sm2.altURL || remoteURL),\r
+ swfTitle = <span class="string">'JS/Flash audio component (SoundManager 2)'</span>,\r
+ oTarget = getDocument(),\r
+ extraClass = getSWFCSS(),\r
+ isRTL = <span class="literal">null</span>,\r
+ html = doc.getElementsByTagName(<span class="string">'html'</span>)[<span class="number">0</span>],\r
+ oEmbed, oMovie, tmp, movieHTML, oEl, s, x, sClass;\r
+\r
+ isRTL = (html && html.dir && html.dir.match(<span class="regexp">/rtl/i</span>));\r
+ smID = (smID === _<span class="literal">undefined</span> ? sm2.id : smID);\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">param</span><span class="params">(name, value)</span> {</span>\r
+ <span class="keyword">return</span> <span class="string">'<param name="'</span> + name + <span class="string">'" value="'</span> + value + <span class="string">'" />'</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-401">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-401">¶</a>
+ </div>
+ <p>safety check for legacy (change to Flash 9 URL)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> setVersionInfo();\r
+ sm2.url = normalizeMovieURL(overHTTP ? remoteURL : localURL);\r
+ smURL = sm2.url;\r
+\r
+ sm2.wmode = (!sm2.wmode && sm2.useHighPerformance ? <span class="string">'transparent'</span> : sm2.wmode);\r
+\r
+ <span class="keyword">if</span> (sm2.wmode !== <span class="literal">null</span> && (ua.match(<span class="regexp">/msie 8/i</span>) || (!isIE && !sm2.useHighPerformance)) && navigator.platform.match(<span class="regexp">/win32|win64/i</span>)) {\r
+ <span class="comment">/**\r
+ * extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here\r
+ * does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout\r
+ * wmode breaks IE 8 on Vista + Win7 too in some cases, as of January 2011 (?)\r
+ */</span>\r
+ messages.push(strings.spcWmode);\r
+ sm2.wmode = <span class="literal">null</span>;\r
+ }\r
+\r
+ oEmbed = {\r
+ <span class="string">'name'</span>: smID,\r
+ <span class="string">'id'</span>: smID,\r
+ <span class="string">'src'</span>: smURL,\r
+ <span class="string">'quality'</span>: <span class="string">'high'</span>,\r
+ <span class="string">'allowScriptAccess'</span>: sm2.allowScriptAccess,\r
+ <span class="string">'bgcolor'</span>: sm2.bgColor,\r
+ <span class="string">'pluginspage'</span>: http + <span class="string">'www.macromedia.com/go/getflashplayer'</span>,\r
+ <span class="string">'title'</span>: swfTitle,\r
+ <span class="string">'type'</span>: <span class="string">'application/x-shockwave-flash'</span>,\r
+ <span class="string">'wmode'</span>: sm2.wmode,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-402">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-402">¶</a>
+ </div>
+ <p><a href="http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html">http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="string">'hasPriority'</span>: <span class="string">'true'</span>\r
+ };\r
+\r
+ <span class="keyword">if</span> (sm2.debugFlash) {\r
+ oEmbed.FlashVars = <span class="string">'debug=1'</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!sm2.wmode) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-403">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-403">¶</a>
+ </div>
+ <p>don't write empty attribute</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">delete</span> oEmbed.wmode;\r
+ }\r
+\r
+ <span class="keyword">if</span> (isIE) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-404">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-404">¶</a>
+ </div>
+ <p>IE is "special".</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> oMovie = doc.createElement(<span class="string">'div'</span>);\r
+ movieHTML = [\r
+ <span class="string">'<object id="'</span> + smID + <span class="string">'" data="'</span> + smURL + <span class="string">'" type="'</span> + oEmbed.type + <span class="string">'" title="'</span> + oEmbed.title +<span class="string">'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">'</span>,\r
+ param(<span class="string">'movie'</span>, smURL),\r
+ param(<span class="string">'AllowScriptAccess'</span>, sm2.allowScriptAccess),\r
+ param(<span class="string">'quality'</span>, oEmbed.quality),\r
+ (sm2.wmode? param(<span class="string">'wmode'</span>, sm2.wmode): <span class="string">''</span>),\r
+ param(<span class="string">'bgcolor'</span>, sm2.bgColor),\r
+ param(<span class="string">'hasPriority'</span>, <span class="string">'true'</span>),\r
+ (sm2.debugFlash ? param(<span class="string">'FlashVars'</span>, oEmbed.FlashVars) : <span class="string">''</span>),\r
+ <span class="string">'</object>'</span>\r
+ ].join(<span class="string">''</span>);\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ oMovie = doc.createElement(<span class="string">'embed'</span>);\r
+ <span class="keyword">for</span> (tmp <span class="keyword">in</span> oEmbed) {\r
+ <span class="keyword">if</span> (oEmbed.hasOwnProperty(tmp)) {\r
+ oMovie.setAttribute(tmp, oEmbed[tmp]);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ initDebug();\r
+ extraClass = getSWFCSS();\r
+ oTarget = getDocument();\r
+\r
+ <span class="keyword">if</span> (oTarget) {\r
+\r
+ sm2.oMC = (id(sm2.movieID) || doc.createElement(<span class="string">'div'</span>));\r
+\r
+ <span class="keyword">if</span> (!sm2.oMC.id) {\r
+\r
+ sm2.oMC.id = sm2.movieID;\r
+ sm2.oMC.className = swfCSS.swfDefault + <span class="string">' '</span> + extraClass;\r
+ s = <span class="literal">null</span>;\r
+ oEl = <span class="literal">null</span>;\r
+\r
+ <span class="keyword">if</span> (!sm2.useFlashBlock) {\r
+ <span class="keyword">if</span> (sm2.useHighPerformance) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-405">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-405">¶</a>
+ </div>
+ <p>on-screen at all times</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s = {\r
+ <span class="string">'position'</span>: <span class="string">'fixed'</span>,\r
+ <span class="string">'width'</span>: <span class="string">'8px'</span>,\r
+ <span class="string">'height'</span>: <span class="string">'8px'</span>,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-406">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-406">¶</a>
+ </div>
+ <blockquote>
+<p>= 6px for flash to run fast, >= 8px to start up under Firefox/win32 in some cases. odd? yes.</p>
+</blockquote>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="string">'bottom'</span>: <span class="string">'0px'</span>,\r
+ <span class="string">'left'</span>: <span class="string">'0px'</span>,\r
+ <span class="string">'overflow'</span>: <span class="string">'hidden'</span>\r
+ };\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-407">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-407">¶</a>
+ </div>
+ <p>hide off-screen, lower priority</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> s = {\r
+ <span class="string">'position'</span>: <span class="string">'absolute'</span>,\r
+ <span class="string">'width'</span>: <span class="string">'6px'</span>,\r
+ <span class="string">'height'</span>: <span class="string">'6px'</span>,\r
+ <span class="string">'top'</span>: <span class="string">'-9999px'</span>,\r
+ <span class="string">'left'</span>: <span class="string">'-9999px'</span>\r
+ };\r
+ <span class="keyword">if</span> (isRTL) {\r
+ s.left = Math.abs(parseInt(s.left, <span class="number">10</span>)) + <span class="string">'px'</span>;\r
+ }\r
+ }\r
+ }\r
+\r
+ <span class="keyword">if</span> (isWebkit) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-408">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-408">¶</a>
+ </div>
+ <p>soundcloud-reported render/crash fix, safari 5</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.oMC.style.zIndex = <span class="number">10000</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!sm2.debugFlash) {\r
+ <span class="keyword">for</span> (x <span class="keyword">in</span> s) {\r
+ <span class="keyword">if</span> (s.hasOwnProperty(x)) {\r
+ sm2.oMC.style[x] = s[x];\r
+ }\r
+ }\r
+ }\r
+\r
+ <span class="keyword">try</span> {\r
+\r
+ <span class="keyword">if</span> (!isIE) {\r
+ sm2.oMC.appendChild(oMovie);\r
+ }\r
+\r
+ oTarget.appendChild(sm2.oMC);\r
+\r
+ <span class="keyword">if</span> (isIE) {\r
+ oEl = sm2.oMC.appendChild(doc.createElement(<span class="string">'div'</span>));\r
+ oEl.className = swfCSS.swfBox;\r
+ oEl.innerHTML = movieHTML;\r
+ }\r
+\r
+ appendSuccess = <span class="literal">true</span>;\r
+\r
+ } <span class="keyword">catch</span>(e) {\r
+\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> Error(str(<span class="string">'domError'</span>) + <span class="string">' \n'</span> + e.toString());\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-409">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-409">¶</a>
+ </div>
+ <p>SM2 container is already in the document (eg. flashblock use case)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sClass = sm2.oMC.className;\r
+ sm2.oMC.className = (sClass ? sClass + <span class="string">' '</span> : swfCSS.swfDefault) + (extraClass ? <span class="string">' '</span> + extraClass : <span class="string">''</span>);\r
+ sm2.oMC.appendChild(oMovie);\r
+\r
+ <span class="keyword">if</span> (isIE) {\r
+ oEl = sm2.oMC.appendChild(doc.createElement(<span class="string">'div'</span>));\r
+ oEl.className = swfCSS.swfBox;\r
+ oEl.innerHTML = movieHTML;\r
+ }\r
+\r
+ appendSuccess = <span class="literal">true</span>;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ didAppend = <span class="literal">true</span>;\r
+\r
+ initMsg();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-410">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-410">¶</a>
+ </div>
+ <p>sm2._wD(sm + ': Trying to load ' + smURL + (!overHTTP && sm2.altURL ? ' (alternate URL)' : ''), 1);</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ initMovie = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">if</span> (sm2.html5Only) {\r
+ createMovie();\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-411">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-411">¶</a>
+ </div>
+ <p>attempt to get, or create, movie (may already exist)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (flash) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!sm2.url) {\r
+\r
+ <span class="comment">/**\r
+ * Something isn't right - we've reached init, but the soundManager url property has not been set.\r
+ * User has not called setup({url: ...}), or has not set soundManager.url (legacy use case) directly before init time.\r
+ * Notify and exit. If user calls setup() with a url: property, init will be restarted as in the deferred loading case.\r
+ */</span>\r
+\r
+ _wDS(<span class="string">'noURL'</span>);\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-412">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-412">¶</a>
+ </div>
+ <p>inline markup case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> flash = sm2.getMovie(sm2.id);\r
+\r
+ <span class="keyword">if</span> (!flash) {\r
+\r
+ <span class="keyword">if</span> (!oRemoved) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-413">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-413">¶</a>
+ </div>
+ <p>try to create</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> createMovie(sm2.id, sm2.url);\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-414">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-414">¶</a>
+ </div>
+ <p>try to re-append removed movie after reboot()</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!isIE) {\r
+ sm2.oMC.appendChild(oRemoved);\r
+ } <span class="keyword">else</span> {\r
+ sm2.oMC.innerHTML = oRemovedHTML;\r
+ }\r
+\r
+ oRemoved = <span class="literal">null</span>;\r
+ didAppend = <span class="literal">true</span>;\r
+\r
+ }\r
+\r
+ flash = sm2.getMovie(sm2.id);\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (<span class="keyword">typeof</span> sm2.oninitmovie === <span class="string">'function'</span>) {\r
+ setTimeout(sm2.oninitmovie, <span class="number">1</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-415">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-415">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> flushMessages();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-416">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-416">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ delayWaitForEI = <span class="keyword">function</span>() {\r
+\r
+ setTimeout(waitForEI, <span class="number">1000</span>);\r
+\r
+ };\r
+\r
+ rebootIntoHTML5 = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-417">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-417">¶</a>
+ </div>
+ <p>special case: try for a reboot with preferFlash: false, if 100% HTML5 mode is possible and useFlashBlock is not enabled.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ window.setTimeout(<span class="keyword">function</span>() {\r
+\r
+ complain(smc + <span class="string">'useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...'</span>);\r
+\r
+ sm2.setup({\r
+ preferFlash: <span class="literal">false</span>\r
+ }).reboot();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-418">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-418">¶</a>
+ </div>
+ <p>if for some reason you want to detect this case, use an ontimeout() callback and look for html5Only and didFlashBlock == true.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.didFlashBlock = <span class="literal">true</span>;\r
+\r
+ sm2.beginDelayedInit();\r
+\r
+ }, <span class="number">1</span>);\r
+\r
+ };\r
+\r
+ waitForEI = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> p,\r
+ loadIncomplete = <span class="literal">false</span>;\r
+\r
+ <span class="keyword">if</span> (!sm2.url) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-419">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-419">¶</a>
+ </div>
+ <p>No SWF url to load (noURL case) - exit for now. Will be retried when url is set.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (waitingForEI) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ waitingForEI = <span class="literal">true</span>;\r
+ event.remove(window, <span class="string">'load'</span>, delayWaitForEI);\r
+\r
+ <span class="keyword">if</span> (hasFlash && tryInitOnFocus && !isFocused) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-420">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-420">¶</a>
+ </div>
+ <p>Safari won't load flash in background tabs, only when focused.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> _wDS(<span class="string">'waitFocus'</span>);\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (!didInit) {\r
+ p = sm2.getMoviePercent();\r
+ <span class="keyword">if</span> (p > <span class="number">0</span> && p < <span class="number">100</span>) {\r
+ loadIncomplete = <span class="literal">true</span>;\r
+ }\r
+ }\r
+\r
+ setTimeout(<span class="keyword">function</span>() {\r
+\r
+ p = sm2.getMoviePercent();\r
+\r
+ <span class="keyword">if</span> (loadIncomplete) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-421">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-421">¶</a>
+ </div>
+ <p>special case: if movie <em>partially</em> loaded, retry until it's 100% before assuming failure.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> waitingForEI = <span class="literal">false</span>;\r
+ sm2._wD(str(<span class="string">'waitSWF'</span>));\r
+ window.setTimeout(delayWaitForEI, <span class="number">1</span>);\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-422">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-422">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (!didInit) {\r
+\r
+ sm2._wD(sm + <span class="string">': No Flash response within expected time. Likely causes: '</span> + (p === <span class="number">0</span> ? <span class="string">'SWF load failed, '</span> : <span class="string">''</span>) + <span class="string">'Flash blocked or JS-Flash security error.'</span> + (sm2.debugFlash ? <span class="string">' '</span> + str(<span class="string">'checkSWF'</span>) : <span class="string">''</span>), <span class="number">2</span>);\r
+\r
+ <span class="keyword">if</span> (!overHTTP && p) {\r
+\r
+ _wDS(<span class="string">'localFail'</span>, <span class="number">2</span>);\r
+\r
+ <span class="keyword">if</span> (!sm2.debugFlash) {\r
+ _wDS(<span class="string">'tryDebug'</span>, <span class="number">2</span>);\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (p === <span class="number">0</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-423">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-423">¶</a>
+ </div>
+ <p>if 0 (not null), probably a 404.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2._wD(str(<span class="string">'swf404'</span>, sm2.url), <span class="number">1</span>);\r
+\r
+ }\r
+\r
+ debugTS(<span class="string">'flashtojs'</span>, <span class="literal">false</span>, <span class="string">': Timed out'</span> + (overHTTP ? <span class="string">' (Check flash security or flash blockers)'</span>:<span class="string">' (No plugin/missing SWF?)'</span>));\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-424">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-424">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-425">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-425">¶</a>
+ </div>
+ <p>give up / time-out, depending</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!didInit && okToDisable) {\r
+\r
+ <span class="keyword">if</span> (p === <span class="literal">null</span>) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-426">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-426">¶</a>
+ </div>
+ <p>SWF failed to report load progress. Possibly blocked.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (sm2.useFlashBlock || sm2.flashLoadTimeout === <span class="number">0</span>) {\r
+\r
+ <span class="keyword">if</span> (sm2.useFlashBlock) {\r
+\r
+ flashBlockHandler();\r
+\r
+ }\r
+\r
+ _wDS(<span class="string">'waitForever'</span>);\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-427">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-427">¶</a>
+ </div>
+ <p>no custom flash block handling, but SWF has timed out. Will recover if user unblocks / allows SWF load.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (!sm2.useFlashBlock && canIgnoreFlash) {\r
+\r
+ rebootIntoHTML5();\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ _wDS(<span class="string">'waitForever'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-428">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-428">¶</a>
+ </div>
+ <p>fire any regular registered ontimeout() listeners.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> processOnEvents({\r
+ type: <span class="string">'ontimeout'</span>,\r
+ ignoreInit: <span class="literal">true</span>,\r
+ error: {\r
+ type: <span class="string">'INIT_FLASHBLOCK'</span>\r
+ }\r
+ });\r
+\r
+ }\r
+\r
+ }\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-429">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-429">¶</a>
+ </div>
+ <p>SWF loaded? Shouldn't be a blocking issue, then.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (sm2.flashLoadTimeout === <span class="number">0</span>) {\r
+\r
+ _wDS(<span class="string">'waitForever'</span>);\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ <span class="keyword">if</span> (!sm2.useFlashBlock && canIgnoreFlash) {\r
+\r
+ rebootIntoHTML5();\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ failSafely(<span class="literal">true</span>);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }, sm2.flashLoadTimeout);\r
+\r
+ };\r
+\r
+ handleFocus = <span class="keyword">function</span>() {\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">cleanup</span><span class="params">()</span> {</span>\r
+ event.remove(window, <span class="string">'focus'</span>, handleFocus);\r
+ }\r
+\r
+ <span class="keyword">if</span> (isFocused || !tryInitOnFocus) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-430">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-430">¶</a>
+ </div>
+ <p>already focused, or not special Safari background tab case</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> cleanup();\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+ }\r
+\r
+ okToDisable = <span class="literal">true</span>;\r
+ isFocused = <span class="literal">true</span>;\r
+ _wDS(<span class="string">'gotFocus'</span>);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-431">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-431">¶</a>
+ </div>
+ <p>allow init to restart</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> waitingForEI = <span class="literal">false</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-432">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-432">¶</a>
+ </div>
+ <p>kick off ExternalInterface timeout, now that the SWF has started</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> delayWaitForEI();\r
+\r
+ cleanup();\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ flushMessages = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-433">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-433">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-434">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-434">¶</a>
+ </div>
+ <p>SM2 pre-init debug messages</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (messages.length) {\r
+ sm2._wD(<span class="string">'SoundManager 2: '</span> + messages.join(<span class="string">' '</span>), <span class="number">1</span>);\r
+ messages = [];\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-435">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-435">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ };\r
+\r
+ showSupport = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-436">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-436">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ flushMessages();\r
+\r
+ <span class="keyword">var</span> item, tests = [];\r
+\r
+ <span class="keyword">if</span> (sm2.useHTML5Audio && sm2.hasHTML5) {\r
+ <span class="keyword">for</span> (item <span class="keyword">in</span> sm2.audioFormats) {\r
+ <span class="keyword">if</span> (sm2.audioFormats.hasOwnProperty(item)) {\r
+ tests.push(item + <span class="string">' = '</span> + sm2.html5[item] + (!sm2.html5[item] && needsFlash && sm2.flash[item] ? <span class="string">' (using flash)'</span> : (sm2.preferFlash && sm2.flash[item] && needsFlash ? <span class="string">' (preferring flash)'</span> : (!sm2.html5[item] ? <span class="string">' ('</span> + (sm2.audioFormats[item].required ? <span class="string">'required, '</span> : <span class="string">''</span>) + <span class="string">'and no flash support)'</span> : <span class="string">''</span>))));\r
+ }\r
+ }\r
+ sm2._wD(<span class="string">'SoundManager 2 HTML5 support: '</span> + tests.join(<span class="string">', '</span>), <span class="number">1</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-437">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-437">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ };\r
+\r
+ initComplete = <span class="keyword">function</span>(bNoDisable) {\r
+\r
+ <span class="keyword">if</span> (didInit) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.html5Only) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-438">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-438">¶</a>
+ </div>
+ <p>all good.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> _wDS(<span class="string">'sm2Loaded'</span>, <span class="number">1</span>);\r
+ didInit = <span class="literal">true</span>;\r
+ initUserOnload();\r
+ debugTS(<span class="string">'onload'</span>, <span class="literal">true</span>);\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+ }\r
+\r
+ <span class="keyword">var</span> wasTimeout = (sm2.useFlashBlock && sm2.flashLoadTimeout && !sm2.getMoviePercent()),\r
+ result = <span class="literal">true</span>,\r
+ error;\r
+\r
+ <span class="keyword">if</span> (!wasTimeout) {\r
+ didInit = <span class="literal">true</span>;\r
+ }\r
+\r
+ error = {\r
+ type: (!hasFlash && needsFlash ? <span class="string">'NO_FLASH'</span> : <span class="string">'INIT_TIMEOUT'</span>)\r
+ };\r
+\r
+ sm2._wD(<span class="string">'SoundManager 2 '</span> + (disabled ? <span class="string">'failed to load'</span> : <span class="string">'loaded'</span>) + <span class="string">' ('</span> + (disabled ? <span class="string">'Flash security/load error'</span> : <span class="string">'OK'</span>) + <span class="string">') '</span> + String.fromCharCode(disabled ? <span class="number">10006</span> : <span class="number">10003</span>), disabled ? <span class="number">2</span>: <span class="number">1</span>);\r
+\r
+ <span class="keyword">if</span> (disabled || bNoDisable) {\r
+\r
+ <span class="keyword">if</span> (sm2.useFlashBlock && sm2.oMC) {\r
+ sm2.oMC.className = getSWFCSS() + <span class="string">' '</span> + (sm2.getMoviePercent() === <span class="literal">null</span> ? swfCSS.swfTimedout : swfCSS.swfError);\r
+ }\r
+\r
+ processOnEvents({\r
+ type: <span class="string">'ontimeout'</span>,\r
+ error: error,\r
+ ignoreInit: <span class="literal">true</span>\r
+ });\r
+\r
+ debugTS(<span class="string">'onload'</span>, <span class="literal">false</span>);\r
+ catchError(error);\r
+\r
+ result = <span class="literal">false</span>;\r
+\r
+ } <span class="keyword">else</span> {\r
+\r
+ debugTS(<span class="string">'onload'</span>, <span class="literal">true</span>);\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (!disabled) {\r
+\r
+ <span class="keyword">if</span> (sm2.waitForWindowLoad && !windowLoaded) {\r
+\r
+ _wDS(<span class="string">'waitOnload'</span>);\r
+ event.add(window, <span class="string">'load'</span>, initUserOnload);\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-439">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-439">¶</a>
+ </div>
+ <d>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> (sm2.waitForWindowLoad && windowLoaded) {\r
+ _wDS(<span class="string">'docLoaded'</span>);\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-440">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-440">¶</a>
+ </div>
+ <p></d></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ initUserOnload();\r
+\r
+ }\r
+\r
+ }\r
+\r
+ <span class="keyword">return</span> result;\r
+\r
+ };\r
+\r
+ <span class="comment">/**\r
+ * apply top-level setupOptions object as local properties, eg., this.setupOptions.flashVersion -> this.flashVersion (soundManager.flashVersion)\r
+ * this maintains backward compatibility, and allows properties to be defined separately for use by soundManager.setup().\r
+ */</span>\r
+\r
+ setProperties = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">var</span> i,\r
+ o = sm2.setupOptions;\r
+\r
+ <span class="keyword">for</span> (i <span class="keyword">in</span> o) {\r
+\r
+ <span class="keyword">if</span> (o.hasOwnProperty(i)) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-441">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-441">¶</a>
+ </div>
+ <p>assign local property if not already defined</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (sm2[i] === _<span class="literal">undefined</span>) {\r
+\r
+ sm2[i] = o[i];\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (sm2[i] !== o[i]) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-442">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-442">¶</a>
+ </div>
+ <p>legacy support: write manually-assigned property (eg., soundManager.url) back to setupOptions to keep things in sync</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.setupOptions[i] = sm2[i];\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+\r
+ init = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-443">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-443">¶</a>
+ </div>
+ <p>called after onload()</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+ <span class="keyword">if</span> (didInit) {\r
+ _wDS(<span class="string">'didInit'</span>);\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ <span class="function"><span class="keyword">function</span> <span class="title">cleanup</span><span class="params">()</span> {</span>\r
+ event.remove(window, <span class="string">'load'</span>, sm2.beginDelayedInit);\r
+ }\r
+\r
+ <span class="keyword">if</span> (sm2.html5Only) {\r
+\r
+ <span class="keyword">if</span> (!didInit) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-444">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-444">¶</a>
+ </div>
+ <p>we don't need no steenking flash!</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> cleanup();\r
+ sm2.enabled = <span class="literal">true</span>;\r
+ initComplete();\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ }</pre></div></div>
+
+ </li>
+
+
+ <li id="section-445">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-445">¶</a>
+ </div>
+ <p>flash path</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> initMovie();\r
+\r
+ <span class="keyword">try</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-446">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-446">¶</a>
+ </div>
+ <p>attempt to talk to Flash</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> flash._externalInterfaceTest(<span class="literal">false</span>);\r
+\r
+ <span class="comment">/**\r
+ * Apply user-specified polling interval, OR, if "high performance" set, faster vs. default polling\r
+ * (determines frequency of whileloading/whileplaying callbacks, effectively driving UI framerates)\r
+ */</span>\r
+ setPolling(<span class="literal">true</span>, (sm2.flashPollingInterval || (sm2.useHighPerformance ? <span class="number">10</span> : <span class="number">50</span>)));\r
+\r
+ <span class="keyword">if</span> (!sm2.debugMode) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-447">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-447">¶</a>
+ </div>
+ <p>stop the SWF from making debug output calls to JS</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> flash._disableDebug();\r
+ }\r
+\r
+ sm2.enabled = <span class="literal">true</span>;\r
+ debugTS(<span class="string">'jstoflash'</span>, <span class="literal">true</span>);\r
+\r
+ <span class="keyword">if</span> (!sm2.html5Only) {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-448">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-448">¶</a>
+ </div>
+ <p>prevent browser from showing cached page state (or rather, restoring "suspended" page state) via back button, because flash may be dead
+<a href="http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/">http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> event.add(window, <span class="string">'unload'</span>, doNothing);\r
+ }\r
+\r
+ } <span class="keyword">catch</span>(e) {\r
+\r
+ sm2._wD(<span class="string">'js/flash exception: '</span> + e.toString());\r
+\r
+ debugTS(<span class="string">'jstoflash'</span>, <span class="literal">false</span>);\r
+\r
+ catchError({\r
+ type: <span class="string">'JS_TO_FLASH_EXCEPTION'</span>,\r
+ fatal: <span class="literal">true</span>\r
+ });</pre></div></div>
+
+ </li>
+
+
+ <li id="section-449">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-449">¶</a>
+ </div>
+ <p>don't disable, for reboot()</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> failSafely(<span class="literal">true</span>);\r
+\r
+ initComplete();\r
+\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+\r
+ }\r
+\r
+ initComplete();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-450">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-450">¶</a>
+ </div>
+ <p>disconnect events</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> cleanup();\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ domContentLoaded = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">if</span> (didDCLoaded) {\r
+ <span class="keyword">return</span> <span class="literal">false</span>;\r
+ }\r
+\r
+ didDCLoaded = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-451">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-451">¶</a>
+ </div>
+ <p>assign top-level soundManager properties eg. soundManager.url</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> setProperties();\r
+\r
+ initDebug();\r
+\r
+ <span class="keyword">if</span> (!hasFlash && sm2.hasHTML5) {\r
+\r
+ sm2._wD(<span class="string">'SoundManager 2: No Flash detected'</span> + (!sm2.useHTML5Audio ? <span class="string">', enabling HTML5.'</span> : <span class="string">'. Trying HTML5-only mode.'</span>), <span class="number">1</span>);\r
+\r
+ sm2.setup({\r
+ <span class="string">'useHTML5Audio'</span>: <span class="literal">true</span>,</pre></div></div>
+
+ </li>
+
+
+ <li id="section-452">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-452">¶</a>
+ </div>
+ <p>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.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> <span class="string">'preferFlash'</span>: <span class="literal">false</span>\r
+ });\r
+\r
+ }\r
+\r
+ testHTML5();\r
+\r
+ <span class="keyword">if</span> (!hasFlash && needsFlash) {\r
+\r
+ messages.push(strings.needFlash);</pre></div></div>
+
+ </li>
+
+
+ <li id="section-453">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-453">¶</a>
+ </div>
+ <p>TODO: Fatal here vs. timeout approach, etc.
+hack: fail sooner.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> sm2.setup({\r
+ <span class="string">'flashLoadTimeout'</span>: <span class="number">1</span>\r
+ });\r
+\r
+ }\r
+\r
+ <span class="keyword">if</span> (doc.removeEventListener) {\r
+ doc.removeEventListener(<span class="string">'DOMContentLoaded'</span>, domContentLoaded, <span class="literal">false</span>);\r
+ }\r
+\r
+ initMovie();\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ domContentLoadedIE = <span class="keyword">function</span>() {\r
+\r
+ <span class="keyword">if</span> (doc.readyState === <span class="string">'complete'</span>) {\r
+ domContentLoaded();\r
+ doc.detachEvent(<span class="string">'onreadystatechange'</span>, domContentLoadedIE);\r
+ }\r
+\r
+ <span class="keyword">return</span> <span class="literal">true</span>;\r
+\r
+ };\r
+\r
+ winOnLoad = <span class="keyword">function</span>() {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-454">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-454">¶</a>
+ </div>
+ <p>catch edge case of initComplete() firing after window.load()</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> windowLoaded = <span class="literal">true</span>;</pre></div></div>
+
+ </li>
+
+
+ <li id="section-455">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-455">¶</a>
+ </div>
+ <p>catch case where DOMContentLoaded has been sent, but we're still in doc.readyState = 'interactive'</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> domContentLoaded();\r
+\r
+ event.remove(window, <span class="string">'load'</span>, winOnLoad);\r
+\r
+ };</pre></div></div>
+
+ </li>
+
+
+ <li id="section-456">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-456">¶</a>
+ </div>
+ <p>sniff up-front</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> detectFlash();</pre></div></div>
+
+ </li>
+
+
+ <li id="section-457">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-457">¶</a>
+ </div>
+ <p>focus and window load, init (primarily flash-driven)</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> event.add(window, <span class="string">'focus'</span>, handleFocus);\r
+ event.add(window, <span class="string">'load'</span>, delayWaitForEI);\r
+ event.add(window, <span class="string">'load'</span>, winOnLoad);\r
+\r
+ <span class="keyword">if</span> (doc.addEventListener) {\r
+\r
+ doc.addEventListener(<span class="string">'DOMContentLoaded'</span>, domContentLoaded, <span class="literal">false</span>);\r
+\r
+ } <span class="keyword">else</span> <span class="keyword">if</span> (doc.attachEvent) {\r
+\r
+ doc.attachEvent(<span class="string">'onreadystatechange'</span>, domContentLoadedIE);\r
+\r
+ } <span class="keyword">else</span> {</pre></div></div>
+
+ </li>
+
+
+ <li id="section-458">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-458">¶</a>
+ </div>
+ <p>no add/attachevent support - safe to assume no JS -> Flash either</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre> debugTS(<span class="string">'onload'</span>, <span class="literal">false</span>);\r
+ catchError({\r
+ type: <span class="string">'NO_DOM2_EVENTS'</span>,\r
+ fatal: <span class="literal">true</span>\r
+ });\r
+\r
+ }\r
+\r
+} <span class="comment">// SoundManager()</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-459">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-459">¶</a>
+ </div>
+ <p>SM2_DEFER details: <a href="http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading">http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading</a></p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>\r
+<span class="keyword">if</span> (window.SM2_DEFER === _<span class="literal">undefined</span> || !SM2_DEFER) {\r
+ soundManager = <span class="keyword">new</span> SoundManager();\r
+}\r
+\r
+<span class="comment">/**\r
+ * SoundManager public interfaces\r
+ * ------------------------------\r
+ */</span>\r
+\r
+<span class="keyword">if</span> (<span class="keyword">typeof</span> module === <span class="string">'object'</span> && module && <span class="keyword">typeof</span> module.exports === <span class="string">'object'</span>) {\r
+\r
+ <span class="comment">/**\r
+ * commonJS module\r
+ */</span>\r
+\r
+ module.exports.SoundManager = SoundManager;\r
+ module.exports.soundManager = soundManager;\r
+\r
+} <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> define === <span class="string">'function'</span> && define.amd) {\r
+\r
+ <span class="comment">/**\r
+ * AMD - requireJS\r
+ * basic usage:\r
+ * require(["/path/to/soundmanager2.js"], function(SoundManager) {\r
+ * SoundManager.getInstance().setup({\r
+ * url: '/swf/',\r
+ * onready: function() { ... }\r
+ * })\r
+ * });\r
+ *\r
+ * SM2_DEFER usage:\r
+ * window.SM2_DEFER = true;\r
+ * require(["/path/to/soundmanager2.js"], function(SoundManager) {\r
+ * SoundManager.getInstance(function() {\r
+ * var soundManager = new SoundManager.constructor();\r
+ * soundManager.setup({\r
+ * url: '/swf/',\r
+ * ...\r
+ * });\r
+ * ...\r
+ * soundManager.beginDelayedInit();\r
+ * return soundManager;\r
+ * })\r
+ * }); \r
+ */</span>\r
+\r
+ define(<span class="keyword">function</span>() {\r
+ <span class="comment">/**\r
+ * Retrieve the global instance of SoundManager.\r
+ * If a global instance does not exist it can be created using a callback.\r
+ *\r
+ * @param {Function} smBuilder Optional: Callback used to create a new SoundManager instance\r
+ * @return {SoundManager} The global SoundManager instance\r
+ */</span>\r
+ <span class="function"><span class="keyword">function</span> <span class="title">getInstance</span><span class="params">(smBuilder)</span> {</span>\r
+ <span class="keyword">if</span> (!window.soundManager && smBuilder <span class="keyword">instanceof</span> Function) {\r
+ <span class="keyword">var</span> instance = smBuilder(SoundManager);\r
+ <span class="keyword">if</span> (instance <span class="keyword">instanceof</span> SoundManager) {\r
+ window.soundManager = instance;\r
+ }\r
+ }\r
+ <span class="keyword">return</span> window.soundManager;\r
+ }\r
+ <span class="keyword">return</span> {\r
+ constructor: SoundManager,\r
+ getInstance: getInstance\r
+ }\r
+ });\r
+\r
+}</pre></div></div>
+
+ </li>
+
+
+ <li id="section-460">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-460">¶</a>
+ </div>
+ <p>standard browser case</p>
+
+ </div>
+
+ </li>
+
+
+ <li id="section-461">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-461">¶</a>
+ </div>
+ <p>constructor</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>window.SoundManager = SoundManager;\r
+\r
+<span class="comment">/**\r
+ * note: SM2 requires a window global due to Flash, which makes calls to window.soundManager.\r
+ * Flash may not always be needed, but this is not known until async init and SM2 may even "reboot" into Flash mode.\r
+ */</span></pre></div></div>
+
+ </li>
+
+
+ <li id="section-462">
+ <div class="annotation">
+
+ <div class="pilwrap ">
+ <a class="pilcrow" href="#section-462">¶</a>
+ </div>
+ <p>public API, flash callbacks etc.</p>
+
+ </div>
+
+ <div class="content"><div class='highlight'><pre>window.soundManager = soundManager;\r
+\r
+}(window));</pre></div></div>
+
+ </li>
+
+ </ul>
+ </div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2 Tutorial: Getting Started</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="SoundManager 2 tutorial, example code, how to get started guide including and configuring SoundManager 2 for playing MP3 audio via Javascript." />\r
+<meta name="keywords" content="soundmanager2 tutorial, javascript sound, javascript audio, javascript play mp3, javascript sound control, mp3, mp4, mpeg4" />\r
+<meta name="robots" content="all" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta name="copyright" content="Copyright (C) 1997 onwards Scott Schiller" />\r
+<meta name="language" content="en-us" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="../../demo/index.css" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="../../troubleshoot/debug.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="../../demo/index.js"></script>\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ url: '../../swf/',\r
+ useFlashBlock: true,\r
+ consoleOnly: false,\r
+ bgColor: '#f6f6f6',\r
+ debugMode: true,\r
+ // enable flash debug output for this page\r
+ debugFlash: true\r
+});\r
+</script>\r
+<script type="text/javascript" src="../../troubleshoot/debug.js"></script>\r
+</head>\r
+\r
+<body>\r
+ \r
+<div id="content">\r
+\r
+ <div id="top">\r
+\r
+ <h1>SoundManager 2: Getting Started</h1>\r
+\r
+ <div id="nav">\r
+ <ul>\r
+\r
+ <li>\r
+ <a href="../../">Home</a>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="#">Demos</a>\r
+ <ul>\r
+ <li><a href="../../demo/template/">Basic Template</a></li>\r
+ <li><a href="../../demo/api/">API Examples</a></li>\r
+ <li><a href="../../demo/bar-ui/">Bar UI</a></li>\r
+ <li><a href="../../demo/play-mp3-links/" class="exclude">Playable MP3 links</a></li>\r
+ <li><a href="../../demo/mp3-player-button/" class="exclude">Basic MP3 Play Button</a></li>\r
+ <li><a href="../../demo/page-player/">Muxtape-style UI</a></li>\r
+ <li><a href="../../demo/360-player/">360° Player UI</a></li>\r
+ <li><a href="../../demo/mpc/">Drum Machine (MPC)</a></li>\r
+ <li><a href="../../demo/animation/">DOM/Animation Demos</a></li>\r
+ <li><a href="../../demo/flashblock/">FlashBlock Handling</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <strong><a href="../getstarted/">Getting Started</a></strong>\r
+ <ul>\r
+ <li><a href="../getstarted/#how-sm2-works">How SoundManager 2 works</a></li>\r
+ <li><a href="../getstarted/#basic-inclusion">Including SM2 on your site</a></li>\r
+ <li><a href="../getstarted/#troubleshooting">Troubleshooting</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="..">Documentation</a>\r
+ <ul>\r
+ <li><a href="../#sm-config">SoundManager Properties</a></li>\r
+ <li><a href="../#sound-object-properties">Sound Object Properties</a></li>\r
+ <li><a href="../#smdefaults">Global Sound Defaults</a></li>\r
+ <li><a href="../#api">SoundManager Core API</a></li>\r
+ <li><a href="../#smsoundmethods">Sound Object (SMSound) API</a></li>\r
+ <li><a href="../generated/soundmanager2.html">Generated Documentation</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <a href="../download/">Download</a>\r
+ <ul>\r
+ <li><a href="../download/#latest">Get SoundManager 2</a></li>\r
+ <li><a href="../download/#revision-history">Revision History</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <a href="../technotes/">Technical Notes</a>\r
+ <ul>\r
+ <li><a href="../technotes/#requirements">System Requirements</a></li>\r
+ <li><a href="../technotes/#serving-audio">Serving To HTML5 + Flash Clients</a></li>\r
+ <li><a href="../technotes/#client-requests">How Clients Download Audio</a></li>\r
+ <li><a href="../technotes/#mobile-device-limitations">Mobile Device Limitations</a></li>\r
+ <li><a href="../technotes/#debug-output">Debug + Console Output</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="../resources/">Resources</a>\r
+ <ul>\r
+ <li><a href="../resources/#licensing">Licensing</a></li>\r
+ <li><a href="../resources/#related">Related Projects</a></li>\r
+ <li><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/">SM2 support / discussion</a></li>\r
+ <li><a href="http://www.schillmania.com/content/react/contact/">Contact Info @ Schillmania.com</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ <div class="clear"></div>\r
+ </div>\r
+ \r
+ </div>\r
+\r
+ <div id="main-wrapper">\r
+\r
+ <div id="main" class="triple">\r
+\r
+ <div class="columnar">\r
+ <div class="c1">\r
+ <h2>How SoundManager Works</h2>\r
+ <p>It starts out easy, but you can go down the rabbit hole if you want.</p>\r
+ </div>\r
+ \r
+ <div class="c2">\r
+ \r
+ <div class="f-block">\r
+\r
+ <!--\r
+ <p style="margin-top:1px"><strong><strong>SoundManager 2 makes it easier to play MP3 audio cross browser / platform, using Javascript.</strong></strong></p>\r
+ -->\r
+ \r
+ <h3>SoundManager 2 Tutorial: What, Why, How</h3>\r
+ \r
+ <p><strong>Problem:</strong> Browsers lack good, consistent native audio support - even with the help of HTML5.</p>\r
+ <p><strong>Solution:</strong> Javascript API using HTML5 Audio() + headless Flash via ExternalInterface, works almost everywhere. If HTML5 is supported but "non-free" MP3/MP4 formats are not, flash can be used as a fallback.</p>\r
+ <p>SoundManager 2 wraps and extends both the HTML Audio and Flash Audio APIs, providing a single, unified sound API to Javascript; the API is consistent regardless of the technology working under the hood to play sound. (The flash portion is hidden, transparent to both developers and end users.)</p>\r
+\r
+ </div>\r
+\r
+ <div class="f-block c-basic-use">\r
+\r
+\r
+ <h4 id="basic-inclusion">Including SoundManager 2</h4>\r
+\r
+ <p>The soundmanager2.js core can get down to 12 KB over the wire, depending on what version you use. A few versions of the SM2 script are available, balancing code size between commented, debug-enabled and production-optimized builds.</p>\r
+ <p>Regardless of which build you use, take advantage of <a href="http://developer.yahoo.com/performance/rules.html#gzip" title="Best Practices for Speeding Up Your Web Site (Yahoo Developer Network)">gzip compression</a> on your server for big savings. As shown below, SoundManager 2 compresses quite well with gzip; the full debug-enabled version served <i>with</i> gzip is smaller than even the minified, no-debug version served without.</p>\r
+ \r
+ <table id="sm2-filesizes" cellpadding="0" cellspacing="0">\r
+\r
+ <tr>\r
+ <th>Build version</th>\r
+ <th>Recommended use</th>\r
+ <th class="nw">File size</th>\r
+ <th class="nw">+ <a href="https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess" title="Friends don't let friends run websites without gzip!">gzip</a></th>\r
+ </tr>\r
+\r
+ <tr>\r
+ <td>\r
+ <p>Original, formatted debug-enabled version with comments. Passes <a href="http://jslint.com" title="jslint, the JavaScript code quality tool.">jslint</a>.</p>\r
+ <pre><script src="<span>soundmanager2.js</span>"></script></pre>\r
+ </td>\r
+ <td>Development, testing, debugging</td>\r
+ <td class="nw">153 KB</td>\r
+ <td class="nw">41 KB</td>\r
+ </tr>\r
+\r
+ <tr>\r
+ <td>\r
+ <p>"No-debug", formatted (comments removed, whitespace retained) version</p>\r
+ <pre><script src="<span>soundmanager2-nodebug.js</span>"></script></pre>\r
+ </td>\r
+ <td>Production, "clean" no-debug code</td>\r
+ <td class="nw">78 KB</td>\r
+ <td class="nw">17 KB</td>\r
+ </tr>\r
+\r
+ <tr>\r
+ <td>\r
+ <p>Minified (Google Closure Compiler-munged, no comments or whitespace), debug-enabled version</p>\r
+ <pre><script src="<span>soundmanager2-jsmin.js</span>"></script></pre>\r
+ </td>\r
+ <td>Production, with debug code</td>\r
+ <td class="nw">47 KB</td>\r
+ <td class="nw">16 KB</td>\r
+ </tr>\r
+\r
+ <tr>\r
+ <td>\r
+ <p>Build-script optimized, minified, no-debug version</p>\r
+ <pre><script src="<span>soundmanager2-nodebug-jsmin.js</span>"></script></pre>\r
+ </td>\r
+ <td>Production-optimized, debug code removed</td>\r
+ <td class="nw">34 KB</td>\r
+ <td class="nw booyaa" title="Best-case scenario for load time/performance">12 KB!</td>\r
+ </tr>\r
+\r
+ </table>\r
+ \r
+ <p>You then need to tell SM2 where to find the flash .SWF it will need (depending on HTML5 support), and optionally what version of Flash (~2.8 KB for flash 8, and ~8.5 KB for flash 9) depending on what API features you want:</p>\r
+\r
+<pre class="block"><code><script>\r
+soundManager.setup({\r
+ url: '<span>/path/to/swf-files/</span>',\r
+ flashVersion: 9, <span><span>// optional: shiny features (default = 8)\r
+ // optional: ignore Flash where possible, use 100% HTML5 mode\r
+ // <a href="../#soundmanager-preferflash" title="soundManager.preferFlash documentation">preferFlash</a>: false,</span></span>\r
+ onready: function() {\r
+ <span><span>// Ready to use; <a href="../#soundmanager-createsound">soundManager.createSound()</a> etc. can now be called.</span></span>\r
+ }\r
+});\r
+</script></code></pre>\r
+\r
+<p>If you plan to eventually use the flash block handling feature (disabled in this example), you'll want to look at the <a href="../../demo/flashblock/" title="SoundManager 2 flash block handling demo">flash block demo</a> and include the relevant CSS it uses.</p>\r
+\r
+\r
+\r
+ <h4 id="basic-template">Basic SoundManager Template</h4>\r
+\r
+ <p>For a live example of a page including SoundManager 2, check the <a href="../../demo/template/" title="SoundManager 2 template example" onclick="checkDomain(this)">bare-bones template</a>.</p>\r
+ \r
+ <h4 id="file-structure">SoundManager File Structure</h4>\r
+ <p>Or, "What you get when you download SM2."</p>\r
+ <p>The core audio API bits require <code>script/soundmanager2.js</code> and the SWF files <code>swf/soundmanager2.swf</code> and <code>swf/soundmanager2_flash9.swf</code>, as well as the <code>_debug</code> versions of the SWFs. The flash 9 SWF enables some extra API features, and is only used if you set <code>soundManager.flashVersion = 9</code> (the default is 8.)</p>\r
+\r
+ <ul class="file-structure">\r
+ <li>\r
+ soundmanager2/\r
+ <ul>\r
+ <li>\r
+ demo/ <span>- Examples, MP3 player UIs etc.</span>\r
+ </li>\r
+ <li>\r
+ doc/ <span>- API method documentation, notes, troubleshooting</span>\r
+ </li>\r
+ <li class="core">\r
+ script/ <span>- API core, soundmanager2.js</span>\r
+ </li>\r
+ <li>\r
+ src/ <span>- AS2/AS3 Flash source used to build SWFs (for flash development)</span>\r
+ </li>\r
+ <li class="core">\r
+ swf/ <span>- API core, SoundManager 2 .SWF files</span>\r
+ </li>\r
+ <li>\r
+ troubleshoot/ <span>- Tool for finding/fixing startup issues</span>\r
+ </li>\r
+ </ul>\r
+ </li>\r
+ </ul>\r
+\r
+<h4 id="tech-architecture">How SoundManager 2 Really Works</h4>\r
+\r
+<p>SoundManager 2 is the result of Javascript talking to a hidden Flash movie. The Flash layer is not something you have to work with directly, but it is the component which makes audio control possible behind the scenes.</p>\r
+\r
+<div class="figure">\r
+\r
+ <div class="code">\r
+ <span>soundmanager2.js</span> <span class="mid"><- Flash + ExternalInterface, and/or HTML5 Audio() -></span> <span class="mid"><- HTTP -></span> <span>audio file</span>\r
+ </div>\r
+\r
+</div>\r
+\r
+<p>Flash can expose methods to Javascript via ExternalInterface, allowing bi-directional calls to be made and thus providing additional functionality to Javascript.</p>\r
+\r
+<p>For the real gory details on the behind-the-scenes action of JS + Flash, see <a href="http://www.schillmania.com/content/entries/2010/how-soundmanager2-works/" title="How SoundManager 2 works (JS + ExternalInterface + Flash)">How SoundManager 2 Works</a> on schillmania.com.</p>\r
+\r
+\r
+ </div>\r
+ \r
+ <div class="f-block f-onload">\r
+\r
+ <h4>Startup / Initialization</h4>\r
+ \r
+ <p>In brief, here is now SM2 starts up:</p>\r
+ <ul>\r
+ <li>soundmanager2.js loads</li>\r
+ <li>new SoundManager() constructor call, event listeners attached for dom ready/init</li>\r
+ <li>document.createElement('embed') (or 'object' for IE), append Flash .SWF to document</li>\r
+ <li>SWF loads, Flash makes call to JS function: "Hi, JS!"</li>\r
+ <li>JS -> Flash test (JS calls Flash function): "Hello, Flash!"</li>\r
+ <li>-- startup is complete, soundManager.onready() fires --</li>\r
+ </ul>\r
+ \r
+ <p class="in">A single Javascript include will link in all of the required code for the library, which will automatically begin loading either at <code>onDOMContentLoaded()</code> if supported, or alternately, after <code>window.onload()</code> (eg., IE 6 and others.) The default behaviour is to start "as soon as possible", but the library can be configured to wait for <code>window.onload()</code> in all cases as well. Loading and initialisation are separate events.</p>\r
+\r
+ <p class="in">Once initialised, SM2 will call event handlers/listeners registered via <code>soundManager.onready()</code>. There are also "old-skool" onload()/onerror() event handlers which you can define just as you would with <code>window.onload()</code>.</p>\r
+ \r
+ <p>If you want to lazy-load or defer SM2, see <a href="#lazy-loading" title="Lazy-loading SM2 and SM2_DEFER object">Lazy-loading and SM2_DEFER</a>.</p>\r
+ \r
+ <h4>SoundManager onready() / ontimeout() Event Handlers</h4>\r
+ \r
+ <p><code>onready()</code> is a flexible method that can be used to queue numerous listeners for SM2's successful start-up. Simply pass a callback function, which will be called when SM2 has successfully started:</p>\r
+\r
+<pre class="block"><code>soundManager.onready(function() {\r
+ <span><span>// SM2 is ready to go!</span></span>\r
+ makeSomeNoise(); <span><span>// soundManager.createSound(), etc.</span></span>\r
+});</code></pre>\r
+\r
+ <p><code>ontimeout()</code> is used to add listeners for SM2 init failures, which can happen due to missing or blocked Flash support. They are not necessarily fatal as in the flash block case, where <code>onready()</code> calls can follow <code>ontimeout()</code> if the user unblocks flash after a failed init attempt.</p>\r
+\r
+<pre class="block"><code>soundManager.ontimeout(function() {\r
+ <span><span>// SM2 could not start. Flash blocked, missing or security error? Complain, etc.?</span></span>\r
+});</code></pre>\r
+\r
+ <h4 id="lazy-loading">Lazy-loading / Dynamically-loading SM2 on-the-fly</h4>\r
+\r
+ <p>Let's say you wanted to load and start SM2 after your page has loaded, using JavaScript to insert a script node etc., or otherwise only start SM2 conditionally. You can load the library dynamically (at or after <code>DOMContentReady</code>), and it will not attempt to init until you call <code>setup()</code> with a <code>url</code> parameter.</p>\r
+ <p>Example:</p>\r
+ \r
+<pre class="block"><code>function loadSM2() {\r
+ <span><span>// -- load soundmanager2.js via <script>, createElement('script') or XHR etc. --\r
+ // imaginary loadJS() function with callback ...</span></span>\r
+ loadJS('<span>/path/to/soundmanager2.js</span>', function() {\r
+ <span><span>// once soundmanager2.js has loaded, call <a href="../#soundmanager-setup">soundManager.setup()</a>.</span></span>\r
+ soundManager.setup({\r
+ url: '<span>/path/to/swfs/</span>',\r
+ onready: function() {\r
+ <span><span>// soundManager.createSound() etc. here</span></span>\r
+ }\r
+ });\r
+ });\r
+}</code></pre>\r
+\r
+ <p>For a live demo, check out the <a href="../../demo/template/deferred-example.html" title="SoundManager 2 deferred loading example">deferred loading example</a>.</p>\r
+\r
+ </div>\r
+\r
+ \r
+ </div>\r
+ \r
+ </div>\r
+\r
+ <div class="columnar">\r
+\r
+ <div class="c1">\r
+ <h2>Sound Options Object Format</h2>\r
+ <p>Object Literal, JSON-style data passed to <code>createSound()</code> and <code>play()</code></p>\r
+ </div>\r
+\r
+ <div class="c2">\r
+\r
+ <div class="f-block s-onload"> <!-- f-createsound s-sid s-url s-autoload s-autoplay s-onload -->\r
+\r
+ <h3 id="object-literal-format">Object Literal Format</h3>\r
+\r
+ <p>Sounds can be created with instance-specific parameters in an object literal (JSON-style) format, where omitted parameters inherit default values as defined in soundManager.</p>\r
+\r
+<pre class="block"><code>soundManager.createSound({\r
+ id: '<span>mySound</span>',\r
+ url: '<span>/path/to/some.mp3</span>',\r
+ autoLoad: <span>true</span>,\r
+ autoPlay: <span>false</span>,\r
+ onload: <span>function() {\r
+ alert('<span>The sound </span>'+<span>this.id</span>+'<span> loaded!</span>');\r
+ }</span>,\r
+ volume: <span>50</span>\r
+});</code></pre>\r
+\r
+ <p>This object can also be passed as an optional argument to the <code class="in">play</code> method, overriding options set at creation time.</p>\r
+\r
+ <p>For a full list of available options, see <a href="../#sound-properties" title="SoundManager 2 API info: Sound Properties" onclick="resetFilter()">Sound Properties Object</a></p>\r
+\r
+ </div>\r
+\r
+\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ <div class="columnar">\r
+ <div class="c1">\r
+ <h2>"Use Responsibly"</h2>\r
+ <p>Only you can prevent audio pollution?</p>\r
+ </div>\r
+ \r
+ <div class="c2">\r
+ \r
+ <div class="f-block">\r
+\r
+ <h3>A Word Of Vice</h3>\r
+ <p>Not every button, link, element or paragraph on the web needs to zoom, move, change colour <em>and</em> be noisy, repetitive and annoying all at the same time. Use your own discretion!</p>\r
+ <p>Sites which automatically start playing background sound, and/or don't have volume or mute controls are the kind of things you should avoid building. As a developer, gentle reader, you may eventually find yourself in such a situation. Please do your part in enhancing the web with sound if you use SM2, while at the same time keeping it audibly usable. :)</p>\r
+\r
+ </div>\r
+ \r
+ </div>\r
+\r
+ </div>\r
+ \r
+ <div id="troubleshooting" class="columnar">\r
+\r
+ <div id="troubleshooting-flash8" class="c1">\r
+ <h2 id="troubleshooting-flash9">Troubleshooting</h2>\r
+ <p>Console-style messaging, useful for troubleshooting start-up and runtime issues.</p>\r
+ </div>\r
+ \r
+ <div id="troubleshooting-flash9-highperformance" class="c2">\r
+\r
+ <h3>SoundManager 2 Start-up and Debug Tools</h3>\r
+ <p>This troubleshooting tool can come in handy for debugging SM2 start-up problems, when Flash support is required.</p>\r
+\r
+ <p class="note">Flash options: <a href="#troubleshooting-flash8" onclick="window.location.replace(this.href);window.location.reload()">Flash 8</a> (default), <a href="#troubleshooting-flash9" onclick="window.location.replace(this.href);window.location.reload()">Flash 9</a> (normal) or <a href="#troubleshooting-flash9-highperformance" onclick="window.location.replace(this.href);window.location.reload()">Flash 9 + highPerformance + fastPolling</a> modes.</p>\r
+\r
+ <div id="sm2-test">\r
+ <ul class="items">\r
+\r
+ <li id="d-onload" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">FAIL</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>SoundManager 2 start-up</span></h3>\r
+ <div id="sm2-startup" class="details">\r
+ <p>soundManager onready() or ontimeout() events are ultimately called when start-up completes.</p>\r
+ <p>If you're seeing a failure, refer to the below for troubleshooting details for common causes.</p>\r
+ </div>\r
+ </li>\r
+\r
+ <li id="d-hasflash" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>Flash</span></h3>\r
+ <div class="details">\r
+ <p>Flash 8 or 9 may be required for SoundManager 2 to start, depending on HTML5 support. You are currently using <b id="d-flashversion">[unknown]</b>.</p>\r
+ </div>\r
+ </li>\r
+\r
+ <li id="d-swf" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>Flash SWF</span></h3>\r
+ <div class="details">\r
+ <p>SoundManager 2 must load a flash movie before initialisation can proceed. If you have errors here, check that soundManager.url is correctly defined and that the URL being loaded is correct.</p>\r
+ <p>If the Flash movie URL is OK, Flash security or flash blockers are the likely cause. Check the section below.</p>\r
+ </div>\r
+ </li>\r
+\r
+ <li id="d-flashtojs" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>Flash -> JS</span></h3>\r
+ <div class="details">\r
+ <p>Once the flash component of SM2 has loaded, it tries to make a call to Javascript-land. This is a common point of failure, for security reasons.</p>\r
+ <ul>\r
+ <li>\r
+ <p><b>Have a flash blocker?</b> Check that the <a href="#flashdebug">SM2 flash movie</a> (below) is loading and is not being blocked.</p>\r
+ </li>\r
+ <li>\r
+ First time opening SM2 after downloading it? Is your browser URL at file:// or c:/path/ or otherwise not using HTTP? Flash security "whitelisting" is required to allow Flash + JS to work when offline, placing it in the "LocalTrusted" Flash security sandbox rather than "localWithFile".\r
+ \r
+ <div id="d-flashtojs-offline" style="padding-bottom:1em">\r
+ <h4>Offline viewing: Adding a "trusted location" to the Flash Security Settings Panel</h4>\r
+ <p>The Flash Player Global Security Settings Panel is a web-based control panel which allows you to configure Flash security. You will need to add the path of the SoundManager 2 project in order for it to work "offline" (ie., when viewing via file:// or c:/)</p>\r
+ <p id="ss"><a href="#screenshots" onclick="document.getElementById('ss-box').style.display = 'block';document.getElementById('ss').style.display='none';return false">Show me how</a>: Adding a "trusted location"</p>\r
+ <div id="ss-box" style="display:none">\r
+ <h4>Illustrated guide: Adding a "trusted location" in Flash</h4>\r
+ <p>Below: Adding a location, and selecting "Browse for folder" (or directory), to whitelist the SoundManager 2 project directory for offline viewing.</p>\r
+ <p><img src="../../troubleshoot/fpgss-add-location.png" alt="Adding a location: Browse for the file or directory to whitelist" style="width:100%;_width:auto;min-width:72px;max-width:396px" /></p>\r
+ <p><img src="../../troubleshoot/fpgss-added-location.png" alt="Whitelisted location has now been added, JS + Flash will work under this path" style="width:100%;_width:auto;min-width:72px;max-width:396px" /></p>\r
+ </div>\r
+ <p><a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html" target="_blank" class="feature">Launch the Flash Security Settings Panel</a></p>\r
+ </div>\r
+ \r
+ </li>\r
+ <li style="margin-top:0.5em">Flash blockers (FlashBlock, "click to flash" etc.) preventing flash load and start-up - need whitelisting/"allow this domain" to work smoothly. If you suspect blocking is the issue, try the <a href="../../demo/flashblock/">SoundManager 2 Flashblock demo</a>.</li>\r
+ <li style="margin-top:0.5em">Online viewing (HTTP/S): Same-domain security rules apply to HTML + Flash content by default (crossdomain.xml/allowDomain() in .AS source required to override.)</li>\r
+ </ul>\r
+ <p>See <a href="#flashdebug" title="SoundManager 2 flash debug output">Flash debug output</a> for more security error details.</p>\r
+\r
+ <div id="d-flashtojs-online">\r
+ <h4>Online viewing: Cross-domain security restrictions</h4>\r
+ <p>HTML page on domain A loading .SWF from domain B: Flash security prevents JS + Flash when a cross-domain XML permission file is not available on domain B, and/or flash movie was not compiled with allowDomain('domainA') or allowDomain('*') - note that the SWF distributed with SM2 does not use this by default; try using the cross-domain version of the SWF, or compile your own which whitelists your own domain(s).</p>\r
+\r
+ <h4>Flash Blockers</h4>\r
+ <p>Browser extensions/add-ons like "FlashBlock" and "click to flash" can prevent the .SWF from loading, and this will mean SM2 will time-out and fail waiting for a response from Flash. For development, it's best to whitelist the domain(s) or the .SWF for SM2 to allow it to work.</p>\r
+ <p>Have a flash blocker installed? Want to test it? Try the <a href="../../demo/flashblock">SoundManager 2 Flashblock demo</a>.</p>\r
+\r
+ </div>\r
+\r
+ </div>\r
+ </li>\r
+\r
+ <li id="d-jstoflash" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>JS -> Flash</span></h3>\r
+ <div class="details">\r
+ <p>At this point, Javascript attempts to respond to Flash's initial outgoing Flash -> JS call, completing the test for JS/flash communication. If SM2 does not receive a response from flash, it will eventually fail.</p>\r
+ <p>Offline viewing conditions and cross-domain security rules will prevent Flash <-> JS communication. See the details of Flash -> JS for information.</p>\r
+ <p><b>Special Firefox Note</b>: Some versions of Firefox (9.0 and newer?) may break JS/Flash in the file:// or offline case even when the path has been whitelisted in the Flash player security settings panel. IE, Chrome, Safari and Opera do not have this issue.</p>\r
+ </div> \r
+ </li>\r
+\r
+ <li id="d-soundtest" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>Sound test</span></h3>\r
+ <div class="details">\r
+ <p>Here, a simple createSound() call is made to test SM2's actual operation. A sound should load and play provided SM2 was able to start successfully.</p>\r
+ </div>\r
+ </li>\r
+\r
+ </ul>\r
+ </div>\r
+ \r
+ <p>Flash detection code from <a href="http://www.featureblend.com/javascript-flash-detection-library.html" title="Javascript flash detection library">Flash Detect</a> (featureblend.com)</p>\r
+\r
+ <h3 id="flashdebug">Flash Movie Debug Output</h3>\r
+ <p>When <code>soundManager.debugFlash = true</code>, Flash will write debug info as text to the flash movie. This can be helpful for troubleshooting Flash/JS issues when timeouts or security errors are involved which prevent Flash from talking to Javascript, potentially hiding useful debug information. A CSS class of <code>flash_debug</code> will also be appended to the Flash <code>#sm2-container</code> DIV element when enabled, if you wish to style it differently.</p>\r
+ <p>You can also specify ?debug=1 in the URL to the SWF, and it will write debug output. Try <a href="../../swf/soundmanager2_debug.swf?debug=1" title="Test debug output" class="norewrite">soundmanager2_debug.swf?debug=1</a>, or <a href="../../swf/soundmanager2_flash9_debug.swf?debug=1" title="Test debug output, Flash 9" class="norewrite">soundmanager2_flash9_debug.swf?debug=1</a>.</p>\r
+\r
+ <div id="sm2-container">\r
+ <!-- flash movie with debug output goes here -->\r
+ </div>\r
+\r
+ <h3>Live Debug Output</h3>\r
+ <p>SoundManager 2 relies on Javascript and Flash communicating via ExternalInterface, and this is subject to a number of timing, loading and browser security conditions. Because of this complexity, debug information is essential for troubleshooting start-up, loading, initialization and error conditions between Flash and Javascript.</p>\r
+ <p class="in">With debug mode enabled via <code>debugMode = true</code>, SM2 can write helpful troubleshooting information to javascript <code>console.log()</code>-style interfaces. Additionally, output can be written to an optional DIV element with the ID of "<code>soundmanager-debug</code>".</p>\r
+ <p>If loading from the local filesystem (offline eg. file://, not over HTTP), Flash security is likely preventing SM2 from talking to Javascript. You will need to add this project's directory to the trusted locations in the <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html">Flash global security settings panel</a>, or simply view this page over HTTP.</p>\r
+ <p>Below is a live example of debug output.</p>\r
+ <div id="live-debug" class="block">\r
+ <div id="soundmanager-debug" class="code">\r
+ <!-- live debug goes here -->\r
+ </div>\r
+ </div>\r
+ <p>For more examples of live debug output, see the <a href="../../demo/template/" title="Basic SoundManager 2 template">Basic Template</a>, <a href="../../demo/api/" title="API demo">API demo</a> and other demos in the top navigation.</p>\r
+\r
+ <h3>Standalone version of troubleshooting tool</h3>\r
+ <p class="in">For debugging your development/production environment with this widget, see the <a href="../../troubleshoot/" title="SoundManager 2: Standalone debug widget">troubleshooting</a> subdirectory of the SoundManager 2 package.</p>\r
+\r
+ </div>\r
+ \r
+ </div>\r
+\r
+ <div id="col3" class="c3">\r
+\r
+ <div id="support-wrapper">\r
+ <div id="get-satisfaction" class="box">\r
+ <div id="gsfn_list_widget">\r
+ <h2><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/" title="User discussion, FAQs and support for SoundManager 2" rel="nofollow">Discussion / Support</a><span class="l"></span><span class="r"></span></h2>\r
+ <div id="gsfn_content"></div>\r
+ <div class="powered_by"><a href="http://getsatisfaction.com/" rel="nofollow">Get Satisfaction support network</a></div>\r
+ </div>\r
+ <!-- /.box -->\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="shortcuts">\r
+\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ <div class="clear"></div>\r
+\r
+ <!-- /main -->\r
+ </div>\r
+\r
+ <!-- /main-wrapper -->\r
+ </div>\r
+\r
+ <!-- /content -->\r
+ </div>\r
+\r
+<script type="text/javascript">\r
+init();\r
+sm2DebugInit();\r
+</script>\r
+ \r
+</body>\r
+\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Documentation</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="API documentation for SoundManager 2, a JavaScript-based MP3 and MP4 audio API. BSD licensed." />\r
+<meta name="keywords" content="javascript sound, javascript audio, documentation, api documentation, soundmanager 2" />\r
+<meta name="robots" content="all" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta name="copyright" content="Copyright (C) 1997 onwards Scott Schiller" />\r
+<meta name="language" content="en-us" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="../demo/index.css" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="../demo/flashblock/flashblock.css" />\r
+<script type="text/javascript" src="../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="../demo/index.js"></script>\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ useFlashBlock: false,\r
+ debugMode: false,\r
+ url: '../swf/'\r
+});\r
+</script>\r
+</head>\r
+\r
+<body id="doc" class="special">\r
+ \r
+<div id="content">\r
+\r
+ <div id="top">\r
+\r
+ <h1>SoundManager 2: Documentation</h1>\r
+\r
+ <div id="nav">\r
+ <ul>\r
+\r
+ <li>\r
+ <a href="..">Home</a>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="#">Demos</a>\r
+ <ul>\r
+ <li><a href="../demo/template/">Basic Template</a></li>\r
+ <li><a href="../demo/api/">API Examples</a></li>\r
+ <li><a href="../demo/bar-ui/">Bar UI</a></li>\r
+ <li><a href="../demo/play-mp3-links/" class="exclude">Playable MP3 links</a></li>\r
+ <li><a href="../demo/mp3-player-button/" class="exclude">Basic MP3 Play Button</a></li>\r
+ <li><a href="../demo/page-player/">Muxtape-style UI</a></li>\r
+ <li><a href="../demo/360-player/">360° Player UI</a></li>\r
+ <li><a href="../demo/mpc/">Drum Machine (MPC)</a></li>\r
+ <li><a href="../demo/animation/">DOM/Animation Demos</a></li>\r
+ <li><a href="../demo/flashblock/">FlashBlock Handling</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="getstarted/">Getting Started</a>\r
+ <ul>\r
+ <li><a href="getstarted/#how-sm2-works">How SoundManager 2 works</a></li>\r
+ <li><a href="getstarted/#basic-inclusion">Including SM2 on your site</a></li>\r
+ <li><a href="getstarted/#troubleshooting">Troubleshooting</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <strong><a href="#">Documentation</a></strong>\r
+ <ul>\r
+ <li><a href="#sm-config">SoundManager Properties</a></li>\r
+ <li><a href="#sound-object-properties">Sound Object Properties</a></li>\r
+ <li><a href="#smdefaults">Global Sound Defaults</a></li>\r
+ <li><a href="#api">SoundManager Core API</a></li>\r
+ <li><a href="#smsoundmethods">Sound Object (SMSound) API</a></li>\r
+ <li><a href="generated/soundmanager2.html">Generated Documentation</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <a href="download/">Download</a>\r
+ <ul>\r
+ <li><a href="download/#latest">Get SoundManager 2</a></li>\r
+ <li><a href="download/#revision-history">Revision History</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <a href="technotes/">Technical Notes</a>\r
+ <ul>\r
+ <li><a href="technotes/#requirements">System Requirements</a></li>\r
+ <li><a href="technotes/#serving-audio">Serving To HTML5 + Flash Clients</a></li>\r
+ <li><a href="technotes/#client-requests">How Clients Download Audio</a></li>\r
+ <li><a href="technotes/#mobile-device-limitations">Mobile Device Limitations</a></li>\r
+ <li><a href="technotes/#debug-output">Debug + Console Output</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="resources/">Resources</a>\r
+ <ul>\r
+ <li><a href="resources/#licensing">Licensing</a></li>\r
+ <li><a href="resources/#related">Related Projects</a></li>\r
+ <li><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/">SM2 support / discussion</a></li>\r
+ <li><a href="http://www.schillmania.com/content/react/contact/">Contact Info @ Schillmania.com</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ <div class="clear"></div>\r
+ </div>\r
+ \r
+ </div>\r
+\r
+ <div id="main-wrapper">\r
+\r
+ <div id="main" class="triple">\r
+\r
+ <div id="col3" class="c3">\r
+ \r
+ <!--\r
+ <div id="get-satisfaction" class="box">\r
+ <div id="gsfn_list_widget">\r
+ <h2><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/" title="User discussion, FAQs and support for SoundManager 2" rel="nofollow">Discussion / Support</a><span class="l"></span><span class="r"></span></h2>\r
+ <div id="gsfn_content"></div>\r
+ <div class="powered_by"><a href="http://getsatisfaction.com/" rel="nofollow">Get Satisfaction support network</a></div>\r
+ </div>\r
+ </div>\r
+ -->\r
+\r
+ <div id="shortcuts">\r
+\r
+<!--\r
+ <div class="box">\r
+\r
+ <h2>Shortcuts<span class="l"></span><span class="r"></span></h2>\r
+\r
+ <ul class="first">\r
+ <li onclick="setFilter(event,'c-')" class="ignore">\r
+\r
+ <ul>\r
+\r
+ <li>Demos</li>\r
+ <li>Getting Started</li>\r
+ <li>Basic Use</li>\r
+ <li>Download</li>\r
+ <li>Requirements</li>\r
+ <li>Limitations</li>\r
+\r
+ <li>Debug Output</li>\r
+ <li>Revision History</li>\r
+ <li>About</li>\r
+ </ul>\r
+\r
+ </li>\r
+ </ul>\r
+\r
+ </div>\r
+-->\r
+ \r
+ <div class="box">\r
+\r
+ <h2>API Elements<span class="l"></span><span class="r"></span></h2>\r
+\r
+ <p>SoundManager and SMSound API</p>\r
+\r
+ <ul id="shortcuts-list" class="first">\r
+ <li onclick="return setFilter(event,'f-')" class="ignore">\r
+\r
+ <h3 class="wedge">SoundManager<span class="l"></span><span class="r"></span></h3>\r
+ \r
+ <h4>Properties</h4>\r
+ <ul>\r
+ <li>allowScriptAccess</li>\r
+ <li><a href="#soundmanager-alturl">altURL</a></li>\r
+ <li><a href="#soundmanager-audioformats">audioFormats</a></li>\r
+ <li><a href="#soundmanager-bgcolor">bgColor</a></li>\r
+ <li>consoleOnly</li>\r
+ <li><a href="#soundmanager-debugflash">debugFlash</a></li>\r
+ <li><a href="#soundmanager-debugmode">debugMode</a></li>\r
+ <li><a href="#smdefaults">defaultOptions</a></li>\r
+ <li class="flash9" title="Flash 9-only"><a href="#sound-properties-flash9">flash9Options</a></li>\r
+ <li><a href="#soundmanager-features">features</a></li>\r
+ <li><a href="#soundmanager-flashloadtimeout">flashLoadTimeout</a></li>\r
+ <li class="flash9" title="Flash 9+ only"><a href="#soundmanager-flashpollinginterval">flashPollingInterval</a></li>\r
+ <li><a href="#soundmanager-flashversion">flashVersion</a></li>\r
+ <li><a href="#soundmanager-forceuseglobalhtml5audio" class="new" title="New for V2.97a.20150601">forceUseGlobalHTML5Audio</a></li>\r
+ <li><a href="#soundmanager-html5only">html5Only</a></li>\r
+ <li><a href="#soundmanager-html5pollinginterval">html5PollingInterval</a></li>\r
+ <li class="new" title="New for V2.97a.20150601"><a href="#soundmanager-ignoremobilerestrictions">ignoreMobileRestrictions</a></li>\r
+ <li class="flash9" title="Flash 9.0r115+ only"><a href="#sound-properties-flash9">movieStarOptions</a></li>\r
+ <li><a href="#soundmanager-preferflash">preferFlash</a></li>\r
+ <li><a href="#soundmanager-url">url</a></li>\r
+ <li>useConsole</li>\r
+ <li class="flash9" title="Flash 9+ only"><a href="#soundmanager-usefastpolling">useFastPolling</a></li>\r
+ <li><a href="#soundmanager-useflashblock">useFlashBlock</a></li>\r
+ <li><a href="#soundmanager-highperformance">useHighPerformance</a></li>\r
+ <li title="Beta-ish feature"><a href="#soundmanager-usehtml5audio">useHTML5Audio</a></li>\r
+ <li class="flash9" title="Flash 9.0r115+ only"><a href="#soundmanager-wmode">wmode</a></li>\r
+ <li>waitForWindowLoad</li>\r
+ </ul>\r
+\r
+ <h4>Methods</h4>\r
+ <ul>\r
+ <li><a href="#soundmanager-canplaylink">canPlayLink()</a></li>\r
+ <li><a href="#soundmanager-canplaymime">canPlayMIME()</a></li>\r
+ <li><a href="#soundmanager-canplayurl">canPlayURL()</a></li>\r
+ <li><a href="#soundmanager-clearonposition">clearOnPosition()</a></li>\r
+ <li><a href="#soundmanager-createsound">createSound()</a></li>\r
+ <li><a href="#soundmanager-destroysound">destroySound()</a></li>\r
+ <li class="flash9" title="Flash 9.0+ only"><a href="#soundmanager-getmemoryuse">getMemoryUse()</a></li>\r
+ <li><a href="#soundmanager-getsoundbyid">getSoundById()</a></li>\r
+ <li><a href="#soundmanager-load">load()</a></li>\r
+ <li><a href="#soundmanager-mute">mute()</a></li>\r
+ <li><a href="#soundmanager-ok">ok()</a></li>\r
+ <li><a href="#soundmanager-onposition">onPosition()</a></li>\r
+ <li><a href="#soundmanager-pause">pause()</a></li>\r
+ <li><a href="#soundmanager-pauseall">pauseAll()</a></li>\r
+ <li><a href="#soundmanager-play">play()</a></li>\r
+ <li><a href="#soundmanager-reboot">reboot()</a></li>\r
+ <li class="new"><a href="#soundmanager-reset" title="New feature">reset()</a></li>\r
+ <li><a href="#soundmanager-resume">resume()</a></li>\r
+ <li><a href="#soundmanager-resumeall">resumeAll()</a></li>\r
+ <li class="recent"><a href="#soundmanager-setup" title="Recently-added feature">setup()</a></li>\r
+ <li><a href="#soundmanager-setpan" title="Flash-only feature">setPan()</a></li>\r
+ <li><a href="#soundmanager-setposition">setPosition()</a></li>\r
+ <li><a href="#soundmanager-setvolume">setVolume()</a></li>\r
+ <li><a href="#soundmanager-supported">supported()</a></li>\r
+ <li><a href="#soundmanager-stop">stop()</a></li>\r
+ <li><a href="#soundmanager-stopall">stopAll()</a></li>\r
+ <li><a href="#soundmanager-togglemute">toggleMute()</a></li>\r
+ <li><a href="#soundmanager-togglepause">togglePause()</a></li>\r
+ <li><a href="#soundmanager-unload">unload()</a></li>\r
+ <li><a href="#soundmanager-unmute">unmute()</a></li>\r
+ </ul>\r
+\r
+ <h4>Events (Callbacks)</h4>\r
+ <ul>\r
+ <li><a href="#soundmanager-onready">onready()</a></li>\r
+ <li><a href="#soundmanager-ontimeout">ontimeout()</a></li>\r
+ </ul>\r
+\r
+ </li>\r
+\r
+ <li onclick="setFilter(event,'s-')" class="ignore">\r
+\r
+ <h3 class="wedge">SMSound <span class="archive">(Sound Object)</span><span class="l"></span><span class="r"></span></h3>\r
+\r
+ <h4>Parameters (Instance Options)</h4>\r
+ <ul>\r
+ <li>autoLoad</li>\r
+ <li>autoPlay</li>\r
+ <li title="Flash 9.0r115+ only" class="flash9">bufferTime</li>\r
+ <li title="Flash 9+ only" class="flash9"><a href="#smsound-eqdata">eqData</a></li>\r
+ <li><a href="#smsound-from">from</a></li>\r
+ <li><a href="#smsound-id">id</a></li>\r
+ <li title="Flash 9.0r115+ only" class="flash9">isMovieStar</li>\r
+ <li>loops</li>\r
+ <li>multiShot</li>\r
+ <li>multiShotEvents</li>\r
+ <li>pan</li>\r
+ <li title="Flash 9+ only" class="flash9"><a href="#smsound-peakdata">peakData</a></li>\r
+ <li><a href="#smsound-position">position</a></li>\r
+ <li title="Flash 9+ only" class="flash9"><a href="#smsound-serverurl">serverURL</a></li>\r
+ <li>stream</li>\r
+ <li><a href="#smsound-to">to</a></li>\r
+ <li><a href="#smsound-type">type</a></li>\r
+ <li><a href="#smsound-url">url</a></li>\r
+ <li><a href="#smsound-usepolicyfile">usePolicyFile</a></li>\r
+ <li>volume</li>\r
+ <li title="Flash 9+ only" class="flash9"><a href="#smsound-waveformdata">waveformData</a></li>\r
+ </ul>\r
+\r
+ <h4>Dynamic Properties</h4>\r
+ <ul>\r
+ <li><a href="#smsound-buffered">buffered</a></li>\r
+ <li><a href="#smsound-bytesloaded">bytesLoaded</a></li>\r
+ <li><a href="#smsound-bytestotal">bytesTotal</a></li>\r
+ <li title="Flash 9+ only" class="flash9"><a href="#smsound-isbuffering">isBuffering</a></li>\r
+ <li title="Flash 9+ only" class="flash9"><a href="#smsound-connected">connected</a></li>\r
+ <li><a href="#smsound-duration">duration</a></li>\r
+ <li><a href="#smsound-durationestimate">durationEstimate</a></li>\r
+ <li><a href="#smsound-ishtml5">isHTML5</a></li>\r
+ <li><a href="#smsound-loaded">loaded</a></li>\r
+ <li><a href="#smsound-muted">muted</a></li>\r
+ <li><a href="#smsound-paused">paused</a></li>\r
+ <li><a href="#smsound-playstate">playState</a></li>\r
+ <li><a href="#smsound-position">position</a></li>\r
+ <li><a href="#smsound-readystate">readyState</a></li>\r
+ </ul>\r
+\r
+ <h4>Events</h4>\r
+ <ul>\r
+ <li title="Flash 9+ only" class="flash9"><a href="#smsound-onbufferchange">onbufferchange</a></li>\r
+ <li title="Flash 9+ only" class="flash9"><a href="#smsound-onconnect">onconnect</a></li>\r
+ <li title="Flash 9.0.r115+" class="flash9"><a href="#smsound-ondataerror">ondataerror</a></li>\r
+ <li><a href="#smsound-onfinish">onfinish</a></li>\r
+ <li><a href="#smsound-onload">onload</a></li>\r
+ <li><a href="#smsound-onpause">onpause</a></li>\r
+ <li><a href="#smsound-onplay">onplay</a></li>\r
+ <!--\r
+ <li><a href="#smsound-onposition-event">onposition</a></li>\r
+ -->\r
+ <li><a href="#smsound-onresume">onresume</a></li>\r
+ <li title="HTML5 only"><a href="#smsound-onsuspend">onsuspend</a></li>\r
+ <li><a href="#smsound-onstop">onstop</a></li>\r
+ <li><a href="#smsound-onid3">onid3</a></li>\r
+ <li><a href="#smsound-whileloading">whileloading</a></li>\r
+ <li><a href="#smsound-whileplaying">whileplaying</a></li>\r
+ </ul>\r
+\r
+ <h4>Methods</h4>\r
+ <ul>\r
+ <li><a href="#smsound-destruct">destruct()</a></li>\r
+ <li><a href="#smsound-load">load()</a></li>\r
+ <li><a href="#smsound-clearonposition">clearOnPosition()</a></li>\r
+ <li><a href="#smsound-onposition">onPosition()</a></li>\r
+ <li><a href="#smsound-mute">mute()</a></li>\r
+ <li><a href="#smsound-pause">pause()</a></li>\r
+ <li><a href="#smsound-play">play()</a></li>\r
+ <li><a href="#smsound-resume">resume()</a></li>\r
+ <li><a href="#smsound-setpan">setPan()</a></li>\r
+ <li><a href="#smsound-setposition">setPosition()</a></li>\r
+ <li><a href="#smsound-setvolume">setVolume()</a></li>\r
+ <li><a href="#smsound-stop">stop()</a></li>\r
+ <li><a href="#smsound-togglemute">toggleMute()</a></li>\r
+ <li><a href="#smsound-togglepause">togglePause()</a></li>\r
+ <li><a href="#smsound-unload">unload()</a></li>\r
+ <li><a href="#smsound-unmute">unmute()</a></li>\r
+ </ul>\r
+\r
+ </li>\r
+ </ul>\r
+ \r
+ <!-- /.box -->\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ <div class="clear"></div>\r
+\r
+\r
+ <div id="filter-box" class="columnar">\r
+\r
+ <div class="c1">\r
+ <div id="reset-filter"></div>\r
+ </div>\r
+\r
+ <div class="c2">\r
+ <div id="search-results"><!-- search results for %s --></div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="soundmanager-properties" class="columnar">\r
+\r
+ <div class="c2">\r
+\r
+ <h3 id="soundmanager-setup">SoundManager Properties: soundManager.setup()</h3>\r
+\r
+ <p>\r
+ Just getting started? See <a href="getstarted/#basic-inclusion">the basics</a>. For nicely-formatted, annotated source code, see the <a href="generated/soundmanager2.html">pretty-printed version</a>.\r
+ </p>\r
+\r
+ <div class="f-block f-useconsole f-consoleonly f-waitforwindowload f-allowscriptaccess f-bgcolor f-setup">\r
+\r
+ <p class="in">The soundManager object has many configurable properties which set debug mode, determine the flash movie path and other behaviours.</p>\r
+ \r
+ <p>When configuring soundManager for your use, <code>soundManager.setup()</code> is the method used to assign these options; for example, <code>soundManager.setup({ url: '/path/to/swfs/', flashVersion: 9 });</code></p>\r
+\r
+ <p>You should call the setup method before "DOM Ready", which is when SM2 applies configuration and starts up.</p>\r
+\r
+ <p>Below are the <i>default</i> settings for SoundManager 2, which are appropriate for the majority of use cases - you shouldn't need to change them. These parameters are defined and stored in <code>soundManager.setupOptions</code>.</p>\r
+\r
+ <p><b>Note</b>: The only property requiring customization is <code>url</code> - this defines the path used to look for the appropriate flash SWF for driving audio when HTML5 is not available. (If not specified, the current working path is used.) Aside from flash-specific items like <code>url</code> and <code>flashVersion</code>, most properties can be set after "DOM Ready" without issue.</p>\r
+\r
+<div id="sm2-properties" class="small code block">\r
+\r
+ <ul class="code code-block">\r
+\r
+ <li>\r
+ <div>url: '<em>/path/to/swf-files/</em>',</div>\r
+ <span>// the directory where SM2 can find the flash movies (soundmanager2.swf, soundmanager2_flash9.swf and debug versions etc.) Note that SM2 will append the correct SWF file name, depending on flashVersion and debugMode settings.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>allowScriptAccess: '<em>always</em>',</div>\r
+ <span>// for scripting the SWF (object/embed property), 'always' or 'sameDomain'</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>bgColor: '<em>#ffffff</em>',</div>\r
+ <span>// SWF background color. N/A when wmode = 'transparent'</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>consoleOnly: <em>true</em>,</div>\r
+ <span>// if console is being used, do not create/write to #soundmanager-debug</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>debugMode: <em>true</em>,</div>\r
+ <span>// enable debugging output (console.log() with HTML fallback)</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>debugFlash: <em>false</em>,</div>\r
+ <span>// enable debugging output inside SWF, troubleshoot Flash/browser issues</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>flashVersion: <em>8</em>,</div>\r
+ <span>// flash build to use (8 or 9.) Some API features require 9.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>flashPollingInterval: <em>null</em>,</div>\r
+ <span>// msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>forceUseGlobalHTML5Audio: <em>false</em>,</div>\r
+ <span>// if true, a single Audio() object is used for all sounds - and only one can play at a time.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>html5PollingInterval: <em>null</em>,</div>\r
+ <span>// msec affecting whileplaying/loading callback frequency. If null, native HTML5 update events are used.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>html5Test: <em>/^(probably|maybe)$/i</em>,</div>\r
+ <span>// HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>flashLoadTimeout: <em>1000</em>,</div>\r
+ <span>// msec to wait for flash movie to load before failing (0 = infinity)</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>idPrefix: <em>'sound'</em>,</div>\r
+ <span>// if an id is not provided to createSound(), this prefix is used for generated IDs - 'sound0', 'sound1' etc.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>ignoreMobileRestrictions: <em>false</em>,</div>\r
+ <span>// if true, SM2 will not apply global HTML5 audio rules to mobile UAs. iOS > 7 and WebViews may allow multiple Audio() instances.</span>\r
+ </li>\r
+ \r
+ <li>\r
+ <div>noSWFCache: <em>false</em>,</div>\r
+ <span>// if true, appends ?ts={date} to break aggressive SWF caching.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>preferFlash: <em>true</em>,</div>\r
+ <span>// overrides useHTML5audio. if true and flash support present, will try to use flash for MP3/MP4 as needed. Useful if HTML5 audio support is quirky.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>useConsole: <em>true</em>,</div>\r
+ <span>// use console.log() if available (otherwise, writes to #soundmanager-debug element)</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>useFlashBlock: <em>false</em>,</div>\r
+ <span>// requires flashblock.css, <a href="../demo/flashblock/" title="SoundManager 2: Flash blocking demos">see demos</a> - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>useHighPerformance: <em>false</em>,</div>\r
+ <span>// position:fixed flash movie can help increase js/flash speed, minimize lag</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>useHTML5Audio: <em>true</em>,</div>\r
+ <span>// use <a href="#soundmanager-usehtml5audio">HTML5 Audio()</a> where supported. Some browsers may not support "non-free" MP3/MP4/AAC codecs. Ideally, transparent vs. Flash API where possible.</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>waitForWindowLoad: <em>false</em>,</div>\r
+ <span>// force SM2 to wait for window.onload() before trying to call soundManager.onready()</span>\r
+ </li>\r
+\r
+ <li>\r
+ <div>wmode: <em>null</em></div>\r
+ <span>// flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index)</span>\r
+ </li>\r
+\r
+\r
+ </ul>\r
+\r
+</div>\r
+\r
+ <p><b>Legacy support note:</b> The new approach defines top-level properties in <code>soundManager.setupOptions</code>. The old approach was to assign properties directly to the soundManager instance. Thus, when <code>soundManager.setup({ url: ... });</code> is called, the updated property value is assigned to both <code>soundManager.setupOptions.url</code> <i>and</i> <code>soundManager.url</code>. You can assign <code>soundManager.url</code> directly as with the old method, but it is recommended to use the new <code>setup()</code>-based method for forward compatibility.</p>\r
+\r
+<div id="sm2-setup-extra-properties">\r
+\r
+ <h4>Bonus: Extended soundManager.setup() Parameters</h4>\r
+\r
+ <p>As it is common to configure soundManager properties and related events all at once, you can also pass <code>onready</code> and <code>ontimeout</code> parameters which will be called as if you had used <code>soundManager.onready()</code> and <code>soundManager.ontimeout()</code>.</p>\r
+\r
+ <p>You can also provide values from the following top-level soundManager properties:</p>\r
+\r
+ <ul>\r
+ <li><code>defaultOptions: {...}</code> (global defaults for new sound objects)</li>\r
+ <li><code>flash9Options: {...}</code> (API feature options specific to Flash 9)</li>\r
+ <li><code>movieStarOptions: {...}</code> (Flash 9-only NetStream/RTMP-specific options)</li>\r
+ </ul>\r
+ \r
+<pre class="block"><code>soundManager.setup({\r
+ url: <span>'/path/to/swfs/'</span>,\r
+ flashVersion: <span>9</span>,\r
+ preferFlash: <span>false</span>, <span><span>// prefer 100% HTML5 mode, where both supported</span></span>\r
+ onready: function() {\r
+ <span><span>// console.log('SM2 ready!');</span></span>\r
+ },\r
+ ontimeout: function() {\r
+ <span><span>// console.log('SM2 init failed!');</span></span>\r
+ },\r
+ defaultOptions: {\r
+ <span><span>// set global default volume for all sound objects</span></span>\r
+ volume: <span>33</span>\r
+ }\r
+});</code></pre>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="f-block f-debugflash">\r
+ <h4 id="soundmanager-debugflash">debugFlash</h4>\r
+ <p class="in"><code>soundManager.debugFlash</code> configures SM2's flash debugging output, disabled (false) by default. When enabled, the Flash portion of SM2 will write debug statements within the Flash movie. This can be useful for troubleshooting Flash/JS/browser (ExternalInterface) issues and so on.</p>\r
+ <p>A CSS class of <code>flash_debug</code> will also be appended to the Flash <code>#sm2-container</code> DIV element when enabled, if you wish to style it differently.</p>\r
+ <p>For a live example, see <a href="getstarted/#flashdebug" title="SoundManager 2 flash debug output demo">Flash Movie Debug Output</a> in the Troubleshooting section.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-debugmode">\r
+ <h4 id="soundmanager-debugmode">debugMode</h4>\r
+ <p class="in"><code>soundManager.debugMode</code> configures SM2's debug behaviour, enabled (true) by default. When enabled, SoundManager 2 will write console-like output to <code>console.log()</code>-style javascript interfaces, and/or an HTML element with the ID <code>soundmanager-debug</code> (will be created if not found in the DOM at runtime.)</p>\r
+ <p>For a live example of debug output, see <a href="technotes/#debug-output" title="SoundManager 2 debug output demo">Debug + Console Output</a>.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-flashversion">\r
+\r
+ <h4 id="soundmanager-flashversion">flashVersion</h4>\r
+\r
+ <p class="in">SoundManager 2 started with a Flash 8 base requirement, but can also use Flash 9 and take advantages of some unique features Flash 9 offers. By default Flash 8 will be used, but the version can be easily changed by setting <code>flashVersion</code> appropriately.</p>\r
+\r
+ <p class="in">Example: <code>soundManager.setup({ <span>flashVersion: 9</span> });</code></p>\r
+\r
+ <p class="in">The Flash 8 version is <code>soundmanager2.swf</code>, and the flash 9 version is <code>soundmanager2_flash9.swf</code>, accordingly. Note that only Flash 8 and Flash 9 are supported at this time; other values will result in errors.</p>\r
+\r
+ </div>\r
+\r
+ <div class="f-block f-flashversion">\r
+\r
+ <p>Flash 9-only features:</p>\r
+\r
+ <ul>\r
+ <li class="in">MPEG-4 (HE-AAC/H.264) audio support</li>\r
+ <li class="in">True "multi-shot" sound behaviour. <code>play()</code> can be called multiple times, giving a layered, "chorus" effect. Sound will also fire <code>onfinish()</code> multiple times. (Previous behaviour did not layer sounds, but would re-play a single instance.)</li>\r
+ <li class="in"><code>waveformData</code> array: 256 waveform data values available while playing sound</li>\r
+ <li class="in"><code>eqData</code> array: 256 EQ spectrum data values available while playing sound</li>\r
+ <li class="in"><code>peakData</code> object: Left and right channel peak/volume data available while playing sound</li>\r
+ </ul>\r
+ \r
+ </div>\r
+\r
+ <div class="f-block f-flashloadtimeout">\r
+ <h4 id="soundmanager-flashloadtimeout">flashLoadTimeout</h4>\r
+ <p class="in">After initializing the flash component during start-up, SM2 will wait for a defined period of time before timing out and calling <code>soundManager.onerror()</code>.</p>\r
+ <p>The default value is 1000 (msec.) Setting a value of 0 disables the timeout and makes SM2 wait indefinitely for a call from the flash component. If you want to handle flash block-type situations, see <a href="#soundmanager-useflashblock" onclick="resetFilter()">soundManager.useFlashBlock</a>.</p>\r
+ <p>Setting this parameter to 0 may be useful when attempting to gracefully recover from a flashBlock situation, where the user has whitelisted the movie after it was blocked etc.</p>\r
+ <p>Note that when the timeout is disabled, soundManager will not fire its onerror() handler if there is an error at the flash loading stage.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-flashpollinginterval f-usefastpolling f-usehighperformance">\r
+ <h4 id="soundmanager-flashpollinginterval">flashPollingInterval</h4>\r
+ <p>Setting this will override <code>useFastPolling</code>, and defines the interval of the internal flash timer used for callbacks to sound events like <code>whileloading()</code> and <code>whileplaying()</code>. For example, set this to 200 to have 200ms intervals. This is useful in the case where your callbacks are CPU intensive, or you simply wish to throttle your calls to be more CPU-conservative.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-forceuseglobalhtml5audio">\r
+ <h4 id="soundmanager-forceuseglobalhtml5audio">forceUseGlobalHTML5Audio</h4>\r
+ <p class="in">By default, SoundManager 2 only applies the "singleton"-style, single HTML5 <code>Audio()</code> object for mobile devices like iOS, Android and the like. If you want to force it for desktop browsers, you can set <code>forceUseGlobalHTML5Audio</code> to <code>true</code>.</p>\r
+ <p class="in">Example: <code>soundManager.setup({ <span>forceUseGlobalHTML5Audio: true</span> });</code></p>\r
+ </div>\r
+\r
+ <div class="f-block f-html5pollinginterval">\r
+ <h4 id="soundmanager-html5pollinginterval">html5PollingInterval</h4>\r
+ <p>Setting this will enable a single interval that will affect the frequency of event callbacks such <code>whileplaying()</code> for HTML5 sounds, with the exclusion of mobile devices. If null, native HTML5 update events are used. The frequency of native events may vary widely across browsers, and may exceed 500 msec on mobile and other resource-limited devices.</p>\r
+ <p>By default, Flash uses a 50-msec timer interval and this is a reasonable value to apply to <code>html5PollingInterval</code> for desktop use cases.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-ignoremobilerestrictions">\r
+ <h4 id="soundmanager-ignoremobilerestrictions">ignoreMobileRestrictions</h4>\r
+ <p class="in">By default, SoundManager 2 only applies the "singleton"-style, single HTML5 <code>Audio()</code> object for mobile devices like iOS, Android and the like. This is because <i>most</i> iOS devices only like playing a single <code>Audio()</code> audio object at a time.</p>\r
+ <p>If you want to avoid applying this to it for desktop browsers, you can set <code>ignoreMobileRestrictions</code> to <code>true</code>.</p>\r
+ <p class="in">Example: <code>soundManager.setup({ <span>ignoreMobileRestrictions: true</span> });</code></p>\r
+ </div>\r
+\r
+ <div class="f-block f-preferflash">\r
+ <h4 id="soundmanager-preferflash">preferFlash</h4>\r
+ <p>This property handles "mixed-mode" HTML5 + flash cases, and may prevent 100% HTML5 mode when enabled depending on the configuration of <a href="#soundmanager-audioformats">soundManager.audioFormats</a>. In the event HTML5 supports the default "required" formats (presently MP3), and <code>preferFlash</code> is true (and flash is installed), flash will be used for MP3/MP4 content while allowing HTML5 to play OGG, WAV and other supported formats.</p>\r
+ <p><em>Important note:</em> Because HTML5 audio has some bugs across various browsers and operating systems, <code>preferFlash</code> is <code>true</code> by default to help ensure MP3/MP4 play consistently. If set to <code>false</code> or flash is not available, "HTML5-only" mode will kick in and will apply to all formats.</p>\r
+ <p>To encourage 100% HTML5 mode, call <code>soundMangager.setup({ preferFlash: false })</code> and then Flash will not be used for MP3/MP4 playback, provided that HTML5 supports them.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-url">\r
+ <h4 id="soundmanager-url">url</h4>\r
+ <p class="in"><code>soundManager.url</code>, applied via <code>soundManager.setup()</code>, specifies the "online", generally HTTP-based path which SM2 will load .SWF movies from. The "local" (current) path of <code>./</code> will be used by default. The appropriate .SWF required (depending on the desired Flash version) will be appended to the URL.</p>\r
+ <p class="in">Example: <code>soundManager.setup({ url: '<span>/path/to/swf-directory/</span>' });</code> (Note trailing slash)</p>\r
+ <p>For a simple demo of this in action, see the <a href="../demo/template/">basic template</a>.</p>\r
+ <p class="in">For cases where SM2 is being used "offline" in non-HTTP cases (eg., development environments), see <code>altURL</code>.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-usefastpolling f-usehighperformance f-flashpollinginterval">\r
+ <h4 id="soundmanager-usefastpolling">useFastPolling</h4>\r
+ <p>By default <code>useFastPolling = false</code>, and thus SoundManager uses a 50-millisecond timer inside Flash when polling for updated sound properties such as <code>bytesLoaded</code> and data and event callbacks eg. <code>whileloading()</code>, <code>whileplaying()</code> and so on. With <code>useFastPolling = true</code>, a 10-msec timer is used and callback frequency may noticeably increase. This is best combined with <code>useHighPerformance</code> for optimal results.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-useflashblock">\r
+ <h4 id="soundmanager-useflashblock">useFlashBlock</h4>\r
+ <p>Flash blockers (eg. FlashBlock, "Click To Flash") can prevent the flash portion of SM2 from loading, which will cause a start-up error with a time-out.</p>\r
+ <p>SM2 historically has kept the flash movie off-screen and out of view, and thus the user could not click on and unblock it. Now with <code>useFlashBlock = true</code>, the movie positioning can be handled by CSS. The initial state is still off-screen by default, but will change to be in view when a blocking (time-out) situation may be encountered. You can also edit the CSS to taste, of course.</p>\r
+ <p>When starting up, CSS classes are appended to the <code>#sm2-container</code> DIV (which you can provide, or SM2 will create and append to the document.) The CSS classes change with the state of SM2's start-up, eg. <code>#sm2-container.swf_timedout { border:1px solid red; }</code> could be used to highlight the movie to the user for unblocking and so on.</p>\r
+ <p>Setting <code>useFlashBlock = true</code> will cause SM2 to wait infinitely for the Flash content to load after an initial (non-fatal) timeout, having already waited for <code>flashLoadTimeout</code> to pass. If <code>flashLoadTimeout = 0</code>, SM2 will immediately go into "flash block mode" on start-up.</p>\r
+ <p>The relevant CSS is as follows:</p>\r
+<pre class="small block"><code>#sm2-container {\r
+ <span><span>/**\r
+ * Initial/default state...\r
+ * position:absolute/off-screen, or left/top:0\r
+ */</span></span>\r
+}\r
+\r
+#sm2-container.swf_timedout {\r
+ <span><span>/**\r
+ * Didn't load before time-out, show to user.\r
+ * Maybe highlight on-screen, red border, etc..? \r
+ */</span></span>\r
+}\r
+\r
+#sm2-container.swf_unblocked {\r
+ <span><span>/**\r
+ * Applied if movie loads successfully\r
+ * (flash started, so move off-screen etc.)\r
+ */</span></span>\r
+}\r
+\r
+#sm2-container.swf_error {\r
+ <span><span>/**\r
+ * "Fatal" error case: SWF loaded, but SM2 was unable to start.\r
+ * (Flash security or other error case.)\r
+ */</span></span>\r
+}\r
+\r
+#sm2-container.high_performance {\r
+ <span><span>/**\r
+ * Additional modifier for "high performance" mode\r
+ * should apply position:fixed and left/bottom 0 to stay on-screen\r
+ * at all times (better flash performance)\r
+ */</span></span>\r
+}\r
+\r
+#sm2-container.flash_debug {\r
+ <span><span>/**\r
+ * Additional modifier for flash debug output mode\r
+ * should use width/height 100% so you can read debug messages\r
+ */</span></span>\r
+}</code></pre>\r
+\r
+ <p>For a live example, see the <a href="../demo/flashblock/">FlashBlock Demo</a>.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-usehighperformance f-usefastpolling f-flashpollinginterval">\r
+ <h4 id="soundmanager-highperformance">useHighPerformance</h4>\r
+ <p>Perhaps intuitively, Flash is given higher priority when positioned within the viewable area of the browser, at least 6px in height (oddly), fully-opaque, visible and displayed on the screen. By default, <code class="in">useHighPerformance</code> is disabled. When enabled, it may noticeably reduce JS/flash lag and increase the frequency of callbacks such as <code class="in">whileplaying()</code> in some circumstances.</p>\r
+ <p><code class="in">soundManager.setup({useHighPerformance: <span>true</span>});</code></p>\r
+ <p>This has made a noticeable impact in responsiveness on Mac OS X, and Safari on Windows; animation lag is practically non-existent (see <a href="../demo/animation-2b/" title="SoundManager JS + DOM + sound demo 2b" style="display:inline" onclick="checkDomain(this)">demo</a>). Because setting wmode=transparent and fixed position has been reported to cause some issues, the feature is disabled by default.</p>\r
+ <p>To be least-obtrusive, SM2 attempts to set position:fixed, and uses bottom/left:0px to stay within view (though using wmode=transparent where possible, to be hidden from view.) It occupies an 8x8px square. If you wish to position the movie yourself or show it inline, have a DIV element with the ID of <code class="in">sm2-container</code> present in the DOM for SM2 to reference and it will write the movie there without positioning.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-usehtml5audio">\r
+\r
+ <h4 id="soundmanager-usehtml5audio">useHTML5Audio</h4>\r
+ \r
+ <p style="background:#f0f9ff">HTML5 support is in active development. See <a href="download/#revision-history">Revision History</a> for the latest updates on HTML5 playback support.</p>\r
+ \r
+ <p><code>useHTML5Audio</code> determines whether HTML5 <code>Audio()</code> support is used (as available) to play sound, with flash as the fallback for playing MP3 and MP4 (AAC) formats. Browser support for HTML5 Audio varies, and format support (eg. MP3, MP4/AAC, OGG, WAV) can vary by browser/platform.</p>\r
+\r
+ <p>The SM2 API is effectively transparent, consistent whether using flash or HTML5 <code>Audio()</code> for sound playback behind the scenes. The HTML5 Audio API is roughly equivalent to the flash 8 feature set, minus ID3 tag support and a few other items. (Flash 9 features like waveform data etc. are not available in HTML5 mode.)</p>\r
+\r
+ <p>By default, "100% HTML5 mode" applies to Apple iPad 3.2+ (iPad version 1.0), iPhone / iOS 4.0+ devices and others without flash. In other cases, HTML5 support is tested and if MP3/MP4 aren't natively supported, flash will be used as a backup method of playing these "required" formats. (It is assumed MP3 playback is required by default, but this is user-configurable via <code><a href="#soundmanager-audioformats">soundManager.audioFormats</a></code>.) HTML5 may also enable support for additional formats such as OGG and WAV.</p>\r
+ <p>On the desktop and other devices with flash support, SM2 will still try for 100% HTML5 mode by default. However, you can use <code>soundManager.setup({ preferFlash: true })</code> if you would like to have Flash play MP3 and MP4 (AAC) formats even when they are supported via HTML5.</p>\r
+\r
+ <h5>SoundManager 2 + useHTML5Audio: Init Process</h5>\r
+\r
+ <p>At DOM ready (if <code>useHTML5Audio</code> = <code>true</code>), a test for <code>Audio()</code> is done followed by a series of <code>canPlayType()</code> tests to see if MP3, MP4, WAV and OGG formats are supported. If any of the "required" formats (by default, MP3) are <i>not</i> supported via HTML5, or if <code>preferFlash</code> = <code>true</code> and MP3 or MP4 are required, then flash is also added as a requirement for SM2 to start.</p>\r
+\r
+ <p><code><a href="#soundmanager-audioformats">soundManager.audioFormats</a></code> defines the list of formats to check (MP3, MP4 and so on), their possible <code>canPlayType()</code> strings (long story short, it's complicated) and whether or not they are "required" - that is, whether flash should be loaded if they don't work under HTML5. (Again, only MP3 + MP4 are supported by flash.) If you had a page solely using OGG, you could make MP3/MP4 non-required, but many browsers do not play OGG files natively.</p>\r
+\r
+ <p>SM2 will indicate its state (HTML 5 support or not, using flash or not) in <code>console.log()</code>-style debug output messages when <code>debugMode = true</code>.</p>\r
+ \r
+ <h5>"My browser does HTML5, why not MP3"?</h5>\r
+\r
+ <p>Despite best efforts, some browsers eg. Chrome on Windows may only return "maybe" for <code>Audio().canPlayType('audio/mpeg; codecs=mp3')</code> and variants; SoundManager 2 will presently assume a format is supported if a "probably" or "maybe" response is given. You can modify <code>html5Test</code> to be <code>/probably/i</code> if you want to be more strict, for example.</p>\r
+ \r
+ <p>Safari, IE 9, and Chrome (excluding Chromium?) support the "non-free" MP3 and MP4 (including AAC) formats. Firefox, in some cases, does support the MP3 codec where the underlying OS has support for it. This includes Windows Vista (and newer), and as of November 2013, Firefox Aurora (development builds) also on OS X.</p>\r
+ <p>For the cases where MP3 is not supported via HTML5, flash is used as the fallback support for MP3/MP4 as needed. Additionally, if flash support is present, <code>soundManager.preferFlash</code> means that MP3/MP4 will be handled by flash even if HTML5 support is present for those formats.</p>\r
+ \r
+ <h5>Additional HTML5 formats: OGG, WAV</h5>\r
+ \r
+ <p>WAVe (uncompressed audio) and OGG (a free/open-source alternative to MP3) are both supported in a majority of browsers via HTML5, so SoundManager 2 will also test for support for these formats. A flash fallback for these formats has not been implemented. In 2011, Adobe suggested they would support OGG audio + video (combined, the "WebM" format) in a future release of flash. As of November 2013, this has yet to materialize.</p>\r
+ \r
+ <p>You may need to make a few server configuration updates given the importance of MIME types and the use of certain HTTP headers when serving audio to HTML5 clients. See <a href="../doc/technotes/#client-requests">Client Requests</a> for more.</p>\r
+ \r
+ <p>HTML5 is not limited to OGG and WAV, of course, as the system is designed to be extensible. Support for other formats may exist, depending on what built-in support exists, and plug-ins or codecs the user has installed on their system.</p>\r
+ \r
+ <h5>Testing audio format support</h5>\r
+ \r
+ <p>Once <code>soundManager.onready()</code> has fired and SM2 has started, you can check for support via a number of methods. Namely, <a href="#soundmanager-canplaylink">soundManager.canPlayLink()</a> will take an <code><a></code> element and check its <code>href</code> and <code>type</code> attributes, if available, for hints as to its format or type. You can also pass arbitrary URLs to <a href="#soundmanager-canplayurl">soundManager.canPlayURL()</a>, which will make a "best guess" based on the extension it finds. In any event, SM2 will return a true/false value from canPlay methods based on HTML and/or flash capabilities.</p>\r
+ \r
+ <p>To see what formats are supported by HTML5, watch SM2's debug/console output when debug is enabled, or dump the contents of <code>soundManager.html5</code> to the console; it will show the results of tests for simple items like "mp3", as well as <code>canPlayType()</code> strings such as 'mpeg; codecs=mp3'</p>\r
+ \r
+ <h5>Apple iPad, iPhone, Palm Pre: Special Cases</h5>\r
+ <p>The "Big iPhone" doesn't do Flash, and does support HTML5 <code>Audio()</code> pretty decently - so SM2 makes a special exception to enable <code>useHTML5Audio</code> when it detects an iPad, iPhone or Palm Pre user agent string by default. Feel free to disable this if you wish.</p>\r
+ <p>iPad and iPhone require user interaction to start a sound, eg. the createSound() and play() call should happen within an onclick() handler on a link, etc. The "security" model here seems to be implemented similarly to the way pop-up blockers work. You may "chain" sounds (eg. create and play a new one) provided it is done via the onfinish() event of a sound initiated by a user, however. The Muxtape-style demo on the SM2 homepage uses this, and will advance the playlist on the iPad/iPhone if allowed.</p>\r
+ <p>iPad 3.2 gets hung up on the "BC quail" HE-AAC example sound for some reason, and endlessly loops it rather than finishing and moving on to the next item. May be an iPad playback bug, as other formats are fine. iPhone OS 4 (iOS 4) does not show this issue.</p>\r
+ <p>iPhone OS version < 3.1 doesn't work, but 3.1 (and possibly earlier versions, not verified) have a native <code>Audio()</code> object. However, they seem to simply not play sound when <code>play()</code> is called, so SM2 looks for and ignores the iPhone with these OS revisions.</p>\r
+ <p>The Palm Pre <a href="http://developer.palm.com/index.php?option=com_content&view=article&id=1741&Itemid=265#using_html_5_audio_objects" title="Palm Developer Center: Audio">supports</a> a number of MP3, MP4 and WAV formats (WebOS 1.4.1 was tested; it didn't seem to like MP3s at 192kbps, but 128kbps was fine.)</p>\r
+\r
+ <h5>General Disclaimer</h5>\r
+ <p>HTML5 audio support may still be in flux, and may not be fully-supported or implemented consistently in modern browsers. Be careful out there.</p>\r
+\r
+ <h5>Related Reading on HTML5</h5>\r
+ <p>For some more backstory on HTML and audio, see the 24ways.org article <a href="http://24ways.org/2010/the-state-of-html5-audio">"Probably, Maybe, No": The State Of HTML5 Audio</a> (published December, 2010.)</p>\r
+\r
+ </div>\r
+\r
+ <div class="f-block f-wmode">\r
+ <h4 id="soundmanager-wmode">wmode</h4>\r
+ <p>The <code>wmode</code> property is applied directly to the flash movie, and can be either <code>null</code>, <code>'window'</code>, <code>'transparent'</code> or <code>'opaque'</code>. By default if <code>useHighPerformance</code> is enabled, transparency will be attempted by SM2 unless there are known issues with the rendering mode.</p>\r
+ <p>It appears that non-IE browsers on Windows will not load SWF content "below the fold" (out of scrollable view) when wmode is set to anything other than null (window). This will break SM2 as it expects Flash to load within a reasonably short amount of time - so SM2 by default will reset wmode for this case. If you wish to force retention of your <code>wmode</code>, set <code>soundManager.flashTimeout = 0</code> which will ensure that if the content is below the fold, SM2 will not time out waiting for it to load.</p>\r
+ <p>Additionally, <code>soundManager.specialWmodeCase</code> will be set to <code>true</code> if wmode has been reset due to this special condition.</p>\r
+ </div>\r
+\r
+\r
+ <div class="f-block">\r
+\r
+ <h3>SoundManager Top-Level Properties</h3>\r
+\r
+ <p>A few additional properties that hang off the <code>soundManager</code> instance object</p>\r
+\r
+ </div>\r
+\r
+ <div class="f-block f-alturl">\r
+ <h4 id="soundmanager-alturl">soundManager.altURL</h4>\r
+ <p class="in"><code>soundManager.altURL</code> specifies an alternate path to <code>soundManager.setupOptions.url</code> which SM2 can load its SWF from. It is a simple convenience for when you may need to load SWFs from different paths depending on your hosting environment (eg., offline development vs. production.)</p>\r
+ <p class="in">Example: <code>soundManager.altURL = '../';</code> (Load from parent directory - note trailing slash)</p>\r
+ <p class="in">For altURL to be used, it must be defined and an "alternate environment" condition must be met:</p>\r
+ <p class="in"><code>soundManager.useAltURL = (!document.location.protocol.match(/http/i));</code></p>\r
+ <p>By default and as shown above, SM2 will use this property when the hosting page is not being served over HTTP, and thus is assumed to being served "offline" - for example, when loading via file://, from the local file system.</p>\r
+ <p>This can easily be adapted to taste, eg., checking the domain matching yourdomain.com vs. localhost:</p>\r
+ <p class="in"><code>soundManager.useAltURL = (!document.location.match(/mydomain.com/i));</code></p>\r
+ <p class="in">If <code>soundManager.altURL</code> is null (the default), <code>soundManager.setupOptions.url</code> will be used for all cases.</p>\r
+ </div>\r
+\r
+ <div class="f-block f-audioformats">\r
+ <h4 id="soundmanager-audioformats">soundManager.audioFormats</h4>\r
+\r
+ <p><code>soundManager.audioFormats</code> defines a structure listing the audio codecs that will be tested for support under both HTML5 and Flash. Each type is defined by a file extension and MIME types, and optionally, a list of related extensions (eg. MPEG-4 content can be in an .mp4 file, but may also be .aac, or .m4a.)</p>\r
+\r
+ <p>Additionally, each format can be defined as "required", meaning that SM2 can fail to start if playback support is not found via either HTML5 or Flash. By default, MP3 is a required format.</p>\r
+<pre class="small block"><code>soundManager.audioFormats = {\r
+\r
+ <span><span>/**\r
+ * determines HTML5 support + flash requirements.\r
+ * if no support (via flash/HTML5) for "required" format, SM2 will fail to start.\r
+ * flash fallback is used for MP3 or MP4 if lacking HTML5 (or preferFlash = true)\r
+ * multiple MIME types may be tried looking for positive canPlayType() response.\r
+ */</span></span>\r
+\r
+ '<span>mp3</span>': {\r
+ 'type': ['<span>audio/mpeg; codecs="mp3"</span>', '<span>audio/mpeg</span>', '<span>audio/mp3</span>', '<span>audio/MPA</span>', '<span>audio/mpa-robust</span>'],\r
+ 'required': <span>true</span>\r
+ },\r
+\r
+ '<span>mp4</span>': {\r
+ 'related': ['<span>aac</span>','<span>m4a</span>'], <span><span>// additional formats under the MP4 container</span></span>\r
+ 'type': ['<span>audio/mp4; codecs="mp4a.40.2"</span>', '<span>audio/aac</span>', '<span>audio/x-m4a</span>', '<span>audio/MP4A-LATM</span>', '<span>audio/mpeg4-generic</span>'],\r
+ 'required': <span>false</span>\r
+ },\r
+\r
+ '<span>ogg</span>': {\r
+ 'type': ['<span>audio/ogg; codecs=vorbis</span>'],\r
+ 'required': <span>false</span>\r
+ },\r
+\r
+ '<span>wav</span>': {\r
+ 'type': ['<span>audio/wav; codecs="1"</span>', '<span>audio/wav</span>', '<span>audio/wave</span>', '<span>audio/x-wav</span>'],\r
+ 'required': <span>false</span>\r
+ }\r
+\r
+};</code></pre>\r
+ \r
+ </div>\r
+\r
+\r
+ </div>\r
+ \r
+ \r
+ </div>\r
+ \r
+ <div id="api" class="columnar">\r
+ \r
+ <div class="c2">\r
+\r
+ <div class="f-block">\r
+ \r
+ <h3>soundManager Global Object</h3>\r
+\r
+ <p>This is a collection of methods, properties and event handlers available via the <span class="code">soundManager</span> Javascript object. Sound properties and methods can be set on a global (inherited) default, or per-sound basis.</p>\r
+\r
+ </div>\r
+\r
+ <dl id="soundmanager-canplaylink" class="f-block f-canplaylink" style="margin-top:2em">\r
+ <dt><span>canPlay:boolean</span> canPlayLink(<span><a>:DOM element</span>)</dt>\r
+ <dd>Normalized method which checks <code>canPlayMIME()</code> and <code>canPlayURL()</code> as needed to estimate the playability of an HTML link; this means both the <code>href</code> and <code>type</code> attributes, if provided, are checked for matching file extension and/or MIME type patterns.</dd>\r
+ <dd>Example:\r
+<pre class="block"><code><span><span>/**\r
+ * example links:\r
+ * <a id="song1" href="/music/player.php?songID=1" type="audio/mp3">play #1</a>\r
+ * <a id="song2" href="song2.mp3">play song 2</a>\r
+ */</span></span>\r
+var aLink = document.getElementById('<span>mySong</span>');\r
+if (soundManager.canPlayLink(aLink)) {\r
+ soundManager.play('<span>mySongSound</span>', aLink.href);\r
+}</code></pre></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-canplaymime" class="f-block f-canplaymime">\r
+ <dt><span>canPlay:boolean</span> canPlayMIME(<span>MIMEtype:string</span>)</dt>\r
+ <dd>Returns a boolean indicating whether soundManager can play the given MIME type - eg., <code>audio/mp3</code>. The types supported vary based on Flash version and MPEG4 (MovieStar mode) options.</dd>\r
+ <dd>\r
+ MIME type patterns are as follows:\r
+ <ul>\r
+ <li>Defaults: <code>/^audio\/(?:x-)?(?:mp(?:eg|3))\s*;?/i;</code> - eg. <code>audio/mp3</code> or <code>audio/mpeg</code></li>\r
+ <li>MovieStar-only formats: <code>/^audio\/(?:x-)?(?:mp(?:eg|3)|mp4a-latm|aac|speex)\s*;?/i; </code> - eg. <code>audio/m4a or audio/aac</code></li>\r
+ </ul>\r
+ </dd>\r
+ <dd>Example:\r
+<pre class="block"><code><span><span>// link example: <a id="song1" href="foo.php?songID=1" type="audio/mp3">play #1</a></span></span>\r
+var aLink = document.getElementById('<span>song1</span>');\r
+if (soundManager.canPlayMIME(aLink.type)) {\r
+ soundManager.createSound('<span>song1Sound</span>', aLink.href);\r
+}</code></pre></dd>\r
+ <dd>If no <code>type</code> attribute is found, this method will return <code>null</code> instead of <code>false</code>.</dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-canplayurl" class="f-block f-canplayurl">\r
+ <dt><span>canplay:boolean</span> canPlayURL(<span>mediaURL:string</span>)</dt>\r
+ <dd>Returns a boolean indicating whether soundManager can play the given URL. Playability is determined by a matching URL pattern set at runtime, based on Flash version and MPEG4 (MovieStar mode) support.</dd>\r
+ <dd>Example:\r
+<pre class="block"><code>var sURL = '<span>/path/to/some.mp3</span>';\r
+if (soundManager.canPlayURL(sURL)) {\r
+ soundManager.createSound('<span>fooSound</span>', sURL);\r
+}</code></pre></dd>\r
+ <dd>If no <code>href</code> attribute is found, this method will return <code>null</code> instead of <code>false</code>.</dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-clearonposition" class="f-block f-clearonposition">\r
+ <dt><span>object:SMSound</span> clearOnPosition(<span>id:string, msecOffset:integer, [callback:function]</span>)</dt>\r
+ <dd>Clears the event listener set via <code>onPosition()</code>, in the same way it was registered. If the callback is omitted, any and all callbacks registered for the given offset will be cleared.</dd>\r
+ <dd>Example: <code>soundManager.clearOnPosition('mySound', 3000, positionHandler);</code></dd>\r
+ <dd>Example 2: <code>soundManager.clearOnPosition('mySound', 3000);</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-createsound" class="f-block f-createsound s-autoplay">\r
+\r
+ <dt><span>object:SMSound </span>createSound(<span>object:options</span>)</dt>\r
+ <dd title="object:options">Creates a sound object, supporting an arbitrary number of optional arguments. Returns a <code>SMSound</code> object instance. At minimum, a <code>url</code> parameter is required.</dd>\r
+ <dd>\r
+ Minimal example:\r
+<pre class="block"><code>var someSound = soundManager.createSound({ <span>\r
+ url: '/path/to/an.mp3'\r
+</span>});</code></pre>\r
+ </dd>\r
+ <dd>\r
+ With optional parameters:\r
+<pre class="block"><code>var mySoundObject = soundManager.createSound({<span>\r
+ <span>// optional id, for getSoundById() look-ups etc. If omitted, an id will be generated.</span>\r
+ id: 'mySound',\r
+ url: '/audio/mysoundfile.mp3',\r
+ <span>// optional sound parameters here, see <a href="#sound-properties" title="SoundManager 2 API Info: Sound Properties Object" onclick="resetFilter()">Sound Properties</a> for full list</span>\r
+ volume: 50,\r
+ autoPlay: true,\r
+ whileloading: function() { console.log(this.id + ' is loading'); }\r
+</span>});</code></pre>\r
+ <p>Each <code>createSound()</code> call results in the creation of a <code>SMSound</code> object which stores all properties, methods and events relevant to that particular sound instance. If you keep the <code>SMSound</code> object in scope, you probably don't need to specify an ID. However, if you <i>do</i> provide an <code>id</code>, you can easily get a reference to the given sound via <code>soundManager.getSoundById()</code> (for the above example, you would use <code>mySound</code>.)</p>\r
+ <p>When specifying an <code>id</code> you can also use controller-level convenience methods, i.e., <code>soundManager.play('<span>mySound</span>')</code>, <code>soundManager.stop('<span>mySound</span>')</code> and so on.</p>\r
+ <p>Individual sound objects can also easily be referenced as returned from <code>createSound()</code>:</p>\r
+<pre class="block"><code>var mySoundObject = soundManager.createSound({<span>\r
+ url: '/audio/mysoundfile.mp3'\r
+</span>});\r
+mySoundObject.play(); <span><span>// SMSound object instance</span></span></code></pre>\r
+\r
+ <p>For more SMSound parameters, see <a href="#object-literal-format" title="SoundManager 2 API Info: Sound Properties Object" onclick="resetFilter()">Object Literal Format</a>.</p>\r
+ </dd>\r
+ <dd>If <code>createSound</code> is called with the ID of an existing sound, that sound object will be returned "as-is". Any other <code>createSound</code> options passed (eg., <code>url</code> or <code>volume</code>, etc.) will be ignored.</dd>\r
+\r
+ </dl>\r
+\r
+ <dl id="soundmanager-createsound-overloaded" class="f-block f-createsound">\r
+ <dt><span>object:SMSound </span>createSound(<span>id:string, url:string</span>) - overloaded method</dt>\r
+ <dd title="id:string,url:string">Creates a sound with the specified ID and URL (simple two-parameter method.)</dd>\r
+ <dd>Example: <code>soundManager.createSound('<span>mySound</span>','<span>/audio/mysoundfile.mp3</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-destroysound" class="f-block f-destroysound">\r
+ <dt>destroySound(<span>id:string</span>)</dt>\r
+ <dd title="id:string">Stops, unloads and destroys a sound specified by ID.</dd>\r
+ <dd>Example: <code>soundManager.destroySound('<span>mySound</span>');</code></dd>\r
+ <dd>SMSound equivalent example: <code>mySound.destruct();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-mute" class="f-block f-mute">\r
+ <dt><span>object:SMSound </span>mute(<span>[id:string]</span>)</dt>\r
+ <dd title="id:string">Mutes the sound specified by ID and returns that sound object. If no ID specified, all sounds will be muted and null is returned. Affects <span>muted</span> property (boolean.)</dd>\r
+ <dd>Example: <code>soundManager.mute('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-onposition" class="f-block f-onposition">\r
+ <dt><span>object:SMSound</span> onPosition(<span>id:string, msecOffset:integer, callback:function, [scope]</span>)</dt>\r
+ <dd>Registers an event listener, fired when a sound reaches or passes a certain position while playing. Position being "listened" for is passed back to event handler. Will also fire if a sound is "rewound" (eg. via <code>setPosition()</code> to an earlier point) and the given position is reached again. Listeners will be removed if a sound is unloaded. An optional scope can be passed as well.</dd>\r
+ <dd>Note that for <code>multiShot</code> cases, only the first play instance's <code>position</code> is tracked in Flash; therefore, subsequent "shots" will not have onPosition() events being fired.</dd>\r
+ <dd>Example: <code>soundManager.onPosition('mySound', 3000, function(eventPosition){<span>console.log(this.id+' reached '+eventPosition</span>});</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-onready" class="f-block f-onready">\r
+ <dt>onready(<span>callback:function, [scope]</span>)</dt>\r
+ <dd title="callback:function">Queues an event callback/handler for successful initialization and "ready to use" state of SoundManager 2. An optional scope parameter can be specified; if none, the callback is scoped to the window. If <code>onready()</code> is called after successful initialization, the callback will be executed immediately. The <code>onready()</code> queue is processed before <code>soundManager.onload()</code>.</dd>\r
+ <dd>Example:\r
+<pre class="block"><code>soundManager.onready(<span>function() {\r
+ alert('Yay, SM2 loaded OK!'); \r
+}</span>);</code></pre>\r
+ </dd>\r
+ <dd>Queueing multiple handlers: <code>soundManager.onready(<span>myOnReadyHandler</span>); soundManager.onready(<span>myOtherHandler</span>);</code></dd>\r
+ <dd>The same listener may be added multiple times; there is no duplicate checking. Queue is processed in order of addition.</dd>\r
+ <dd>If <code>soundManager.reboot()</code> is called, all listeners' "fired" flags will be reset and they will be eligible to fire again when SM2 starts.</dd>\r
+ <dd>This method can also be used via <code><a href="#sm2-setup-extra-properties" onclick="resetFilter()">soundManager.setup</a>({ <span>onready: function() { ... }</span> });</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-ontimeout" class="f-block f-ontimeout">\r
+ <dt>ontimeout(<span>callback:function, [scope]</span>)</dt>\r
+ <dd title="callback:function">Queues an event callback/handler for SM2 init failure, processed at (or immediately, if added after) SM2 initialization has failed, just before <code>soundManager.onerror()</code> is called. An optional scope parameter can be specified; if none, the callback is scoped to the window.</dd>\r
+ <dd>Additionally, a <code>status</code> object containing <code>success</code> and <code>error->type</code> parameters is passed as an argument to your callback.</dd>\r
+ <dd>Example:\r
+<pre class="block"><code>soundManager.ontimeout(<span>function(status) {\r
+ alert('SM2 failed to start. Flash missing, blocked or security error?');\r
+ alert('The status is ' + status.success + ', the error type is ' + status.error.type);\r
+}</span>);</code></pre>\r
+ </dd>\r
+ <dd>Queueing multiple handlers: <code>soundManager.ontimeout(<span>myOnTimeoutHandler</span>); soundManager.ontimeout(<span>myOtherHandler</span>);</code></dd>\r
+ <dd>The timeout event is not necessarily fatal, as SM2 may be rebooted and fire an <code>onready()</code> in the <code>useFlashBlock</code> case (where the user sees, and chooses to unblock the Flash component after a failed init attempt.)</dd>\r
+ <dd>The same listener may be added multiple times; there is no duplicate checking. Queue is processed in order of addition.</dd>\r
+ <dd>If <code>soundManager.reboot()</code> is called, all listeners' "fired" flags will be reset and they will be eligible to fire again when SM2 starts.</dd>\r
+ <dd>This method can also be used via <code><a href="#sm2-setup-extra-properties" onclick="resetFilter()">soundManager.setup</a>({ <span>ontimeout: function() { ... }</span> });</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-play" class="f-block f-play">\r
+ <dt><span>object:SMSound</span> play(<span>id:string, [options object]</span>)</dt>\r
+ <dd title="soundID:string">Starts playing the sound specified by ID. (Will start loading if applicable, and will play ASAP.)</dd>\r
+ <dd>Returns an <code>SMSound</code> (sound object) instance.</dd>\r
+ <dd>Example: <code>soundManager.play('<span>mySound</span>');</code></dd>\r
+ <dd>Note that the second parameter, <code>options object</code>, is not required and can take almost any argument from the object literal format (eg. volume.) It is convenient when you wish to override the sound defaults for a single instance.</dd>\r
+ <dd>Example: <code>soundManager.play('<span>mySound</span>',{<span>volume:50,onfinish:playNextSound</span>});</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-pause" class="f-block f-pause">\r
+ <dt><span>object:SMSound</span> pause(<span>id:string</span>)</dt>\r
+ <dd title="soundID:string">Pauses the sound specified by ID. Does not toggle. Affects <span>paused</span> property (boolean.) Returns the given sound object.</dd>\r
+ <dd>Example: <code>soundManager.pause('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-pauseall" class="f-block f-pauseall">\r
+ <dt>pauseAll()</dt>\r
+ <dd>Pauses all sounds whose playState is >0. Affects <span>paused</span> property (boolean.)</dd>\r
+ <dd>Example: <code>soundManager.pauseAll();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-reboot" class="f-block f-reboot">\r
+ <dt>reboot()</dt>\r
+ <dd>Destroys any created SMSound objects, unloads the flash movie (removing it from the DOM) and restarts the SM2 init process, retaining all currently-set properties.</dd>\r
+ <dd>Example: \r
+<pre class="block"><code>soundManager.ontimeout(function() {<span>\r
+ <span>// Something went wrong during init - in this example, we *assume* flashblock etc.</span>\r
+ soundManager.flashLoadTimeout = 0; <span>// When restarting, wait indefinitely for flash</span>\r
+ soundManager.onerror = {}; <span>// Prevent an infinite loop, in case it's not flashblock</span>\r
+ soundManager.reboot(); <span>// and, go!</span>\r
+});</span></code></pre>\r
+ </dd>\r
+ <dd>This method may be helpful when trying to gracefully recover from FlashBlock-type situations where the user has prevented the SWF from loading, but is able to whitelist it. For more ideas, see <a href="../demo/flashblock/">Flashblock demo</a>.</dd>\r
+ <dd>When using this method also consider <a href="#soundmanager-flashloadtimeout" onclick="resetFilter()">flashLoadTimeout</a>, which can have SM2 wait indefinitely for the flash to load if desired.</dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-reset" class="f-block f-reset">\r
+ <dt>reset()</dt>\r
+ <dd>Effectively restores SoundManager's original state without rebooting (re-initializing).</dd>\r
+ <dd>Similar to <a href="#soundmanager-reboot" onclick="resetFilter()">reboot()</a> which destroys sound objects and the flash movie (as applicable), but also nukes any registered <code>onready()</code> and related callbacks.</dd>\r
+ <dd>Once <code>soundManager.reset()</code> has been called, <code>soundManager.beginDelayedInit()</code> (or <code>soundManager.setup()</code> with a <code>url</code> property) may be called to re-init SM2.</dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-resume" class="f-block f-resume">\r
+ <dt><span>object:SMSound</span> resume(<span>id:string</span>)</dt>\r
+ <dd title="soundID:string">Resumes and returns the currently-paused sound specified by ID.</dd>\r
+ <dd>Example: <code>soundManager.resume('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-resumeall" class="f-block f-resumeall">\r
+ <dt>resumeAll()</dt>\r
+ <dd title="soundID:string">Resumes all currently-paused sounds.</dd>\r
+ <dd>Example: <code>soundManager.resumeAll();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-setpan" class="f-block f-setpan">\r
+ <dt><span>object:SMSound</span> setPan(<span>id:string,volume:integer</span>)</dt>\r
+ <dd title="id:string,volume:integer">Sets the stereo pan (left/right bias) of the sound specified by ID, and returns the related sound object. Accepted values: -100 to 100 (L/R, 0 = center.) Affects <span>pan</span> property.</dd>\r
+ <dd>Example: <code>soundManager.setPan('<span>mySound</span>',<span>-80</span>);</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-setposition" class="f-block f-setposition">\r
+ <dt><span>object:SMSound</span> setPosition(<span>id:string,msecOffset:integer</span>)</dt>\r
+ <dd title="id:string,msecOffset:integer">Seeeks to a given position within a sound, specified by miliseconds (1000 msec = 1 second) and returns the related sound object. Affects <span>position</span> property.</dd>\r
+ <dd>Example: <code>soundManager.setPosition('<span>mySound</span>',<span>2500</span>);</code></dd>\r
+ <dd>Can only seek within loaded sound data, as defined by the <span>duration</span> property.</dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-setvolume" class="f-block f-setvolume">\r
+ <dt><span>object:SMSound</span> setVolume(<span>id:string, volume:integer</span>)</dt>\r
+ <dd title="id:string,volume:integer">Sets the volume of the sound specified by ID and returns the related sound object. Accepted values: 0-100. Affects <span>volume</span> property.</dd>\r
+ <dd>Example: <code>soundManager.setVolume('<span>mySound</span>',<span>50</span>);</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-setvolume-overloaded" class="f-block f-setvolume">\r
+ <dt>setVolume(<span>volume:integer</span>) - overloaded method</dt>\r
+ <dd title="id:string,volume:integer">Sets the volume of all sound objects. Accepted values: 0-100. Affects <span>volume</span> property.</dd>\r
+ <dd>Example: <code>soundManager.setVolume(<span>50</span>);</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-stop" class="f-block f-stop">\r
+ <dt><span>object:SMSound</span> stop(<span>id:string</span>)</dt>\r
+ <dd title="soundID:string">Stops playing the sound specified by ID. Returns the related sound object.</dd>\r
+ <dd>Example: <code>soundManager.stop('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-stopall" class="f-block f-stopall">\r
+ <dt>stopAll()</dt>\r
+ <dd>Stops any currently-playing sounds.</dd>\r
+ <dd>Example: <code>soundManager.stopAll();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-togglemute" class="f-block f-togglemute">\r
+ <dt><span>object:SMSound</span> toggleMute(<span>id:string</span>)</dt>\r
+ <dd title="soundID:string">Mutes/unmutes the sound specified by ID. Returns the related sound object.</dd>\r
+ <dd>Example: <code>soundManager.toggleMute('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-togglepause" class="f-block f-togglepause">\r
+ <dt><span>object:SMSound</span> togglePause(<span>id:string</span>)</dt>\r
+ <dd title="soundID:string">Pauses/resumes play on the sound specified by ID. Returns the related sound object.</dd>\r
+ <dd>Example: <code>soundManager.togglePause('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-unload" class="f-block f-unload">\r
+ <dt><span>object:SMSound</span> unload(<span>id:string</span>)</dt>\r
+ <dd title="soundID:string">Stops loading the sound specified by ID, canceling any current HTTP request. Returns the related sound object.</dd>\r
+ <dd>Example: <code>soundManager.unload('<span>mySound</span>');</code></dd>\r
+ <dd>Note that for Flash 8, SoundManager does this by pointing the sound object to <code>about:blank</code>, which replaces the current one from loading.</dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-unmute" class="f-block f-unmute">\r
+ <dt><span>object:SMSound</span> unmute(<span>[id:string]</span>)</dt>\r
+ <dd title="id:string">Unmutes the sound specified by ID. If no ID specified, all sounds will be unmuted. Affects <span>muted</span> property (boolean.) Returns the related sound object.</dd>\r
+ <dd>Example: <code>soundManager.unmute('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-load" class="f-block f-load">\r
+ <dt><span>object:SMSound</span> load(<span>id:string, [options object]</span>)</dt>\r
+ <dd title="soundID:string">Starts loading the sound specified by ID, with options if specified. Returns the related sound object.</dd>\r
+ <dd>Example: <code>soundManager.load('<span>mySound</span>');</code></dd>\r
+ <dd>Example 2: <code>soundManager.load('<span>mySound</span>',{<span>volume:50,onfinish:playNextSound</span>});</code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-getsoundbyid" class="f-block f-getsoundbyid">\r
+ <dt><span>object:SMSound </span>getSoundById(<span>id:string</span>)</dt>\r
+ <dd title="id:string">Returns an <code>SMSound</code> object specified by ID, or null if a sound with that ID is not found.</dd>\r
+ <dd>Example: <code>var mySMSound = soundManager.getSoundById('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+ \r
+ <dl id="soundmanager-getmemoryuse" class="f-block f-getmemoryuse">\r
+ <dt class="flash9" title="Requires Flash 9.0+"><span>number:bytesUsed </span>getMemoryUse()</dt>\r
+ <dd>Returns the total number of bytes allocated to the Adobe Flash player or Adobe AIR, or 0 if unsupported (Flash 9+ only.) This number may include memory use across all tabs, browsers etc. See <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/System.html#totalMemory" title="System.totalMemory property documentation">system.totalMemory</a> (livedocs.adobe.com)</dd>\r
+ <dd>Example: <code>var mbUsed = (soundManager.getMemoryUse()/1024/1024).toFixed(2); <span><span>// eg. 12.05 MB</span></span></code></dd>\r
+ </dl>\r
+\r
+ <dl id="soundmanager-ok" class="f-block f-ok f-supported">\r
+ <dt id="soundmanager-supported"><span>isSupported:boolean</span> ok() ( previous name: supported() )</dt>\r
+ <dd>Returns a boolean indicating whether soundManager has attempted to and succeeded in initialising. This function will return false if called before initialisation has occurred, and is useful when you want to create or play a sound without knowing SM2's current state.</dd>\r
+ <dd>Example: <code>var isSupported = soundManager.ok();</code></dd>\r
+ </dl>\r
+\r
+ </div>\r
+ \r
+ </div>\r
+\r
+ <div id="smsoundmethods" class="columnar">\r
+\r
+ <div class="c2">\r
+\r
+ <div>\r
+ \r
+ <h3>Sound Object Methods</h3>\r
+ \r
+ <p class="in">Each sound under SoundManager 2 is given a <code>SMSound</code> object instance which includes the following events, methods and properties. Note that most methods will return the sound object instance, allowing for method chaining if desired.</p>\r
+\r
+ <dl id="smsound-clearonposition" class="f-block f-clearonposition">\r
+ <dt><span>object:SMSound</span> clearOnPosition(<span>msecOffset:integer, [callback:function]</span>)</dt>\r
+ <dd>Clears the event listener set via <code>onPosition()</code>, in the same way it was registered. If the callback is omitted, any and all callbacks registered for the given offset will be cleared.</dd>\r
+ <dd>Example: <code>mySound.clearOnPosition(3000, positionHandler);</code></dd>\r
+ <dd>Example 2: <code>mySound.clearOnPosition('mySound', 3000);</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-destruct" class="f-block s-destruct">\r
+ <dt>destruct()</dt>\r
+ <dd>Stops, unloads and destroys a sound, freeing resources etc.</dd>\r
+ <dd>Example: <code>mySound.destruct();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-load" class="f-block s-load">\r
+ <dt><span>object:SMSound</span> load(<span>[options object]</span>)</dt>\r
+ <dd title="soundID:string">Starts loading the given sound, with options if specified.</dd>\r
+ <dd>Example: <code>mySound.load();</code></dd>\r
+ <dd>Example 2: <code>mySound.load({<span>volume:50,onfinish:playNextSound</span>});</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-mute" class="f-block s-mute">\r
+ <dt><span>object:SMSound</span> mute()</dt>\r
+ <dd>Mutes the given sound. Affects <span>muted</span> property.</dd>\r
+ <dd>Example: <code>mySound.mute();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-onposition" class="f-block s-onposition">\r
+ <dt><span>object:SMSound</span> onPosition(<span>msecOffset:integer, callback:function, [scope]</span>)</dt>\r
+ <dd>Registers an event listener, fired when a sound reaches or passes a certain position while playing. Position being "listened" for is passed back to event handler. Will also fire if a sound is "rewound" (eg. via <code>setPosition()</code> to an earlier point) and the given position is reached again. Listeners will be removed if a sound is unloaded. An optional scope can be passed as well.</dd>\r
+ <dd>Note that for <code>multiShot</code> cases, only the first play instance's <code>position</code> is tracked in Flash; therefore, subsequent "shots" will not have onPosition() events being fired.</dd>\r
+ <dd>Example: <code>mySound.onPosition(3000, function(eventPosition){<span>console.log(this.id+' reached '+eventPosition</span>});</code></dd>\r
+ <dd>If you need to fire an event relative to the true duration of the sound, reference its duration once the sound has fully-loaded - ie., at or after the <code>onload()</code> event - as the duration will not be completely accurate until that time. <code>durationEstimate</code> may be referenced before <code>onload()</code>, but it should not be relied on when "precise" timings of say, < 1 second are desired.</dd>\r
+ <dd>Example:<pre class="block"><code>mySound.load({\r
+ onload: function() {\r
+ this.onPosition(this.duration * 0.5, function(eventPosition) {\r
+ console.log(<span>'the sound '</span> + this.id + <span>' is now at position '</span> + this.position + ' (event position: ' + eventPosition + ')');\r
+ });\r
+ }\r
+});</code></pre>\r
+ </dd>\r
+ <dd>Again, note that due to the interval / polling-based methods of both HTML5 and flash audio, sound status updates and thus precision can vary between 20 msec to perhaps 0.5 seconds and the sound's position property will reflect this delta when the <code>onPosition()</code> callback fires.</dd>\r
+\r
+ </dl>\r
+\r
+ <dl id="smsound-pause" class="f-block s-pause s-paused">\r
+ <dt><span>object:SMSound</span> pause()</dt>\r
+ <dd>Pauses the given sound. (Does not toggle.) Affects <span>paused</span> property (boolean.)</dd>\r
+ <dd>Example: <code>mySound.pause();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-play" class="f-block s-play">\r
+ <dt><span>object:SMSound</span> play(<span>[options object]</span>)</dt>\r
+ <dd>Starts playing the given sound, with an optional options object. (Will start loading if applicable, and will play ASAP.)</dd>\r
+ <dd>Note that the <code>options object</code> parameter is not required and can take almost any argument from the object literal format (eg. volume.)</dd>\r
+ <dd>Example: <code>mySound.play('<span>mySound</span>',{<span>volume:50,onfinish:playNextSound</span>});</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-setposition" class="f-block s-setposition">\r
+ <dt><span>object:SMSound</span> setPosition(<span>msecOffset:integer</span>)</dt>\r
+ <dd title="msecOffset:integer">Seeks to a given position within a sound, specified by miliseconds (1000 msec = 1 second.) Affects <span>position</span> property.</dd>\r
+ <dd>Example: <code>mySound.setPosition(<span>2500</span>);</code></dd>\r
+ <dd>Can only seek within loaded sound data, as defined by the <span>duration</span> property.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-resume" class="f-block s-resume">\r
+ <dt><span>object:SMSound</span> resume()</dt>\r
+ <dd>Resumes the currently-paused sound. Does not affect currently-playing sounds.</dd>\r
+ <dd>Example: <code>mySound.resume();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-setpan" class="f-block s-setpan">\r
+ <dt><span>object:SMSound</span> setPan(<span>volume:integer</span>)</dt>\r
+ <dd title="volume:integer">Sets the stereo pan (left/right bias) of the given sound. Accepted values: -100 to 100 (L/R, 0 = center.) Affects <span>pan</span> property.</dd>\r
+ <dd>Example: <code>mySound.setPan(<span>-80</span>);</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-setvolume" class="f-block s-setvolume">\r
+ <dt><span>object:SMSound</span> setVolume(<span>volume:integer</span>)</dt>\r
+ <dd title="volume:integer">Sets the volume of the given sound. Accepted values: 0-100. Affects <span>volume</span> property.</dd>\r
+ <dd>Example: <code>mySound.setVolume(<span>50</span>);</code></dd>\r
+ </dl>\r
+ \r
+ <dl id="smsound-togglemute" class="f-block s-togglemute">\r
+ <dt><span>object:SMSound</span> toggleMute()</dt>\r
+ <dd>Mutes/unmutes the given sound. Affected <span>muted</span> property (boolean.)</dd>\r
+ <dd>Example: <code>mySound.toggleMute();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-togglepause" class="f-block s-togglepause">\r
+ <dt><span>object:SMSound</span> togglePause()</dt>\r
+ <dd>Pauses/resumes play of the given sound. Will also start a sound if it is has not yet been played.</dd>\r
+ <dd>Example: <code>mySound.togglePause();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-stop" class="f-block s-stop">\r
+ <dt><span>object:SMSound</span> stop()</dt>\r
+ <dd>Stops playing the given sound.</dd>\r
+ <dd>Example: <code>mySound.stop();</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-unload" class="f-block s-unload">\r
+ <dt><span>object:SMSound</span> unload()</dt>\r
+ <dd>Stops loading the given sound, canceling any current HTTP request.</dd>\r
+ <dd>Example: <code>mySound.unload();</code></dd>\r
+ <dd>Note that for Flash 8, SoundManager does this by pointing the sound object to <code>about:blank</code>, which replaces the current one from loading.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-unmute" class="f-block s-unmute">\r
+ <dt><span>object:SMSound</span> unmute()</dt>\r
+ <dd>Unmutes the given sound. Affects <span>muted</span> property.</dd>\r
+ <dd>Example: <code>mySound.unmute();</code></dd>\r
+ </dl>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+ <div id="smsoundevents" class="columnar">\r
+ \r
+ <div class="c2">\r
+ \r
+ <div>\r
+ \r
+ <h3>Sound Object Events</h3>\r
+\r
+ <p class="in">Like native javascript objects, each SoundManager <code>SMSound</code> (sound instance) object can fire a number of <code>onload</code>-like events. Handlers cannot be "directly" assigned (eg. someSound.onload), but can be passed as option parameters to several sound methods.</p>\r
+ <div>\r
+<pre class="block"><code>soundManager.play('<span>mySound</span>',{\r
+ onfinish: function() {\r
+ alert('<span>The sound </span>'+this.id+' <span>finished playing.</span>');\r
+ }\r
+});</code></pre>\r
+ </div>\r
+ <p>Event handlers are scoped to the relevant sound object, so the <code>this</code> keyword will point to the sound object on which the event fired such that its properties can easily be accessed - eg. within an <code>SMSound</code> event handler, <code>this.id</code> will give the sound ID.</p>\r
+\r
+ </div>\r
+\r
+ <div style="margin-top:2em">\r
+ \r
+ <dl id="smsound-onbufferchange" class="f-block s-onbufferchange">\r
+ <dt class="flash9">onbufferchange()</dt>\r
+ <dd>Fires when a sound's reported buffering state has changed while playing and/or loading. The current state is reflected in the boolean <code>isBuffering</code> property.</dd>\r
+ <dd>Flash 9+ only. Related information on Adobe, <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/Sound.html#isBuffering">Sound.isBuffering</a>.</dd>\r
+ </dl>\r
+ \r
+ <dl id="smsound-ondataerror" class="f-block s-ondataerror s-waveformdata s-eqdata">\r
+ <dt title="Flash 9+ only" class="flash9">ondataerror()</dt>\r
+ <dd>Fires at least once per sound play instance when Flash encounters a security error when trying to call computeSpectrum() internally. This typically happens when sounds are 'inaccessible' due to another Flash movie (eg. YouTube) in another tab which has loaded, and may (or may not be) playing sound. Flash attempts to read the "combined" output to the sound card, and must have security permissions for all sounds as a result. See <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#areSoundsInaccessible()">areSoundsInaccessible()</a> on Adobe for more info.</dd>\r
+ <dd>If the offending resource causing the security error is closed or becomes inactive(?), the data will become available again. Intermittent availability will result in intermittent calls to <code>ondataerror()</code>.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-onbeforefinishcomplete" class="f-block s-onbeforefinishcomplete">\r
+ <dt>onbeforefinishcomplete()</dt>\r
+ <dd class="deprecation-note"><b>This method has been removed.</b> Use the newer <a href="#smsound-onposition" onclick="resetFilter()">SMSound.onPosition()</a> as a replacement.</dd>\r
+<!--\r
+ <dd>Fires when a sound has finished, <code>onfinish()</code> has been called, but before the sound play state and other meta data (position, etc.) are reset.</dd>\r
+-->\r
+ </dl>\r
+\r
+ <dl id="smsound-onbeforefinish" class="f-block s-onbeforefinish">\r
+ <dt>onbeforefinish()</dt>\r
+ <dd class="deprecation-note"><b>This method has been removed.</b> Use the newer <a href="#smsound-onposition" onclick="resetFilter()">SMSound.onPosition()</a> as a replacement.</dd>\r
+<!--\r
+ <dd>Fires when a playing, fully-loaded sound has reached <code>onbeforefinishtime</code> (eg. 5000 msec) from its end.</dd>\r
+-->\r
+ </dl>\r
+\r
+ <dl id="smsound-onconnect" class="f-block s-onconnect flash9">\r
+ <dt>onconnect()</dt>\r
+ <dd>Fires when a sound using an RTMP <code>serverURL</code> property has attempted to connect, and has either succeeded or failed. Affects <code>connected</code> property. Once connected, a stream can be requested from the RTMP server.</dd>\r
+ <dd>Example:\r
+<pre class="block"><code>var s = soundManager.createSound({<span>\r
+ id: 'rtmpTest',\r
+ serverURL: 'rtmp://localhost/test/',\r
+ url: 'song.mp3',\r
+ onconnect: function(bConnect) {\r
+ <span><span>// <b>this.connected</b> can also be used</span></span>\r
+ soundManager._writeDebug(this.id+' connected: '+(bConnect?'true':'false'));\r
+ }\r
+</span>}).play();<span><span> // will result in connection being made</span></span></code></pre>\r
+ </dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-onfinish" class="f-block s-onfinish">\r
+ <dt>onfinish()</dt>\r
+ <dd>Fires when a playing sound has reached its end. By this point, relevant properties like <code>playState</code> will have been reset to non-playing status.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-onid3" class="f-block s-onid3">\r
+ <dt id="onid3">onid3()</dt>\r
+ <dd>Fires when ID3 data has been received. Relevant property is <code>id3</code>, which is an object literal (JSON)-style object. Only fields with data will be populated.</dd>\r
+ <dd>Note that ID3V2 data is located at the beginning (header) of an MP3 file and will load almost immediately, whereas ID3V1 data is at the end and will not be received until the MP3 has fully loaded.</dd>\r
+ <dd>\r
+ Example handler code:\r
+ <div>\r
+<pre class="block"><code>soundManager._writeDebug(<span>'sound '+this.id+' ID3 data received'</span>);\r
+var prop = null;\r
+var data = '';\r
+for (prop in this.id3) {\r
+ data += prop+': '+this.id3[prop]+','; <span><span>// eg. title: Loser, artist: Beck</span></span>\r
+}</code></pre>\r
+ </div>\r
+ </dd>\r
+ <dd>Refer to the <a href="http://livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002676.html" title="Flash 8 Sound.id3 property documentation">Flash 8 Sound.id3</a> documentation for a list of ID3 properties.</dd>\r
+ <dd>When parsing ID3 data, it is best to check for the existance of ID3V1 data first, and apply ID3V2 if no matching ID3V1 data is defined. (V1 should "inherit" from V2, ideally, if available.)</dd>\r
+ <dd>Note that Flash's cross-domain security restrictions may prevent access to ID3 information, even though the MP3 itself can be loaded. (crossdomain.xml files on the remote host can grant Flash permission to access this.)</dd>\r
+ <dd>Also note some <a href="#id3-parsing" onclick="resetFilter()">issues with parsing ID3 from iTunes</a>.</dd>\r
+ </dl>\r
+\r
+\r
+ <dl id="smsound-onjustbeforefinish" class="f-block s-onjustbeforefinish">\r
+ <dt>onjustbeforefinish()</dt>\r
+ <dd class="deprecation-note"><b>This method has been removed.</b> Use the newer <a href="#smsound-onposition" onclick="resetFilter()">SMSound.onPosition()</a> as a replacement.</dd>\r
+<!--\r
+ <dd>Fires approximately <code>justbeforefinishtime</code> before the end of a fully-loaded, playing sound.</dd>\r
+ <dd>This is based on a polling approach given SM2 must track the sound's position, and is approximated (eg. a 200 msec value may fire at 187 msec before the end of the sound.)</dd>\r
+-->\r
+ </dl>\r
+\r
+ <dl id="smsound-onload" class="f-block s-onload">\r
+ <dt>onload(<span>boolean:success</span>)</dt>\r
+ <dd>Fires on sound load. Boolean reflects successful load (true), or fail/load from cache (false).</dd>\r
+ <dd>False value should seemingly only be for failure, but appears to be returned for load from cache as well. This strange behaviour comes from Flash. More detail may be available from the Flash 8 sound object documentation.</dd>\r
+ <dd>Failure can occur if the Flash sandbox (security) model is preventing access, for example loading SoundManager 2 on the local file system and trying to access an MP3 on a network (or internet) URL. (Security can be configured in the Flash security panel, [<a href="#fpgss" title="Configure your Flash player security settings" onclick="resetFilter()">see here</a>].)</dd>\r
+ <!-- <dd>Example: <code>soundManager.createSound('<span>mySound</span>','<span>/audio/mysoundfile.mp3</span>');</code></dd> -->\r
+ </dl>\r
+\r
+ <dl id="smsound-onpause" class="f-block s-onpause">\r
+ <dt>onpause()</dt>\r
+ <dd>Fires when a sound pauses, eg. via <code>sound.pause()</code>.</dd>\r
+ <dd>Example: <code>soundManager.pause('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-onplay" class="f-block s-onplay">\r
+ <dt>onplay()</dt>\r
+ <dd>Fires when <code>sound.play()</code> is called.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-onresume" class="f-block s-onresume">\r
+ <dt>onresume()</dt>\r
+ <dd>Fires when a sound resumes playing, eg. via <code>sound.resume()</code>.</dd>\r
+ <dd>Example: <code>soundManager.resume('<span>mySound</span>');</code></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-onsuspend" class="f-block s-onsuspend">\r
+ <dt>onsuspend()</dt>\r
+ <dd>HTML5-only event: Fires when a browser has chosen to stop downloading of an audio file.</dd>\r
+ <dd>Per spec: "The user agent is intentionally not currently fetching media data, but does not have the entire media resource downloaded."</dd>\r
+ <dd>One use case may be catching the behaviour where mobile Safari (iOS) will not auto-load or auto-play audio without user interaction, and using this event to show a message where the user can click/tap to start audio.</dd>\r
+ <dd>The HTML5 <code>stalled</code> event may also fire in desktop cases and might behave differently across browsers and platforms, so careful testing is recommended.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-onstop" class="f-block s-onstop">\r
+ <dt>onstop()</dt>\r
+ <dd>Fires when <code>sound.stop()</code> is explicitly called. For natural "sound finished" <code>onfinish()</code> case, see below.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-whileloading" class="f-block s-whileloading s-bytesloaded s-bytestotal">\r
+ <dt>whileloading()</dt>\r
+ <dd>Fires at a regular interval when a sound is loading and new data has been received. The relevant, updated property is <code>bytesLoaded</code>.</dd>\r
+ <dd>Example handler code: <code>soundManager._writeDebug(<span>'sound '+this.id+' loading, '+this.bytesLoaded+' of '+this.bytesTotal</span>);</code></dd>\r
+ <dd>Note that the <code>duration</code> property starts from 0 and is updated during <code>whileloading()</code> to reflect the duration of currently-loaded sound data (ie. when a 4:00 MP3 has loaded 50%, the duration will be reported as 2:00 in milliseconds.) However, an estimate of final duration can be calculated using <code>bytesLoaded</code>, <code>bytesTotal</code> and <code>duration</code> while loading. Once fully-loaded, <code>duration</code> will reflect the true and accurate value.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-whileplaying" class="f-block s-whileplaying">\r
+ <dt>whileplaying()</dt>\r
+ <dd>Fires at a regular interval when a sound is playing, and a position (time) change is detected. The relevant, updated property is <code>position</code>.</dd>\r
+ <dd>Example handler code: <code>soundManager._writeDebug(<span>'sound '+this.id+' playing, '+this.position+' of '+this.duration</span>);</code></dd>\r
+ </dl>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+\r
+ <div id="sound-object-properties" class="columnar">\r
+\r
+ <div class="c2">\r
+\r
+ <div class="f-block">\r
+\r
+ <h3 id="soundmanager-sound-properties">Sound Object Properties</h3>\r
+ <p>Each sound object inherits these properties from soundManager.defaultOptions. They can be set individually or at once when enclosed in object literal form to either <code>createSound()</code> or <code>play()</code>.</p>\r
+\r
+ </div>\r
+\r
+ <div style="margin-top:2em">\r
+\r
+ <dl id="smsound-id" class="f-block s-id">\r
+ <dt>id</dt>\r
+ <dd>Sound ID string as provided from the <code>id</code> parameter via <code>createSound()</code>. Can be referenced as <code>this.id</code> from within sound object event handlers such as <code>onload()</code>, <code>whileloading()</code> or <code>whileplaying()</code>, etc.</dd>\r
+ <dd>If an ID is known, the related SMSound object can be retrieved via <code>getSoundById</code> or directly referencing <code>sounds[id]</code> on the SoundManager global object.</dd>\r
+ <dd><b>Legacy note:</b> The sound ID property used to be referenced as <b>sID</b> from within the sound object; this name is maintained for backward compatibility.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-url" class="f-block s-url">\r
+ <dt>url</dt>\r
+ <dd>The specified URL from which the sound is loaded, typically over HTTP. Can be referenced as <code>this.url</code> from within sound object event handlers such as <code>onload()</code> or <code>whileplaying()</code>, etc.</dd>\r
+ <dd><b>Experimental feature</b>: Multiple formats/encodings can now be applied to the <code>url</code> parameter by specifying an array instead of a single string.</dd>\r
+ <dd>Example:\r
+<pre class="block"><code>soundManager.createSound({<span>\r
+ id: 'foo',\r
+ url: ['bar.ogg','bar.mp3']\r
+});</span></code></pre></dd>\r
+ <dd>SoundManager 2 will use the first playable URL it finds (according to <code>canPlayURL()</code> and/or <code>canPlayType()</code>), and the URL property will then reflect the playable URL after that point. Note that this means the original array data will be lost.</dd>\r
+ <dd>In this alternate format, the array accepts "type" attributes.</dd>\r
+ <dd>\r
+<pre class="block"><code>soundManager.createSound({<span>\r
+ id: 'foo',\r
+ <span>// useful for URLs without obvious filetype extensions</span>\r
+ url: [\r
+ {type:'audio/mp3',url:'/path/to/play.php?song=123'},\r
+ {type:'audio/mp4',url:'/path/to/play.php?song=256'}\r
+ ]\r
+});</span></code></pre></dd>\r
+ </dl>\r
+ \r
+ <dl id="smsound-serverurl" class="f-block s-serverurl">\r
+ <dt>serverURL</dt>\r
+ <dd><b>Note: <em>Experimental feature.</em></b> Only for use with RTMP streaming, ie., Flash Media Server and similar servers.</dd>\r
+ <dd>The RTMP server address which Flash will connect to using a <a href="http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/net/NetStream.html" title="NetStream documentation">NetStream</a> object. Only the server address is specified here, when RTMP is in use; the <code>url</code> property is used to point to a specific resource on the server.</dd>\r
+ <dd>Example:\r
+<pre class="block"><code>soundManager.createSound({<span>\r
+ id: 'mySound',\r
+ serverURL: 'rtmp://localhost/rtmpDemo/', <span><span>// RTMP server</span></span>\r
+ url: 'mysong.mp3' <span><span>// path to stream</span></span>\r
+}</span>).play();</code></pre></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-usepolicyfile" class="f-block s-usepolicyfile">\r
+ <dt>usePolicyFile</dt>\r
+ <dd>Boolean value (default: <code>false</code>) which instructs Flash, when loading MP3/MP4 content from remote/third party domains, to request example.com/crossdomain.xml first in order to determine permissions for access to metadata such as ID3 info, waveform, peak and/or spectrum data.</dd>\r
+ <dd><code>usePolicyFile</code> will be automagically set to <code>true</code> if your sound options have an <code>onid3()</code> event handler, or uses sound data (peak/wave/spectrum) features. By default, Flash will not have access to this metadata on remote domains unless granted cross-domain security permissions via the crossdomain.xml file.</dd>\r
+ <dd>Consider additional HTTP traffic (albeit, perhaps with caching-like behaviour for subsequent checks?) and silent 404s in most cases given few hosts use crossdomain.xml files.</dd>\r
+ <dd>See Adobe's knowledge base for <a href="http://kb2.adobe.com/cps/963/50c96388.html" title="Adobe KB: ID3 does not load on cross-domain MP3s">related ID3 + crossdomain.xml</a> documentation.</dd>\r
+ </dl>\r
+\r
+ </div>\r
+\r
+ <div style="margin-top:2em">\r
+\r
+ <div class="f-block">\r
+\r
+ <h3 id="soundmanager-sound-dynamic-properties">Sound Object Dynamic Properties</h3>\r
+ <p>Each sound includes a number of properties that are updated throughout the life of a sound - while loading or playing, for example. Many of these properties have related events that fire when they are updated, and should be treated as read-only.</p>\r
+\r
+ </div>\r
+\r
+ <dl id="smsound-buffered" class="f-block s-buffered">\r
+ <dt>buffered</dt>\r
+ <dd>Based loosely on the native HTML5 attribute, SM2 defines <code>buffered</code> as an array of objects which include <b>start</b> and <b>end</b> position (time) values. This property is updated during the SM2 <code>whileloading</code> event; internally, SM2 uses HTML5's <code>progress</code> event to track changes.</dd>\r
+ <dd>It is important to note that the buffered values may not always be contiguous and can change, particularly if the user seeks within the file during downloading. With ranges, you can draw highlighted segments on a progress bar UI which would reflect the current "slices" of buffered data.</dd>\r
+ <dd>Example: a <code>buffered</code> array of <code>[{ start: 0, end: 2 }, { start: 5, end: 7 }];</code> shows a sound that has buffered data for the ranges 0-2 seconds, and 5-7 seconds.</dd>\r
+ <dd>In order to determine the total buffered data and thus "total percent loaded" under HTML5, you can loop through the <code>buffered</code> array and sum the total of <code>(buffered[i].end - buffered[i].start)</code>. If you want to draw ranges, you can use the start and end values of each buffered item and draw that relative to the total <code>duration</code> (normalized as <code>durationEstimate</code> for flash compatibility).</dd>\r
+ <dd>Example:\r
+<pre class="block"><code>var i, total = 0;\r
+for (i=0, j=this.buffered.length; i<j; i++) {\r
+ <span><span>// draw current range in progress bar UI?</span></span>\r
+ drawProgressUI(this.buffered[i].start, this.buffered[i].end);\r
+ <span><span>// sum of all ranges vs. whole file duration</span></span>\r
+ total += (this.buffered[i].end - this.buffered[i].start);\r
+}</code></pre>\r
+ </dd>\r
+ <dd>Note that under Flash, downloading is always sequential and thus the buffered array will always be a single item with <code>start: 0</code> and an <code>end</code> value of <code>duration</code> (eg., the amount of currently-downloaded "time").</dd>\r
+ <dd>Additional behaviour note: A browser might download additional bytes of a sound in advance under HTML5, but may only update the buffered state to reflect the newly-downloaded range(s) when the "playback head" reaches near the end of the current buffer. This can also be affected if the user seeks within the file.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-bytesloaded" class="f-block s-bytesloaded">\r
+ <dt>bytesLoaded</dt>\r
+ <dd>The number of bytes currently received while loading a sound.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-bytestotal" class="f-block s-bytestotal">\r
+ <dt>bytesTotal</dt>\r
+ <dd>The total number of bytes to be downloaded, while loading a sound.</dd>\r
+ </dl>\r
+ \r
+ <dl id="smsound-didbeforefinish" class="f-block s-didbeforefinish">\r
+ <dt>didBeforeFinish</dt>\r
+ <dd class="deprecation-note"><b>This property has been removed.</b> Use the newer <a href="#smsound-onposition" onclick="resetFilter()">SMSound.onPosition()</a> as a replacement.</dd>\r
+<!--\r
+ <dd>Boolean indicating whether <code>beforeFinish()</code> condition was reached.</dd>\r
+-->\r
+ </dl>\r
+\r
+ <dl id="smsound-didjustbeforefinish" class="f-block s-didjustbeforefinish">\r
+ <dt>didJustBeforeFinish</dt>\r
+ <dd class="deprecation-note"><b>This property has been removed.</b> Use the newer <a href="#smsound-onposition" onclick="resetFilter()">SMSound.onPosition()</a> as a replacement.</dd>\r
+<!--\r
+ <dd>Boolean indicating whether <code>justBeforeFinish()</code> condition was reached.</dd>\r
+-->\r
+ </dl>\r
+ \r
+ <dl id="smsound-duration" class="f-block s-duration">\r
+ <dt>duration</dt>\r
+ <dd>The current length of the sound, specified in milliseconds.</dd>\r
+ <dd>Note that during loading, this property reflects the length of downloaded data, not the full length, until completely loaded (see <a href="#smsound-whileloading" onclick="resetFilter()">whileloading()</a>.) For an approximate "full duration" value while loading, see <code>durationEstimate</code>.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-durationestimate" class="f-block s-durationestimate">\r
+ <dt>durationEstimate</dt>\r
+ <dd>The estimated duration of the sound, specified in milliseconds.</dd>\r
+ <dd>Due to the dynamic nature of <code>duration</code> while loading, this attempts to provide the full duration by calculating <code>parseInt((self.bytesTotal/self.bytesLoaded)*self.duration)</code> and is updated with each <code>whileloading()</code> interval.</dd>\r
+ <dd>(Flash-only): Once the sound has fully loaded (<code>onload()</code> has fired), <code>durationEstimate</code> will be updated with the final, Flash-calculated value of <code>duration</code>.</dd>\r
+ <dd>Note that the <code>durationEstimate</code> method works only with Constant Bitrate (CBR)-encoded MP3s due to the consistent data/time assumption. VBR-encoded MP3s will give inaccurate results.</dd>\r
+ <dd>HTML5 behaviour: Both <code>duration</code> and <code>durationEstimate</code> are updated at regular intervals during loading of HTML5 audio, directly referencing the duration property provided on the native HTML5 object. Unlike Flash, HTML5 typically gets the true and final duration value by the time playback begins.</dd>\r
+ </dl>\r
+ \r
+ <dl id="smsound-eqdata" class="f-block s-eqdata">\r
+ <dt title="Flash 9+ only" class="flash9">eqData = {<span>left:[], right: []</span>}</dt>\r
+ <dd>Object containing two arrays of 256 floating-point (three decimal place) values from 0 to 1, the result of an FFT on the waveform data. Can be used to draw a spectrum (frequency range) graph while playing a sound. See <a href="../demo/page-player/#debug=1" title="Muxtape.com-style page-as-playlist, with debug output" onclick="checkDomain(this,true)">Page-as-playlist demo</a> for example implementation. Requires Flash 9+.</dd>\r
+ <dd>A spectrum frequency graph reflects the level of frequencies being played, from left to right, low to high (i.e., 0 to 20,000 Hz.)</dd>\r
+ <dd><code>eqData</code> is set and updated during <code>whileplaying()</code>. A simple graph could be drawn by looping through the values and multiplying by a vertical scale value (eg. 32, thus a graph with peaks of 32 pixels.)</dd>\r
+ <dd>Example code:\r
+<pre class="block"><code>someSoundObject.whileplaying = function() {<span>\r
+ <span>// Move 256 absolutely-positioned 1x1-pixel DIVs, for example (ugly, but works)</span>\r
+ var gPixels = document.getElementById('graphPixels').getElementsByTagName('div');\r
+ var gScale = 32; <span>// draw 0 to 32px from bottom</span>\r
+ for (var i=0; i<256; i++) {\r
+ graphPixels[i].style.top = (32-(gScale+Math.ceil(this.waveformData.left[i]*gScale)))+'px';\r
+ }\r
+</span>}</code></pre>\r
+ </dd>\r
+ <dd>Related Adobe technical documentation (Flash 9/AS3 Sound() object): <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum()" title="Adobe Flash 9, sound object documentation">computeSpectrum()</a></dd>\r
+ <dd><strong>Note</strong>: Flash security measures may deny access to waveformData when loading MP3s from remote domains.</dd>\r
+ <dd><strong>Warning:</strong> This feature can eat up a lot of CPU in some cases. The amount of data passed from Flash to JS is not terribly large, but the JS-DOM updates and browser reflow can be expensive. Use with caution.</dd>\r
+ <dd><strong>Backward compatibility note:</strong> Up to SoundManager 2.95a.20090717, eqData was a single array containing one channel of data. In newer versions this is unchanged, except the array now has .left[] and .right[] objects attached to it. To ensure future compatibility, use eqData.left[0] instead of eqData[0] and so on.</dd>\r
+ </dl>\r
+ \r
+ <dl id="smsound-id3" class="f-block s-id3">\r
+ <dt>id3</dt>\r
+ <dd>An object literal populated, if applicable, when ID3 data is received (related handler: <code>onid3()</code>)</dd>\r
+ <dd>For property details, see <a href="#onid3" title="onid3() documentation" onclick="resetFilter()">onid3()</a>.</dd>\r
+ </dl>\r
+ \r
+ <dl id="smsound-isbuffering" class="f-block s-isbuffering">\r
+ <dt class="flash9">isBuffering</dt>\r
+ <dd>Boolean value reflecting the buffering state of a playing or loading object. To be notified when this property changes, see <a href="#smsound-onbufferchange" onclick="resetFilter()">onbufferchange()</a>.</dd>\r
+ <dd>Flash 9+ only. Related information on Adobe, <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/Sound.html#isBuffering">Sound.isBuffering</a>.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-ishtml5" class="f-block s-ishtml5">\r
+ <dt>isHTML5</dt>\r
+ <dd>Boolean property indicating whether a sound object is using HTML5 Audio for playback. Treat as read-only.</dd>\r
+ <dd>This should not really be relied on for anything, but it is provided as an indicator of support on a per-sound basis.</dd>\r
+ <dd><code>isHTML5</code> is set based on the URL provided to <code>createSound()</code>, and is updated when the URL changes.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-connected" class="f-block s-connected">\r
+ <dt class="flash9">connected</dt>\r
+ <dd>Boolean value reflecting the state of an RTMP server connection (when <code>serverURL</code> is used to connect to a Flash Media Server or similar RTMP service.) Calls to <code>load</code> or <code>play</code> will result in a connection attempt being made, and <code>onconnect()</code> ultimately being called.</dd>\r
+ <dd>For example code using <code>connected</code>, see <a href="#smsound-onconnect" onclick="resetFilter()">onconnect()</a>.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-loaded" class="f-block s-loaded">\r
+ <dt>loaded</dt>\r
+ <dd>Boolean value indicating load success as returned from Flash. True indicates success, False is a failure.</dd>\r
+ <dd>Because of the potential for false positives, <code>duration</code> and other properties could be checked as a test of whether sound data actually loaded. For more granular state information, see <a href="#readystate" title="SMSound readyState documentation" onclick="resetFilter()">readyState</a>.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-muted" class="f-block s-muted">\r
+ <dt>muted</dt>\r
+ <dd>Boolean indicating muted status. True/False.</dd>\r
+ <dd>Treat as read-only; use <code>mute()</code>, <code>unmute()</code> and <code>toggleMute()</code> methods to affect state.</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-paused" class="f-block s-paused">\r
+ <dt>paused</dt>\r
+ <dd>Boolean indicating pause status. True/False.</dd>\r
+ <dd>Treat as read-only; use <code>pause()</code>, <code>resume()</code> and <code>togglePause()</code> methods to affect state.</dd>\r
+ </dl>\r
+ \r
+ <dl id="smsound-peakdata" class="f-block s-peakdata">\r
+ <dt title="Flash 9+ only" class="flash9">peakData = {<span>left:0.0, right:0.0</span>}</dt>\r
+ <dd>Object literal format including <code>left</code> and <code>right</code> properties with floating-point values ranging from 0 to 1, indicating "peak" (volume) level. Updated during <code>whileplaying()</code>. See <a href="../demo/page-player/#debug=1" title="Muxtape.com-style page-as-playlist, with debug output" onclick="checkDomain(this,true)">Page-as-playlist demo</a> as one example. Requires Flash 9+.</dd>\r
+ <dd>Example (within relevant sound object handler):\r
+<pre class="block"><code>someSoundObject.whileplaying = function() {<span>\r
+ soundManager._writeDebug('Peaks, L/R: '+this.peakData.left+'/'+this.peakData.right);\r
+</span>}</code></pre></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-playstate" class="f-block s-playstate">\r
+ <dt>playState</dt>\r
+ <dd>Numeric value indicating the current playing state of the sound.</dd>\r
+ <dd>0 = stopped/uninitialised</dd>\r
+ <dd>1 = playing <em>or</em> buffering sound (play has been called, waiting for data etc.)</dd>\r
+ <dd>Note that a 1 may not always guarantee that sound is being heard, given buffering and autoPlay status.</dd>\r
+ </dl>\r
+\r
+\r
+ <dl id="smsound-position" class="f-block s-position">\r
+ <dt>position</dt>\r
+ <dd>The current location of the "play head" within the sound, specified in milliseconds (1 sec = 1000 msec).</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-readystate" class="f-block s-readystate s-onload">\r
+ <dt id="readystate">readyState</dt>\r
+ <dd>Numeric value indicating a sound's current load status</dd>\r
+ <dd>0 = uninitialised</dd>\r
+ <dd>1 = loading</dd>\r
+ <dd>2 = failed/error</dd>\r
+ <dd>3 = loaded/success</dd>\r
+ <dd>Under Flash, <code>readyState</code> will move from 0 to 1, and then change to 3 when the sound's <code>onload()</code> event fires (and all bytes have loade.)</dd>\r
+ <dd>Under HTML5, <code>readyState</code> will move from 0 to 1 when initializing the HTTP request (from <code>load()</code>), and will quickly change to 3 when the sound is ready to play. Note that HTML5 is buffer-based and <code>onload()</code> means "enough audio data has buffered to begin playback".</dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-type" class="f-block s-type">\r
+ <dt>type</dt>\r
+ <dd>A MIME type-like string eg. <code>audio/mp3</code>, used as a hint for SM2 to determine playability of a link with methods like <code>canPlayURL()</code>.</dd>\r
+ <dd>This can be helpful when you have a sound URL that does not have an .mp3 extension, but serves MP3 data (eg., a PHP or other CGI script.)</dd>\r
+ <dd>Example:\r
+<pre class="block"><code>var s = soundManager.createSound({<span>\r
+ id: 'aSound',\r
+ url: '/path/to/some.php?songID=123',\r
+ type: 'audio/mp3' <span><span>// indicates an MP3 link, so SM2 can handle it appropriately</span></span>\r
+</span>});</code></pre></dd>\r
+ </dl>\r
+\r
+ <dl id="smsound-waveformdata" class="f-block s-waveformdata">\r
+ <dt title="Flash 9+ only" class="flash9">waveformData = {<span>left:[], right:[]</span>}</dt>\r
+ <dd>Array of 256 floating-point (three decimal place) values from -1 to 1, can be used to draw a waveform while playing a sound. See <a href="../demo/page-player/#debug=1" title="Muxtape.com-style page-as-playlist, with debug output" onclick="checkDomain(this,true)">Page-as-playlist demo</a> for example implementation. Requires Flash 9+.</dd>\r
+ <dd><code>waveformData</code> is set and updated during <code>whileplaying()</code>. A simple graph could be drawn by looping through the values and multiplying by a vertical scale value (eg. 32, which would make a graph with peaks of -32 and +32 pixels.)</dd>\r
+ <dd>Example code:\r
+ <pre class="block"><code>someSoundObject.whileplaying = function() {<span>\r
+ <span>// Move 256 absolutely-positioned 1x1-pixel DIVs, for example (ugly, but works)</span>\r
+ var gPixels = document.getElementById('graphPixels').getElementsByTagName('div');\r
+ var gScale = 32; <span>// draw -32 to +32px from "zero" (i.e., center Y-axis point)</span>\r
+ for (var i=0; i<256; i++) {\r
+ graphPixels[i].style.top = (gScale+Math.ceil(this.waveformData.left[i]*-gScale))+'px';\r
+ }\r
+</span>}</code></pre>\r
+ </dd>\r
+ <dd><strong>SM2 implementation note</strong>: <code>waveformData</code> contains both left and right channels, and the data represents a raw sound wave rather than a frequency spectrum.</dd>\r
+ <dd>Related Adobe technical documentation (Flash 9/AS3 Sound() object): <a href="http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum()" title="Adobe Flash 9, sound object documentation">computeSpectrum()</a></dd>\r
+ <dd><strong>Note</strong>: Flash security measures may deny access to waveformData when loading MP3s from remote domains.</dd>\r
+ <dd><strong>Warning:</strong> This feature can eat up a lot of CPU in some cases. The amount of data passed from Flash to JS is not terribly large, but the JS-DOM updates and browser reflow can be expensive. Use with caution.</dd>\r
+ </dl>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="smsound-methods" class="columnar">\r
+\r
+ <div class="c2">\r
+ \r
+ <div class="f-block">\r
+ <h3>SMSound Object Methods</h3>\r
+ <p class="in">SoundManager provides wrappers for most SMSound methods - eg. <code>soundManager.play('<span>mySound</span>')</code> checks for a valid sound object, and then calls <code>soundManager.sounds['<span>mySound</span>'].play()</code> on that particular object; thus, it is the same as <code>var sound = soundManager.getSoundById('mySound'); mySound.play();</code></p>\r
+ <p>The following methods can be called directly on a SMSound instance. The method calls are the same as the SoundManager global methods documented above for existing sound objects, minus the sound ID parameter.</p>\r
+ </div>\r
+\r
+\r
+ <div class="f-block"> <!-- s-play s-setposition s-pause s-resume s-togglepause s-mute s-setvolume s-setpan s-stop s-unload s-destruct -->\r
+\r
+ <dl class="tight">\r
+\r
+ <dt>destruct() <span class="archive">(also called via <a href="#soundmanager-destroysound" onclick="resetFilter()">soundManager.destroySound()</a>)</span></dt>\r
+ <dt><a href="#smsound-load" onclick="resetFilter()">load()</a></dt>\r
+ <dt><a href="#smsound-mute" onclick="resetFilter()">mute()</a></dt>\r
+ <dt><a href="#smsound-pause" onclick="resetFilter()">pause()</a></dt>\r
+ <dt><a href="#smsound-play" onclick="resetFilter()">play(<span>[options object]</span>)</a></dt>\r
+ <dt><a href="#smsound-resume" onclick="resetFilter()">resume()</a></dt>\r
+ <dt><a href="#smsound-setposition" onclick="resetFilter()">setPosition(<span>msecOffset:integer</span>)</a></dt>\r
+ <dt><a href="#smsound-togglepause" onclick="resetFilter()">togglePause()</a></dt>\r
+ <dt><a href="#smsound-setvolume" onclick="resetFilter()">setVolume(<span>volume:integer</span>)</a></dt>\r
+ <dt><a href="#smsound-setpan" onclick="resetFilter()">setPan(<span>pan:integer</span>)</a></dt>\r
+ <dt><a href="#smsound-stop" onclick="resetFilter()">stop()</a></dt>\r
+ <dt><a href="#smsound-unload" onclick="resetFilter()">unload()</a></dt>\r
+ <dt><a href="#smsound-unmute" onclick="resetFilter()">unmute()</a></dt>\r
+\r
+ </dl>\r
+\r
+ </div>\r
+\r
+ </div>\r
+ </div>\r
+ \r
+ \r
+ <!-- options -->\r
+ <div id="smdefaults" class="columnar">\r
+ \r
+ <div class="c2">\r
+ \r
+ <div class="f-block f-defaultoptions s-autoload s-buffertime s-loops s-stream s-onbeforefinish s-onbeforefinishtime s-onjustbeforefinishtime s-multishot s-multishotevents s-from s-to s-pan s-volume">\r
+\r
+ <h3 id="sound-properties">SoundManager: Default Sound Options</h3>\r
+\r
+ <p>Sound objects inherit properties from <code>soundManager.defaultOptions</code> when they are created.</p>\r
+ <p>Sound parameters can be overridden on a per-sound basis at create time, or changed dynamically in some cases. Note that none of these options are required when calling <code class="in">createSound()</code> except for <code>id</code> and <code>url</code>; the others will inherit the default values if unspecified.</p>\r
+ <p><code class="in">soundManager.defaultOptions</code> apply the properties and event handlers as specified above. Defaults are shown below as an example.</p>\r
+\r
+<pre class="small block"><code>soundManager.defaultOptions = {<span>\r
+ autoLoad: false, <span>// enable automatic loading (otherwise .load() will call with .play())</span>\r
+ autoPlay: false, <span>// enable playing of file ASAP (much faster if "stream" is true)</span>\r
+ from: null, <span>// position to start playback within a sound (msec), see <a href="../demo/api/#fitter-happier">demo</a></span>\r
+ loops: 1, <span>// number of times to play the sound. Related: <a href="../demo/api/#looping">looping</a> (API demo)</span>\r
+ multiShot: true, <span>// let sounds "restart" or "chorus" when played multiple times..</span>\r
+ multiShotEvents: false, <span>// allow events (onfinish()) to fire for each shot, if supported.</span>\r
+ onid3: null, <span>// callback function for "ID3 data is added/available"</span>\r
+ onload: null, <span>// callback function for "load finished"</span>\r
+ onstop: null, <span>// callback for "user stop"</span>\r
+ onfinish: null, <span>// callback function for "sound finished playing"</span>\r
+ onpause: null, <span>// callback for "pause"</span>\r
+ onplay: null, <span>// callback for "play" start</span>\r
+ onresume: null, <span>// callback for "resume" (pause toggle)</span>\r
+ position: null, <span>// offset (milliseconds) to seek to within downloaded sound.</span>\r
+ pan: 0, <span>// "pan" settings, left-to-right, -100 to 100</span>\r
+ stream: true, <span>// allows playing before entire file has loaded (recommended)</span>\r
+ to: null, <span>// position to end playback within a sound (msec), see <a href="../demo/api/#fitter-happier">demo</a></span>\r
+ type: null, <span>// MIME-like hint for canPlay() tests, eg. 'audio/mp3'</span>\r
+ usePolicyFile: false, <span>// enable crossdomain.xml request for remote domains (for ID3/waveform access)</span>\r
+ volume: 100, <span>// self-explanatory. 0-100, the latter being the max.</span>\r
+ whileloading: null, <span>// callback function for updating progress (X of Y bytes received)</span>\r
+ whileplaying: null, <span>// callback during play (position update)</span>\r
+ <span>// see optional <a href="#sound-properties-flash9" title="SoundManager 2: Additional Flash 9-based options">flash 9-specific options</a>, too</span>\r
+</span>}\r
+</code></pre>\r
+\r
+ <p class="in">As a simple example, the following code would override the default <code>autoPlay</code>, <code>pan</code> and <code>volume</code> options for a given sound:</p>\r
+\r
+<pre class="block"><code>soundManager.createSound({\r
+ <span>url: '/path/to/some.mp3',\r
+ autoPlay: true,\r
+ pan: -75,\r
+ volume: 50</span>\r
+});</code></pre> \r
+\r
+ <p class="alternate"><em>Note</em>: For live examples, see the code behind the "<a href="../demo/page-player/" title="muxtape-style page as playlist demo" onclick="checkDomain(this)">page as playlist</a>" demo which uses much of this functionality.</p>\r
+\r
+ </div>\r
+ \r
+ <div class="f-block f-defaultoptions f-flash9options f-moviestaroptions s-ismoviestar s-usepeakdata s-usewaveformdata s-useeqdata">\r
+\r
+ <h3 id="sound-properties-flash9" title="Flash 9-only" class="flash9">Sound Properties Object: Version-specific Options (Merging)</h3>\r
+\r
+ <p>Some sound properties object items (eg. <code class="in">usePeakData</code>) are flash version-specific, non-default and are intentionally separated from <code class="in">soundManager.defaultOptions</code>. Flash 9-specific options fall under this category.</p>\r
+\r
+ <p><code class="in">soundManager.flash9Options</code> and <code class="in">soundManager.movieStarOptions</code> are both defined as separate objects, and if supported according to <code class="in">flashVersion</code> and <code class="in">defaultOptions</code> parameters, are merged at the property level into <code class="in">soundManager.defaultOptions</code>.</p>\r
+\r
+<pre class="small block"><code><span><span>// Note: These are merged into soundManager.defaultOptions when <a href="#soundmanager-flashversion" title="soundManager.flashVersion parameter" onclick="resetFilter()">flashVersion</a> = 9.</span></span>\r
+\r
+soundManager.flash9Options = {<span>\r
+ isMovieStar: null, <span>// "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL</span>\r
+ usePeakData: false, <span>// enable left/right channel peak (level) data</span>\r
+ useWaveformData: false, <span>// enable sound spectrum (raw waveform data) - WARNING: May set CPUs on fire.</span>\r
+ useEQData: false, <span>// enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.</span>\r
+ onbufferchange: null, <span>// callback for "isBuffering" property change</span>\r
+ ondataerror: null <span>// callback for waveform/eq data access error (flash playing audio in other tabs/domains)</span>\r
+</span>}\r
+\r
+soundManager.movieStarOptions = {<span>\r
+ bufferTime: null <span>// seconds of data to buffer (null = flash default of 0.1 - if AAC gappy, try up to 3 seconds)</span>\r
+</span>}\r
+\r
+<span><span>// when merged, soundManager.flash9Options.isMovieStar -> soundManager.defaultOptions.isMovieStar, etc.</span></span></code></pre>\r
+ \r
+ </div>\r
+ \r
+ </div>\r
+ \r
+ </div>\r
+ \r
+ <div id="soundmanager2-dynamic-properties" class="columnar">\r
+\r
+ <div class="c2">\r
+ \r
+ <div class="f-block f-html5 f-html5only f-features f-waveformdata f-peakdata">\r
+\r
+ <h3 id="soundmanager-dynamic">SoundManager Dynamic (Runtime) Properties</h3>\r
+\r
+ <p class="in">Some properties are dynamic, determined at initialisation or later during runtime, and should be treated as read-only.</p>\r
+\r
+\r
+ <h4 id="soundmanager-features">soundManager.features Object</h4>\r
+\r
+ <p class="in">As certain sound functionality is only available beginning with Flash 9, <code>soundManager.features</code> can provide a consistent way of checking for feature support.</p>\r
+\r
+ <p>The structure (intended as read-only) is currently as follows:</p>\r
+\r
+<pre class="block"><code>soundManager.features = {<span>\r
+ buffering: <span>[boolean]</span>,\r
+ peakData: <span>[boolean]</span>,\r
+ waveformData: <span>[boolean]</span>,\r
+ eqData: <span>[boolean]</span>,\r
+ movieStar: <span>[boolean]</span>\r
+</span>}</code></pre>\r
+\r
+ <p class="in">Example (checking for <code>peakData</code> support):</p>\r
+<pre class="block"><code>if (<span>soundManager.features.peakData</span>) {<span>\r
+ <span>// do peak data-related things here</span>\r
+</span>}</code></pre>\r
+\r
+ <p class="in">The features object is populated at initialisation time; the current feature support tests simply check the value of <code>soundManager.flashVersion</code> being >= 9. This object has been added in anticipation of additional features with future versions of Flash.</p>\r
+\r
+ </div>\r
+\r
+ <h4 id="soundmanager-html5only">soundManager.html5Only [boolean, read-only]</h4>\r
+ <p>This property is set during initialization and reflects whether SM2 is running in "100% HTML5 mode", based on support for required formats defined by <code>soundManager.audioFormats</code>.</p>\r
+\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ <div id="soundmanager-events" class="columnar">\r
+\r
+ <div class="c2">\r
+ \r
+ <div class="f-block f-onload f-onerror f-oninitmovie">\r
+\r
+ <h3>SoundManager Core Events</h3>\r
+\r
+ <p class="in">The following events are attached to the <code>soundManager</code> global object and are useful for detecting the success/failure of the API's initialisation.</p>\r
+ <p>Keep in mind that these core events are effectively asynchronous (ie., they may fire long before or after <code class="in">window.onload()</code>) and therefore should not be relied on as the "ready" event for starting your application. Use the standard "DOM content loaded" or window load events for your own initialization routines.</p>\r
+\r
+ <dl>\r
+\r
+ <dt title="method(object:function)">onready(<span>callback:function(status),[scope]</span>)</dt>\r
+ <dd title="callback:function">Queue <code>onload()</code>-style event listener(s), triggered when soundManager has successfully started.</dd>\r
+ <dd>Example: <code>soundManager.onready(<span>myOnReadyHandler</span>); soundManager.onready(<span>myOtherHandler</span>);</code></dd>\r
+ <dd>For more detail and examples, see <a href="#soundmanager-onready" onclick="resetFilter()">soundManager.onready()</a>.</dd>\r
+\r
+ <dt title="method(object:function)">ontimeout(<span>callback:function(status),[scope]</span>)</dt>\r
+ <dd title="callback:function">Queue <code>onload()</code>-style event listener(s), triggered when soundManager has successfully started.</dd>\r
+ <dd>Example: <code>soundManager.ontimeout(<span>myOnTimeoutHandler</span>); soundManager.ontimeout(<span>myOtherHandler</span>);</code></dd>\r
+ <dd>For more detail and examples, see <a href="#soundmanager-ontimeout" onclick="resetFilter()">soundManager.ontimeout()</a>.</dd>\r
+\r
+ <dt id="soundmanager-onerror" title="object:function">onerror(status)</dt>\r
+ <dd class="deprecation-note"><b>Deprecation note:</b> Use the newer <a href="#soundmanager-ontimeout" onclick="resetFilter()">soundManager.ontimeout()</a> instead of this method.</dd>\r
+<!--\r
+ <dd>Function called when SoundManager fails to successfully initialise after Flash attempts an init call via ExternalInterface.</dd>\r
+ <dd>Example: <code>soundManager.onerror = <span>function(status) { alert('SoundManager failed to load: ' + status.type); }</span></code></dd>\r
+ <dd>This handler should be called if there is an ExternalInterface problem or other exceptions that fire when the initialisation function is called.</dd>\r
+ <dd>If a specific type of error occurred, it will be provided in the status object as a <code>type</code> parameter.</dd>\r
+ <dd>If you want multiple listeners for this event, see <a href="#soundmanager-ontimeout" onclick="resetFilter()">soundManager.ontimeout()</a>.</dd>\r
+-->\r
+\r
+ <dt id="soundmanager-oninitmovie" title="object:function">oninitmovie()</dt>\r
+ <dd class="deprecation-note"><b>Deprecation note:</b> Use the newer <a href="#soundmanager-ontimeout" onclick="resetFilter()">soundManager.ontimeout()</a> instead of this method.</dd>\r
+<!--\r
+ <dd>Function called immediately after the SWF is either written to (or retrieved from) the DOM as part of the start-up process. This event can be useful if you wish to implement your own start-up time-out, eg. for handling flash blockers, start-up failures or other custom messaging.</dd>\r
+ <dd>Example: <code>soundManager.oninitmovie = <span>function(){ alert('SWF init.'); }</span></code></dd>\r
+-->\r
+ <dt id="soundmanager-onload" title="object:function">onload()</dt>\r
+\r
+ <dd class="deprecation-note"><b>Deprecation note:</b> Use the newer <a href="#soundmanager-onready" onclick="resetFilter()">soundManager.onready()</a> instead of this method.</dd>\r
+<!--\r
+\r
+ <dd>Function called when SoundManager has successfully loaded.</dd>\r
+ <dd>Example: <code>soundManager.onload = <span>function() { alert('SoundManager ready to use'); }</span></code></dd>\r
+ <dd>Once this function has been called, all core methods will be available to use.</dd>\r
+ <dd>Note that <code>onload()</code> is not called when SoundManager fails to load; instead, <code>onerror()</code> is called.</dd>\r
+ <dd>If you want multiple listeners for this event, see <a href="#soundmanager-onready" onclick="resetFilter()">soundManager.onready()</a>.</dd>\r
+-->\r
+\r
+ </dl>\r
+\r
+ </div>\r
+ \r
+ \r
+ </div>\r
+ </div>\r
+ \r
+ <div class="columnar">\r
+\r
+ <div class="c2">\r
+ \r
+ <div class="f-block">\r
+\r
+ <h3>SoundManager Object Collections</h3>\r
+\r
+ <dl>\r
+ <dt title="object:array">soundIDs[]</dt>\r
+ <dd>An array of sound ID strings, ordered by creation. Can be used to iterate through <code>sounds{}</code> by ID.</dd>\r
+ <dt title="object:array">sounds{}</dt>\r
+ <dd>An object literal/JSON-style instance of <code>SMSound</code> objects indexed by sound ID (as in <code>sounds['mySound']</code> or <code>sounds.mySound</code>), used internally by SoundManager. <code>soundManager.getSoundById()</code> may be used as an alternate to directly accessing this object.</dd>\r
+ </dl>\r
+\r
+ </div>\r
+ \r
+ </div>\r
+ </div>\r
+ \r
+ <div id="sound-options-object" class="columnar">\r
+\r
+ <div class="c2">\r
+ \r
+ <div class="f-block s-onload"> <!-- f-createsound s-id s-url s-autoload s-autoplay s-onload -->\r
+\r
+ <h3 id="object-literal-format">Object Literal Format</h3>\r
+\r
+ <p>Sounds can be created with instance-specific parameters in an object literal (JSON) format, where omitted parameters inherit default values as defined in soundManager.</p>\r
+\r
+<pre class="block"><code>soundManager.createSound({<span>\r
+ id: 'mySound',\r
+ url: '/path/to/some.mp3',\r
+ autoLoad: true,\r
+ autoPlay: false,\r
+ onload: function() {\r
+ alert('The sound '+this.id+' loaded!');\r
+ },\r
+ volume: 50\r
+</span>});</code></pre>\r
+\r
+ <p>This object can also be passed as an optional argument to the <code class="in">play</code> method, overriding options set at creation time.</p>\r
+\r
+ <p>For a full list of available options, see <a href="#sound-properties" title="SoundManager 2 API info: Sound Properties" onclick="resetFilter()">Sound Properties Object</a></p>\r
+\r
+ </div>\r
+\r
+ \r
+ </div>\r
+\r
+ </div>\r
+\r
+ <!-- /main -->\r
+ </div>\r
+\r
+ <!-- /main-wrapper -->\r
+ </div>\r
+\r
+ <!-- /content -->\r
+ </div>\r
+\r
+<script type="text/javascript">\r
+init();\r
+</script>\r
+\r
+ \r
+</body>\r
+\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Resources</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Sound and media web projects related to SoundManager 2." />\r
+<meta name="keywords" content="javascript sound, javascript audio, media web, embedded audio, embedded video" />\r
+<meta name="robots" content="all" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta name="copyright" content="Copyright (C) 1997 onwards Scott Schiller" />\r
+<meta name="language" content="en-us" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="../../demo/index.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="../../demo/index.js"></script>\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ debugMode: false,\r
+ url: '../../swf/'\r
+});\r
+</script>\r
+</head>\r
+\r
+<body>\r
+ \r
+<div id="content">\r
+\r
+ <div id="top">\r
+\r
+ <h1>SoundManager 2: Resources</h1>\r
+\r
+ <div id="nav">\r
+ <ul>\r
+\r
+ <li>\r
+ <a href="../../">Home</a>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="#">Demos</a>\r
+ <ul>\r
+ <li><a href="../../demo/template/">Basic Template</a></li>\r
+ <li><a href="../../demo/api/">API Examples</a></li>\r
+ <li><a href="../../demo/bar-ui/">Bar UI</a></li>\r
+ <li><a href="../../demo/play-mp3-links/" class="exclude">Playable MP3 links</a></li>\r
+ <li><a href="../../demo/mp3-player-button/" class="exclude">Basic MP3 Play Button</a></li>\r
+ <li><a href="../../demo/page-player/">Muxtape-style UI</a></li>\r
+ <li><a href="../../demo/360-player/">360° Player UI</a></li>\r
+ <li><a href="../../demo/mpc/">Drum Machine (MPC)</a></li>\r
+ <li><a href="../../demo/animation/">DOM/Animation Demos</a></li>\r
+ <li><a href="../../demo/flashblock/">FlashBlock Handling</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="../getstarted/">Getting Started</a>\r
+ <ul>\r
+ <li><a href="../getstarted/#how-sm2-works">How SoundManager 2 works</a></li>\r
+ <li><a href="../getstarted/#basic-inclusion">Including SM2 on your site</a></li>\r
+ <li><a href="../getstarted/#troubleshooting">Troubleshooting</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="..">Documentation</a>\r
+ <ul>\r
+ <li><a href="../#sm-config">SoundManager Properties</a></li>\r
+ <li><a href="../#sound-object-properties">Sound Object Properties</a></li>\r
+ <li><a href="../#smdefaults">Global Sound Defaults</a></li>\r
+ <li><a href="../#api">SoundManager Core API</a></li>\r
+ <li><a href="../#smsoundmethods">Sound Object (SMSound) API</a></li>\r
+ <li><a href="../generated/soundmanager2.html">Generated Documentation</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <a href="../download/">Download</a>\r
+ <ul>\r
+ <li><a href="../download/#latest">Get SoundManager 2</a></li>\r
+ <li><a href="../download/#revision-history">Revision History</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <a href="../technotes/">Technical Notes</a>\r
+ <ul>\r
+ <li><a href="../technotes/#requirements">System Requirements</a></li>\r
+ <li><a href="../technotes/#serving-audio">Serving To HTML5 + Flash Clients</a></li>\r
+ <li><a href="../technotes/#client-requests">How Clients Download Audio</a></li>\r
+ <li><a href="../technotes/#mobile-device-limitations">Mobile Device Limitations</a></li>\r
+ <li><a href="../technotes/#debug-output">Debug + Console Output</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <strong><a href="#">Resources</a></strong>\r
+ <ul>\r
+ <li><a href="#licensing">Licensing</a></li>\r
+ <li><a href="#related">Related Projects</a></li>\r
+ <li><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/">SM2 support / discussion</a></li>\r
+ <li><a href="http://www.schillmania.com/content/react/contact/">Contact Info @ Schillmania.com</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ <div class="clear"></div>\r
+ </div>\r
+ \r
+ </div>\r
+\r
+ <div id="main-wrapper">\r
+\r
+ <div id="main" class="triple">\r
+\r
+ <div class="columnar"> \r
+\r
+ <div class="c1">\r
+ <h2>Licensing</h2>\r
+ <p>BSD licensed.</p>\r
+ </div>\r
+\r
+ <div class="c2">\r
+ <h3>SoundManager 2 License</h3>\r
+ <p>SoundManager 2 is provided under a <a href="../../license.txt" title="SoundManager 2 BSD license" class="norewrite">BSD license</a>.</p>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ \r
+ <div id="related" class="columnar">\r
+ <div class="c1">\r
+ <h2>General + Related</h2>\r
+ <p>Other information about SoundManager 2.</p>\r
+ </div>\r
+ \r
+ <div class="c2">\r
+ \r
+ <div class="f-block c-about">\r
+ <h3 id="general">General</h3>\r
+ <p>SoundManager was written to meet a desire to have Javascript-driven sound for interactive web-based projects, and "to make it easy to play MP3s in the browser." It is free for use in both personal and commercial projects (see license, above.) It was originally developed for personal use and has been packaged with the hopes of being useful to others.</p>\r
+ </div>\r
+\r
+ <div class="f-block">\r
+\r
+ <h3 id="related-projects">Related Projects</h3>\r
+\r
+ <h4 id="html5-compatibility">JavaScript/DHTML/Flash MP3 and video players</h4>\r
+ <p>Searching for an included/embedded-type media player? These related projects might be of use.</p>\r
+ <ul>\r
+ <li><a href="http://jplayer.org/" title="Happyworm jPlayer">jPlayer</a> is a HTML5/Flash player which jQuery fans should feel at home with; several different players and skins are provided.</li>\r
+ <li><a href="http://flowplayer.org" title="Flowplayer does video, with free and commercial versions available">Flowplayer</a> is a pretty solid GPL Flash-based video player with a JS API.</li>\r
+ <li><a href="http://www.longtailvideo.com/players/jw-flv-player/">JW FLV Player</a> is a general-purpose Flash-based player which can handle FLV, MP3, MP4 and a number of image formats.</li>\r
+ <li><a href="http://jssoundkit.sourceforge.net/" title="A Javascript/Flash MP3 player">JSSoundkit</a>, an MP3 player with a simple UI.</li>\r
+ </ul>\r
+\r
+ <h3 id="external-links">Links</h3>\r
+ <ul>\r
+ <li><a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 Web Home">SoundManager 2 Project Page</a> (schillmania.com)</li>\r
+ <li><a href="http://livedocs.adobe.com/flash/8/" title="Info on Flash 8's sound object">Flash 8 / AS2 documentation</a> (livedocs.macromedia.com) - download, open index.html under "main" subdirectory, use navigation: ActionScript 2.0 Language Reference -> ActionScript Classes -> Sound</li>\r
+ <li id="fpgss"><a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html" title="Configure Flash security settings">Flash Player Global Security Settings Panel</a> - Configure your Flash Player security, eg., allow SM2 .swf on your local filesystem to have internet access for testing by whitelisting its location eg. file://Users/Administrator/Desktop/soundmanager... etc. Alternately, view the page over HTTP and access internet resources that way.</li> \r
+ </ul>\r
+\r
+ </div>\r
+\r
+ <div class="f-block c-about">\r
+ <h3 id="sonundmanager-about">About</h3>\r
+ <p><a href="http://www.schillmania.com" title="Scott Schiller's experimental design site">Scott Schiller</a> (<a href="http://www.schillmania.com/content/react/contact/" title="Contact Info @ Schillmania.comrmation for Scott Schiller">contact</a>) is a Front-end Engineer (previously "Web Developer") who builds fun creative and technical stuff on the web - or failing that, tries - when he has free time. He likes building cool things which contribute to, yet enjoys mocking, the <a href="http://www.schillmania.com/content/opinion/2005/10/dont-believe-the-web-20-hype/" title="Web 2.0: Don't Believe The Hype!">Web 2.0 meme</a>. (See <a href="http://www.schillmania.com/content/entries/2006/08/how-web20-aware-are-you/" title="Take the Web 2.0 Awareness Test!">How Web 2.0-Aware Are You?</a>)</p>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ \r
+ <div id="col3" class="c3">\r
+\r
+ <div id="support-wrapper">\r
+ <div id="get-satisfaction" class="box">\r
+ <div id="gsfn_list_widget">\r
+ <h2><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/" title="User discussion, FAQs and support for SoundManager 2" rel="nofollow">Discussion / Support</a><span class="l"></span><span class="r"></span></h2>\r
+ <div id="gsfn_content"></div>\r
+ <div class="powered_by"><a href="http://getsatisfaction.com/" rel="nofollow">Get Satisfaction support network</a></div>\r
+ </div>\r
+ <!-- /.box -->\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="shortcuts">\r
+\r
+<!--\r
+ <div class="box">\r
+\r
+ <h2>Shortcuts<span class="l"></span><span class="r"></span></h2>\r
+\r
+ <ul class="first">\r
+ <li onclick="setFilter(event,'c-')" class="ignore">\r
+\r
+ <ul>\r
+\r
+ <li>Demos</li>\r
+ <li>Getting Started</li>\r
+ <li>Basic Use</li>\r
+ <li>Download</li>\r
+ <li>Requirements</li>\r
+ <li>Limitations</li>\r
+\r
+ <li>Debug Output</li>\r
+ <li>Revision History</li>\r
+ <li>About</li>\r
+ </ul>\r
+\r
+ </li>\r
+ </ul>\r
+\r
+ </div>\r
+-->\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="clear"></div>\r
+\r
+ <!-- /main-wrapper -->\r
+ </div>\r
+\r
+ <!-- /main -->\r
+ </div>\r
+\r
+ <!-- /content -->\r
+ </div>\r
+\r
+<script type="text/javascript">\r
+init();\r
+</script>\r
+ \r
+</body>\r
+\r
+</html>\r
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">\r
+<head>\r
+<title>SoundManager 2: Technical Notes</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Requirements and Specifications for SoundManager 2, the Javascript Sound API" />\r
+<meta name="keywords" content="javascript sound, javascript audio, technical specifications, requirements, licensing" />\r
+<meta name="robots" content="all" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta name="copyright" content="Copyright (C) 1997 onwards Scott Schiller" />\r
+<meta name="language" content="en-us" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="../../demo/index.css" />\r
+<script type="text/javascript" src="../../script/soundmanager2.js"></script>\r
+<script type="text/javascript" src="../../demo/index.js"></script>\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ url: '../../swf/',\r
+ debugMode: true,\r
+ consoleOnly: false,\r
+ debugFlash: true\r
+});\r
+</script>\r
+</head>\r
+\r
+<body>\r
+ \r
+<div id="content">\r
+\r
+ <div id="top">\r
+\r
+ <h1>SoundManager 2: Technical Notes</h1>\r
+\r
+ <div id="nav">\r
+ <ul>\r
+\r
+ <li>\r
+ <a href="../../">Home</a>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="#">Demos</a>\r
+ <ul>\r
+ <li><a href="../../demo/template/">Basic Template</a></li>\r
+ <li><a href="../../demo/api/">API Examples</a></li>\r
+ <li><a href="../../demo/bar-ui/">Bar UI</a></li>\r
+ <li><a href="../../demo/play-mp3-links/" class="exclude">Playable MP3 links</a></li>\r
+ <li><a href="../../demo/mp3-player-button/" class="exclude">Basic MP3 Play Button</a></li>\r
+ <li><a href="../../demo/page-player/">Muxtape-style UI</a></li>\r
+ <li><a href="../../demo/360-player/">360° Player UI</a></li>\r
+ <li><a href="../../demo/mpc/">Drum Machine (MPC)</a></li>\r
+ <li><a href="../../demo/animation/">DOM/Animation Demos</a></li>\r
+ <li><a href="../../demo/flashblock/">FlashBlock Handling</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="../getstarted/">Getting Started</a>\r
+ <ul>\r
+ <li><a href="../getstarted/#how-sm2-works">How SoundManager 2 works</a></li>\r
+ <li><a href="../getstarted/#basic-inclusion">Including SM2 on your site</a></li>\r
+ <li><a href="../getstarted/#troubleshooting">Troubleshooting</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="..">Documentation</a>\r
+ <ul>\r
+ <li><a href="../#sm-config">SoundManager Properties</a></li>\r
+ <li><a href="../#sound-object-properties">Sound Object Properties</a></li>\r
+ <li><a href="../#smdefaults">Global Sound Defaults</a></li>\r
+ <li><a href="../#api">SoundManager Core API</a></li>\r
+ <li><a href="../#smsoundmethods">Sound Object (SMSound) API</a></li>\r
+ <li><a href="../generated/soundmanager2.html">Generated Documentation</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <a href="../download/">Download</a>\r
+ <ul>\r
+ <li><a href="../download/#latest">Get SoundManager 2</a></li>\r
+ <li><a href="../download/#revision-history">Revision History</a></li>\r
+ </ul>\r
+ </li>\r
+ \r
+ <li>\r
+ <strong><a href="../technotes/">Technical Notes</a></strong>\r
+ <ul>\r
+ <li><a href="../technotes/#requirements">System Requirements</a></li>\r
+ <li><a href="../technotes/#serving-audio">Serving To HTML5 + Flash Clients</a></li>\r
+ <li><a href="../technotes/#client-requests">How Clients Download Audio</a></li>\r
+ <li><a href="../technotes/#mobile-device-limitations">Mobile Device Limitations</a></li>\r
+ <li><a href="../technotes/#debug-output">Debug + Console Output</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ <li>\r
+ <a href="../resources/">Resources</a>\r
+ <ul>\r
+ <li><a href="../resources/#licensing">Licensing</a></li>\r
+ <li><a href="../resources/#related">Related Projects</a></li>\r
+ <li><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/">SM2 support / discussion</a></li>\r
+ <li><a href="http://www.schillmania.com/content/react/contact/">Contact Info @ Schillmania.com</a></li>\r
+ </ul>\r
+ </li>\r
+\r
+ </ul>\r
+ <div class="clear"></div>\r
+ </div>\r
+ \r
+ </div>\r
+\r
+ <div id="main-wrapper">\r
+\r
+ <div id="main" class="triple">\r
+\r
+ <div id="filter-box" class="columnar">\r
+\r
+ <div class="c1">\r
+ <div id="reset-filter"></div>\r
+ </div>\r
+\r
+ <div class="c2">\r
+ <div id="search-results"><!-- search results for %s --></div>\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ <div class="columnar">\r
+ \r
+ <div class="c1">\r
+ <h2>Requirements + Specifications</h2>\r
+ <p>What SM2 needs, and how it works.</p>\r
+ </div>\r
+ \r
+ <div class="c2">\r
+\r
+ <div class="f-block c-requirements">\r
+\r
+ <h3>Requirements + Specifications</h3>\r
+\r
+ <h4 style="margin-top:1.5em">Prerequisites (client)</h4>\r
+\r
+ <ul>\r
+ <li>HTML5 <code>Audio()</code> support and/or Flash plugin, version 8 or higher</li>\r
+ <li>Supported web browser + platform</li>\r
+ </ul>\r
+\r
+ <h4>Tested Browsers and Platforms</h4>\r
+\r
+ <ul>\r
+ <li>Firefox (all versions), Windows/Mac</li>\r
+ <li>Safari 1.3+ (Mac) / All Windows versions</li>\r
+ <li>Mobile Webkit: iOS 4.0 devices, iPad 3.2 (original iPad iOS release) and newer</li>\r
+ <li>Android (2.3+, confirmed on 2.3.3.)</li>\r
+ <li>Google Chrome (all versions/OSes)</li>\r
+ <li>Internet Explorer 5.0+, Windows</li>\r
+ <li>Opera 9.10 (slightly buggy, 9.5+ ideal), Windows/Mac</li>\r
+ <li>Netscape 8.0+, Windows/Mac</li>\r
+ <li>Firefox 1.5+, Linux (Flash 9 beta)</li>\r
+ </ul>\r
+\r
+ <p>In the absence of native HTML5 audio support, JavaScript-to-flash communication is used to provide Flash-based audio playback. JS-to-flash is possible through Flash 8's ExternalInterface feature, which uses a standard browser plugin architecture implemented by each browser manufacturer (see <a href="http://www.mozilla.org/projects/plugins/npruntime.html" title="Mozilla plugin scripting reference">NPAPI</a>.)</p>\r
+\r
+ <p>For further JS/flash reference, see Adobe's <a href="http://livedocs.macromedia.com/flash/8/" title="Adobe Flash 8 documentation">Flash 8 documentation</a>, under the "ExternalInterface support" page which details supported browsers.</p>\r
+\r
+ <p>Of course, not all possible combinations of browser/OS have been tested. Most modern browsers and devices should work reasonably well.</p>\r
+\r
+ </div>\r
+\r
+ <div class="f-block c-limitations">\r
+\r
+ <h3 id="caveats">Caveats + Limitations / FAQ</h3>\r
+\r
+ </div>\r
+\r
+ <div class="f-block c-limitations">\r
+\r
+ <h4>Supported sound formats (MP3 via Flash 8 and MP4/M4A/AAC via Flash 9 "MovieStar", with caveats)</h4>\r
+ <p>SM2 uses Flash's native Sound object for loading and managing sound, so it is subject to the same limitations that Flash 8 is. Perhaps a design decision, the Flash 8 sound object only supports MP3 files through the <code class="in">loadSound()</code> ActionScript method. SM2 is not able to load other sound formats, including audio-only SWF files, due to this limitation. Refer to the <a href="http://livedocs.macromedia.com/flash/8/" title="Info on Flash 8's sound object">Flash 8 documentation</a> for details.</p>\r
+\r
+ <h4>MP3 Format Caveats</h4>\r
+ <p>Additionally, some very low and very high bitrate MP3s, and Variable Bitrate (VBR) MP3s may play either too quickly or too slowly (see <a href="http://www.boutell.com/newfaq/creating/chipmunk.html" title="Flash mp3 chipmunk problem description">"the chipmunk problem"</a>); if you are encountering this issue, try re-encoding at a different bitrate (between 64 kbps and 192 kbps, for example.) Using Constant Bitrate (CBR) encoding may also alleviate this problem.</p>\r
+ <p>It has been suggested that sample rates that are neither 22/44 KHz can also contribute to this issue. 44 KHz is the standard CD-spec sample rate, and is recommended for "hi-fi" recordings.</p>\r
+\r
+ <h4>Looping</h4>\r
+ <p class="in">Perhaps due to the way Flash dynamically loads and decodes MP3 data, seamless looping doesn't seem to be fully implemented. Loops have a noticeable gap between the finish and start. This has been an issue since the original version of SoundManager. Rather than have a broken feature, the funcionality has been omitted until a solid workaround is found.</p>\r
+\r
+ <h4>Flash 8 limitations with multiShot (overlaying/"chorus") effects</h4>\r
+ <p class="in">Regarding "layering" sounds (calling <code>play()</code> on a sound multiple times): Even though a multi-shot option can be specified, it does not work with Flash 8; a single instance of a sound can only have one timeline. The current behaviour is that when <code>multiShot</code> is specified and <code>play()</code> is called on a currently-playing sound, it will restart from the beginning without an overlay.</p>\r
+ <p>However, the API does provide some creative ways (<code>onfinish</code> for looping, multiple sound objects for multi-shot layering) of working around these Flash limitations.</p>\r
+ <p>It should be noted that sounds can loop seamlessly and be layered when linked and exported to SWF from within the Flash IDE, but SoundManager does not support SWF-based audio.</p>\r
+\r
+ <h4>Flash 9 multiShot capabilities</h4>\r
+ <p class="in">The Flash 9-based version of SoundManager2 can successfully layer sounds via "multiShot", truly playing a single sound multiple times on top of itself. However the API will only call certain timing-related methods such as <code>whileplaying()</code> for the first <code>play()</code> "instance" of the sound, to avoid confusion. By contrast, simpler methods such as <code>onfinish()</code> will be called multiple times, one for each instance of <code>play()</code>.</p>\r
+\r
+ <h4 id="id3-parsing">ID3 Parsing</h4>\r
+ <p>ID3 data can differ in formatting, version and subsequently be oddly-parsed by Flash. Values may sometimes be repeated across different fields.</p>\r
+ <p>ID3 info seems to fail to load for iTunes 7-edited files, perhaps due to the format or inclusion of album artwork (image data.)</p>\r
+\r
+ <h4>Performance Notes: Caching + RAM Obeservations</h4>\r
+ <p>Flash appears to use the browser cache (presumably the OS' native, or closest browser,) so the browser's cache size and other settings may affect Flash's cache behaviour. It is safe to assume a 100 MB MP3 will probably not be cached, for example, but a 16 MB one most likely will be.</p>\r
+ <p>MP3s appear to be loaded and stored in RAM while loading over HTTP, so memory use needs to be considered for both large MP3s and streaming radio-type applications.</p>\r
+\r
+ <h4>Timing/Latency (JS + Flash, ExternalInterface-related)</h4>\r
+ <p>JavaScript-to-Flash communication is not instantaneous on slower systems, but can be much better on more modern systems. Latency (timing lag/delays) can be noted in some cases from function call to sound execution. It is possible some performance analysis can help to speed up this area for timing-critical applications involving animation etc., but this area has not been thoroughly investigated yet. Brad Neuberg has some notes on <a href="http://codinginparadise.org/weblog/2006/02/how-to-speed-up-flash-8s.html" title="Brad Neuberg - How To Speed Up ExternalInterface">speeding up ExternalInterface</a> which may be relevant.</p>\r
+ <p>Flash-to-OS/hardware latency (where flash reports progress, but no sound is heard for a number of milliseconds) may also be an unfortunate reality of Flash-based audio, varying between platform and OS version etc.</p>\r
+ <p>Additionally, MP3 files may contain audible gaps at the beginning or end by default when encoded, even if the source (eg. WAVE) file did not. Using optional "nogap" encoding options with programs such as LAME may help to remedy this.</p>\r
+ <p>Finally, the <code class="in">useHighPerformance</code> option may help with JS/flash lag. Using this option causes the flash movie to be placed with position:fixed on-screen at all times (though in a small, hidden box) and has been shown to notably improve performance on Mac OS X. As well, <code class="in">flashPollingInterval</code> will use a lower timer value, making polling calls run as quickly as reasonably possible and increasing the frequency of calls to <code class="in">whileplaying()</code>, <code class="in">whileloading()</code> and other time-related events.</p>\r
+ <p>Use these options with caution, as overly-aggressive intervals may hinder performance if event callbacks become too frequent.</p>\r
+\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ </div>\r
+\r
+ <div id="serving-audio" class="columnar">\r
+\r
+ <div class="c1">\r
+\r
+ <h2>Serving to HTML5 + Flash Clients</h2>\r
+ <p>A few notes on HTTP response headers, configuration and so forth.</p>\r
+\r
+ </div>\r
+\r
+ <div class="c2">\r
+\r
+ <h3>Tips for serving audio to HTML5 + Flash Clients</h3>\r
+ <p>HTTP response headers from your server are important. Below is a brief list of recommended practices for serving audio content to clients using HTML5, and/or Flash.</p>\r
+\r
+ <h4>HTML5</h4>\r
+\r
+ <ul>\r
+ <li>Likes <code>Content-Length</code> HTTP response headers (can affect duration and playback events if missing.)</li>\r
+ <li>Arbitrary seeking, dynamic loading/buffering works when the server supports <a href="#byte-serving">Byte Serving</a> via byte ranges, also known as HTTP partials / range requests. Without this support, behaviour falls back to a Flash-like single-connection, sequential/progressive-style download.</li>\r
+ <li>Likes a proper MIME type response from the server, e.g., <code>audio/mpeg</code> for MP3 content.</li>\r
+ </ul>\r
+\r
+ <h4>Flash</h4>\r
+\r
+ <ul>\r
+ <li>Likes <code>Content-Length</code> HTTP response headers. When missing, duration may be unknown and certain events like <code>whileloading()</code> / <code>whileplaying()</code> may not fire.</li>\r
+ <li>Does not care about MIME type or partials in server responses.</li>\r
+ </ul>\r
+\r
+ <p><b>In summary...</b></p>\r
+\r
+ <p>Always serve a proper <code>Content-Length</code> HTTP response header. For HTML5, review that HTTP partials / range requests are enabled and that you are serving the correct MIME type in your response as well.</p>\r
+ <p>Never apply <code>gzip</code> or <code>mod_deflate</code> compression to binary assets. It causes playback problems, costs CPU and in some cases, may even increase the transfer size.</p>\r
+ \r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="client-requests" class="columnar">\r
+\r
+ <div class="c1">\r
+\r
+ <h2>How Clients Download Audio</h2>\r
+ <p>Progressive, sequential HTTP vs. HTTP 206 partials / range requests.</p>\r
+\r
+ </div>\r
+\r
+ <div class="c2">\r
+\r
+ <h3>How HTML5 + Flash Clients Download Audio</h3>\r
+\r
+ <p>In terms of HTTP, assets are typically requested and downloaded in sequential byte order over a single connection. Flash typically works this way, but HTML5 clients can use behaviours that are closer to streaming - instead, using multiple requests for pieces of data.</p>\r
+\r
+ <p>Browsers can request audio from servers either sequentially or using <a href="#byte-serving">Byte Serving</a> (AKA "partials"), depending on client and server capabilities. The key difference is that with byte serving, clients request data in a "streaming" fashion and can buffer at will, therefore allowing arbitrary seeking, pausing and requesting of audio data in pieces - similar to how video playback typically works on YouTube, for example. Thus, preloading and <code>onload()</code> is less-meaningful when byte serving is involved.</p>\r
+\r
+ <h4 id="progressive-download">Traditional, "progressive" download (single request)</h4>\r
+\r
+ <p>The typical HTTP file download can be described as follows:</p>\r
+\r
+ <ul>\r
+ <li>Single HTTP request, one TCP connection</li>\r
+ <li>All bytes are sent sequentially "over the wire"</li>\r
+ <li>Network connection is closed when the download completes (or fails)</li>\r
+ <li>SoundManager 2 fires relevant sound <code>onload()</code> callback when the connection closes and the sound is deemed to be valid</li>\r
+ </ul>\r
+\r
+ <p>In terms of HTTP traffic, the sequence is something like this (excluding some headers for brevity):</p>\r
+\r
+ <ul>\r
+ <li><b>Client request</b>\r
+ <ul class="flat">\r
+ <li>GET some.mp3 HTTP/1.1</li>\r
+ </ul>\r
+ </li>\r
+ <li>\r
+ <b>Server response</b>\r
+ <ul class="flat">\r
+ <li>HTTP/1.1 200 OK</li>\r
+ <li>Content-Length: 158958</li>\r
+ <li>Connection: close</li>\r
+ <li>Content-type: audio/mpeg</li>\r
+ </ul>\r
+ </ul>\r
+\r
+ <h4>Progressive downloading behaviour in SoundManager 2</h4>\r
+\r
+ <p>This method is typically used by Flash when requesting audio via standard HTTP, and HTML5 clients in the event that <a href="#byte-serving">Byte Serving</a> (HTTP 206/Partial Content) is not implemented or cannot be negotiated.</p>\r
+\r
+ <ul>\r
+ <li>Playback begins after a small amount of buffering, once the download has started.</li>\r
+ <li>Once started, the download progress continues until all bytes are received. Stopping or pausing playback does not cancel the download.</li>\r
+ <li>During load, a SM2 sound object's <code>whileloading()</code> event will fire at a regular interval with <code>bytesLoaded</code>, <code>bytesTotal</code> and <code>duration</code> properties updating as the file progresses. Because Flash only reflects the "amount of duration loaded", <code>durationEstimate</code> is provided as a means of reflecting the total duration before load has completed (at which point duration is 100% and accurate.)</li>\r
+ <li>During load, the user can only seek within the amount of data (duration) downloaded.</li>\r
+ <li><code>onload()</code> fires when the connection is closed, and all bytes have been received.</li>\r
+ </ul>\r
+\r
+ <h4 id="byte-serving">Byte Serving (partials / byte range requests, "streaming"-style delivery)</h4>\r
+\r
+ <p>HTML5 clients will send a <b>Accept-ranges: bytes</b> header in the HTTP request for an audio asset to indicate their capability for Byte Serving, along with a <b>Range</b> header indicating what piece of the file to download.</p>\r
+ <p>If the server supports partials, it will reply with a <b>HTTP/1.1 206 Partial Content</b> header and a <b>Content-Range</b> header indicating the bytes it is going to send.</p>\r
+ <p>It appears that servers will return the whole range in the first response unless interrupted (and when a client requests a range of <b>"0-"</b> as in this case), but the initial connection may be dropped by the client if it wishes to stop "buffering" at any point, or if the user tries to seek to a new position in the audio that has not yet buffered.</p>\r
+\r
+ <ul>\r
+ <li>\r
+ <b>Client request</b>\r
+ <ul class="flat">\r
+ <li>GET some.mp3 HTTP/1.1</li>\r
+ <li>Range: bytes=0-</li>\r
+ </ul>\r
+ </li>\r
+ <li>\r
+ <b>Server response</b>\r
+ <ul class="flat">\r
+ <li>HTTP/1.1 206 Partial Content</li>\r
+ <li>Accept-ranges: bytes</li>\r
+ <li>Content-length: 4237566</li>\r
+ <li>Content-Range: bytes 0-4237565/7237566</li>\r
+ </ul>\r
+ </li>\r
+ <li>The first response includes all bytes in this case, but a client may drop this connection and make a new range request, if needed; for example, the user may seek to a new position in the file where data is not yet available, and the client will make a new request to buffer data beginning at the appropriate offset.</li>\r
+ </ul>\r
+\r
+ <h4>HTTP/1.1 206 Partial Content request/response example</h4>\r
+\r
+ <ul>\r
+ <li>\r
+ <b>Client request</b>\r
+ <ul class="flat">\r
+ <li>GET some.ogg HTTP/1.1</li>\r
+ <li>Range: bytes=5210604-5275910</li>\r
+ <li>If-Range: "508107-4d8a0b4e90d26"</li>\r
+ </ul>\r
+ </li>\r
+ <li>\r
+ <b>Server response</b>\r
+ <ul class="flat">\r
+ <li>HTTP/1.1 206 Partial Content</li>\r
+ <li>Accept-Ranges: bytes</li>\r
+ <li>Content-length: 65307</li>\r
+ <li>Content-Range: bytes 5210604-5275910/5275911</li>\r
+ <li>Content-Type: audio/ogg</li>\r
+ </ul>\r
+ </li>\r
+ </ul>\r
+\r
+ <h4>Byte Serving behaviour in SoundManager 2</h4>\r
+\r
+ <p>Byte Serving is automatically negotiated between client and server, and offers a number of advantages over traditional downloads. Most notably, Byte Serving is closer to a "streaming" technology and enables clients to seek, buffer and resume playback at arbitrary positions within a file once the duration is known. Larger files benefit most from this technique, since they can be handled in smaller chunks vs. being held entirely in memory <i>a la</i> Flash.</p>\r
+\r
+ <p>While SoundManager 2 uses the same events for HTML5 and Flash regardless of transport mechanism, there are some notable differences in SoundManager 2's behaviour when using HTML5 and Byte Serving.</p>\r
+\r
+ <p>Most importantly, the concept of "loaded" (i.e., preloading data and waiting for <code>onload()</code>) with partials is irrelevant due to the way clients are able to pause, cancel and resume requests.</p>\r
+\r
+ <ul>\r
+ <li>Playback begins after a small amount of buffering, once the download has started.</li>\r
+ <li>The HTML5-native <code>canplay()</code> event fires when playback is ready to begin. This will cause SoundManager 2 to fire a sound's <code>onload()</code> callback. At this point, the sound's duration should be known, but the SM2-provided <code>bytesLoaded</code> and <code>bytesTotal</code> sound properties may not be known and thus are 0/0 during load time, and 1/1 if still undefined at load time.</li>\r
+ <li>SoundManager 2 attempts to fire <code>whileloading()</code> events as the HTML5-native <code>progress()</code> event fires, but keep in mind that any "bytes loaded" data may refer to blocks (i.e., buffered sequences of data) that are non-sequential and thus <code>bytesLoaded</code> and <code>bytesTotal</code> should not be relied on as an indicator of "total load progress".</li>\r
+ <li>HTML5 clients may use their own heuristic to determine how much to buffer, if and when to pause, cancel or resume requesting data.</li>\r
+ <li>Clients may request metadata from the end of a file in some cases, as with OGG formats, in order to determine information like the total duration of the sound.</li>\r
+ <li>During load (and once the duration is known), the user can seek to any position within the file.</li>\r
+ <li>A client may drop an open request in order to request a new byte range - for example, to buffer and resume playback if the user jumps to half-way through the file where that data has not been downloaded yet.</li>\r
+ </ul>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="mobile-device-limitations" class="columnar">\r
+\r
+ <div class="c1">\r
+ <h2>Mobile Device Limitations</h2>\r
+ <p>Known restrictions, quirks and annoyances relating to HTML5 + mobile Webkit (iOS / Android) software.</p>\r
+ </div>\r
+ \r
+ <div class="c2">\r
+ <h3>Mobile Device Restrictions, Quirks and Issues</h3>\r
+ <p>Mobile devices tend to be somewhat limited in terms of battery life, network connection and other resources. Furthermore, they are unlike larger (laptop/desktop) devices in that audio is often not a "shareable" resource, and only one application may be using the sound hardware at any given time. Thus, mobile devices must be treated slightly differently in terms of playing audio via JavaScript.</p>\r
+ <h3>iOS (mobile Safari/Webkit)</h3>\r
+ <ul>\r
+ <li>Sound <code>play()</code> calls are blocked by the OS unless in direct response to a user event like touch or click. ("Auto-play" attempts will be blocked, and the sound may fire a <code>suspend</code> event in this case.) For the curious, <code>setTimeout()</code> calls will also result in playback being blocked.</li>\r
+ <li>Sound <code>load()</code> and load-related methods may also have some limitations, similar to <code>play()</code>.</li>\r
+ <li>Only one sound may be actively playing at a time. If an other sound (or application) is playing audio, it will be stopped by the OS in order to play the new sound.</li>\r
+ <li>Chained playback (sequential / playlist-style behaviour) works when using the <code>onfinish</code> event handler. Otherwise, blocking occurs.</li>\r
+ </ul>\r
+ <h3>Possible Alternatives</h3>\r
+ <p>The Webkit Audio API (possibly a future standard as the Web Audio API) allows for low-level access, manipulation and control of audio from JavaScript. This API is mostly separate from the HTML5 audio API, but will ultimately allow for better fine-grained control and mixing of sound.</p>\r
+ <p>Once playback is allowed, the Webkit Audio API should be able to get around many of the current HTML5 audio limitations present on iOS including multiple sound playback, volume and pan control, and dynamic filtering / processing effects. However, the API is not a standard and is not consistently supported in Webkit, let alone other browsers.</p> \r
+ <p>SM2 does not presently use the Webkit Audio API. It may be experimentally or more formally added at some point in the future, when the API is more universally-supported.</p>\r
+ </div>\r
+\r
+ </div>\r
+ \r
+ <div id="debug-output" class="columnar">\r
+\r
+ <div class="c1">\r
+ <h2>Debug + Console Output</h2>\r
+ <p>Console-style messaging, useful for troubleshooting start-up and runtime issues.</p>\r
+ </div>\r
+ \r
+ <div class="c2">\r
+ <h3>Live Debug Output</h3>\r
+ <p class="in">With debug mode enabled via <code>soundManager.setup({debugMode: true})</code>, SM2 can write helpful troubleshooting information to JavaScript <code>console.log()</code>-style interfaces. Additionally, output can be written to an optional DIV element with the ID of <code>soundmanager-debug</code>.</p>\r
+ <p class="in"><code>soundManager.setup({consoleOnly: true})</code> can be applied to disable HTML output (using <code>console.log()</code>-only methods) as well.</p>\r
+ <p>Additionally, debugging within the Flash portion of SM2 is also available and set using <code>soundManager.setup({debugFlash: true})</code>. Debug messages are written to the flash movie itself.</p>\r
+ <p>For info on SoundManager 2 loading/initialization failures and how to fix them, see <a href="../getstarted/#troubleshooting">troubleshooting</a>.</p>\r
+ \r
+ <p>Below is a live example of debug output from SM2:</p>\r
+\r
+ <div id="live-debug" class="block">\r
+ <div id="soundmanager-debug" class="code">\r
+ <!-- live debug goes here -->\r
+ </div>\r
+ </div>\r
+ \r
+ <p>Flash debug output, as applicable:</p>\r
+\r
+ <div id="sm2-container">\r
+ <!-- flash movie goes here -->\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+\r
+ <div id="col3" class="c3">\r
+\r
+ <div id="support-wrapper">\r
+ <div id="get-satisfaction" class="box">\r
+ <div id="gsfn_list_widget">\r
+ <h2><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/" title="User discussion, FAQs and support for SoundManager 2" rel="nofollow">Discussion / Support</a><span class="l"></span><span class="r"></span></h2>\r
+ <div id="gsfn_content"></div>\r
+ <div class="powered_by"><a href="http://getsatisfaction.com/" rel="nofollow">Get Satisfaction support network</a></div>\r
+ </div>\r
+ <!-- /.box -->\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="shortcuts">\r
+\r
+<!--\r
+ <div class="box">\r
+\r
+ <h2>Shortcuts<span class="l"></span><span class="r"></span></h2>\r
+\r
+ <ul class="first">\r
+ <li onclick="setFilter(event,'c-')" class="ignore">\r
+\r
+ <ul>\r
+\r
+ <li>Demos</li>\r
+ <li>Getting Started</li>\r
+ <li>Basic Use</li>\r
+ <li>Download</li>\r
+ <li>Requirements</li>\r
+ <li>Limitations</li>\r
+\r
+ <li>Debug Output</li>\r
+ <li>Revision History</li>\r
+ <li>About</li>\r
+ </ul>\r
+\r
+ </li>\r
+ </ul>\r
+\r
+ </div>\r
+-->\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="clear"></div>\r
+\r
+ <!-- /main-wrapper -->\r
+ </div>\r
+\r
+ <!-- /main -->\r
+ </div>\r
+\r
+ <!-- /content -->\r
+ </div>\r
+\r
+<script type="text/javascript">\r
+init();\r
+</script>\r
+ \r
+</body>\r
+\r
+</html>\r
--- /dev/null
+<!doctype html>\r
+<html lang="en">\r
+<head>\r
+<title>SoundManager 2: JavaScript Sound For The Web</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="Play sound from JavaScript including MP3, MPEG-4 and HTML5-supported audio formats with SoundManager 2, a cross-browser/platform sound API. BSD licensed."/>\r
+<meta name="keywords" content="javascript sound, html5 audio, html5 sound, javascript audio, javascript play mp3, javascript sound control, mp3, mp4, mpeg4, aac, Scott Schiller, Schill, Schillmania"/>\r
+<meta name="author" content="Scott Schiller"/>\r
+<meta name="dcterms.rights" content="Copyright (C) 1997 onwards Scott Schiller"/>\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>\r
+\r
+<!-- inline demo CSS (combined + minified for performance; see comments for raw source URLs) -->\r
+<link rel="stylesheet" type="text/css" href="demo/index-rollup.css"/>\r
+\r
+<!-- the SoundManager 2 API -->\r
+<script type="text/javascript" src="script/soundmanager2.js"></script>\r
+\r
+<!-- 360 UI demo, canvas magic for IE -->\r
+<!--[if lt IE 9]><script type="text/javascript" src="demo/360-player/script/excanvas.js"></script><![endif]-->\r
+\r
+<!-- SM2 demo/homepage-specific stuff -->\r
+<script type="text/javascript">var is_home = true;</script>\r
+\r
+<!-- inline demo JS (combined + minified; see comments for raw source URLs) -->\r
+<script type="text/javascript" src="demo/index-rollup.js"></script>\r
+\r
+<!-- testing 2 -->\r
+<script src="demo/bar-ui/script/bar-ui.js"></script>\r
+\r
+<!-- IE CSS font hax -->\r
+<!--[if lte IE 8]>\r
+<style>\r
+ #turntable-demo {\r
+ /* nope. */\r
+ display: none;\r
+ }\r
+ #tidal-link { display: none; /* this uses SVG, so, meh. */ }\r
+ h2.special {\r
+ /* IE 6-8 font reset, doesn't like sort-of-defined @font-family */\r
+ font-family:"helvetica neue",helvetica,arial,verdana,tahoma,"sans serif";\r
+ }\r
+ body.home #about-header {\r
+ padding-left: 0px;\r
+ }\r
+.sm2-speaker,\r
+ #inline-video {\r
+ display: none;\r
+ }\r
+</style>\r
+<![endif]-->\r
+</head>\r
+\r
+<body class="home">\r
+\r
+<div id="content">\r
+\r
+ <div id="lights"></div>\r
+\r
+ <div id="top">\r
+\r
+ <h1>A JavaScript Sound API supporting MP3, MPEG4 and HTML5 Audio.</h1>\r
+\r
+ <div id="nav">\r
+ <div id="version" title="Version of SM2 loaded on this page"></div>\r
+ <ul>\r
+ <li>\r
+ <strong><a href="#home">Home</a></strong>\r
+ </li>\r
+ <li>\r
+ <a href="#">Demos</a>\r
+ <ul>\r
+ <li><a href="demo/template/">Basic Template</a></li>\r
+ <li><a href="demo/api/">API Examples</a></li>\r
+ <li><a href="demo/bar-ui/">Bar UI</a></li>\r
+ <li><a href="demo/play-mp3-links/">Playable MP3 links</a></li>\r
+ <li><a href="demo/mp3-player-button/" class="exclude">Basic MP3 Play Button</a></li>\r
+ <li><a href="demo/page-player/">Muxtape-style UI</a></li>\r
+ <li><a href="demo/360-player/">360° Player UI</a></li>\r
+ <li><a href="demo/mpc/">Drum Machine (MPC)</a></li>\r
+ <li><a href="demo/animation/">DOM/Animation Demos</a></li>\r
+ <li><a href="demo/flashblock/">FlashBlock Handling</a></li>\r
+ </ul>\r
+ </li>\r
+ <li>\r
+ <a href="doc/getstarted/">Getting Started</a>\r
+ <ul>\r
+ <li><a href="doc/getstarted/#how-sm2-works">How SoundManager 2 works</a></li>\r
+ <li><a href="doc/getstarted/#basic-inclusion">Including SM2 on your site</a></li>\r
+ <li><a href="doc/getstarted/#troubleshooting">Troubleshooting</a></li>\r
+ </ul>\r
+ </li>\r
+ <li>\r
+ <a href="doc/">Documentation</a>\r
+ <ul>\r
+ <li><a href="doc/#sm-config">SoundManager Properties</a></li>\r
+ <li><a href="doc/#sound-object-properties">Sound Object Properties</a></li>\r
+ <li><a href="doc/#smdefaults">Global Sound Defaults</a></li>\r
+ <li><a href="doc/#api">SoundManager Core API</a></li>\r
+ <li><a href="doc/#smsoundmethods">Sound Object (SMSound) API</a></li>\r
+ <li><a href="doc/generated/soundmanager2.html">Generated Documentation</a></li>\r
+ </ul>\r
+ </li>\r
+ <li>\r
+ <a href="doc/download/">Download</a>\r
+ <ul>\r
+ <li><a href="doc/download/#latest">Get SoundManager 2</a></li>\r
+ <li><a href="doc/download/#revision-history">Revision History</a></li>\r
+ </ul>\r
+ </li>\r
+ <li>\r
+ <a href="doc/technotes/">Technical Notes</a>\r
+ <ul>\r
+ <li><a href="doc/technotes/#requirements">System Requirements</a></li>\r
+ <li><a href="doc/technotes/#serving-audio">Serving To HTML5 + Flash Clients</a></li>\r
+ <li><a href="doc/technotes/#client-requests">How Clients Download Audio</a></li>\r
+ <li><a href="doc/technotes/#mobile-device-limitations">Mobile Device Limitations</a></li>\r
+ <li><a href="doc/technotes/#debug-output">Debug + Console Output</a></li>\r
+ </ul>\r
+ </li>\r
+ <li>\r
+ <a href="doc/resources/">Resources</a>\r
+ <ul>\r
+ <li><a href="doc/resources/#licensing">Licensing</a></li>\r
+ <li><a href="doc/resources/#related">Related Projects</a></li>\r
+ <li><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/">SM2 support / discussion</a></li>\r
+ <li><a href="http://www.schillmania.com/content/react/contact/">Contact Info @ Schillmania.com</a></li>\r
+ </ul>\r
+ </li>\r
+ </ul>\r
+ <div class="clear"></div>\r
+ </div>\r
+ </div>\r
+\r
+<div id="main-wrapper">\r
+\r
+ <div id="main" class="triple">\r
+\r
+ <div id="col3" class="c3">\r
+\r
+ <div id="support-wrapper">\r
+ <div id="get-satisfaction" class="box">\r
+ <div id="gsfn_list_widget">\r
+ <h2><a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2/" title="User discussion, FAQs and support for SoundManager 2" rel="nofollow">Discussion / Support</a><span class="l"></span><span class="r"></span></h2>\r
+ <div id="gsfn_content">\r
+ </div>\r
+ <div class="powered_by">\r
+ <a href="http://getsatisfaction.com/" rel="nofollow">Get Satisfaction support network</a>\r
+ </div>\r
+ </div>\r
+ <!-- /.box -->\r
+ </div>\r
+\r
+ <div id="sm2-options">\r
+ <p>\r
+ SM2 options: <span id="with-html5"><a href="?sm2-usehtml5audio=1" title="View this page with HTML5 audio support enabled">+html5</a></span>\r
+ <span id="options-divider-with-html5" class="options-divider"> | </span>\r
+ <span id="without-html5"><a href="?sm2-usehtml5audio=0" title="View this page with HTML5 audio support disabled">-html5</a></span>\r
+ <span id="options-divider-without-html5" class="options-divider"> | </span>\r
+ <span id="with-debug"><a href="#debug=1" title="View this page with debug output mode enabled (console.log() or HTML-based)" onclick="document.location.href=this.href;document.location.reload()">+debug</a></span>\r
+ </p>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <!-- /main -->\r
+ </div>\r
+\r
+ <div id="live-demos" class="columnar">\r
+\r
+ <div id="about-sm2">\r
+\r
+ <div id="sm2-support-warning">\r
+ <!-- as needed, warning is displayed here -->\r
+ </div>\r
+\r
+ <div id="about-header">\r
+\r
+ <div class="sm2-speaker"></div>\r
+\r
+ <h2 class="special">SoundManager 2 makes it easier to play audio using JavaScript.</h2>\r
+\r
+ <p>\r
+ <a href="doc/download/" title="Download SoundManager 2" class="feature" style="float:right;font-family:helvetica;font-weight:500;margin:0px;white-space:nowrap">Get SoundManager 2</a>\r
+ <span style="line-height:1.75em;font-size:110%">SoundManager 2 provides simple, reliable cross-platform audio under a single JavaScript API. </span>\r
+ </p>\r
+\r
+ </div>\r
+\r
+ <div id="inline-video">\r
+\r
+ <video id="turntable-video" loop autoplay onclick="if (!this.paused) { this.pause(); } else { this.play(); }">\r
+ <source src="demo/_image/turntable-loop-1920x500-bw.webm" type="video/webm">\r
+ <source src="demo/_image/turntable-loop-1920x500-h264-512kbps-h264.mp4">\r
+ <source src="demo/_image/turntable-loop-1920x500-h264-512kbps-bw.mov" type="video/mp4">\r
+ <img id="turntable-static-video" src="demo/_image/turntable-loop-poster.jpg" alt="" style="width:100%;max-width:1920px" />\r
+ </video>\r
+\r
+ <script>\r
+\r
+ (function() {\r
+\r
+ /**\r
+ * iPhone doesn't play inline video, nor does iOS < 7 on iPad (IIRC.)\r
+ * This is a dirty hack to not show video in the general mobile / tablet / "you're not a desktop (and not Windows XP)" case.\r
+ * GIF made using the following...\r
+ * gifsicle source.gif --colors 32 --optimize --dither=o3 > output.gif\r
+ * from source GIF:\r
+ * gifsicle turntable-loop-original.gif --delay 8 --colors 32 --dither=o3 `seq -f "#%g" 0 2 43` -O2 --gamma=3 -o turntable-loop-960-22f-32c-03.gif\r
+ * APNG made with APNG Anime Maker (Windows.)\r
+ */\r
+\r
+ var i, doesAPNG, replacements, ua, url, video;\r
+\r
+ replacements = {\r
+ 'gif': 'demo/_image/turntable-loop-960-22f-32c-03.gif', // framerate / quality / file size trade-off\r
+ 'apng': 'demo/_image/turntable-loop-960-27f.apng' // pretty good all-around\r
+ }\r
+\r
+ ua = navigator.userAgent;\r
+\r
+ // that oughta get enough of you guys. YOU get a .GIF, and *YOU* get a .GIF!\r
+ if (ua.match(/iphone|ipad|ios|mobile|windows phone|tablet/i) || navigator.userAgent.match(/windows nt 5\.1/i) || window.location.href.match(/img/i)) {\r
+ // if your device lies about its capabilities, you will probably now pay the price for this naive detection.\r
+ video = document.getElementById('inline-video');\r
+ if (video) {\r
+ // dirty, evil tricks.\r
+ doesAPNG = (ua.match(/os (8|9|10)\s/i) || window.location.href.match(/apng/i)); // iOS 8+ is presumed as "OS 8|9|10" or whatever's eventually released.\r
+ url = replacements[(doesAPNG ? 'apng' : 'gif')];\r
+ video.innerHTML = '<img src="demo/_image/turntable-loop-poster.jpg" alt="" style="width:100%;max-width:1920px" /><div style="position:absolute;left:0px;top:0px;width:100%;height:100%;background: transparent url(' + url + ');background-size:100% auto;background-repeat:no-repeat' + (!doesAPNG ? ';opacity:0.8' : '') + '" onclick="this.style.display=\'none\'"></div>';\r
+ }\r
+ }\r
+\r
+ }());\r
+\r
+ </script>\r
+\r
+ <div id="bar-ui-1" class="sm2-bar-ui full-width bottom">\r
+\r
+ <div class="bd sm2-main-controls">\r
+\r
+ <div class="sm2-inline-texture"></div>\r
+ <div class="sm2-inline-gradient"></div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#play" class="sm2-inline-button play-pause">Play / pause</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-inline-status">\r
+\r
+ <div class="sm2-playlist">\r
+ <div class="sm2-playlist-target">\r
+ <!-- playlist <ul> + <li> markup will be injected here -->\r
+ <!-- if you want default / non-JS content, you can put that here. -->\r
+ <noscript><p>JavaScript is required.</p></noscript>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-progress">\r
+ <div class="sm2-row">\r
+ <div class="sm2-inline-time">0:00</div>\r
+ <div class="sm2-progress-bd">\r
+ <div class="sm2-progress-track">\r
+ <div class="sm2-progress-bar"></div>\r
+ <div class="sm2-progress-ball"><div class="icon-overlay"></div></div>\r
+ </div>\r
+ </div>\r
+ <div class="sm2-inline-duration">0:00</div>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-volume">\r
+ <div class="sm2-button-bd">\r
+ <span class="sm2-inline-button sm2-volume-control volume-shade"></span>\r
+ <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#prev" title="Previous" class="sm2-inline-button previous">< previous</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#next" title="Next" class="sm2-inline-button next">> next</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-menu">\r
+ <div class="sm2-button-bd">\r
+ <a href="#menu" class="sm2-inline-button menu">menu</a>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="bd sm2-playlist-drawer sm2-element">\r
+\r
+ <!-- playlist content is mirrored here -->\r
+\r
+ <div class="sm2-playlist-wrapper">\r
+ <ul class="sm2-playlist-bd">\r
+ <!-- example: playable link, "buy" link, "download" link -->\r
+ <li>\r
+ <div class="sm2-row">\r
+ <div class="sm2-col sm2-wide">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/Figub%20Brazlevi%C4%8D%20-%20Bosnian%20Syndicate.mp3" class="exclude button-exclude inline-exclude"><b>Figub Brazlevič</b> - Bosnian Syndicate <span title="Published under a Creative Commons BY-NC-ND license" class="label">(BY-CC-ND license)</span></a>\r
+ </div>\r
+ <div class="sm2-col">\r
+ <a href="http://figubbrazlevic.bandcamp.com/track/bosnian-syndicate" target="_blank" title="Buy "Bosnian Syndicate"" class="sm2-icon sm2-cart">Buy this track</a>\r
+ </div>\r
+ </div>\r
+ </li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Let%20Me%20%28Prod%202oolman%29.mp3" class="exclude button-exclude inline-exclude"><b>SonReal</b> - Let Me <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3" class="exclude button-exclude inline-exclude"><b>SonReal</b> - LA (Prod. Chin Injetti)<span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20People%20Asking.mp3" class="exclude button-exclude inline-exclude"><b>SonReal</b> - People Asking <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Already%20There%20Remix%20ft.%20Rich%20Kidd%2C%20Saukrates.mp3" class="exclude button-exclude inline-exclude"><b>SonReal</b> - Already There Remix ft. Rich Kidd, Saukrates <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/The%20Fugitives%20-%20Graffiti%20Sex.mp3" class="exclude button-exclude inline-exclude"><b>The Fugitives</b> - Graffiti Sex</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Seven%20Or%20Eight%20Days.mp3" class="exclude button-exclude inline-exclude"><b>Adrian Glynn</b> - Seven Or Eight Days</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20I%20Tried.mp3" class="exclude button-exclude inline-exclude"><b>SonReal</b> - I Tried</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3" class="exclude button-exclude inline-exclude">Armstrong Beat</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20090119%20-%20Untitled%20Groove.mp3" class="exclude button-exclude inline-exclude">Untitled Groove</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/birds-in-kauai-128kbps-aac-lc.mp4" class="exclude button-exclude inline-exclude">Birds In Kaua'i (AAC)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/20130320%20-%20Po%27ipu%20Beach%20Waves.ogg" class="exclude button-exclude inline-exclude">Po'ipu Beach Waves (OGG)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/bottle-pop.wav" class="exclude button-exclude inline-exclude">A corked beer bottle (WAV)</a></li>\r
+ <li><a href="demo/_mp3/rain.mp3" class="norewrite exclude button-exclude inline-exclude">Rain</a></li>\r
+ </ul>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="demo-more" style="margin-top:-45px">\r
+ Featured demo: <a href="demo/bar-ui/" title="Bar UI: Demo" class="cta dark-cta">Bar UI <span>»</span></a>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <hr />\r
+\r
+ <div class="threeup first">\r
+\r
+ <div class="column">\r
+\r
+ <div class="column-wrapper">\r
+\r
+ <h3>Speak and <b style="white-space:nowrap">be heard<span class="music-note icon"></span></b></h3>\r
+ <h4>More sound, <b>in more places</b></h4>\r
+\r
+ <p>Despite being one of the senses, sound has largely been missing from the web due to inconsistent technology support. SoundManager 2 bridges this gap, making it easier to use audio across a growing variety of devices and platforms, both desktop and mobile.</p>\r
+\r
+ <p><a href="#getting-started" class="cta">Getting started</a> is pretty easy, too.</p>\r
+\r
+ <p>A few live examples:</p>\r
+\r
+ <div id="sm2-support" class="demo-block">\r
+ <!-- "oh snap", SM2 didn't load etc. messaging -->\r
+ </div>\r
+\r
+ <div style="position:relative;*zoom:1;min-width:275px">\r
+\r
+ <div id="special-demo-left" class="sm2-inline-list">\r
+\r
+ <div class="ui360">\r
+ <a href="demo/_mp3/office_lobby.mp3" class="norewrite exclude button-exclude inline-exclude">Office lobby sound</a>\r
+ </div>\r
+\r
+ <div class="ui360" style="float:left;display:inline">\r
+ <a href="demo/_mp3/mak.mp3" title="360 demo: Angry Cow Sound" class="norewrite exclude button-exclude inline-exclude">Random</a>\r
+ </div>\r
+\r
+ <div class="ui360" style="float:left;display:inline">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/water-drop.mp3" title="360 Demo: Water Drop" class="exclude button-exclude inline-exclude">Water Drop</a>\r
+ </div>\r
+\r
+ <div class="demo-more-abs" style="margin-right:1.5em">\r
+ <a href="demo/360-player/" title="360° UI player demo" class="cta">360° UI <span>»</span></a>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="special-demo-right">\r
+ <a href="demo/_mp3/coins.mp3" title="Play "Change"" class="sm2_button exclude inline-exclude norewrite">coins.mp3</a>\r
+ <a href="demo/christmas-lights/sound/glass0.mp3" class="sm2_button exclude inline-exclude norewrite" title="Play "Glass break 1"">glass0.mp3</a>\r
+ <a href="demo/christmas-lights/sound/glass1.mp3" class="sm2_button exclude inline-exclude threesixty-exclude norewrite" title="Play "Glass break 2"">glass1.mp3</a>\r
+\r
+ <div class="demo-more-abs">\r
+ <a href="demo/mp3-player-button/" title="MP3 buttons demo" class="cta">mp3 buttons <span>»</span></a>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="html5-audio-notes">\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+\r
+ <div class="column">\r
+ <div class="column-wrapper">\r
+\r
+ <h3>HTML5 + flash <b style="white-space:nowrap">hybrid<span class="package icon"></span></b></h3>\r
+ <h4>Complexity, <b>reduced</b></h4>\r
+\r
+ <p>Supporting HTML5 audio can be tedious in modern browsers, let alone legacy ones. With real-world visitors using browsers ranging from mobile Safari to IE 6 across a wide range of devices, there can be many support cases to consider.</p>\r
+\r
+ <p>SoundManager 2 gives you a single, powerful API that supports both new and old, using HTML5 audio where supported and optional Flash-based fallback where needed. Ideally when using SoundManager 2, audio "just works."</p>\r
+ \r
+ <div class="icons">\r
+ <ul>\r
+ <li class="desktop" title="Desktop support: Windows, Mac OS, Linux">Desktop support: Windows, Mac OS, Linux</li>\r
+ <li class="laptop" title="Laptop/tablet support: Windows, Mac OS, Linux / Blackberry Playbook, Kindle Fire + other HTML5/Flash devices">Laptop/tablet support: Windows, Mac OS, Linux / Blackberry Playbook, Kindle Fire + other HTML5/Flash devices</li>\r
+ <li class="iphone" title="iPhone support: iPhone with iOS 4.0 and newer">iPhone support: iOS 4.0 and newer</li>\r
+ <li class="ipad" title="iPad support: Version 1.0 (iOS 3.2) and newer">iPad support: Version 1.0 (iOS 3.2) and newer</li>\r
+ <li class="android" title="Android OS supporting HTML5 and/or Flash (Version 2.3 or newer)">Android OS supporting HTML5 and/or Flash (Version 2.3 or newer)</li>\r
+ </ul>\r
+ The details: <a href="doc/getstarted/#intro" class="cta" style="text-align:right">how it works <span>»</span></a>\r
+ </div>\r
+\r
+ </div>\r
+ </div>\r
+\r
+ <div class="column">\r
+ <div class="column-wrapper">\r
+ <h3 style="cursor:help" title="Gzip-compressed file size on a typical set-up is 12 KB. And was it supposed to be the "Swiss Army" kind? I forget.">The ginsu knife: <b style="white-space:nowrap">12 KB<span class="performance icon"></span></b></h3>\r
+ <h4>Big features, <b>small footprint</b></h4>\r
+ <p><em>But wait, there's more!</em></p>\r
+ <p>Performance is an important metric, too. SoundManager 2 packs a comprehensive, feature-rich API into as little as <a href="doc/getstarted/#basic-inclusion" title="SoundManager 2: Build options (down to ~12 KB in size)" style="white-space:nowrap" class="cta">12 KB</a> over the wire when optimized; that's less than 8% of the original, uncompressed file size.</p>\r
+ <p>SM2 is self-contained, having no external dependencies, and is compatible with popular JavaScript frameworks.</p>\r
+ <p>The source code is BSD-licensed and is provided in fully-commented, non-debug and compiler-optimized "minified" versions appropriate for development and production use.</p>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+\r
+ <div class="threeup">\r
+\r
+ <div class="column">\r
+ <div class="column-wrapper">\r
+\r
+ <h3>Basic</h3>\r
+ <h4>Playable <b>links and playlists</b></h4>\r
+\r
+ <p>These demos use unordered lists with MP3 links that play in-place; the UI is easily customized via CSS.</p>\r
+\r
+ <ul id="graphic-playlist" class="graphic">\r
+ <li><a href="demo/_mp3/rain.mp3" class="exclude">Rain</a></li>\r
+ <li><a href="demo/_mp3/walking.mp3" class="exclude">Walking</a></li>\r
+ <!-- files from the web (note that ID3 information will *not* load from remote domains without permission, Flash restriction) -->\r
+ <li><a href="http://freshly-ground.com/data/video/Rain%20on%20Car%20Roof.aac" title="Rain on car roof (AAC)" class="exclude">Rain On Car Roof <span class="sidenote">(AAC)</span></a></li>\r
+ </ul>\r
+\r
+ <div class="demo-more" style="text-align:right;white-space:normal">\r
+ <a href="demo/play-mp3-links/" title=""Play MP3 Links" demo" class="cta">play MP3 links <span>»</span></a>\r
+ </div>\r
+\r
+ <div style="clear:both"></div>\r
+\r
+ <p>A richer playlist theme with optional time, seekable progress bar and a VU meter where supported:</p>\r
+\r
+ <ul id="inline-playlist" class="playlist">\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3" class="button-exclude inline-exclude threesixty-exclude">Armstrong Beat</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20090119%20-%20Untitled%20Groove.mp3" class="button-exclude inline-exclude threesixty-exclude">Untitled Groove</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/birds-in-kauai-128kbps-aac-lc.mp4" title="128 kbps MPEG-4 AAC LC (Low Complexity) sound: Birds in Kaua'i" class="button-exclude inline-exclude threesixty-exclude">Birds In Kaua'i <span class="sidenote">(128 kbps AAC)</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/20130320%20-%20Po%27ipu%20Beach%20Waves.ogg" title="Po'ipu Beach Waves: OGG sound format, requires HTML5 Audio() support to play" class="muxtape-html5 button-exclude inline-exclude threesixty-exclude">Po'ipu Beach Waves <span class="sidenote">(OGG)</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/bottle-pop.wav" title="WAV sound format, requires HTML5 Audio() support to play" class="muxtape-html5 button-exclude inline-exclude threesixty-exclude">A corked beer bottle <span class="sidenote">(WAV)</span></a></li>\r
+ </ul>\r
+ <div class="demo-more">\r
+ <a href="demo/page-player/" title="Muxtape-style UI demo" class="cta">muxtape-style UI <span>»</span></a>\r
+ </div>\r
+\r
+ </div>\r
+ </div>\r
+\r
+ <div class="column">\r
+ <div class="column-wrapper">\r
+\r
+ <h3>Shiny</h3>\r
+ <h4>Fancier UI, more features</h4>\r
+\r
+ <p>The <em>Bar UI</em> uses SVG for a resolution-independent UI, with HTML and CSS that makes customization easy.</p>\r
+\r
+ <div class="sm2-bar-ui" style="min-width:10em">\r
+\r
+ <div class="bd sm2-main-controls">\r
+\r
+ <div class="sm2-inline-texture"></div>\r
+ <div class="sm2-inline-gradient"></div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <div class="sm2-button-bd">\r
+ <a href="#play" class="sm2-inline-button play-pause">Play / pause</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-inline-status">\r
+\r
+ <div class="sm2-playlist">\r
+ <div class="sm2-playlist-target">\r
+ <!-- playlist <ul> + <li> markup will be injected here -->\r
+ <!-- if you want default / non-JS content, you can put that here. -->\r
+ <noscript><p>JavaScript is required.</p></noscript>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-progress">\r
+ <div class="sm2-row">\r
+ <div class="sm2-inline-time">0:00</div>\r
+ <div class="sm2-progress-bd">\r
+ <div class="sm2-progress-track">\r
+ <div class="sm2-progress-bar"></div>\r
+ <div class="sm2-progress-ball"><div class="icon-overlay"></div></div>\r
+ </div>\r
+ </div>\r
+ <div class="sm2-inline-duration">0:00</div>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-volume">\r
+ <div class="sm2-button-bd">\r
+ <span class="sm2-inline-button sm2-volume-control volume-shade"></span>\r
+ <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a>\r
+ </div>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element sm2-menu">\r
+ <div class="sm2-button-bd">\r
+ <a href="#menu" class="sm2-inline-button menu">menu</a>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="bd sm2-playlist-drawer sm2-element">\r
+\r
+ <div class="sm2-inline-texture">\r
+ <div class="sm2-box-shadow"></div>\r
+ </div>\r
+\r
+ <!-- playlist content is mirrored here -->\r
+\r
+ <div class="sm2-playlist-wrapper">\r
+ <ul class="sm2-playlist-bd">\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20(Prod%20Chin%20Injetti).mp3" class="exclude button-exclude inline-exclude">SonReal - LA (Prod. Chin Injetti)<span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Let%20Me%20(Prod%202oolman).mp3" class="exclude button-exclude inline-exclude"><b>SonReal</b> - Let Me <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20People%20Asking.mp3" class="exclude button-exclude inline-exclude"><b>SonReal</b> - People Asking <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20Already%20There%20Remix%20ft.%20Rich%20Kidd,%20Saukrates.mp3" class="exclude button-exclude inline-exclude"><b>SonReal</b> - Already There Remix ft. Rich Kidd, Saukrates <span class="label">Explicit</span></a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/The%20Fugitives%20-%20Graffiti%20Sex.mp3" class="exclude button-exclude inline-exclude"><b>The Fugitives</b> - Graffiti Sex</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Seven%20Or%20Eight%20Days.mp3" class="exclude button-exclude inline-exclude"><b>Adrian Glynn</b> - Seven Or Eight Days</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20I%20Tried.mp3" class="exclude button-exclude inline-exclude"><b>SonReal</b> - I Tried</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/gong-192kbps.mp3" class="exclude button-exclude inline-exclude">32" Gong Sounds (rubber + standard mallets)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3" class="exclude button-exclude inline-exclude">Armstrong Beat</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/mpc/20090119%20-%20Untitled%20Groove.mp3" class="exclude button-exclude inline-exclude">Untitled Groove</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/birds-in-kauai-128kbps-aac-lc.mp4" class="exclude button-exclude inline-exclude">Birds In Kaua'i (AAC)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/20130320%20-%20Po%27ipu%20Beach%20Waves.ogg" class="exclude button-exclude inline-exclude">Po'ipu Beach Waves (OGG)</a></li>\r
+ <li><a href="http://freshly-ground.com/data/audio/sm2/bottle-pop.wav" class="exclude button-exclude inline-exclude">A corked beer bottle (WAV)</a></li>\r
+ <li><a href="demo/_mp3/rain.mp3" class="norewrite exclude button-exclude inline-exclude">Rain</a></li>\r
+ </ul>\r
+ </div>\r
+\r
+ <div class="sm2-extra-controls">\r
+\r
+ <div class="bd">\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <a href="#prev" title="Previous" class="sm2-inline-button previous">< previous</a>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element">\r
+ <a href="#next" title="Next" class="sm2-inline-button next">> next</a>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element disabled">\r
+ <a href="#repeat" title="Repeat playlist" class="sm2-inline-button repeat">∞ repeat</a>\r
+ </div>\r
+\r
+ <div class="sm2-inline-element sm2-button-element disabled">\r
+ <a href="#shuffle" title="Shuffle" class="sm2-inline-button shuffle">shuffle</a>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="demo-more">\r
+ <a href="demo/bar-ui/" title="Bar UI: Demo" class="cta">Bar UI <span>»</span></a>\r
+ </div>\r
+\r
+ <!-- 360 player -->\r
+\r
+ <p>The 360° player UI demo uses <canvas> and includes options for waveform and spectrum analysis data via Flash 9, adding beautiful visual feedback to the interface.</p>\r
+\r
+ <p style="font-size:92%;text-align:left;color:#666;white-space:normal"><em>Seven Or Eight Days</em> courtesy of <a href="http://www.adrianglynn.com/" title="Adrian Glynn, Vancouver, Canadian singer/songwriter" class="cta">Adrian Glynn</a>, from the album <em>Bruise</em>. For more, see the <a href="https://www.youtube.com/watch?v=dFc2QQiGcUQ" title="Adrian Glynn: "Seven Or Eight Days" video" rel="nofollow" class="cta">music video</a>.</p>\r
+\r
+ <!--\r
+ <div id="inline-demos">\r
+ <h4 id="inline-demo-header">Inline demos using SoundManager 2</h4>\r
+ </div>\r
+ -->\r
+\r
+ <div>\r
+ \r
+ <div id="sm2-visualization" class="sm2-inline-list">\r
+\r
+ <div class="ui360 ui360-vis">\r
+ <a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Seven%20Or%20Eight%20Days.mp3" class="exclude button-exclude inline-exclude" style="position:absolute;color:#333">Adrian Glynn - Seven Or Eight Days</a>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="demo-more" style="width:256px;margin:0.5em auto 0px auto;clear:both">\r
+ <a href="demo/360-player/canvas-visualization.html" title="360° UI: JavaScript + Canvas Visualization" class="cta">360° + spectrum UI <span>»</span></a>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+ </div>\r
+ \r
+ <div class="column">\r
+\r
+ <div class="column-wrapper">\r
+\r
+ <h3>Experimental</h3>\r
+ <h4>Advanced <b>prototypes</b></h4>\r
+\r
+ <div id="turntable-demo">\r
+\r
+ <div style="clear:both;position:relative;text-align:center;margin-top:-7.5%">\r
+\r
+ <!-- note: inline-block is just for centering -->\r
+\r
+ <div id="turntable-large" class="turntable has-slipmat" style="display:inline-block">\r
+\r
+ <div class="frame"></div>\r
+\r
+ <div class="table-bg"></div>\r
+\r
+ <!-- image that sets the base dimensions-->\r
+ <img src="demo/turntable/image/tt_case_and_lighting.png" alt="" class="stub" />\r
+\r
+ <div class="bd">\r
+\r
+ <div class="platter"></div>\r
+ \r
+ <div class="slipmat-holder">\r
+ <div class="slipmat"></div>\r
+ </div>\r
+\r
+ <div class="record-holder">\r
+ <div class="record"></div>\r
+ <div class="record-grooves"></div>\r
+ <div class="label"></div>\r
+ </div>\r
+\r
+ <div class="spindle"></div>\r
+ <div class="power-light"></div>\r
+ <a href="#" class="power-dial" data-method="powerToggle"></a>\r
+ <a href="#" class="button start-stop" data-method="toggle"></a>\r
+ <a href="#" class="button speed-33 on"></a>\r
+ <a href="#" class="button speed-45"></a>\r
+ <div class="light light-on"></div>\r
+ <a href="#" class="button light"></a>\r
+ <div class="tonearm-holder">\r
+ <div class="tonearm"></div>\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="demo-more" style="position:relative;z-index:2;margin-right:7%;margin-top:-5.25%">\r
+ <a href="demo/turntable/" title="Turntable UI Demo" class="cta dark-cta">Turntable UI <span>»</span></a>\r
+ </div>\r
+\r
+ <!-- end turntable -->\r
+\r
+ <ul class="tt-playlist">\r
+ <li>\r
+ <a href="http://freshly-ground.com/data/audio/sm2/Beckyoncé%20-%20Single%20Loser.mp3" data-turntable="turntable-large" data-artwork="http://freshly-ground.com/data/image/sm2/beckyonce.jpg" class="norewrite exclude button-exclude inline-exclude sm2-exclude cta turntable-include">Beckyoncé - Single Loser (Put A Beck On It)</a> (<span title="Published under a Creative Commons BY-NC-SA license">BY-NC-SA</span>, <a href="https://soundcloud.com/beckyonce/single-loser-put-a-beck-on-it" target="_blank" class="cta">via</a>)\r
+ </li>\r
+ <li>\r
+ <a href="http://freshly-ground.com/data/audio/sm2/Figub%20Brazlevi%C4%8D%20-%20Bosnian%20Syndicate.mp3" data-turntable="turntable-large" data-artwork="http://freshly-ground.com/data/image/sm2/trainyards-cover-640.jpg" class="norewrite exclude button-exclude inline-exclude sm2-exclude cta turntable-include"><b>Figub Brazlevič</b> - Bosnian Syndicate</a> (<span title="Published under a Creative Commons BY-NC-ND license">BY-CC-ND license</span>, <a href="http://figubbrazlevic.bandcamp.com/track/bosnian-syndicate" target="_blank" class="cta">via</a>)\r
+ </li>\r
+ <li>\r
+ <a href="http://freshly-ground.com/data/audio/sm2/Chill With Schill (Summer 2012 Session Excerpt).mp3" data-turntable="turntable-large" class="norewrite exclude button-exclude inline-exclude sm2-exclude cta turntable-include">Chill With Schill (Summer 2012 Session Excerpt)</a>\r
+ </li>\r
+ <li>\r
+ <a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20LA%20%28Prod%20Chin%20Injetti%29.mp3" data-turntable="turntable-large" data-artwork="http://freshly-ground.com/data/image/sm2/sonreal-onelongday-65.jpg" class="norewrite exclude button-exclude inline-exclude cta turntable-include">SonReal - L.A. (Prod. Injetti)</a>\r
+ </li>\r
+ </ul>\r
+\r
+ </div>\r
+\r
+ <style>\r
+ /* quick hack for playlist above */\r
+ ul.tt-playlist {\r
+ position: relative;\r
+ color: #999;\r
+ padding-left: 2.75em;\r
+ font-size: 92%;\r
+ }\r
+ ul.tt-playlist li {\r
+ margin: 0px;\r
+ padding: 0px;\r
+ }\r
+ /*\r
+ .turntable .frame {\r
+ background: url(demo/turntable/image/pinstriped_suit_vertical.png);\r
+ background-size: 142px 76px;\r
+ }\r
+ */\r
+ </style>\r
+\r
+ <p>The Cassette Tape UI is a skinnable player based on the TDK MA-R90 cassette tape, a classic design from 1982.</p>\r
+\r
+ <div>\r
+ <a href="demo/cassette-tape/" title="Cassette Tape UI (Prototype Demo)"><img src="demo/_image/cassette-tape-ui-screenshot.jpg" alt="Cassette Tape UI Prototype Screenshot" style="max-width:506px;min-width:100%;width:100%;border-radius:12px" /></a>\r
+ </div>\r
+\r
+ <p style="margin:0.5em 0px 0px 0px;padding:0px;font-size:92%;text-align:left;color:#666;margin-bottom:0.5em;white-space:normal">Remember Type IV, Metal & Chromium/CrO2? <a href="http://www.youtube.com/watch?v=uMUnaI_IdBU" title="TDK TV ad, 1980s" class="cta">Those were the days</a>.</p>\r
+\r
+ </div>\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div id="how-to" class="twoup">\r
+\r
+ <div class="column">\r
+ <div id="getting-started" class="column-wrapper">\r
+\r
+ <h3>Getting <b>started</b></h3>\r
+\r
+ <h4>Basic SoundManager 2 set-up</h4>\r
+\r
+ <p>Including the script, configuring the <code>url</code> and registering an <code>onready()</code> callback:</p>\r
+\r
+<pre class="block"><code><script src="soundmanager2.js"></script>\r
+<script>\r
+<a href="doc/#soundmanager-setup" title="soundManager.setup() documentation" onclick="checkDomain()">soundManager.setup</a>({\r
+ <span><span>// where to find flash audio SWFs, as needed</span></span>\r
+ url: '<span>/path/to/swf-files/</span>',\r
+ onready: function() {\r
+ <span><span>// SM2 is ready to play audio!</span></span>\r
+ }\r
+});\r
+</script></code></pre>\r
+\r
+ <p>Upon execution of soundmanager2.js, SM2 will determine what Flash SWF to load (if any) based on the path defined in <code>soundManager.url</code>.</p>\r
+ <p>After successful initialization, <code>soundManager.onready()</code> will fire and sounds can be played.</p>\r
+ <p>By default, SM2 uses a Flash 8-based SWF build. Some <a href="#flash9-features" title="SoundManager 2: Flash 9 API-based features" class="cta">additional features</a> are available when using the Flash 9-based build.</p>\r
+\r
+ <p>For a live example, see the <a href="demo/template/" class="cta">basic template demo</a>.</p>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+\r
+ <div class="column">\r
+\r
+ <div class="column-wrapper">\r
+\r
+ <h3>Playing <b>audio</b></h3>\r
+ <h4>Basic playback control</h4>\r
+\r
+ <p>Once <code>soundManager.onready()</code> has fired, sounds can be loaded and played.</p>\r
+\r
+ <h4>Creating and playing a sound object</h4>\r
+\r
+<pre class="block"><code><span><span>// create "mySound"...</span></span>\r
+var mySound = <a href="doc/#soundmanager-createsound" title="soundManager.createSound() documentation" onclick="checkDomain()">soundManager.createSound</a>({\r
+ url: '<span>/path/to/an.mp3</span>'\r
+});\r
+\r
+<span><span>// ...and play it</span></span>\r
+mySound.play();\r
+</code></pre>\r
+\r
+ <p>Additional options and events can be specified when loading and playing sounds. For more examples of playback features, see <a href="demo/api/" class="cta">API Demos</a>.</p>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="twoup">\r
+\r
+ <div class="column">\r
+ <div class="column-wrapper">\r
+\r
+ <h3>Bonus</h3>\r
+ <h4>Additional <b>demos</b></h4>\r
+\r
+ <p>\r
+ Examples using multi-track playback, progress and combinations of sound and animation:\r
+ </p>\r
+\r
+ <h4>Armor Alley: Web Prototype (PC-DOS game remake)</strong></h4>\r
+\r
+ <iframe width="100%" height="400" src="https://www.youtube.com/embed/bTH2OYJ6vVY" frameborder="0" allowfullscreen></iframe>\r
+\r
+ <p><a href="http://schillmania.com/armor-alley/" class="cta">Armor Alley</a> is a side-scrolling, real-time vehicle simulation / strategy game, originally released for the Mac and PC-DOS computers in 1990. This web-based remake is a tribute to the attention to detail shown in the original. Your goal is to defend a convoy as it moves into enemy territory; the game ends when a van reaches the opposing base. See the <a href="http://www.schillmania.com/content/entries/2013/armor-alley-web-prototype/" class="cta">making-of</a> for more.</p>\r
+\r
+ <h4>SURVIVOR (Commodore 64 game remake)</strong></h4>\r
+\r
+ <iframe width="100%" height="390" src="https://www.youtube.com/embed/h6DyJbCnLvw" frameborder="0" allowfullscreen></iframe>\r
+\r
+ <p><a href="http://schillmania.com/survivor/" class="cta">SURVIVOR</a> is a web-based remake of a Commodore 64 game. The goal is to shoot out turrets and destroy bases, while avoiding contact with basically everything around you. Sound was used creatively in the original, and it has been re-implemented in this modern interpretation. See the <a href="http://www.schillmania.com/content/entries/2012/survivor-c64-html-remake/" class="cta">making-of</a> for more.</p>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="column">\r
+ <div class="column-wrapper">\r
+\r
+ <h3>Elsewhere</h3>\r
+ <h4>As heard on <b><span class="scratched-out">TV</span> the internets</b></h4>\r
+\r
+ <p>A few nifty places SoundManager 2 has been seen in use on the Wild World Web:</p>\r
+\r
+ <div class="inthewild active">\r
+\r
+ <ul class="inthewild">\r
+ <li id="tidal-link">\r
+ <a id="tidal" href="http://tidal.com/" title="TIDAL (web player, non-FLAC streaming)"><span>TIDAL</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="beats-music" href="http://beatsmusic.com/" title="Beats Music (web player)"><span>Beats Music</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="songza" href="http://songza.com/" title="Songza"><span>Songza</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="earbits" href="http://earbits.com/" title="Earbits"><span>Earbits</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="lastfm" href="http://www.last.fm/" title="last.fm"><span>last.fm</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="pitchfork" href="http://www.pitchfork.com/" title="Pitchfork"><span>Pitchfork</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="eight-tracks" href="http://8tracks.com/" title="8tracks"><span>8tracks</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="discogs" href="http://www.discogs.com/" title="Discogs"><span>Discogs</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="hypem" href="http://hypem.com/" title="The Hype Machine"><span>The Hype Machine</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="nyancat" href="http://nyan.cat/" title="NON-STOP NYAN CAT!"><span>NON-STOP NYAN CAT!</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="freesound" href="http://freesound.org" title="Freesound.org"><span>freesound.org</span></a>\r
+ </li>\r
+ <li>\r
+ <a id="baroque-me" href="http://www.chenalexander.com/Bach" title="Alexander Chen's "baroque.me""><span>Baroque</span></a>\r
+ </li>\r
+ </ul>\r
+\r
+ </div>\r
+\r
+ <h4 style="padding-top:1em">Articles and presentations</h4>\r
+\r
+ <p>Some other words, pictures and video on the subject of HTML5 and web audio:</p>\r
+\r
+ <ul class="standard">\r
+ <li>Video, 02/2012: <a href="http://www.youtube.com/watch?v=C2Tw0BeZb8Q" title="Scott Schiller: Web Audio: HTML5 + Flash (in a tree)" class="cta">Web Audio: HTML5 + Flash (in a tree)</a> (<a href="http://isflashdeadyet.com/talks/html5/bayjax_yahoo_sunnyvale_02-06-2012/" title=""Web Audio: HTML5 + Flash (in a tree)" presentation slides" class="cta">slides</a>.) Updated HTML5 content, demos and <a href="http://www.schillmania.com/content/entries/2012/survivor-c64-html-remake/" title="SURVIVOR: Remaking a Commodore 64 game in HTML" class="cta">SURVIVOR</a> C64 game demo.</li>\r
+ <li>Video presentation: <a href="http://www.youtube.com/watch?v=KjdPNtWV3Z0#t=56s" title="Scott Schiller: "Adding Sound To HTML"" class="cta">Adding Sound To HTML</a> (<a href="http://isflashdeadyet.com/talks/html5/" title=""Adding Sound To HTML" presentation slides" class="cta">slides</a>) (12/2011)</li>\r
+ <li>Video: <a href="http://www.youtube.com/watch?v=ffk65q5Rl9I" title="Yahoo!/YUI Blog, video presentation: Scott Schiller on the State of HTML5 Audio" class="cta">Probably, Maybe, No: The State of HTML5 Audio</a> + turntable demo (05/2011)</li>\r
+ <li>24ways.org article, <a href="http://24ways.org/2010/the-state-of-html5-audio" title="Probably, Maybe, No: The State Of HTML5 Audio (24ways.org)" class="cta">The State Of HTML5 Audio</a> (12/2010)</li>\r
+ </ul>\r
+\r
+ <h4 style="padding-top:1em">Credits and thank-yous</h4>\r
+\r
+ <ul class="standard">\r
+ <li>Icons: Desktop / mobile / iOS device iconography via <a href="http://glyphish.com/" class="cta">glyphish.com</a> (<a href="http://creativecommons.org/licenses/by/3.0/" title="Creative Commons Attribution 3.0 Unported" class="cta">CC</a>). Tile background: "<a href="http://subtlepatterns.com/tiny-grid/" class="cta">Tiny Grid</a>". Homepage header typeface: <a href="http://work.meredithmandel.com/#379252/Typeface-Chunk-Five" class="cta">Chunk (Five)</a> by Meredith Mandel (<a href="http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL&_sc=1" title="SIL Open Font License (OFL)" class="cta">OFL</a>).</li>\r
+ <li>Music: <em>Seven Or Eight Days</em> courtesy of <a href="http://www.adrianglynn.com/" title="Adrian Glynn, Vancouver-based Singer/Songwriter" class="cta">Adrian Glynn</a>. <em>Graffiti Sex</em> courtesy of <a href="http://www.fugitives.ca/" title="The Fugitives, multi-instrumentalists from Vancouver" class="cta">The Fugitives</a>, from the album <em>In Streetlight Communion</em>. <em>Let Me</em>, <em>LA</em>, <em>I Tried</em> and <em>People Asking</em> courtesy of <a href="http://sonreal.ca/" title="SonReal, Vancouver-based hip-hop artist" class="cta">SonReal</a>.</li>\r
+ </ul>\r
+\r
+ <h4 style="clear:left;padding-top:1em">Additional experimental demo</h4>\r
+\r
+ <p>The "Wheels Of Steel" started as a simple CSS prototype, and evolved to replicate most of the UI and functionality of a traditional DJ set-up. Pitch bending, scratch and EQ effects are present where supported.</p>\r
+ <p style="margin:0px 0px 0.5em 0px;padding:0px;text-align:center" class="bonus-demo"><a href="http://wheelsofsteel.net/" title="The Wheels Of Steel: Online turntable / browser-based DJ prototype" style="margin:0px;padding:0px;background:#fff"><img src="demo/_image/wheelsofsteel-full-ui.jpg" alt="wheelsofsteel.net: Online turntable demo (screenshot)" style="display:block;width:100%;min-width:100%;max-width:315px;margin-left:-4px;border:1px solid #f0f0f0" /></a></p>\r
+ <p style="margin:0px;padding:0px;font-size:92%;text-align:left;color:#666;margin-bottom:0.5em;white-space:normal">The <a href="http://wheelsofsteel.net/" title="The Wheels Of Steel: Online turntable / browser-based DJ prototype" class="cta">Wheels Of Steel</a>, a browser-based DJ turntable prototype. For the tech details, read <a href="http://www.schillmania.com/content/entries/2011/wheels-of-steel/" title="The making of 'The Wheels Of Steel': An Ode To Turntables (in HTML)" class="cta">An Ode To Turntables (in HTML.)</a></p>\r
+\r
+ </div>\r
+\r
+ </div>\r
+\r
+<!--\r
+ <div class="column">\r
+ <div class="column-wrapper">\r
+\r
+ <h3>Download <b>the code</b></h3>\r
+\r
+ <p>\r
+ <a href="doc/download/" class="feature">Get SoundManager 2</a>\r
+ </p>\r
+\r
+ </div>\r
+ </div>\r
+-->\r
+\r
+ </div>\r
+\r
+ <div class="threeup">\r
+\r
+ <div class="column">\r
+ <div class="column-wrapper">\r
+\r
+ <h3>Technical <b>overview</b></h3>\r
+\r
+ <h4>HTML5 audio + optional Flash fallback</h4>\r
+\r
+ <ul class="standard">\r
+ <li>100% Flash-free audio on iPad, iPhone (iOS4) and other HTML5-enabled devices + browsers</li>\r
+ <li>Invisible Flash SWF provides HTML5 fallback as needed</li>\r
+ <li>API is consistent whether using HTML5 or Flash</li>\r
+ <li>See <a href="doc/#soundmanager-usehtml5audio" title="soundManager.useHTML5Audio HTML5 Audio() support feature documentation" class="cta">useHTML5Audio</a> for implementation details</li>\r
+ </ul>\r
+\r
+ </div>\r
+ </div>\r
+\r
+ <div class="column">\r
+ <div class="column-wrapper"> <!-- spaced-out -->\r
+\r
+ <h3>API <b>specifics</b></h3>\r
+ <h4>Basic API features (HTML5, Flash 8*)</h4>\r
+\r
+ <ul class="standard">\r
+ <li>Load, stop, play, pause, mute, seek, pan*, volume control from JavaScript</li>\r
+ <li>Events: <code>onload()</code>, <code>whileloading()</code>, <code>whileplaying()</code>, <code>onfinish()</code> and more</li>\r
+ <li>ID3V1 + ID3V2 tag support for MP3s (title, artist, genre etc.)*</li>\r
+ </ul>\r
+\r
+ <br />\r
+\r
+ <h4 id="flash9-features">Additional Flash 9-based API features</h4>\r
+\r
+ <ul class="standard">\r
+ <li>RTMP / Flash Media Server streaming support (experimental) - see <a href="doc/#smsound-serverurl" title="SMSound.serverURL parameter" class="cta">serverURL</a></li>\r
+ <li>MPEG-4 (AAC, HE-AAC, H.264) audio support</li>\r
+ <li>"MultiShot" play (layered/chorusing effects)</li>\r
+ <li>Waveform/frequency spectrum data</li>\r
+ <li>Peak (L/R channel volume) data</li>\r
+ <li>Audio buffering state/event handling</li>\r
+ </ul>\r
+\r
+ </div>\r
+ </div>\r
+\r
+ <div class="column">\r
+ <div class="column-wrapper"> <!-- spaced-out -->\r
+\r
+ <h3>Everything <b>else</b></h3>\r
+ <h4>Documentation, tools and demos</h4>\r
+\r
+ <ul class="standard">\r
+ <li>Extensive <a href="doc/" title="SoundManager 2 documentation" class="cta">API Documentation</a> with examples and notes</li>\r
+ <li>Built-in <a href="doc/technotes/#debug-output" title="SoundManager 2 console.log()-style debug output" class="cta">debugging</a> and <a href="doc/getstarted/#troubleshooting" title="SoundManager 2 troubleshooting tool" class="cta">troubleshooting tools</a></li>\r
+ <li>Community-based <a href="http://getsatisfaction.com/schillmania/products/schillmania_soundmanager_2" title="discussion/support for SoundManager 2 on Get Satisfaction" class="cta">discussion/support</a></li>\r
+ <li id="licensing"><a href="license.txt" title="SoundManager 2 BSD license" class="cta norewrite">BSD licensed</a></li>\r
+ </ul>\r
+\r
+ <br />\r
+ <h4 class="home-shopping-network">Not only do you get the ginsu knife...</h4>\r
+ <p style="font-size:92%">Even more demos and examples using the SoundManager 2 API...</p>\r
+ <ul class="standard">\r
+ <li><a href="demo/play-mp3-links/" title="Links to MP3 files that play inline" class="cta">Playable MP3 links</a></li>\r
+ <li><a href="demo/mpc/" title="MPC sampler/drum machine demo" class="cta">MPC sampler/drum machine</a></li>\r
+ <li><a href="demo/animation-1/" title="Bouncing ball animation with sound effects" class="cta">Basic animation + sound</a></li>\r
+ <li><a href="demo/christmas-lights/" title="Smashable christmas lights demo (animation and sound)" class="cta">Smashable christmas lights</a></li>\r
+ <li><a href="demo/api/" title="See the code, click the button, watch it run: Live API demos using test sounds" class="cta">Live API + code examples</a></li>\r
+ </ul>\r
+\r
+\r
+ </div>\r
+ </div>\r
+\r
+ <!--/min-width -->\r
+\r
+ </div>\r
+\r
+<!-- three -->\r
+\r
+ <!-- /#about-sm2 -->\r
+ </div>\r
+\r
+ </div>\r
+\r
+ <div class="clear"> </div>\r
+\r
+ <!-- /content -->\r
+\r
+ </div>\r
+\r
+ <script type="text/javascript">\r
+ // <![CDATA[\r
+ if (document.location.href.match(/debug=1/i)) {\r
+ document.getElementById('with-debug').style.display = 'none';\r
+ }\r
+ if (document.location.href.match(/debug/i)) {\r
+ document.getElementById('options-divider-with-html5').style.display = 'none';\r
+ }\r
+ if (soundManager.useHTML5Audio || document.location.href.match(/html5audio=1/i)) {\r
+ document.getElementById('with-html5').style.display = 'none';\r
+ document.getElementById('options-divider-with-html5').style.display = 'none';\r
+ } else {\r
+ document.getElementById('without-html5').style.display = 'none';\r
+ document.getElementById('options-divider-without-html5').style.display = 'none';\r
+ }\r
+ init();\r
+ // ]]>\r
+ </script>\r
+\r
+ </div>\r
+\r
+</div>\r
+\r
+</body>\r
+</html>\r
--- /dev/null
+Software License Agreement (BSD License)\r
+\r
+Copyright (c) 2007, Scott Schiller (schillmania.com)\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without modification,\r
+are permitted provided that the following conditions are met:\r
+\r
+* Redistributions of source code must retain the above copyright notice, this \r
+ list of conditions and the following disclaimer.\r
+\r
+* Redistributions in binary form must reproduce the above copyright notice, this\r
+ list of conditions and the following disclaimer in the documentation and/or\r
+ other materials provided with the distribution.\r
+\r
+* Neither the name of schillmania.com nor the names of its contributors may be\r
+ used to endorse or promote products derived from this software without\r
+ specific prior written permission from schillmania.com.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR\r
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
--- /dev/null
+{
+ "name": "soundmanager2",
+ "version": "2.97.20150601a",
+ "description": "A JavaScript Sound API supporting MP3, MPEG4 and HTML5 audio + RTMP, providing reliable cross-browser/platform audio control in as little as 12 KB.",
+ "main": "script/soundmanager2.js",
+ "directories": {
+ "lib": "./script"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/scottschiller/SoundManager2/"
+ },
+ "keywords": [
+ "browser",
+ "audio",
+ "sound",
+ "mp3",
+ "mpeg4",
+ "html5"
+ ],
+ "author": {
+ "name": "Scott Schiller",
+ "email": "spam@schillmania.com",
+ "url": "http://schillmania.com/"
+ },
+ "license": "BSD",
+ "bugs": {
+ "url": "https://github.com/scottschiller/SoundManager2/issues/"
+ },
+ "homepage": "http://www.schillmania.com/projects/soundmanager2/"
+}
--- /dev/null
+/** @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.20150601
+*/
+(function(h,g){function K(sb,K){function ha(b){return c.preferFlash&&H&&!c.ignoreFlash&&c.flash[b]!==g&&c.flash[b]}function r(b){return function(d){var e=this._s;e&&e._a?d=b.call(this,d):(e&&e.id?c._wD(e.id+": Ignoring "+d.type):c._wD("HTML5::Ignoring "+d.type),d=null);return d}}this.setupOptions={url:sb||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,forceUseGlobalHTML5Audio:!1,ignoreMobileRestrictions:!1,html5Test:/^(probably|maybe)$/i,preferFlash:!1,noSWFCache:!1,idPrefix:"sound"};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},opus:{type:["audio/ogg; codecs=opus","audio/opus"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave","audio/x-wav"],required:!1}};this.movieID="sm2-container";this.id=K||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20150601";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={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};this.html5=
+{usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var W,c=this,Ya=null,l=null,F,v=navigator.userAgent,ia=h.location.href.toString(),m=document,ya,Za,za,n,I=[],Aa=!0,D,X=!1,Y=!1,q=!1,y=!1,ja=!1,p,tb=0,Z,A,Ba,R,Ca,P,S,T,$a,Da,Ea,ka,z,la,Q,Fa,aa,ma,na,U,ab,Ga,bb=["log","info","warn","error"],cb,Ha,db,ba=null,Ia=null,t,Ja,V,eb,oa,pa,L,w,ca=!1,Ka=!1,fb,gb,hb,qa=0,da=null,ra,M=[],ea,u=null,ib,sa,fa,N,ta,La,jb,x,kb=Array.prototype.slice,C=!1,Ma,H,Na,lb,J,mb,Oa,ua,nb=0,Pa,Qa=v.match(/(ipad|iphone|ipod)/i),
+Ra=v.match(/android/i),O=v.match(/msie/i),ub=v.match(/webkit/i),va=v.match(/safari/i)&&!v.match(/chrome/i),Sa=v.match(/opera/i),wa=v.match(/(mobile|pre\/|xoom)/i)||Qa||Ra,Ta=!ia.match(/usehtml5audio/i)&&!ia.match(/sm2\-ignorebadua/i)&&va&&!v.match(/silk/i)&&v.match(/OS X 10_6_([3-7])/i),Ua=h.console!==g&&console.log!==g,Va=m.hasFocus!==g?m.hasFocus():null,xa=va&&(m.hasFocus===g||!m.hasFocus()),ob=!xa,pb=/(mp3|mp4|mpa|m4a|m4b)/i,ga=m.location?m.location.protocol.match(/http/i):null,vb=ga?"":"http://",
+qb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,rb="mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "),wb=new RegExp("\\.("+rb.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!ga;var Wa;try{Wa=Audio!==g&&(Sa&&opera!==g&&10>opera.version()?new Audio(null):new Audio).canPlayType!==g}catch(xb){Wa=!1}this.hasHTML5=Wa;this.setup=function(b){var d=!c.url;b!==g&&q&&u&&c.ok()&&(b.flashVersion!==g||
+b.url!==g||b.html5Test!==g)&&L(t("setupLate"));Ba(b);if(!C)if(wa){if(!c.setupOptions.ignoreMobileRestrictions||c.setupOptions.forceUseGlobalHTML5Audio)M.push(z.globalHTML5),C=!0}else c.setupOptions.forceUseGlobalHTML5Audio&&(M.push(z.globalHTML5),C=!0);if(!Pa&&wa)if(c.setupOptions.ignoreMobileRestrictions)M.push(z.ignoreMobile);else if(c.setupOptions.useHTML5Audio&&!c.setupOptions.preferFlash||c._wD(z.mobileUA),c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,Qa)c.ignoreFlash=!0;else if(Ra&&
+!v.match(/android\s2\.3/i)||!Ra)c._wD(z.globalHTML5),C=!0;b&&(d&&aa&&b.url!==g&&c.beginDelayedInit(),aa||b.url===g||"complete"!==m.readyState||setTimeout(Q,1));Pa=!0;return c};this.supported=this.ok=function(){return u?q&&!y:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return F(c)||m[c]||h[c]};this.createSound=function(b,d){function e(){f=oa(f);c.sounds[f.id]=new W(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var a,f;a=null;a="soundManager.createSound(): "+t(q?"notOK":"notReady");if(!q||
+!c.ok())return L(a),!1;d!==g&&(b={id:b,url:d});f=A(b);f.url=ra(f.url);f.id===g&&(f.id=c.setupOptions.idPrefix+nb++);f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+t("badID",f.id),2);c._wD("soundManager.createSound(): "+f.id+(f.url?" ("+f.url+")":""),1);if(w(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];if(sa(f))a=e(),c.html5Only||c._wD(f.id+": Using HTML5"),a._setup_html5(f);else{if(c.html5Only)return c._wD(f.id+": No HTML5 support for this sound, and no Flash. Exiting."),
+e();if(c.html5.usingFlash&&f.url&&f.url.match(/data\:/i))return c._wD(f.id+": data: URIs not supported via Flash. Exiting."),e();8<n&&(null===f.isMovieStar&&(f.isMovieStar=!!(f.serverURL||f.type&&f.type.match(qb)||f.url&&f.url.match(wb))),f.isMovieStar&&(c._wD("soundManager.createSound(): using MovieStar handling"),1<f.loops&&p("noNSLoop")));f=pa(f,"soundManager.createSound(): ");a=e();8===n?l._createSound(f.id,f.loops||1,f.usePolicyFile):(l._createSound(f.id,f.url,f.usePeakData,f.useWaveformData,
+f.useEQData,f.isMovieStar,f.isMovieStar?f.bufferTime:!1,f.loops||1,f.serverURL,f.duration||null,f.autoPlay,!0,f.autoLoad,f.usePolicyFile),f.serverURL||(a.connected=!0,f.onconnect&&f.onconnect.apply(a)));f.serverURL||!f.autoLoad&&!f.autoPlay||a.load(f)}!f.serverURL&&f.autoPlay&&a.play();return a};this.destroySound=function(b,d){if(!w(b))return!1;var e=c.sounds[b],a;e.stop();e._iO={};e.unload();for(a=0;a<c.soundIDs.length;a++)if(c.soundIDs[a]===b){c.soundIDs.splice(a,1);break}d||e.destruct(!0);delete c.sounds[b];
+return!0};this.load=function(b,d){return w(b)?c.sounds[b].load(d):!1};this.unload=function(b){return w(b)?c.sounds[b].unload():!1};this.onposition=this.onPosition=function(b,d,e,a){return w(b)?c.sounds[b].onposition(d,e,a):!1};this.clearOnPosition=function(b,d,e){return w(b)?c.sounds[b].clearOnPosition(d,e):!1};this.start=this.play=function(b,d){var e=null,a=d&&!(d instanceof Object);if(!q||!c.ok())return L("soundManager.play(): "+t(q?"notOK":"notReady")),!1;if(w(b,a))a&&(d={url:d});else{if(!a)return!1;
+a&&(d={url:d});d&&d.url&&(c._wD('soundManager.play(): Attempting to create "'+b+'"',1),d.id=b,e=c.createSound(d).play())}null===e&&(e=c.sounds[b].play(d));return e};this.setPosition=function(b,d){return w(b)?c.sounds[b].setPosition(d):!1};this.stop=function(b){if(!w(b))return!1;c._wD("soundManager.stop("+b+")",1);return c.sounds[b].stop()};this.stopAll=function(){var b;c._wD("soundManager.stopAll()",1);for(b in c.sounds)c.sounds.hasOwnProperty(b)&&c.sounds[b].stop()};this.pause=function(b){return w(b)?
+c.sounds[b].pause():!1};this.pauseAll=function(){var b;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].pause()};this.resume=function(b){return w(b)?c.sounds[b].resume():!1};this.resumeAll=function(){var b;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].resume()};this.togglePause=function(b){return w(b)?c.sounds[b].togglePause():!1};this.setPan=function(b,d){return w(b)?c.sounds[b].setPan(d):!1};this.setVolume=function(b,d){var e,a;if(b===g||isNaN(b)||d!==g)return w(b)?c.sounds[b].setVolume(d):
+!1;e=0;for(a=c.soundIDs.length;e<a;e++)c.sounds[c.soundIDs[e]].setVolume(b)};this.mute=function(b){var d=0;b instanceof String&&(b=null);if(b){if(!w(b))return!1;c._wD('soundManager.mute(): Muting "'+b+'"');return c.sounds[b].mute()}c._wD("soundManager.mute(): Muting all sounds");for(d=c.soundIDs.length-1;0<=d;d--)c.sounds[c.soundIDs[d]].mute();return c.muted=!0};this.muteAll=function(){c.mute()};this.unmute=function(b){b instanceof String&&(b=null);if(b){if(!w(b))return!1;c._wD('soundManager.unmute(): Unmuting "'+
+b+'"');return c.sounds[b].unmute()}c._wD("soundManager.unmute(): Unmuting all sounds");for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].unmute();c.muted=!1;return!0};this.unmuteAll=function(){c.unmute()};this.toggleMute=function(b){return w(b)?c.sounds[b].toggleMute():!1};this.getMemoryUse=function(){var c=0;l&&8!==n&&(c=parseInt(l._getMemoryUse(),10));return c};this.disable=function(b){var d;b===g&&(b=!1);if(y)return!1;y=!0;p("shutdown",1);for(d=c.soundIDs.length-1;0<=d;d--)cb(c.sounds[c.soundIDs[d]]);
+Z(b);x.remove(h,"load",S);return!0};this.canPlayMIME=function(b){var d;c.hasHTML5&&(d=fa({type:b}));!d&&u&&(d=b&&c.ok()?!!(8<n&&b.match(qb)||b.match(c.mimePattern)):null);return d};this.canPlayURL=function(b){var d;c.hasHTML5&&(d=fa({url:b}));!d&&u&&(d=b&&c.ok()?!!b.match(c.filePattern):null);return d};this.canPlayLink=function(b){return b.type!==g&&b.type&&c.canPlayMIME(b.type)?!0:c.canPlayURL(b.href)};this.getSoundById=function(b,d){if(!b)return null;var e=c.sounds[b];e||d||c._wD('soundManager.getSoundById(): Sound "'+
+b+'" not found.',2);return e};this.onready=function(b,d){if("function"===typeof b)q&&c._wD(t("queue","onready")),d||(d=h),Ca("onready",b,d),P();else throw t("needFunction","onready");return!0};this.ontimeout=function(b,d){if("function"===typeof b)q&&c._wD(t("queue","ontimeout")),d||(d=h),Ca("ontimeout",b,d),P({type:"ontimeout"});else throw t("needFunction","ontimeout");return!0};this._writeDebug=function(b,d){var e,a;if(!c.setupOptions.debugMode)return!1;if(Ua&&c.useConsole){if(d&&"object"===typeof d)console.log(b,
+d);else if(bb[d]!==g)console[bb[d]](b);else console.log(b);if(c.consoleOnly)return!0}e=F("soundmanager-debug");if(!e)return!1;a=m.createElement("div");0===++tb%2&&(a.className="sm2-alt");d=d===g?0:parseInt(d,10);a.appendChild(m.createTextNode(b));d&&(2<=d&&(a.style.fontWeight="bold"),3===d&&(a.style.color="#ff3333"));e.insertBefore(a,e.firstChild);return!0};-1!==ia.indexOf("sm2-debug=alert")&&(this._writeDebug=function(c){h.alert(c)});this._wD=this._writeDebug;this._debug=function(){var b,d;p("currentObj",
+1);b=0;for(d=c.soundIDs.length;b<d;b++)c.sounds[c.soundIDs[b]]._debug()};this.reboot=function(b,d){c.soundIDs.length&&c._wD("Destroying "+c.soundIDs.length+" SMSound object"+(1!==c.soundIDs.length?"s":"")+"...");var e,a,f;for(e=c.soundIDs.length-1;0<=e;e--)c.sounds[c.soundIDs[e]].destruct();if(l)try{O&&(Ia=l.innerHTML),ba=l.parentNode.removeChild(l)}catch(g){p("badRemove",2)}Ia=ba=u=l=null;c.enabled=aa=q=ca=Ka=X=Y=y=C=c.swfLoaded=!1;c.soundIDs=[];c.sounds={};nb=0;Pa=!1;if(b)I=[];else for(e in I)if(I.hasOwnProperty(e))for(a=
+0,f=I[e].length;a<f;a++)I[e][a].fired=!1;d||c._wD("soundManager: Rebooting...");c.html5={usingFlash:null};c.flash={};c.html5Only=!1;c.ignoreFlash=!1;h.setTimeout(function(){d||c.beginDelayedInit()},20);return c};this.reset=function(){p("reset");return c.reboot(!0,!0)};this.getMoviePercent=function(){return l&&"PercentLoaded"in l?l.PercentLoaded():null};this.beginDelayedInit=function(){ja=!0;Q();setTimeout(function(){if(Ka)return!1;na();la();return Ka=!0},20);T()};this.destruct=function(){c._wD("soundManager.destruct()");
+c.disable(!0)};W=function(b){var d,e,a=this,f,h,k,G,m,q,r=!1,E=[],v=0,Xa,y,u=null,z;e=d=null;this.sID=this.id=b.id;this.url=b.url;this._iO=this.instanceOptions=this.options=A(b);this.pan=this.options.pan;this.volume=this.options.volume;this.isHTML5=!1;this._a=null;z=this.url?!1:!0;this.id3={};this._debug=function(){c._wD(a.id+": Merged options:",a.options)};this.load=function(b){var d=null,e;b!==g?a._iO=A(b,a.options):(b=a.options,a._iO=b,u&&u!==a.url&&(p("manURL"),a._iO.url=a.url,a.url=null));a._iO.url||
+(a._iO.url=a.url);a._iO.url=ra(a._iO.url);e=a.instanceOptions=a._iO;c._wD(a.id+": load ("+e.url+")");if(!e.url&&!a.url)return c._wD(a.id+": load(): url is unassigned. Exiting.",2),a;a.isHTML5||8!==n||a.url||e.autoPlay||c._wD(a.id+": Flash 8 load() limitation: Wait for onload() before calling play().",1);if(e.url===a.url&&0!==a.readyState&&2!==a.readyState)return p("onURL",1),3===a.readyState&&e.onload&&ua(a,function(){e.onload.apply(a,[!!a.duration])}),a;a.loaded=!1;a.readyState=1;a.playState=0;a.id3=
+{};if(sa(e))d=a._setup_html5(e),d._called_load?c._wD(a.id+": Ignoring request to load again"):(a._html5_canplay=!1,a.url!==e.url&&(c._wD(p("manURL")+": "+e.url),a._a.src=e.url,a.setPosition(0)),a._a.autobuffer="auto",a._a.preload="auto",a._a._called_load=!0);else{if(c.html5Only)return c._wD(a.id+": No flash support. Exiting."),a;if(a._iO.url&&a._iO.url.match(/data\:/i))return c._wD(a.id+": data: URIs not supported via Flash. Exiting."),a;try{a.isHTML5=!1,a._iO=pa(oa(e)),a._iO.autoPlay&&(a._iO.position||
+a._iO.from)&&(c._wD(a.id+": Disabling autoPlay because of non-zero offset case"),a._iO.autoPlay=!1),e=a._iO,8===n?l._load(a.id,e.url,e.stream,e.autoPlay,e.usePolicyFile):l._load(a.id,e.url,!!e.stream,!!e.autoPlay,e.loops||1,!!e.autoLoad,e.usePolicyFile)}catch(f){p("smError",2),D("onload",!1),U({type:"SMSOUND_LOAD_JS_EXCEPTION",fatal:!0})}}a.url=e.url;return a};this.unload=function(){0!==a.readyState&&(c._wD(a.id+": unload()"),a.isHTML5?(G(),a._a&&(a._a.pause(),u=ta(a._a))):8===n?l._unload(a.id,"about:blank"):
+l._unload(a.id),f());return a};this.destruct=function(b){c._wD(a.id+": Destruct");a.isHTML5?(G(),a._a&&(a._a.pause(),ta(a._a),C||k(),a._a._s=null,a._a=null)):(a._iO.onfailure=null,l._destroySound(a.id));b||c.destroySound(a.id,!0)};this.start=this.play=function(b,d){var e,f,k,G,h,B=!0,B=null;e=a.id+": play(): ";d=d===g?!0:d;b||(b={});a.url&&(a._iO.url=a.url);a._iO=A(a._iO,a.options);a._iO=A(b,a._iO);a._iO.url=ra(a._iO.url);a.instanceOptions=a._iO;if(!a.isHTML5&&a._iO.serverURL&&!a.connected)return a.getAutoPlay()||
+(c._wD(e+" Netstream not connected yet - setting autoPlay"),a.setAutoPlay(!0)),a;sa(a._iO)&&(a._setup_html5(a._iO),m());1!==a.playState||a.paused||((f=a._iO.multiShot)?c._wD(e+"Already playing (multi-shot)",1):(c._wD(e+"Already playing (one-shot)",1),a.isHTML5&&a.setPosition(a._iO.position),B=a));if(null!==B)return B;b.url&&b.url!==a.url&&(a.readyState||a.isHTML5||8!==n||!z?a.load(a._iO):z=!1);a.loaded?c._wD(e.substr(0,e.lastIndexOf(":"))):0===a.readyState?(c._wD(e+"Attempting to load"),a.isHTML5||
+c.html5Only?a.isHTML5?a.load(a._iO):(c._wD(e+"Unsupported type. Exiting."),B=a):(a._iO.autoPlay=!0,a.load(a._iO)),a.instanceOptions=a._iO):2===a.readyState?(c._wD(e+"Could not load - exiting",2),B=a):c._wD(e+"Loading - attempting to play...");if(null!==B)return B;!a.isHTML5&&9===n&&0<a.position&&a.position===a.duration&&(c._wD(e+"Sound at end, resetting to position: 0"),b.position=0);if(a.paused&&0<=a.position&&(!a._iO.serverURL||0<a.position))c._wD(e+"Resuming from paused state",1),a.resume();else{a._iO=
+A(b,a._iO);if((!a.isHTML5&&null!==a._iO.position&&0<a._iO.position||null!==a._iO.from&&0<a._iO.from||null!==a._iO.to)&&0===a.instanceCount&&0===a.playState&&!a._iO.serverURL){f=function(){a._iO=A(b,a._iO);a.play(a._iO)};a.isHTML5&&!a._html5_canplay?(c._wD(e+"Beginning load for non-zero offset case"),a.load({_oncanplay:f}),B=!1):a.isHTML5||a.loaded||a.readyState&&2===a.readyState||(c._wD(e+"Preloading for non-zero offset case"),a.load({onload:f}),B=!1);if(null!==B)return B;a._iO=y()}(!a.instanceCount||
+a._iO.multiShotEvents||a.isHTML5&&a._iO.multiShot&&!C||!a.isHTML5&&8<n&&!a.getAutoPlay())&&a.instanceCount++;a._iO.onposition&&0===a.playState&&q(a);a.playState=1;a.paused=!1;a.position=a._iO.position===g||isNaN(a._iO.position)?0:a._iO.position;a.isHTML5||(a._iO=pa(oa(a._iO)));a._iO.onplay&&d&&(a._iO.onplay.apply(a),r=!0);a.setVolume(a._iO.volume,!0);a.setPan(a._iO.pan,!0);a.isHTML5?2>a.instanceCount?(m(),e=a._setup_html5(),a.setPosition(a._iO.position),e.play()):(c._wD(a.id+": Cloning Audio() for instance #"+
+a.instanceCount+"..."),k=new Audio(a._iO.url),G=function(){x.remove(k,"ended",G);a._onfinish(a);ta(k);k=null},h=function(){x.remove(k,"canplay",h);try{k.currentTime=a._iO.position/1E3}catch(c){L(a.id+": multiShot play() failed to apply position of "+a._iO.position/1E3)}k.play()},x.add(k,"ended",G),a._iO.volume!==g&&(k.volume=Math.max(0,Math.min(1,a._iO.volume/100))),a.muted&&(k.muted=!0),a._iO.position?x.add(k,"canplay",h):k.play()):(B=l._start(a.id,a._iO.loops||1,9===n?a.position:a.position/1E3,
+a._iO.multiShot||!1),9!==n||B||(c._wD(e+"No sound hardware, or 32-sound ceiling hit",2),a._iO.onplayerror&&a._iO.onplayerror.apply(a)))}return a};this.stop=function(b){var d=a._iO;1===a.playState&&(c._wD(a.id+": stop()"),a._onbufferchange(0),a._resetOnPosition(0),a.paused=!1,a.isHTML5||(a.playState=0),Xa(),d.to&&a.clearOnPosition(d.to),a.isHTML5?a._a&&(b=a.position,a.setPosition(0),a.position=b,a._a.pause(),a.playState=0,a._onTimer(),G()):(l._stop(a.id,b),d.serverURL&&a.unload()),a.instanceCount=
+0,a._iO={},d.onstop&&d.onstop.apply(a));return a};this.setAutoPlay=function(b){c._wD(a.id+": Autoplay turned "+(b?"on":"off"));a._iO.autoPlay=b;a.isHTML5||(l._setAutoPlay(a.id,b),b&&!a.instanceCount&&1===a.readyState&&(a.instanceCount++,c._wD(a.id+": Incremented instance count to "+a.instanceCount)))};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===g&&(b=0);var d=a.isHTML5?Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/
+1E3;a._resetOnPosition(a.position);a._iO.position=d;if(!a.isHTML5)b=9===n?a.position:b,a.readyState&&2!==a.readyState&&l._setPosition(a.id,b,a.paused||!a.playState,a._iO.multiShot);else if(a._a){if(a._html5_canplay){if(a._a.currentTime!==b){c._wD(a.id+": setPosition("+b+")");try{a._a.currentTime=b,(0===a.playState||a.paused)&&a._a.pause()}catch(e){c._wD(a.id+": setPosition("+b+") failed: "+e.message,2)}}}else if(b)return c._wD(a.id+": setPosition("+b+"): Cannot seek yet, sound not ready",2),a;a.paused&&
+a._onTimer(!0)}return a};this.pause=function(b){if(a.paused||0===a.playState&&1!==a.readyState)return a;c._wD(a.id+": pause()");a.paused=!0;a.isHTML5?(a._setup_html5().pause(),G()):(b||b===g)&&l._pause(a.id,a._iO.multiShot);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){var b=a._iO;if(!a.paused)return a;c._wD(a.id+": resume()");a.paused=!1;a.playState=1;a.isHTML5?(a._setup_html5().play(),m()):(b.isMovieStar&&!b.serverURL&&a.setPosition(a.position),l._pause(a.id,b.multiShot));
+!r&&b.onplay?(b.onplay.apply(a),r=!0):b.onresume&&b.onresume.apply(a);return a};this.togglePause=function(){c._wD(a.id+": togglePause()");if(0===a.playState)return a.play({position:9!==n||a.isHTML5?a.position/1E3:a.position}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(c,b){c===g&&(c=0);b===g&&(b=!1);a.isHTML5||l._setPan(a.id,c);a._iO.pan=c;b||(a.pan=c,a.options.pan=c);return a};this.setVolume=function(b,d){b===g&&(b=100);d===g&&(d=!1);a.isHTML5?a._a&&(c.muted&&!a.muted&&(a.muted=
+!0,a._a.muted=!0),a._a.volume=Math.max(0,Math.min(1,b/100))):l._setVolume(a.id,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;d||(a.volume=b,a.options.volume=b);return a};this.mute=function(){a.muted=!0;a.isHTML5?a._a&&(a._a.muted=!0):l._setVolume(a.id,0);return a};this.unmute=function(){a.muted=!1;var b=a._iO.volume!==g;a.isHTML5?a._a&&(a._a.muted=!1):l._setVolume(a.id,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=this.onPosition=
+function(b,c,d){E.push({position:parseInt(b,10),method:c,scope:d!==g?d:a,fired:!1});return a};this.clearOnPosition=function(a,b){var c;a=parseInt(a,10);if(isNaN(a))return!1;for(c=0;c<E.length;c++)a!==E[c].position||b&&b!==E[c].method||(E[c].fired&&v--,E.splice(c,1))};this._processOnPosition=function(){var b,c;b=E.length;if(!b||!a.playState||v>=b)return!1;for(--b;0<=b;b--)c=E[b],!c.fired&&a.position>=c.position&&(c.fired=!0,v++,c.method.apply(c.scope,[c.position]));return!0};this._resetOnPosition=
+function(a){var b,c;b=E.length;if(!b)return!1;for(--b;0<=b;b--)c=E[b],c.fired&&a<=c.position&&(c.fired=!1,v--);return!0};y=function(){var b=a._iO,d=b.from,e=b.to,f,g;g=function(){c._wD(a.id+': "To" time of '+e+" reached.");a.clearOnPosition(e,g);a.stop()};f=function(){c._wD(a.id+': Playing "from" '+d);if(null!==e&&!isNaN(e))a.onPosition(e,g)};null===d||isNaN(d)||(b.position=d,b.multiShot=!1,f());return b};q=function(){var b,c=a._iO.onposition;if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b,
+10),c[b])};Xa=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};m=function(){a.isHTML5&&fb(a)};G=function(){a.isHTML5&&gb(a)};f=function(b){b||(E=[],v=0);r=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.buffered=[];a.eqData=[];a.eqData.left=[];a.eqData.right=[];a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=
+0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,g={};if(a._hasTimer||b)return a._a&&(b||(0<a.playState||1===a.readyState)&&!a.paused)&&(c=a._get_html5_duration(),c!==d&&(d=c,a.duration=c,f=!0),a.durationEstimate=a.duration,c=1E3*a._a.currentTime||0,c!==e&&(e=c,f=!0),(f||b)&&a._whileplaying(c,g,g,g,g)),f};this._get_html5_duration=function(){var b=
+a._iO;return(b=a._a&&a._a.duration?1E3*a._a.duration:b&&b.duration?b.duration:null)&&!isNaN(b)&&Infinity!==b?b:null};this._apply_loop=function(a,b){!a.loop&&1<b&&c._wD("Note: Native HTML5 looping is infinite.",1);a.loop=1<b?"loop":""};this._setup_html5=function(b){b=A(a._iO,b);var c=C?Ya:a._a,d=decodeURI(b.url),e;C?d===decodeURI(Ma)&&(e=!0):d===decodeURI(u)&&(e=!0);if(c){if(c._s)if(C)c._s&&c._s.playState&&!e&&c._s.stop();else if(!C&&d===decodeURI(u))return a._apply_loop(c,b.loops),c;e||(u&&f(!1),
+c.src=b.url,Ma=u=a.url=b.url,c._called_load=!1)}else b.autoLoad||b.autoPlay?(a._a=new Audio(b.url),a._a.load()):a._a=Sa&&10>opera.version()?new Audio(null):new Audio,c=a._a,c._called_load=!1,C&&(Ya=c);a.isHTML5=!0;a._a=c;c._s=a;h();a._apply_loop(c,b.loops);b.autoLoad||b.autoPlay?a.load():(c.autobuffer=!1,c.preload="auto");return c};h=function(){if(a._a._added_events)return!1;var b;a._a._added_events=!0;for(b in J)J.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,J[b],!1);return!0};k=function(){var b;
+c._wD(a.id+": Removing event listeners");a._a._added_events=!1;for(b in J)J.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,J[b],!1)};this._onload=function(b){var d=!!b||!a.isHTML5&&8===n&&a.duration;b=a.id+": ";c._wD(b+(d?"onload()":"Failed to load / invalid sound?"+(a.duration?" -":" Zero-length duration reported.")+" ("+a.url+")"),d?1:2);d||a.isHTML5||(!0===c.sandbox.noRemote&&c._wD(b+t("noNet"),1),!0===c.sandbox.noLocal&&c._wD(b+t("noLocal"),1));a.loaded=d;a.readyState=d?3:2;a._onbufferchange(0);
+a._iO.onload&&ua(a,function(){a._iO.onload.apply(a,[d])});return!0};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=1===b;a._iO.onbufferchange&&(c._wD(a.id+": Buffer state change: "+b),a._iO.onbufferchange.apply(a,[b]));return!0};this._onsuspend=function(){a._iO.onsuspend&&(c._wD(a.id+": Playback suspended"),a._iO.onsuspend.apply(a));return!0};this._onfailure=function(b,d,e){a.failures++;c._wD(a.id+": Failure ("+a.failures+"): "+b);
+if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(b,d,e);else c._wD(a.id+": Ignoring failure")};this._onwarning=function(b,c,d){if(a._iO.onwarning)a._iO.onwarning(b,c,d)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);a.instanceCount&&(a.instanceCount--,a.instanceCount||(Xa(),a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},G(),a.isHTML5&&(a.position=0)),a.instanceCount&&!a._iO.multiShotEvents||!b||(c._wD(a.id+": onfinish()"),ua(a,
+function(){b.apply(a)})))};this._whileloading=function(b,c,d,e){var f=a._iO;a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(d);a.bufferLength=e;a.durationEstimate=a.isHTML5||f.isMovieStar?a.duration:f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*a.duration,10);a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,d,e,f){var k=a._iO;if(isNaN(b)||null===
+b)return!1;a.position=Math.max(0,b);a._processOnPosition();!a.isHTML5&&8<n&&(k.usePeakData&&c!==g&&c&&(a.peakData={left:c.leftPeak,right:c.rightPeak}),k.useWaveformData&&d!==g&&d&&(a.waveformData={left:d.split(","),right:e.split(",")}),k.useEQData&&f!==g&&f&&f.leftEQ&&(b=f.leftEQ.split(","),a.eqData=b,a.eqData.left=b,f.rightEQ!==g&&f.rightEQ&&(a.eqData.right=f.rightEQ.split(","))));1===a.playState&&(a.isHTML5||8!==n||a.position||!a.isBuffering||a._onbufferchange(0),k.whileplaying&&k.whileplaying.apply(a));
+return!0};this._oncaptiondata=function(b){c._wD(a.id+": Caption data received.");a.captiondata=b;a._iO.oncaptiondata&&a._iO.oncaptiondata.apply(a,[b])};this._onmetadata=function(b,d){c._wD(a.id+": Metadata received.");var e={},f,g;f=0;for(g=b.length;f<g;f++)e[b[f]]=d[f];a.metadata=e;a._iO.onmetadata&&a._iO.onmetadata.call(a,a.metadata)};this._onid3=function(b,d){c._wD(a.id+": ID3 data received.");var e=[],f,g;f=0;for(g=b.length;f<g;f++)e[b[f]]=d[f];a.id3=A(a.id3,e);a._iO.onid3&&a._iO.onid3.apply(a)};
+this._onconnect=function(b){b=1===b;c._wD(a.id+": "+(b?"Connected.":"Failed to connect? - "+a.url),b?1:2);if(a.connected=b)a.failures=0,w(a.id)&&(a.getAutoPlay()?a.play(g,a.getAutoPlay()):a._iO.autoLoad&&a.load()),a._iO.onconnect&&a._iO.onconnect.apply(a,[b])};this._ondataerror=function(b){0<a.playState&&(c._wD(a.id+": Data error: "+b),a._iO.ondataerror&&a._iO.ondataerror.apply(a))};this._debug()};ma=function(){return m.body||m.getElementsByTagName("div")[0]};F=function(b){return m.getElementById(b)};
+A=function(b,d){var e=b||{},a,f;a=d===g?c.defaultOptions:d;for(f in a)a.hasOwnProperty(f)&&e[f]===g&&(e[f]="object"!==typeof a[f]||null===a[f]?a[f]:A(e[f],a[f]));return e};ua=function(b,c){b.isHTML5||8!==n?c():h.setTimeout(c,0)};R={onready:1,ontimeout:1,defaultOptions:1,flash9Options:1,movieStarOptions:1};Ba=function(b,d){var e,a=!0,f=d!==g,h=c.setupOptions;if(b===g){a=[];for(e in h)h.hasOwnProperty(e)&&a.push(e);for(e in R)R.hasOwnProperty(e)&&("object"===typeof c[e]?a.push(e+": {...}"):c[e]instanceof
+Function?a.push(e+": function() {...}"):a.push(e));c._wD(t("setup",a.join(", ")));return!1}for(e in b)if(b.hasOwnProperty(e))if("object"!==typeof b[e]||null===b[e]||b[e]instanceof Array||b[e]instanceof RegExp)f&&R[d]!==g?c[d][e]=b[e]:h[e]!==g?(c.setupOptions[e]=b[e],c[e]=b[e]):R[e]===g?(L(t(c[e]===g?"setupUndef":"setupError",e),2),a=!1):c[e]instanceof Function?c[e].apply(c,b[e]instanceof Array?b[e]:[b[e]]):c[e]=b[e];else if(R[e]===g)L(t(c[e]===g?"setupUndef":"setupError",e),2),a=!1;else return Ba(b[e],
+e);return a};x=function(){function b(a){a=kb.call(a);var b=a.length;e?(a[1]="on"+a[1],3<b&&a.pop()):3===b&&a.push(!1);return a}function c(b,d){var g=b.shift(),h=[a[d]];if(e)g[h](b[0],b[1]);else g[h].apply(g,b)}var e=h.attachEvent,a={add:e?"attachEvent":"addEventListener",remove:e?"detachEvent":"removeEventListener"};return{add:function(){c(b(arguments),"add")},remove:function(){c(b(arguments),"remove")}}}();J={abort:r(function(){c._wD(this._s.id+": abort")}),canplay:r(function(){var b=this._s,d;if(b._html5_canplay)return!0;
+b._html5_canplay=!0;c._wD(b.id+": canplay");b._onbufferchange(0);d=b._iO.position===g||isNaN(b._iO.position)?null:b._iO.position/1E3;if(this.currentTime!==d){c._wD(b.id+": canplay: Setting position to "+d);try{this.currentTime=d}catch(e){c._wD(b.id+": canplay: Setting position of "+d+" failed: "+e.message,2)}}b._iO._oncanplay&&b._iO._oncanplay()}),canplaythrough:r(function(){var b=this._s;b.loaded||(b._onbufferchange(0),b._whileloading(b.bytesLoaded,b.bytesTotal,b._get_html5_duration()),b._onload(!0))}),
+durationchange:r(function(){var b=this._s,d;d=b._get_html5_duration();isNaN(d)||d===b.duration||(c._wD(this._s.id+": durationchange ("+d+")"+(b.duration?", previously "+b.duration:"")),b.durationEstimate=b.duration=d)}),ended:r(function(){var b=this._s;c._wD(b.id+": ended");b._onfinish()}),error:r(function(){c._wD(this._s.id+": HTML5 error, code "+this.error.code);this._s._onload(!1)}),loadeddata:r(function(){var b=this._s;c._wD(b.id+": loadeddata");b._loaded||va||(b.duration=b._get_html5_duration())}),
+loadedmetadata:r(function(){c._wD(this._s.id+": loadedmetadata")}),loadstart:r(function(){c._wD(this._s.id+": loadstart");this._s._onbufferchange(1)}),play:r(function(){this._s._onbufferchange(0)}),playing:r(function(){c._wD(this._s.id+": playing "+String.fromCharCode(9835));this._s._onbufferchange(0)}),progress:r(function(b){var d=this._s,e,a,f;e=0;var g="progress"===b.type,k=b.target.buffered,h=b.loaded||0,m=b.total||1;d.buffered=[];if(k&&k.length){e=0;for(a=k.length;e<a;e++)d.buffered.push({start:1E3*
+k.start(e),end:1E3*k.end(e)});e=1E3*(k.end(0)-k.start(0));h=Math.min(1,e/(1E3*b.target.duration));if(g&&1<k.length){f=[];a=k.length;for(e=0;e<a;e++)f.push(1E3*b.target.buffered.start(e)+"-"+1E3*b.target.buffered.end(e));c._wD(this._s.id+": progress, timeRanges: "+f.join(", "))}g&&!isNaN(h)&&c._wD(this._s.id+": progress, "+Math.floor(100*h)+"% loaded")}isNaN(h)||(d._whileloading(h,m,d._get_html5_duration()),h&&m&&h===m&&J.canplaythrough.call(this,b))}),ratechange:r(function(){c._wD(this._s.id+": ratechange")}),
+suspend:r(function(b){var d=this._s;c._wD(this._s.id+": suspend");J.progress.call(this,b);d._onsuspend()}),stalled:r(function(){c._wD(this._s.id+": stalled")}),timeupdate:r(function(){this._s._onTimer()}),waiting:r(function(){var b=this._s;c._wD(this._s.id+": waiting");b._onbufferchange(1)})};sa=function(b){return b&&(b.type||b.url||b.serverURL)?b.serverURL||b.type&&ha(b.type)?!1:b.type?fa({type:b.type}):fa({url:b.url})||c.html5Only||b.url.match(/data\:/i):!1};ta=function(b){var d;b&&(d=va?"about:blank":
+c.html5.canPlayType("audio/wav")?"data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w==":"about:blank",b.src=d,b._called_unload!==g&&(b._called_load=!1));C&&(Ma=null);return d};fa=function(b){if(!c.useHTML5Audio||!c.hasHTML5)return!1;var d=b.url||null;b=b.type||null;var e=c.audioFormats,a;if(b&&c.html5[b]!==g)return c.html5[b]&&!ha(b);if(!N){N=[];for(a in e)e.hasOwnProperty(a)&&(N.push(a),e[a].related&&(N=N.concat(e[a].related)));N=new RegExp("\\.("+N.join("|")+
+")(\\?.*)?$","i")}(a=d?d.toLowerCase().match(N):null)&&a.length?a=a[1]:b&&(d=b.indexOf(";"),a=(-1!==d?b.substr(0,d):b).substr(6));a&&c.html5[a]!==g?d=c.html5[a]&&!ha(a):(b="audio/"+a,d=c.html5.canPlayType({type:b}),d=(c.html5[a]=d)&&c.html5[b]&&!ha(b));return d};jb=function(){function b(a){var b,e=b=!1;if(!d||"function"!==typeof d.canPlayType)return b;if(a instanceof Array){k=0;for(b=a.length;k<b;k++)if(c.html5[a[k]]||d.canPlayType(a[k]).match(c.html5Test))e=!0,c.html5[a[k]]=!0,c.flash[a[k]]=!!a[k].match(pb);
+b=e}else a=d&&"function"===typeof d.canPlayType?d.canPlayType(a):!1,b=!(!a||!a.match(c.html5Test));return b}if(!c.useHTML5Audio||!c.hasHTML5)return u=c.html5.usingFlash=!0,!1;var d=Audio!==g?Sa&&10>opera.version()?new Audio(null):new Audio:null,e,a,f={},h,k;h=c.audioFormats;for(e in h)if(h.hasOwnProperty(e)&&(a="audio/"+e,f[e]=b(h[e].type),f[a]=f[e],e.match(pb)?(c.flash[e]=!0,c.flash[a]=!0):(c.flash[e]=!1,c.flash[a]=!1),h[e]&&h[e].related))for(k=h[e].related.length-1;0<=k;k--)f["audio/"+h[e].related[k]]=
+f[e],c.html5[h[e].related[k]]=f[e],c.flash[h[e].related[k]]=f[e];f.canPlayType=d?b:null;c.html5=A(c.html5,f);c.html5.usingFlash=ib();u=c.html5.usingFlash;return!0};z={notReady:"Unavailable - wait until onready() has fired.",notOK:"Audio support is not available.",domError:"soundManagerexception caught while appending SWF to DOM.",spcWmode:"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 ("+m.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...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...",
+waitSWF:"soundManager: Waiting for 100% SWF load...",needFunction:"soundManager: Function object expected for %s",badID:'Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"soundManager: _debug(): Current sound objects",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",onload:"soundManager: initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",didInit:"soundManager: init(): Already called?",
+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:"soundManager: Failed to remove Flash node.",shutdown:"soundManager.disable(): Shutting down",queue:"soundManager: Queueing %s handler",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.",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 and html5Test property changes will not take effect until reboot().",
+noURL:"soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started.",sm2Loaded:"SoundManager 2: Ready. "+String.fromCharCode(10003),reset:"soundManager.reset(): Removing event callbacks",mobileUA:"Mobile UA detected, preferring HTML5 by default.",globalHTML5:"Using singleton HTML5 Audio() pattern for this device.",ignoreMobile:"Ignoring mobile restrictions for this device."};t=function(){var b,c,e,a;b=kb.call(arguments);c=b.shift();if((a=z&&z[c]?z[c]:"")&&b&&b.length)for(c=
+0,e=b.length;c<e;c++)a=a.replace("%s",b[c]);return a};oa=function(b){8===n&&1<b.loops&&b.stream&&(p("as2loop"),b.stream=!1);return b};pa=function(b,d){b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||b.useWaveformData||b.useEQData)&&(c._wD((d||"")+t("policy")),b.usePolicyFile=!0);return b};L=function(b){Ua&&console.warn!==g?console.warn(b):c._wD(b)};ya=function(){return!1};cb=function(b){for(var c in b)b.hasOwnProperty(c)&&"function"===typeof b[c]&&(b[c]=ya)};Ha=function(b){b===g&&(b=!1);(y||b)&&c.disable(b)};
+db=function(b){var d=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(d=b.substr(b.toLowerCase().lastIndexOf(".swf?")+4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");b=(b&&-1!==b.lastIndexOf("/")?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL;c.noSWFCache&&(b+="?ts="+(new Date).getTime());return b};Ea=function(){n=parseInt(c.flashVersion,10);8!==n&&9!==n&&(c._wD(t("badFV",n,8)),c.flashVersion=n=8);var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";c.useHTML5Audio&&!c.html5Only&&c.audioFormats.mp4.required&&
+9>n&&(c._wD(t("needfl9")),c.flashVersion=n=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===n?" (AS3/Flash 9)":" (AS2/Flash 8)");8<n?(c.defaultOptions=A(c.defaultOptions,c.flash9Options),c.features.buffering=!0,c.defaultOptions=A(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=new RegExp("\\.(mp3|"+rb.join("|")+")(\\?.*)?$","i"),c.features.movieStar=!0):c.features.movieStar=!1;c.filePattern=c.filePatterns[8!==n?"flash9":"flash8"];c.movieURL=(8===n?"soundmanager2.swf":
+"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=8<n};ab=function(b,c){if(!l)return!1;l._setPolling(b,c)};Ga=function(){c.debugURLParam.test(ia)&&(c.setupOptions.debugMode=c.debugMode=!0);if(F(c.debugID))return!1;var b,d,e,a;if(!(!c.debugMode||F(c.debugID)||Ua&&c.useConsole&&c.consoleOnly)){b=m.createElement("div");b.id=c.debugID+"-toggle";d={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};b.appendChild(m.createTextNode("-"));b.onclick=eb;b.title="Toggle SM2 debug console";v.match(/msie 6/i)&&(b.style.position="absolute",b.style.cursor="hand");for(a in d)d.hasOwnProperty(a)&&(b.style[a]=d[a]);d=m.createElement("div");d.id=c.debugID;d.style.display=c.debugMode?"block":"none";if(c.debugMode&&!F(b.id)){try{e=ma(),e.appendChild(b)}catch(f){throw Error(t("domError")+" \n"+f.toString());
+}e.appendChild(d)}}};w=this.getSoundById;p=function(b,d){return b?c._wD(t(b),d):""};eb=function(){var b=F(c.debugID),d=F(c.debugID+"-toggle");if(!b)return!1;Aa?(d.innerHTML="+",b.style.display="none"):(d.innerHTML="-",b.style.display="block");Aa=!Aa};D=function(b,c,e){if(h.sm2Debugger!==g)try{sm2Debugger.handleEvent(b,c,e)}catch(a){return!1}return!0};V=function(){var b=[];c.debugMode&&b.push("sm2_debug");c.debugFlash&&b.push("flash_debug");c.useHighPerformance&&b.push("high_performance");return b.join(" ")};
+Ja=function(){var b=t("fbHandler"),d=c.getMoviePercent(),e={type:"FLASHBLOCK"};if(c.html5Only)return!1;c.ok()?(c.didFlashBlock&&c._wD(b+": Unblocked"),c.oMC&&(c.oMC.className=[V(),"movieContainer","swf_loaded"+(c.didFlashBlock?" swf_unblocked":"")].join(" "))):(u&&(c.oMC.className=V()+" movieContainer "+(null===d?"swf_timedout":"swf_error"),c._wD(b+": "+t("fbTimeout")+(d?" ("+t("fbLoaded")+")":""))),c.didFlashBlock=!0,P({type:"ontimeout",ignoreInit:!0,error:e}),U(e))};Ca=function(b,c,e){I[b]===g&&
+(I[b]=[]);I[b].push({method:c,scope:e||null,fired:!1})};P=function(b){b||(b={type:c.ok()?"onready":"ontimeout"});if(!q&&b&&!b.ignoreInit||"ontimeout"===b.type&&(c.ok()||y&&!b.ignoreInit))return!1;var d={success:b&&b.ignoreInit?c.ok():!y},e=b&&b.type?I[b.type]||[]:[],a=[],f,d=[d],g=u&&!c.ok();b.error&&(d[0].error=b.error);b=0;for(f=e.length;b<f;b++)!0!==e[b].fired&&a.push(e[b]);if(a.length)for(b=0,f=a.length;b<f;b++)a[b].scope?a[b].method.apply(a[b].scope,d):a[b].method.apply(this,d),g||(a[b].fired=
+!0);return!0};S=function(){h.setTimeout(function(){c.useFlashBlock&&Ja();P();"function"===typeof c.onload&&(p("onload",1),c.onload.apply(h),p("onloadOK",1));c.waitForWindowLoad&&x.add(h,"load",S)},1)};Na=function(){if(H!==g)return H;var b=!1,c=navigator,e=c.plugins,a,f=h.ActiveXObject;if(e&&e.length)(c=c.mimeTypes)&&c["application/x-shockwave-flash"]&&c["application/x-shockwave-flash"].enabledPlugin&&c["application/x-shockwave-flash"].enabledPlugin.description&&(b=!0);else if(f!==g&&!v.match(/MSAppHost/i)){try{a=
+new f("ShockwaveFlash.ShockwaveFlash")}catch(m){a=null}b=!!a}return H=b};ib=function(){var b,d,e=c.audioFormats;Qa&&v.match(/os (1|2|3_0|3_1)\s/i)?(c.hasHTML5=!1,c.html5Only=!0,c.oMC&&(c.oMC.style.display="none")):c.useHTML5Audio&&(c.html5&&c.html5.canPlayType||(c._wD("SoundManager: No HTML5 Audio() support detected."),c.hasHTML5=!1),Ta&&c._wD("soundManager: Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - "+(H?"will use flash fallback for MP3/MP4, if available":
+" would use flash fallback for MP3/MP4, but none detected."),1));if(c.useHTML5Audio&&c.hasHTML5)for(d in ea=!0,e)e.hasOwnProperty(d)&&e[d].required&&(c.html5.canPlayType(e[d].type)?c.preferFlash&&(c.flash[d]||c.flash[e[d].type])&&(b=!0):(ea=!1,b=!0));c.ignoreFlash&&(b=!1,ea=!0);c.html5Only=c.hasHTML5&&c.useHTML5Audio&&!b;return!c.html5Only};ra=function(b){var d,e,a=0;if(b instanceof Array){d=0;for(e=b.length;d<e;d++)if(b[d]instanceof Object){if(c.canPlayMIME(b[d].type)){a=d;break}}else if(c.canPlayURL(b[d])){a=
+d;break}b[a].url&&(b[a]=b[a].url);b=b[a]}return b};fb=function(b){b._hasTimer||(b._hasTimer=!0,!wa&&c.html5PollingInterval&&(null===da&&0===qa&&(da=setInterval(hb,c.html5PollingInterval)),qa++))};gb=function(b){b._hasTimer&&(b._hasTimer=!1,!wa&&c.html5PollingInterval&&qa--)};hb=function(){var b;if(null!==da&&!qa)return clearInterval(da),da=null,!1;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].isHTML5&&c.sounds[c.soundIDs[b]]._hasTimer&&c.sounds[c.soundIDs[b]]._onTimer()};U=function(b){b=
+b!==g?b:{};"function"===typeof c.onerror&&c.onerror.apply(h,[{type:b.type!==g?b.type:null}]);b.fatal!==g&&b.fatal&&c.disable()};lb=function(){if(!Ta||!Na())return!1;var b=c.audioFormats,d,e;for(e in b)if(b.hasOwnProperty(e)&&("mp3"===e||"mp4"===e)&&(c._wD("soundManager: Using flash fallback for "+e+" format"),c.html5[e]=!1,b[e]&&b[e].related))for(d=b[e].related.length-1;0<=d;d--)c.html5[b[e].related[d]]=!1};this._setSandboxType=function(b){var d=c.sandbox;d.type=b;d.description=d.types[d.types[b]!==
+g?b:"unknown"];"localWithFile"===d.type?(d.noRemote=!0,d.noLocal=!1,p("secNote",2)):"localWithNetwork"===d.type?(d.noRemote=!1,d.noLocal=!0):"localTrusted"===d.type&&(d.noRemote=!1,d.noLocal=!1)};this._externalInterfaceOK=function(b){if(c.swfLoaded)return!1;var d;D("swf",!0);D("flashtojs",!0);c.swfLoaded=!0;xa=!1;Ta&&lb();if(!b||b.replace(/\+dev/i,"")!==c.versionNumber.replace(/\+dev/i,""))return d='soundManager: Fatal: JavaScript file build "'+c.versionNumber+'" does not match Flash SWF build "'+
+b+'" at '+c.url+". Ensure both are up-to-date.",setTimeout(function(){throw Error(d);},0),!1;setTimeout(za,O?100:1)};na=function(b,d){function e(){var a=[],b,d=[];b="SoundManager "+c.version+(!c.html5Only&&c.useHTML5Audio?c.hasHTML5?" + HTML5 audio":", no HTML5 audio support":"");c.html5Only?c.html5PollingInterval&&a.push("html5PollingInterval ("+c.html5PollingInterval+"ms)"):(c.preferFlash&&a.push("preferFlash"),c.useHighPerformance&&a.push("useHighPerformance"),c.flashPollingInterval&&a.push("flashPollingInterval ("+
+c.flashPollingInterval+"ms)"),c.html5PollingInterval&&a.push("html5PollingInterval ("+c.html5PollingInterval+"ms)"),c.wmode&&a.push("wmode ("+c.wmode+")"),c.debugFlash&&a.push("debugFlash"),c.useFlashBlock&&a.push("flashBlock"));a.length&&(d=d.concat([a.join(" + ")]));c._wD(b+(d.length?" + "+d.join(", "):""),1);mb()}function a(a,b){return'<param name="'+a+'" value="'+b+'" />'}if(X&&Y)return!1;if(c.html5Only)return Ea(),e(),c.oMC=F(c.movieID),za(),Y=X=!0,!1;var f=d||c.url,h=c.altURL||f,k=ma(),l=V(),
+n=null,n=m.getElementsByTagName("html")[0],p,r,q,n=n&&n.dir&&n.dir.match(/rtl/i);b=b===g?c.id:b;Ea();c.url=db(ga?f:h);d=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;null!==c.wmode&&(v.match(/msie 8/i)||!O&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i)&&(M.push(z.spcWmode),c.wmode=null);k={name:b,id:b,src:d,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:vb+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",
+type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};c.debugFlash&&(k.FlashVars="debug=1");c.wmode||delete k.wmode;if(O)f=m.createElement("div"),r=['<object id="'+b+'" data="'+d+'" type="'+k.type+'" title="'+k.title+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">',a("movie",d),a("AllowScriptAccess",c.allowScriptAccess),a("quality",k.quality),c.wmode?a("wmode",c.wmode):"",a("bgcolor",
+c.bgColor),a("hasPriority","true"),c.debugFlash?a("FlashVars",k.FlashVars):"","</object>"].join("");else for(p in f=m.createElement("embed"),k)k.hasOwnProperty(p)&&f.setAttribute(p,k[p]);Ga();l=V();if(k=ma())if(c.oMC=F(c.movieID)||m.createElement("div"),c.oMC.id)q=c.oMC.className,c.oMC.className=(q?q+" ":"movieContainer")+(l?" "+l:""),c.oMC.appendChild(f),O&&(p=c.oMC.appendChild(m.createElement("div")),p.className="sm2-object-box",p.innerHTML=r),Y=!0;else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+
+l;p=l=null;c.useFlashBlock||(c.useHighPerformance?l={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"}:(l={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},n&&(l.left=Math.abs(parseInt(l.left,10))+"px")));ub&&(c.oMC.style.zIndex=1E4);if(!c.debugFlash)for(q in l)l.hasOwnProperty(q)&&(c.oMC.style[q]=l[q]);try{O||c.oMC.appendChild(f),k.appendChild(c.oMC),O&&(p=c.oMC.appendChild(m.createElement("div")),p.className="sm2-object-box",p.innerHTML=
+r),Y=!0}catch(u){throw Error(t("domError")+" \n"+u.toString());}}X=!0;e();return!0};la=function(){if(c.html5Only)return na(),!1;if(l)return!1;if(!c.url)return p("noURL"),!1;l=c.getMovie(c.id);l||(ba?(O?c.oMC.innerHTML=Ia:c.oMC.appendChild(ba),ba=null,X=!0):na(c.id,c.url),l=c.getMovie(c.id));"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);Oa();return!0};T=function(){setTimeout($a,1E3)};Da=function(){h.setTimeout(function(){L("soundManager: useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...");
+c.setup({preferFlash:!1}).reboot();c.didFlashBlock=!0;c.beginDelayedInit()},1)};$a=function(){var b,d=!1;if(!c.url||ca)return!1;ca=!0;x.remove(h,"load",T);if(H&&xa&&!Va)return p("waitFocus"),!1;q||(b=c.getMoviePercent(),0<b&&100>b&&(d=!0));setTimeout(function(){b=c.getMoviePercent();if(d)return ca=!1,c._wD(t("waitSWF")),h.setTimeout(T,1),!1;q||(c._wD("soundManager: No Flash response within expected time. Likely causes: "+(0===b?"SWF load failed, ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?
+" "+t("checkSWF"):""),2),!ga&&b&&(p("localFail",2),c.debugFlash||p("tryDebug",2)),0===b&&c._wD(t("swf404",c.url),1),D("flashtojs",!1,": Timed out"+(ga?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)")));!q&&ob&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&Ja(),p("waitForever")):!c.useFlashBlock&&ea?Da():(p("waitForever"),P({type:"ontimeout",ignoreInit:!0,error:{type:"INIT_FLASHBLOCK"}})):0===c.flashLoadTimeout?p("waitForever"):!c.useFlashBlock&&ea?Da():
+Ha(!0))},c.flashLoadTimeout)};ka=function(){if(Va||!xa)return x.remove(h,"focus",ka),!0;Va=ob=!0;p("gotFocus");ca=!1;T();x.remove(h,"focus",ka);return!0};Oa=function(){M.length&&(c._wD("SoundManager 2: "+M.join(" "),1),M=[])};mb=function(){Oa();var b,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&d.push(b+" = "+c.html5[b]+(!c.html5[b]&&u&&c.flash[b]?" (using flash)":c.preferFlash&&c.flash[b]&&u?" (preferring flash)":c.html5[b]?"":" ("+(c.audioFormats[b].required?
+"required, ":"")+"and no flash support)"));c._wD("SoundManager 2 HTML5 support: "+d.join(", "),1)}};Z=function(b){if(q)return!1;if(c.html5Only)return p("sm2Loaded",1),q=!0,S(),D("onload",!0),!0;var d=!0,e;c.useFlashBlock&&c.flashLoadTimeout&&!c.getMoviePercent()||(q=!0);e={type:!H&&u?"NO_FLASH":"INIT_TIMEOUT"};c._wD("SoundManager 2 "+(y?"failed to load":"loaded")+" ("+(y?"Flash security/load error":"OK")+") "+String.fromCharCode(y?10006:10003),y?2:1);y||b?(c.useFlashBlock&&c.oMC&&(c.oMC.className=
+V()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),P({type:"ontimeout",error:e,ignoreInit:!0}),D("onload",!1),U(e),d=!1):D("onload",!0);y||(c.waitForWindowLoad&&!ja?(p("waitOnload"),x.add(h,"load",S)):(c.waitForWindowLoad&&ja&&p("docLoaded"),S()));return d};Za=function(){var b,d=c.setupOptions;for(b in d)d.hasOwnProperty(b)&&(c[b]===g?c[b]=d[b]:c[b]!==d[b]&&(c.setupOptions[b]=c[b]))};za=function(){if(q)return p("didInit"),!1;if(c.html5Only)return q||(x.remove(h,"load",c.beginDelayedInit),
+c.enabled=!0,Z()),!0;la();try{l._externalInterfaceTest(!1),ab(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||l._disableDebug(),c.enabled=!0,D("jstoflash",!0),c.html5Only||x.add(h,"unload",ya)}catch(b){return c._wD("js/flash exception: "+b.toString()),D("jstoflash",!1),U({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),Ha(!0),Z(),!1}Z();x.remove(h,"load",c.beginDelayedInit);return!0};Q=function(){if(aa)return!1;aa=!0;Za();Ga();!H&&c.hasHTML5&&(c._wD("SoundManager 2: No Flash detected"+
+(c.useHTML5Audio?". Trying HTML5-only mode.":", enabling HTML5."),1),c.setup({useHTML5Audio:!0,preferFlash:!1}));jb();!H&&u&&(M.push(z.needFlash),c.setup({flashLoadTimeout:1}));m.removeEventListener&&m.removeEventListener("DOMContentLoaded",Q,!1);la();return!0};La=function(){"complete"===m.readyState&&(Q(),m.detachEvent("onreadystatechange",La));return!0};Fa=function(){ja=!0;Q();x.remove(h,"load",Fa)};Na();x.add(h,"focus",ka);x.add(h,"load",T);x.add(h,"load",Fa);m.addEventListener?m.addEventListener("DOMContentLoaded",
+Q,!1):m.attachEvent?m.attachEvent("onreadystatechange",La):(D("onload",!1),U({type:"NO_DOM2_EVENTS",fatal:!0}))}if(!h||!h.document)throw Error("SoundManager requires a browser with window and document objects.");var W=null;h.SM2_DEFER!==g&&SM2_DEFER||(W=new K);"object"===typeof module&&module&&"object"===typeof module.exports?(module.exports.SoundManager=K,module.exports.soundManager=W):"function"===typeof define&&define.amd&&define(function(){return{constructor:K,getInstance:function(g){!h.soundManager&&
+g instanceof Function&&(g=g(K),g instanceof K&&(h.soundManager=g));return h.soundManager}}});h.SoundManager=K;h.soundManager=W})(window);
\ No newline at end of file
--- /dev/null
+/** @license\r
+ *\r
+ * SoundManager 2: JavaScript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code provided under the BSD License:\r
+ * http://schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * V2.97a.20150601\r
+ */\r
+(function(h,g){function w(gb,w){function Z(b){return c.preferFlash&&A&&!c.ignoreFlash&&c.flash[b]!==g&&c.flash[b]}function r(b){return function(c){var d=this._s;return d&&d._a?b.call(this,c):null}}this.setupOptions={url:gb||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,
+forceUseGlobalHTML5Audio:!1,ignoreMobileRestrictions:!1,html5Test:/^(probably|maybe)$/i,preferFlash:!1,noSWFCache:!1,idPrefix:"sound"};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},opus:{type:["audio/ogg; codecs=opus",
+"audio/opus"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave","audio/x-wav"],required:!1}};this.movieID="sm2-container";this.id=w||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20150601";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={};this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var N,c=this,Oa=null,k=null,aa,u=navigator.userAgent,Pa=h.location.href.toString(),p=document,pa,Qa,qa,m,y=[],O=!1,P=!1,l=!1,B=!1,ra=!1,Q,x,sa,ba,ta,F,H,I,Ra,ua,va,ca,J,da,G,wa,R,xa,ea,K,Sa,ya,Ta,za,Ua,S=null,Aa=null,T,Ba,L,fa,ga,q,U=!1,Ca=!1,Va,Wa,Xa,ha=0,V=null,ia,W=[],X,v=null,Ya,ja,Y,D,ka,Da,Za,t,hb=Array.prototype.slice,
+z=!1,Ea,A,Fa,$a,C,la,ab=0,Ga,Ha=u.match(/(ipad|iphone|ipod)/i),Ia=u.match(/android/i),E=u.match(/msie/i),ib=u.match(/webkit/i),ma=u.match(/safari/i)&&!u.match(/chrome/i),Ja=u.match(/opera/i),na=u.match(/(mobile|pre\/|xoom)/i)||Ha||Ia,bb=!Pa.match(/usehtml5audio/i)&&!Pa.match(/sm2\-ignorebadua/i)&&ma&&!u.match(/silk/i)&&u.match(/OS X 10_6_([3-7])/i),Ka=p.hasFocus!==g?p.hasFocus():null,oa=ma&&(p.hasFocus===g||!p.hasFocus()),cb=!oa,db=/(mp3|mp4|mpa|m4a|m4b)/i,La=p.location?p.location.protocol.match(/http/i):
+null,jb=La?"":"http://",eb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,fb="mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "),kb=new RegExp("\\.("+fb.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!La;var Ma;try{Ma=Audio!==g&&(Ja&&opera!==g&&10>opera.version()?new Audio(null):new Audio).canPlayType!==g}catch(lb){Ma=!1}this.hasHTML5=Ma;this.setup=function(b){var e=!c.url;b!==g&&l&&v&&c.ok();
+sa(b);if(!z)if(na){if(!c.setupOptions.ignoreMobileRestrictions||c.setupOptions.forceUseGlobalHTML5Audio)W.push(J.globalHTML5),z=!0}else c.setupOptions.forceUseGlobalHTML5Audio&&(W.push(J.globalHTML5),z=!0);if(!Ga&&na)if(c.setupOptions.ignoreMobileRestrictions)W.push(J.ignoreMobile);else if(c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,Ha)c.ignoreFlash=!0;else if(Ia&&!u.match(/android\s2\.3/i)||!Ia)z=!0;b&&(e&&R&&b.url!==g&&c.beginDelayedInit(),R||b.url===g||"complete"!==p.readyState||
+setTimeout(G,1));Ga=!0;return c};this.supported=this.ok=function(){return v?l&&!B:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(b){return aa(b)||p[b]||h[b]};this.createSound=function(b,e){function d(){a=fa(a);c.sounds[a.id]=new N(a);c.soundIDs.push(a.id);return c.sounds[a.id]}var a,f=null;if(!l||!c.ok())return!1;e!==g&&(b={id:b,url:e});a=x(b);a.url=ia(a.url);a.id===g&&(a.id=c.setupOptions.idPrefix+ab++);if(q(a.id,!0))return c.sounds[a.id];if(ja(a))f=d(),f._setup_html5(a);else{if(c.html5Only||
+c.html5.usingFlash&&a.url&&a.url.match(/data\:/i))return d();8<m&&null===a.isMovieStar&&(a.isMovieStar=!!(a.serverURL||a.type&&a.type.match(eb)||a.url&&a.url.match(kb)));a=ga(a,void 0);f=d();8===m?k._createSound(a.id,a.loops||1,a.usePolicyFile):(k._createSound(a.id,a.url,a.usePeakData,a.useWaveformData,a.useEQData,a.isMovieStar,a.isMovieStar?a.bufferTime:!1,a.loops||1,a.serverURL,a.duration||null,a.autoPlay,!0,a.autoLoad,a.usePolicyFile),a.serverURL||(f.connected=!0,a.onconnect&&a.onconnect.apply(f)));
+a.serverURL||!a.autoLoad&&!a.autoPlay||f.load(a)}!a.serverURL&&a.autoPlay&&f.play();return f};this.destroySound=function(b,e){if(!q(b))return!1;var d=c.sounds[b],a;d.stop();d._iO={};d.unload();for(a=0;a<c.soundIDs.length;a++)if(c.soundIDs[a]===b){c.soundIDs.splice(a,1);break}e||d.destruct(!0);delete c.sounds[b];return!0};this.load=function(b,e){return q(b)?c.sounds[b].load(e):!1};this.unload=function(b){return q(b)?c.sounds[b].unload():!1};this.onposition=this.onPosition=function(b,e,d,a){return q(b)?
+c.sounds[b].onposition(e,d,a):!1};this.clearOnPosition=function(b,e,d){return q(b)?c.sounds[b].clearOnPosition(e,d):!1};this.start=this.play=function(b,e){var d=null,a=e&&!(e instanceof Object);if(!l||!c.ok())return!1;if(q(b,a))a&&(e={url:e});else{if(!a)return!1;a&&(e={url:e});e&&e.url&&(e.id=b,d=c.createSound(e).play())}null===d&&(d=c.sounds[b].play(e));return d};this.setPosition=function(b,e){return q(b)?c.sounds[b].setPosition(e):!1};this.stop=function(b){return q(b)?c.sounds[b].stop():!1};this.stopAll=
+function(){for(var b in c.sounds)c.sounds.hasOwnProperty(b)&&c.sounds[b].stop()};this.pause=function(b){return q(b)?c.sounds[b].pause():!1};this.pauseAll=function(){var b;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].pause()};this.resume=function(b){return q(b)?c.sounds[b].resume():!1};this.resumeAll=function(){var b;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].resume()};this.togglePause=function(b){return q(b)?c.sounds[b].togglePause():!1};this.setPan=function(b,e){return q(b)?
+c.sounds[b].setPan(e):!1};this.setVolume=function(b,e){var d,a;if(b===g||isNaN(b)||e!==g)return q(b)?c.sounds[b].setVolume(e):!1;d=0;for(a=c.soundIDs.length;d<a;d++)c.sounds[c.soundIDs[d]].setVolume(b)};this.mute=function(b){var e=0;b instanceof String&&(b=null);if(b)return q(b)?c.sounds[b].mute():!1;for(e=c.soundIDs.length-1;0<=e;e--)c.sounds[c.soundIDs[e]].mute();return c.muted=!0};this.muteAll=function(){c.mute()};this.unmute=function(b){b instanceof String&&(b=null);if(b)return q(b)?c.sounds[b].unmute():
+!1;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].unmute();c.muted=!1;return!0};this.unmuteAll=function(){c.unmute()};this.toggleMute=function(b){return q(b)?c.sounds[b].toggleMute():!1};this.getMemoryUse=function(){var b=0;k&&8!==m&&(b=parseInt(k._getMemoryUse(),10));return b};this.disable=function(b){var e;b===g&&(b=!1);if(B)return!1;B=!0;for(e=c.soundIDs.length-1;0<=e;e--)Ta(c.sounds[c.soundIDs[e]]);Q(b);t.remove(h,"load",H);return!0};this.canPlayMIME=function(b){var e;c.hasHTML5&&
+(e=Y({type:b}));!e&&v&&(e=b&&c.ok()?!!(8<m&&b.match(eb)||b.match(c.mimePattern)):null);return e};this.canPlayURL=function(b){var e;c.hasHTML5&&(e=Y({url:b}));!e&&v&&(e=b&&c.ok()?!!b.match(c.filePattern):null);return e};this.canPlayLink=function(b){return b.type!==g&&b.type&&c.canPlayMIME(b.type)?!0:c.canPlayURL(b.href)};this.getSoundById=function(b,e){return b?c.sounds[b]:null};this.onready=function(b,c){if("function"===typeof b)c||(c=h),ta("onready",b,c),F();else throw T("needFunction","onready");
+return!0};this.ontimeout=function(b,c){if("function"===typeof b)c||(c=h),ta("ontimeout",b,c),F({type:"ontimeout"});else throw T("needFunction","ontimeout");return!0};this._wD=this._writeDebug=function(b,c){return!0};this._debug=function(){};this.reboot=function(b,e){var d,a,f;for(d=c.soundIDs.length-1;0<=d;d--)c.sounds[c.soundIDs[d]].destruct();if(k)try{E&&(Aa=k.innerHTML),S=k.parentNode.removeChild(k)}catch(g){}Aa=S=v=k=null;c.enabled=R=l=U=Ca=O=P=B=z=c.swfLoaded=!1;c.soundIDs=[];c.sounds={};ab=
+0;Ga=!1;if(b)y=[];else for(d in y)if(y.hasOwnProperty(d))for(a=0,f=y[d].length;a<f;a++)y[d][a].fired=!1;c.html5={usingFlash:null};c.flash={};c.html5Only=!1;c.ignoreFlash=!1;h.setTimeout(function(){e||c.beginDelayedInit()},20);return c};this.reset=function(){return c.reboot(!0,!0)};this.getMoviePercent=function(){return k&&"PercentLoaded"in k?k.PercentLoaded():null};this.beginDelayedInit=function(){ra=!0;G();setTimeout(function(){if(Ca)return!1;ea();da();return Ca=!0},20);I()};this.destruct=function(){c.disable(!0)};
+N=function(b){var e,d,a=this,f,n,h,M,p,r,u=!1,l=[],v=0,y,B,w=null,A;d=e=null;this.sID=this.id=b.id;this.url=b.url;this._iO=this.instanceOptions=this.options=x(b);this.pan=this.options.pan;this.volume=this.options.volume;this.isHTML5=!1;this._a=null;A=this.url?!1:!0;this.id3={};this._debug=function(){};this.load=function(b){var e=null,d;b!==g?a._iO=x(b,a.options):(b=a.options,a._iO=b,w&&w!==a.url&&(a._iO.url=a.url,a.url=null));a._iO.url||(a._iO.url=a.url);a._iO.url=ia(a._iO.url);d=a.instanceOptions=
+a._iO;if(!d.url&&!a.url)return a;if(d.url===a.url&&0!==a.readyState&&2!==a.readyState)return 3===a.readyState&&d.onload&&la(a,function(){d.onload.apply(a,[!!a.duration])}),a;a.loaded=!1;a.readyState=1;a.playState=0;a.id3={};if(ja(d))e=a._setup_html5(d),e._called_load||(a._html5_canplay=!1,a.url!==d.url&&(a._a.src=d.url,a.setPosition(0)),a._a.autobuffer="auto",a._a.preload="auto",a._a._called_load=!0);else{if(c.html5Only||a._iO.url&&a._iO.url.match(/data\:/i))return a;try{a.isHTML5=!1,a._iO=ga(fa(d)),
+a._iO.autoPlay&&(a._iO.position||a._iO.from)&&(a._iO.autoPlay=!1),d=a._iO,8===m?k._load(a.id,d.url,d.stream,d.autoPlay,d.usePolicyFile):k._load(a.id,d.url,!!d.stream,!!d.autoPlay,d.loops||1,!!d.autoLoad,d.usePolicyFile)}catch(f){K({type:"SMSOUND_LOAD_JS_EXCEPTION",fatal:!0})}}a.url=d.url;return a};this.unload=function(){0!==a.readyState&&(a.isHTML5?(M(),a._a&&(a._a.pause(),w=ka(a._a))):8===m?k._unload(a.id,"about:blank"):k._unload(a.id),f());return a};this.destruct=function(b){a.isHTML5?(M(),a._a&&
+(a._a.pause(),ka(a._a),z||h(),a._a._s=null,a._a=null)):(a._iO.onfailure=null,k._destroySound(a.id));b||c.destroySound(a.id,!0)};this.start=this.play=function(b,e){var d,f,n,h,Na;f=!0;f=null;e=e===g?!0:e;b||(b={});a.url&&(a._iO.url=a.url);a._iO=x(a._iO,a.options);a._iO=x(b,a._iO);a._iO.url=ia(a._iO.url);a.instanceOptions=a._iO;if(!a.isHTML5&&a._iO.serverURL&&!a.connected)return a.getAutoPlay()||a.setAutoPlay(!0),a;ja(a._iO)&&(a._setup_html5(a._iO),p());1!==a.playState||a.paused||(d=a._iO.multiShot,
+d||(a.isHTML5&&a.setPosition(a._iO.position),f=a));if(null!==f)return f;b.url&&b.url!==a.url&&(a.readyState||a.isHTML5||8!==m||!A?a.load(a._iO):A=!1);a.loaded||(0===a.readyState?(a.isHTML5||c.html5Only?a.isHTML5?a.load(a._iO):f=a:(a._iO.autoPlay=!0,a.load(a._iO)),a.instanceOptions=a._iO):2===a.readyState&&(f=a));if(null!==f)return f;!a.isHTML5&&9===m&&0<a.position&&a.position===a.duration&&(b.position=0);if(a.paused&&0<=a.position&&(!a._iO.serverURL||0<a.position))a.resume();else{a._iO=x(b,a._iO);
+if((!a.isHTML5&&null!==a._iO.position&&0<a._iO.position||null!==a._iO.from&&0<a._iO.from||null!==a._iO.to)&&0===a.instanceCount&&0===a.playState&&!a._iO.serverURL){d=function(){a._iO=x(b,a._iO);a.play(a._iO)};a.isHTML5&&!a._html5_canplay?(a.load({_oncanplay:d}),f=!1):a.isHTML5||a.loaded||a.readyState&&2===a.readyState||(a.load({onload:d}),f=!1);if(null!==f)return f;a._iO=B()}(!a.instanceCount||a._iO.multiShotEvents||a.isHTML5&&a._iO.multiShot&&!z||!a.isHTML5&&8<m&&!a.getAutoPlay())&&a.instanceCount++;
+a._iO.onposition&&0===a.playState&&r(a);a.playState=1;a.paused=!1;a.position=a._iO.position===g||isNaN(a._iO.position)?0:a._iO.position;a.isHTML5||(a._iO=ga(fa(a._iO)));a._iO.onplay&&e&&(a._iO.onplay.apply(a),u=!0);a.setVolume(a._iO.volume,!0);a.setPan(a._iO.pan,!0);a.isHTML5?2>a.instanceCount?(p(),f=a._setup_html5(),a.setPosition(a._iO.position),f.play()):(n=new Audio(a._iO.url),h=function(){t.remove(n,"ended",h);a._onfinish(a);ka(n);n=null},Na=function(){t.remove(n,"canplay",Na);try{n.currentTime=
+a._iO.position/1E3}catch(b){}n.play()},t.add(n,"ended",h),a._iO.volume!==g&&(n.volume=Math.max(0,Math.min(1,a._iO.volume/100))),a.muted&&(n.muted=!0),a._iO.position?t.add(n,"canplay",Na):n.play()):(f=k._start(a.id,a._iO.loops||1,9===m?a.position:a.position/1E3,a._iO.multiShot||!1),9!==m||f||a._iO.onplayerror&&a._iO.onplayerror.apply(a))}return a};this.stop=function(b){var c=a._iO;1===a.playState&&(a._onbufferchange(0),a._resetOnPosition(0),a.paused=!1,a.isHTML5||(a.playState=0),y(),c.to&&a.clearOnPosition(c.to),
+a.isHTML5?a._a&&(b=a.position,a.setPosition(0),a.position=b,a._a.pause(),a.playState=0,a._onTimer(),M()):(k._stop(a.id,b),c.serverURL&&a.unload()),a.instanceCount=0,a._iO={},c.onstop&&c.onstop.apply(a));return a};this.setAutoPlay=function(b){a._iO.autoPlay=b;a.isHTML5||(k._setAutoPlay(a.id,b),b&&(a.instanceCount||1!==a.readyState||a.instanceCount++))};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===g&&(b=0);var c=a.isHTML5?Math.max(b,0):Math.min(a.duration||a._iO.duration,
+Math.max(b,0));a.position=c;b=a.position/1E3;a._resetOnPosition(a.position);a._iO.position=c;if(!a.isHTML5)b=9===m?a.position:b,a.readyState&&2!==a.readyState&&k._setPosition(a.id,b,a.paused||!a.playState,a._iO.multiShot);else if(a._a){if(a._html5_canplay){if(a._a.currentTime!==b)try{a._a.currentTime=b,(0===a.playState||a.paused)&&a._a.pause()}catch(e){}}else if(b)return a;a.paused&&a._onTimer(!0)}return a};this.pause=function(b){if(a.paused||0===a.playState&&1!==a.readyState)return a;a.paused=!0;
+a.isHTML5?(a._setup_html5().pause(),M()):(b||b===g)&&k._pause(a.id,a._iO.multiShot);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){var b=a._iO;if(!a.paused)return a;a.paused=!1;a.playState=1;a.isHTML5?(a._setup_html5().play(),p()):(b.isMovieStar&&!b.serverURL&&a.setPosition(a.position),k._pause(a.id,b.multiShot));!u&&b.onplay?(b.onplay.apply(a),u=!0):b.onresume&&b.onresume.apply(a);return a};this.togglePause=function(){if(0===a.playState)return a.play({position:9!==m||a.isHTML5?
+a.position/1E3:a.position}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,c){b===g&&(b=0);c===g&&(c=!1);a.isHTML5||k._setPan(a.id,b);a._iO.pan=b;c||(a.pan=b,a.options.pan=b);return a};this.setVolume=function(b,e){b===g&&(b=100);e===g&&(e=!1);a.isHTML5?a._a&&(c.muted&&!a.muted&&(a.muted=!0,a._a.muted=!0),a._a.volume=Math.max(0,Math.min(1,b/100))):k._setVolume(a.id,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;e||(a.volume=b,a.options.volume=b);return a};this.mute=function(){a.muted=
+!0;a.isHTML5?a._a&&(a._a.muted=!0):k._setVolume(a.id,0);return a};this.unmute=function(){a.muted=!1;var b=a._iO.volume!==g;a.isHTML5?a._a&&(a._a.muted=!1):k._setVolume(a.id,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=this.onPosition=function(b,c,e){l.push({position:parseInt(b,10),method:c,scope:e!==g?e:a,fired:!1});return a};this.clearOnPosition=function(a,b){var c;a=parseInt(a,10);if(isNaN(a))return!1;for(c=0;c<l.length;c++)a!==
+l[c].position||b&&b!==l[c].method||(l[c].fired&&v--,l.splice(c,1))};this._processOnPosition=function(){var b,c;b=l.length;if(!b||!a.playState||v>=b)return!1;for(--b;0<=b;b--)c=l[b],!c.fired&&a.position>=c.position&&(c.fired=!0,v++,c.method.apply(c.scope,[c.position]));return!0};this._resetOnPosition=function(a){var b,c;b=l.length;if(!b)return!1;for(--b;0<=b;b--)c=l[b],c.fired&&a<=c.position&&(c.fired=!1,v--);return!0};B=function(){var b=a._iO,c=b.from,e=b.to,d,f;f=function(){a.clearOnPosition(e,f);
+a.stop()};d=function(){if(null!==e&&!isNaN(e))a.onPosition(e,f)};null===c||isNaN(c)||(b.position=c,b.multiShot=!1,d());return b};r=function(){var b,c=a._iO.onposition;if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b,10),c[b])};y=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};p=function(){a.isHTML5&&Va(a)};M=function(){a.isHTML5&&Wa(a)};f=function(b){b||(l=[],v=0);u=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=
+null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.buffered=[];a.eqData=[];a.eqData.left=[];a.eqData.right=[];a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,g={};if(a._hasTimer||b)return a._a&&(b||(0<a.playState||1===a.readyState)&&
+!a.paused)&&(c=a._get_html5_duration(),c!==e&&(e=c,a.duration=c,f=!0),a.durationEstimate=a.duration,c=1E3*a._a.currentTime||0,c!==d&&(d=c,f=!0),(f||b)&&a._whileplaying(c,g,g,g,g)),f};this._get_html5_duration=function(){var b=a._iO;return(b=a._a&&a._a.duration?1E3*a._a.duration:b&&b.duration?b.duration:null)&&!isNaN(b)&&Infinity!==b?b:null};this._apply_loop=function(a,b){a.loop=1<b?"loop":""};this._setup_html5=function(b){b=x(a._iO,b);var c=z?Oa:a._a,e=decodeURI(b.url),d;z?e===decodeURI(Ea)&&(d=!0):
+e===decodeURI(w)&&(d=!0);if(c){if(c._s)if(z)c._s&&c._s.playState&&!d&&c._s.stop();else if(!z&&e===decodeURI(w))return a._apply_loop(c,b.loops),c;d||(w&&f(!1),c.src=b.url,Ea=w=a.url=b.url,c._called_load=!1)}else b.autoLoad||b.autoPlay?(a._a=new Audio(b.url),a._a.load()):a._a=Ja&&10>opera.version()?new Audio(null):new Audio,c=a._a,c._called_load=!1,z&&(Oa=c);a.isHTML5=!0;a._a=c;c._s=a;n();a._apply_loop(c,b.loops);b.autoLoad||b.autoPlay?a.load():(c.autobuffer=!1,c.preload="auto");return c};n=function(){if(a._a._added_events)return!1;
+var b;a._a._added_events=!0;for(b in C)C.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,C[b],!1);return!0};h=function(){var b;a._a._added_events=!1;for(b in C)C.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,C[b],!1)};this._onload=function(b){var c=!!b||!a.isHTML5&&8===m&&a.duration;a.loaded=c;a.readyState=c?3:2;a._onbufferchange(0);a._iO.onload&&la(a,function(){a._iO.onload.apply(a,[c])});return!0};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;
+a.isBuffering=1===b;a._iO.onbufferchange&&a._iO.onbufferchange.apply(a,[b]);return!0};this._onsuspend=function(){a._iO.onsuspend&&a._iO.onsuspend.apply(a);return!0};this._onfailure=function(b,c,e){a.failures++;if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(b,c,e)};this._onwarning=function(b,c,e){if(a._iO.onwarning)a._iO.onwarning(b,c,e)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);a.instanceCount&&(a.instanceCount--,a.instanceCount||(y(),a.playState=
+0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},M(),a.isHTML5&&(a.position=0)),(!a.instanceCount||a._iO.multiShotEvents)&&b&&la(a,function(){b.apply(a)}))};this._whileloading=function(b,c,e,d){var f=a._iO;a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(e);a.bufferLength=d;a.durationEstimate=a.isHTML5||f.isMovieStar?a.duration:f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*a.duration,10);a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);
+(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,e,d,f){var n=a._iO;if(isNaN(b)||null===b)return!1;a.position=Math.max(0,b);a._processOnPosition();!a.isHTML5&&8<m&&(n.usePeakData&&c!==g&&c&&(a.peakData={left:c.leftPeak,right:c.rightPeak}),n.useWaveformData&&e!==g&&e&&(a.waveformData={left:e.split(","),right:d.split(",")}),n.useEQData&&f!==g&&f&&f.leftEQ&&(b=f.leftEQ.split(","),a.eqData=b,a.eqData.left=b,f.rightEQ!==g&&f.rightEQ&&(a.eqData.right=
+f.rightEQ.split(","))));1===a.playState&&(a.isHTML5||8!==m||a.position||!a.isBuffering||a._onbufferchange(0),n.whileplaying&&n.whileplaying.apply(a));return!0};this._oncaptiondata=function(b){a.captiondata=b;a._iO.oncaptiondata&&a._iO.oncaptiondata.apply(a,[b])};this._onmetadata=function(b,c){var e={},d,f;d=0;for(f=b.length;d<f;d++)e[b[d]]=c[d];a.metadata=e;a._iO.onmetadata&&a._iO.onmetadata.call(a,a.metadata)};this._onid3=function(b,c){var e=[],d,f;d=0;for(f=b.length;d<f;d++)e[b[d]]=c[d];a.id3=x(a.id3,
+e);a._iO.onid3&&a._iO.onid3.apply(a)};this._onconnect=function(b){b=1===b;if(a.connected=b)a.failures=0,q(a.id)&&(a.getAutoPlay()?a.play(g,a.getAutoPlay()):a._iO.autoLoad&&a.load()),a._iO.onconnect&&a._iO.onconnect.apply(a,[b])};this._ondataerror=function(b){0<a.playState&&a._iO.ondataerror&&a._iO.ondataerror.apply(a)}};xa=function(){return p.body||p.getElementsByTagName("div")[0]};aa=function(b){return p.getElementById(b)};x=function(b,e){var d=b||{},a,f;a=e===g?c.defaultOptions:e;for(f in a)a.hasOwnProperty(f)&&
+d[f]===g&&(d[f]="object"!==typeof a[f]||null===a[f]?a[f]:x(d[f],a[f]));return d};la=function(b,c){b.isHTML5||8!==m?c():h.setTimeout(c,0)};ba={onready:1,ontimeout:1,defaultOptions:1,flash9Options:1,movieStarOptions:1};sa=function(b,e){var d,a=!0,f=e!==g,n=c.setupOptions;for(d in b)if(b.hasOwnProperty(d))if("object"!==typeof b[d]||null===b[d]||b[d]instanceof Array||b[d]instanceof RegExp)f&&ba[e]!==g?c[e][d]=b[d]:n[d]!==g?(c.setupOptions[d]=b[d],c[d]=b[d]):ba[d]===g?a=!1:c[d]instanceof Function?c[d].apply(c,
+b[d]instanceof Array?b[d]:[b[d]]):c[d]=b[d];else if(ba[d]===g)a=!1;else return sa(b[d],d);return a};t=function(){function b(a){a=hb.call(a);var b=a.length;d?(a[1]="on"+a[1],3<b&&a.pop()):3===b&&a.push(!1);return a}function c(b,e){var g=b.shift(),h=[a[e]];if(d)g[h](b[0],b[1]);else g[h].apply(g,b)}var d=h.attachEvent,a={add:d?"attachEvent":"addEventListener",remove:d?"detachEvent":"removeEventListener"};return{add:function(){c(b(arguments),"add")},remove:function(){c(b(arguments),"remove")}}}();C={abort:r(function(){}),
+canplay:r(function(){var b=this._s,c;if(b._html5_canplay)return!0;b._html5_canplay=!0;b._onbufferchange(0);c=b._iO.position===g||isNaN(b._iO.position)?null:b._iO.position/1E3;if(this.currentTime!==c)try{this.currentTime=c}catch(d){}b._iO._oncanplay&&b._iO._oncanplay()}),canplaythrough:r(function(){var b=this._s;b.loaded||(b._onbufferchange(0),b._whileloading(b.bytesLoaded,b.bytesTotal,b._get_html5_duration()),b._onload(!0))}),durationchange:r(function(){var b=this._s,c;c=b._get_html5_duration();isNaN(c)||
+c===b.duration||(b.durationEstimate=b.duration=c)}),ended:r(function(){this._s._onfinish()}),error:r(function(){this._s._onload(!1)}),loadeddata:r(function(){var b=this._s;b._loaded||ma||(b.duration=b._get_html5_duration())}),loadedmetadata:r(function(){}),loadstart:r(function(){this._s._onbufferchange(1)}),play:r(function(){this._s._onbufferchange(0)}),playing:r(function(){this._s._onbufferchange(0)}),progress:r(function(b){var c=this._s,d,a,f=0,f=b.target.buffered;d=b.loaded||0;var g=b.total||1;
+c.buffered=[];if(f&&f.length){d=0;for(a=f.length;d<a;d++)c.buffered.push({start:1E3*f.start(d),end:1E3*f.end(d)});f=1E3*(f.end(0)-f.start(0));d=Math.min(1,f/(1E3*b.target.duration))}isNaN(d)||(c._whileloading(d,g,c._get_html5_duration()),d&&g&&d===g&&C.canplaythrough.call(this,b))}),ratechange:r(function(){}),suspend:r(function(b){var c=this._s;C.progress.call(this,b);c._onsuspend()}),stalled:r(function(){}),timeupdate:r(function(){this._s._onTimer()}),waiting:r(function(){this._s._onbufferchange(1)})};
+ja=function(b){return b&&(b.type||b.url||b.serverURL)?b.serverURL||b.type&&Z(b.type)?!1:b.type?Y({type:b.type}):Y({url:b.url})||c.html5Only||b.url.match(/data\:/i):!1};ka=function(b){var e;b&&(e=ma?"about:blank":c.html5.canPlayType("audio/wav")?"data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w==":"about:blank",b.src=e,b._called_unload!==g&&(b._called_load=!1));z&&(Ea=null);return e};Y=function(b){if(!c.useHTML5Audio||!c.hasHTML5)return!1;var e=b.url||null;b=b.type||
+null;var d=c.audioFormats,a;if(b&&c.html5[b]!==g)return c.html5[b]&&!Z(b);if(!D){D=[];for(a in d)d.hasOwnProperty(a)&&(D.push(a),d[a].related&&(D=D.concat(d[a].related)));D=new RegExp("\\.("+D.join("|")+")(\\?.*)?$","i")}(a=e?e.toLowerCase().match(D):null)&&a.length?a=a[1]:b&&(e=b.indexOf(";"),a=(-1!==e?b.substr(0,e):b).substr(6));a&&c.html5[a]!==g?e=c.html5[a]&&!Z(a):(b="audio/"+a,e=c.html5.canPlayType({type:b}),e=(c.html5[a]=e)&&c.html5[b]&&!Z(b));return e};Za=function(){function b(a){var b,d=b=
+!1;if(!e||"function"!==typeof e.canPlayType)return b;if(a instanceof Array){h=0;for(b=a.length;h<b;h++)if(c.html5[a[h]]||e.canPlayType(a[h]).match(c.html5Test))d=!0,c.html5[a[h]]=!0,c.flash[a[h]]=!!a[h].match(db);b=d}else a=e&&"function"===typeof e.canPlayType?e.canPlayType(a):!1,b=!(!a||!a.match(c.html5Test));return b}if(!c.useHTML5Audio||!c.hasHTML5)return v=c.html5.usingFlash=!0,!1;var e=Audio!==g?Ja&&10>opera.version()?new Audio(null):new Audio:null,d,a,f={},n,h;n=c.audioFormats;for(d in n)if(n.hasOwnProperty(d)&&
+(a="audio/"+d,f[d]=b(n[d].type),f[a]=f[d],d.match(db)?(c.flash[d]=!0,c.flash[a]=!0):(c.flash[d]=!1,c.flash[a]=!1),n[d]&&n[d].related))for(h=n[d].related.length-1;0<=h;h--)f["audio/"+n[d].related[h]]=f[d],c.html5[n[d].related[h]]=f[d],c.flash[n[d].related[h]]=f[d];f.canPlayType=e?b:null;c.html5=x(c.html5,f);c.html5.usingFlash=Ya();v=c.html5.usingFlash;return!0};J={};T=function(){};fa=function(b){8===m&&1<b.loops&&b.stream&&(b.stream=!1);return b};ga=function(b,c){b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||
+b.useWaveformData||b.useEQData)&&(b.usePolicyFile=!0);return b};pa=function(){return!1};Ta=function(b){for(var c in b)b.hasOwnProperty(c)&&"function"===typeof b[c]&&(b[c]=pa)};za=function(b){b===g&&(b=!1);(B||b)&&c.disable(b)};Ua=function(b){var e=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(e=b.substr(b.toLowerCase().lastIndexOf(".swf?")+4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");b=(b&&-1!==b.lastIndexOf("/")?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL;c.noSWFCache&&(b+="?ts="+
+(new Date).getTime());return b};va=function(){m=parseInt(c.flashVersion,10);8!==m&&9!==m&&(c.flashVersion=m=8);var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";c.useHTML5Audio&&!c.html5Only&&c.audioFormats.mp4.required&&9>m&&(c.flashVersion=m=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===m?" (AS3/Flash 9)":" (AS2/Flash 8)");8<m?(c.defaultOptions=x(c.defaultOptions,c.flash9Options),c.features.buffering=!0,c.defaultOptions=x(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=
+new RegExp("\\.(mp3|"+fb.join("|")+")(\\?.*)?$","i"),c.features.movieStar=!0):c.features.movieStar=!1;c.filePattern=c.filePatterns[8!==m?"flash9":"flash8"];c.movieURL=(8===m?"soundmanager2.swf":"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=8<m};Sa=function(b,c){if(!k)return!1;k._setPolling(b,c)};ya=function(){};q=this.getSoundById;L=function(){var b=[];c.debugMode&&b.push("sm2_debug");c.debugFlash&&b.push("flash_debug");c.useHighPerformance&&
+b.push("high_performance");return b.join(" ")};Ba=function(){T("fbHandler");var b=c.getMoviePercent(),e={type:"FLASHBLOCK"};if(c.html5Only)return!1;c.ok()?c.oMC&&(c.oMC.className=[L(),"movieContainer","swf_loaded"+(c.didFlashBlock?" swf_unblocked":"")].join(" ")):(v&&(c.oMC.className=L()+" movieContainer "+(null===b?"swf_timedout":"swf_error")),c.didFlashBlock=!0,F({type:"ontimeout",ignoreInit:!0,error:e}),K(e))};ta=function(b,c,d){y[b]===g&&(y[b]=[]);y[b].push({method:c,scope:d||null,fired:!1})};
+F=function(b){b||(b={type:c.ok()?"onready":"ontimeout"});if(!l&&b&&!b.ignoreInit||"ontimeout"===b.type&&(c.ok()||B&&!b.ignoreInit))return!1;var e={success:b&&b.ignoreInit?c.ok():!B},d=b&&b.type?y[b.type]||[]:[],a=[],f,e=[e],g=v&&!c.ok();b.error&&(e[0].error=b.error);b=0;for(f=d.length;b<f;b++)!0!==d[b].fired&&a.push(d[b]);if(a.length)for(b=0,f=a.length;b<f;b++)a[b].scope?a[b].method.apply(a[b].scope,e):a[b].method.apply(this,e),g||(a[b].fired=!0);return!0};H=function(){h.setTimeout(function(){c.useFlashBlock&&
+Ba();F();"function"===typeof c.onload&&c.onload.apply(h);c.waitForWindowLoad&&t.add(h,"load",H)},1)};Fa=function(){if(A!==g)return A;var b=!1,c=navigator,d=c.plugins,a,f=h.ActiveXObject;if(d&&d.length)(c=c.mimeTypes)&&c["application/x-shockwave-flash"]&&c["application/x-shockwave-flash"].enabledPlugin&&c["application/x-shockwave-flash"].enabledPlugin.description&&(b=!0);else if(f!==g&&!u.match(/MSAppHost/i)){try{a=new f("ShockwaveFlash.ShockwaveFlash")}catch(n){a=null}b=!!a}return A=b};Ya=function(){var b,
+e,d=c.audioFormats;Ha&&u.match(/os (1|2|3_0|3_1)\s/i)?(c.hasHTML5=!1,c.html5Only=!0,c.oMC&&(c.oMC.style.display="none")):!c.useHTML5Audio||c.html5&&c.html5.canPlayType||(c.hasHTML5=!1);if(c.useHTML5Audio&&c.hasHTML5)for(e in X=!0,d)d.hasOwnProperty(e)&&d[e].required&&(c.html5.canPlayType(d[e].type)?c.preferFlash&&(c.flash[e]||c.flash[d[e].type])&&(b=!0):(X=!1,b=!0));c.ignoreFlash&&(b=!1,X=!0);c.html5Only=c.hasHTML5&&c.useHTML5Audio&&!b;return!c.html5Only};ia=function(b){var e,d,a=0;if(b instanceof
+Array){e=0;for(d=b.length;e<d;e++)if(b[e]instanceof Object){if(c.canPlayMIME(b[e].type)){a=e;break}}else if(c.canPlayURL(b[e])){a=e;break}b[a].url&&(b[a]=b[a].url);b=b[a]}return b};Va=function(b){b._hasTimer||(b._hasTimer=!0,!na&&c.html5PollingInterval&&(null===V&&0===ha&&(V=setInterval(Xa,c.html5PollingInterval)),ha++))};Wa=function(b){b._hasTimer&&(b._hasTimer=!1,!na&&c.html5PollingInterval&&ha--)};Xa=function(){var b;if(null!==V&&!ha)return clearInterval(V),V=null,!1;for(b=c.soundIDs.length-1;0<=
+b;b--)c.sounds[c.soundIDs[b]].isHTML5&&c.sounds[c.soundIDs[b]]._hasTimer&&c.sounds[c.soundIDs[b]]._onTimer()};K=function(b){b=b!==g?b:{};"function"===typeof c.onerror&&c.onerror.apply(h,[{type:b.type!==g?b.type:null}]);b.fatal!==g&&b.fatal&&c.disable()};$a=function(){if(!bb||!Fa())return!1;var b=c.audioFormats,e,d;for(d in b)if(b.hasOwnProperty(d)&&("mp3"===d||"mp4"===d)&&(c.html5[d]=!1,b[d]&&b[d].related))for(e=b[d].related.length-1;0<=e;e--)c.html5[b[d].related[e]]=!1};this._setSandboxType=function(b){};
+this._externalInterfaceOK=function(b){if(c.swfLoaded)return!1;c.swfLoaded=!0;oa=!1;bb&&$a();setTimeout(qa,E?100:1)};ea=function(b,e){function d(a,b){return'<param name="'+a+'" value="'+b+'" />'}if(O&&P)return!1;if(c.html5Only)return va(),c.oMC=aa(c.movieID),qa(),P=O=!0,!1;var a=e||c.url,f=c.altURL||a,h=xa(),k=L(),m=null,m=p.getElementsByTagName("html")[0],l,r,q,m=m&&m.dir&&m.dir.match(/rtl/i);b=b===g?c.id:b;va();c.url=Ua(La?a:f);e=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;
+null!==c.wmode&&(u.match(/msie 8/i)||!E&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i)&&(W.push(J.spcWmode),c.wmode=null);h={name:b,id:b,src:e,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:jb+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};c.debugFlash&&(h.FlashVars="debug=1");c.wmode||delete h.wmode;if(E)a=p.createElement("div"),r=
+['<object id="'+b+'" data="'+e+'" type="'+h.type+'" title="'+h.title+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">',d("movie",e),d("AllowScriptAccess",c.allowScriptAccess),d("quality",h.quality),c.wmode?d("wmode",c.wmode):"",d("bgcolor",c.bgColor),d("hasPriority","true"),c.debugFlash?d("FlashVars",h.FlashVars):"","</object>"].join("");else for(l in a=p.createElement("embed"),h)h.hasOwnProperty(l)&&
+a.setAttribute(l,h[l]);ya();k=L();if(h=xa())if(c.oMC=aa(c.movieID)||p.createElement("div"),c.oMC.id)q=c.oMC.className,c.oMC.className=(q?q+" ":"movieContainer")+(k?" "+k:""),c.oMC.appendChild(a),E&&(l=c.oMC.appendChild(p.createElement("div")),l.className="sm2-object-box",l.innerHTML=r),P=!0;else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+k;l=k=null;c.useFlashBlock||(c.useHighPerformance?k={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"}:(k={position:"absolute",
+width:"6px",height:"6px",top:"-9999px",left:"-9999px"},m&&(k.left=Math.abs(parseInt(k.left,10))+"px")));ib&&(c.oMC.style.zIndex=1E4);if(!c.debugFlash)for(q in k)k.hasOwnProperty(q)&&(c.oMC.style[q]=k[q]);try{E||c.oMC.appendChild(a),h.appendChild(c.oMC),E&&(l=c.oMC.appendChild(p.createElement("div")),l.className="sm2-object-box",l.innerHTML=r),P=!0}catch(t){throw Error(T("domError")+" \n"+t.toString());}}return O=!0};da=function(){if(c.html5Only)return ea(),!1;if(k||!c.url)return!1;k=c.getMovie(c.id);
+k||(S?(E?c.oMC.innerHTML=Aa:c.oMC.appendChild(S),S=null,O=!0):ea(c.id,c.url),k=c.getMovie(c.id));"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);return!0};I=function(){setTimeout(Ra,1E3)};ua=function(){h.setTimeout(function(){c.setup({preferFlash:!1}).reboot();c.didFlashBlock=!0;c.beginDelayedInit()},1)};Ra=function(){var b,e=!1;if(!c.url||U)return!1;U=!0;t.remove(h,"load",I);if(A&&oa&&!Ka)return!1;l||(b=c.getMoviePercent(),0<b&&100>b&&(e=!0));setTimeout(function(){b=c.getMoviePercent();
+if(e)return U=!1,h.setTimeout(I,1),!1;!l&&cb&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?c.useFlashBlock&&Ba():!c.useFlashBlock&&X?ua():F({type:"ontimeout",ignoreInit:!0,error:{type:"INIT_FLASHBLOCK"}}):0!==c.flashLoadTimeout&&(!c.useFlashBlock&&X?ua():za(!0)))},c.flashLoadTimeout)};ca=function(){if(Ka||!oa)return t.remove(h,"focus",ca),!0;Ka=cb=!0;U=!1;I();t.remove(h,"focus",ca);return!0};Q=function(b){if(l)return!1;if(c.html5Only)return l=!0,H(),!0;var e=!0,d;c.useFlashBlock&&c.flashLoadTimeout&&
+!c.getMoviePercent()||(l=!0);d={type:!A&&v?"NO_FLASH":"INIT_TIMEOUT"};if(B||b)c.useFlashBlock&&c.oMC&&(c.oMC.className=L()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),F({type:"ontimeout",error:d,ignoreInit:!0}),K(d),e=!1;B||(c.waitForWindowLoad&&!ra?t.add(h,"load",H):H());return e};Qa=function(){var b,e=c.setupOptions;for(b in e)e.hasOwnProperty(b)&&(c[b]===g?c[b]=e[b]:c[b]!==e[b]&&(c.setupOptions[b]=c[b]))};qa=function(){if(l)return!1;if(c.html5Only)return l||(t.remove(h,"load",
+c.beginDelayedInit),c.enabled=!0,Q()),!0;da();try{k._externalInterfaceTest(!1),Sa(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||k._disableDebug(),c.enabled=!0,c.html5Only||t.add(h,"unload",pa)}catch(b){return K({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),za(!0),Q(),!1}Q();t.remove(h,"load",c.beginDelayedInit);return!0};G=function(){if(R)return!1;R=!0;Qa();ya();!A&&c.hasHTML5&&c.setup({useHTML5Audio:!0,preferFlash:!1});Za();!A&&v&&(W.push(J.needFlash),c.setup({flashLoadTimeout:1}));
+p.removeEventListener&&p.removeEventListener("DOMContentLoaded",G,!1);da();return!0};Da=function(){"complete"===p.readyState&&(G(),p.detachEvent("onreadystatechange",Da));return!0};wa=function(){ra=!0;G();t.remove(h,"load",wa)};Fa();t.add(h,"focus",ca);t.add(h,"load",I);t.add(h,"load",wa);p.addEventListener?p.addEventListener("DOMContentLoaded",G,!1):p.attachEvent?p.attachEvent("onreadystatechange",Da):K({type:"NO_DOM2_EVENTS",fatal:!0})}if(!h||!h.document)throw Error("SoundManager requires a browser with window and document objects.");
+var N=null;h.SM2_DEFER!==g&&SM2_DEFER||(N=new w);"object"===typeof module&&module&&"object"===typeof module.exports?(module.exports.SoundManager=w,module.exports.soundManager=N):"function"===typeof define&&define.amd&&define(function(){return{constructor:w,getInstance:function(g){!h.soundManager&&g instanceof Function&&(g=g(w),g instanceof w&&(h.soundManager=g));return h.soundManager}}});h.SoundManager=w;h.soundManager=N})(window);
\ No newline at end of file
--- /dev/null
+/** @license\r
+ *\r
+ * SoundManager 2: JavaScript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code provided under the BSD License:\r
+ * http://schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * V2.97a.20150601\r
+ */\r
+\r
+/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio, opera, module, define */\r
+/*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true, todo: true */\r
+\r
+(function(window, _undefined) {\r
+"use strict";\r
+if (!window || !window.document) {\r
+ throw new Error('SoundManager requires a browser with window and document objects.');\r
+}\r
+var soundManager = null;\r
+function SoundManager(smURL, smID) {\r
+ this.setupOptions = {\r
+ 'url': (smURL || null),\r
+ 'flashVersion': 8,\r
+ 'debugMode': true,\r
+ 'debugFlash': false,\r
+ 'useConsole': true,\r
+ 'consoleOnly': true,\r
+ 'waitForWindowLoad': false,\r
+ 'bgColor': '#ffffff',\r
+ 'useHighPerformance': false,\r
+ 'flashPollingInterval': null,\r
+ 'html5PollingInterval': null,\r
+ 'flashLoadTimeout': 1000,\r
+ 'wmode': null,\r
+ 'allowScriptAccess': 'always',\r
+ 'useFlashBlock': false,\r
+ 'useHTML5Audio': true,\r
+ 'forceUseGlobalHTML5Audio': false,\r
+ 'ignoreMobileRestrictions': false,\r
+ 'html5Test': /^(probably|maybe)$/i,\r
+ 'preferFlash': false,\r
+ 'noSWFCache': false,\r
+ 'idPrefix': 'sound'\r
+ };\r
+ this.defaultOptions = {\r
+ 'autoLoad': false,\r
+ 'autoPlay': false,\r
+ 'from': null,\r
+ 'loops': 1,\r
+ 'onid3': null,\r
+ 'onload': null,\r
+ 'whileloading': null,\r
+ 'onplay': null,\r
+ 'onpause': null,\r
+ 'onresume': null,\r
+ 'whileplaying': null,\r
+ 'onposition': null,\r
+ 'onstop': null,\r
+ 'onfailure': null,\r
+ 'onfinish': null,\r
+ 'multiShot': true,\r
+ 'multiShotEvents': false,\r
+ 'position': null,\r
+ 'pan': 0,\r
+ 'stream': true,\r
+ 'to': null,\r
+ 'type': null,\r
+ 'usePolicyFile': false,\r
+ 'volume': 100\r
+ };\r
+ this.flash9Options = {\r
+ 'isMovieStar': null,\r
+ 'usePeakData': false,\r
+ 'useWaveformData': false,\r
+ 'useEQData': false,\r
+ 'onbufferchange': null,\r
+ 'ondataerror': null\r
+ };\r
+ this.movieStarOptions = {\r
+ 'bufferTime': 3,\r
+ 'serverURL': null,\r
+ 'onconnect': null,\r
+ 'duration': null\r
+ };\r
+ this.audioFormats = {\r
+ 'mp3': {\r
+ 'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'],\r
+ 'required': true\r
+ },\r
+ 'mp4': {\r
+ 'related': ['aac','m4a','m4b'],\r
+ 'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'],\r
+ 'required': false\r
+ },\r
+ 'ogg': {\r
+ 'type': ['audio/ogg; codecs=vorbis'],\r
+ 'required': false\r
+ },\r
+ 'opus': {\r
+ 'type': ['audio/ogg; codecs=opus', 'audio/opus'],\r
+ 'required': false\r
+ },\r
+ 'wav': {\r
+ 'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'],\r
+ 'required': false\r
+ }\r
+ };\r
+ this.movieID = 'sm2-container';\r
+ this.id = (smID || 'sm2movie');\r
+ this.debugID = 'soundmanager-debug';\r
+ this.debugURLParam = /([#?&])debug=1/i;\r
+ this.versionNumber = 'V2.97a.20150601';\r
+ this.version = null;\r
+ this.movieURL = null;\r
+ this.altURL = null;\r
+ this.swfLoaded = false;\r
+ this.enabled = false;\r
+ this.oMC = null;\r
+ this.sounds = {};\r
+ this.soundIDs = [];\r
+ this.muted = false;\r
+ this.didFlashBlock = false;\r
+ this.filePattern = null;\r
+ this.filePatterns = {\r
+ 'flash8': /\.mp3(\?.*)?$/i,\r
+ 'flash9': /\.mp3(\?.*)?$/i\r
+ };\r
+ this.features = {\r
+ 'buffering': false,\r
+ 'peakData': false,\r
+ 'waveformData': false,\r
+ 'eqData': false,\r
+ 'movieStar': false\r
+ };\r
+ this.sandbox = {\r
+ };\r
+ this.html5 = {\r
+ 'usingFlash': null\r
+ };\r
+ this.flash = {};\r
+ this.html5Only = false;\r
+ this.ignoreFlash = false;\r
+ var SMSound,\r
+ sm2 = this, globalHTML5Audio = null, flash = null, sm = 'soundManager', smc = sm + ': ', h5 = 'HTML5::', id, ua = navigator.userAgent, wl = window.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, rebootIntoHTML5, 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, messages = [],\r
+ canIgnoreFlash, needsFlash = null, featureCheck, html5OK, html5CanPlay, html5Ext, html5Unload, domContentLoadedIE, testHTML5, event, slice = Array.prototype.slice, useGlobalHTML5Audio = false, lastGlobalHTML5URL, hasFlash, detectFlash, badSafariFix, html5_events, showSupport, flushMessages, wrapCallback, idCounter = 0, didSetup, msecScale = 1000,\r
+ is_iDevice = ua.match(/(ipad|iphone|ipod)/i), isAndroid = ua.match(/android/i), isIE = ua.match(/msie/i),\r
+ isWebkit = ua.match(/webkit/i),\r
+ isSafari = (ua.match(/safari/i) && !ua.match(/chrome/i)),\r
+ isOpera = (ua.match(/opera/i)),\r
+ mobileHTML5 = (ua.match(/(mobile|pre\/|xoom)/i) || is_iDevice || isAndroid),\r
+ isBadSafari = (!wl.match(/usehtml5audio/i) && !wl.match(/sm2\-ignorebadua/i) && isSafari && !ua.match(/silk/i) && ua.match(/OS X 10_6_([3-7])/i)),\r
+ hasConsole = (window.console !== _undefined && console.log !== _undefined),\r
+ isFocused = (doc.hasFocus !== _undefined ? doc.hasFocus() : null),\r
+ tryInitOnFocus = (isSafari && (doc.hasFocus === _undefined || !doc.hasFocus())),\r
+ okToDisable = !tryInitOnFocus,\r
+ flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i,\r
+ emptyURL = 'about:blank',\r
+ emptyWAV = 'data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w==',\r
+ overHTTP = (doc.location ? doc.location.protocol.match(/http/i) : null),\r
+ http = (!overHTTP ? 'http:/'+'/' : ''),\r
+ netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,\r
+ netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'm4b', 'mp4v', '3gp', '3g2'],\r
+ netStreamPattern = new RegExp('\\.(' + netStreamTypes.join('|') + ')(\\?.*)?$', 'i');\r
+ this.mimePattern = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;\r
+ this.useAltURL = !overHTTP;\r
+ swfCSS = {\r
+ 'swfBox': 'sm2-object-box',\r
+ 'swfDefault': 'movieContainer',\r
+ 'swfError': 'swf_error',\r
+ 'swfTimedout': 'swf_timedout',\r
+ 'swfLoaded': 'swf_loaded',\r
+ 'swfUnblocked': 'swf_unblocked',\r
+ 'sm2Debug': 'sm2_debug',\r
+ 'highPerf': 'high_performance',\r
+ 'flashDebug': 'flash_debug'\r
+ };\r
+ this.hasHTML5 = (function() {\r
+ try {\r
+ return (Audio !== _undefined && (isOpera && opera !== _undefined && opera.version() < 10 ? new Audio(null) : new Audio()).canPlayType !== _undefined);\r
+ } catch(e) {\r
+ return false;\r
+ }\r
+ }());\r
+ this.setup = function(options) {\r
+ var noURL = (!sm2.url);\r
+ if (options !== _undefined && didInit && needsFlash && sm2.ok() && (options.flashVersion !== _undefined || options.url !== _undefined || options.html5Test !== _undefined)) {\r
+ }\r
+ assign(options);\r
+ if (!useGlobalHTML5Audio) {\r
+ if (mobileHTML5) {\r
+ if (!sm2.setupOptions.ignoreMobileRestrictions || sm2.setupOptions.forceUseGlobalHTML5Audio) {\r
+ messages.push(strings.globalHTML5);\r
+ useGlobalHTML5Audio = true;\r
+ }\r
+ } else {\r
+ if (sm2.setupOptions.forceUseGlobalHTML5Audio) {\r
+ messages.push(strings.globalHTML5);\r
+ useGlobalHTML5Audio = true;\r
+ }\r
+ }\r
+ }\r
+ if (!didSetup && mobileHTML5) {\r
+ if (sm2.setupOptions.ignoreMobileRestrictions) {\r
+ messages.push(strings.ignoreMobile);\r
+ } else {\r
+ sm2.setupOptions.useHTML5Audio = true;\r
+ sm2.setupOptions.preferFlash = false;\r
+ if (is_iDevice) {\r
+ sm2.ignoreFlash = true;\r
+ } else if ((isAndroid && !ua.match(/android\s2\.3/i)) || !isAndroid) {\r
+ useGlobalHTML5Audio = true;\r
+ }\r
+ }\r
+ }\r
+ if (options) {\r
+ if (noURL && didDCLoaded && options.url !== _undefined) {\r
+ sm2.beginDelayedInit();\r
+ }\r
+ if (!didDCLoaded && options.url !== _undefined && doc.readyState === 'complete') {\r
+ setTimeout(domContentLoaded, 1);\r
+ }\r
+ }\r
+ didSetup = true;\r
+ return sm2;\r
+ };\r
+ this.ok = function() {\r
+ return (needsFlash ? (didInit && !disabled) : (sm2.useHTML5Audio && sm2.hasHTML5));\r
+ };\r
+ this.supported = this.ok;\r
+ this.getMovie = function(smID) {\r
+ return id(smID) || doc[smID] || window[smID];\r
+ };\r
+ this.createSound = function(oOptions, _url) {\r
+ var cs, cs_string, options, oSound = null;\r
+ if (!didInit || !sm2.ok()) {\r
+ return false;\r
+ }\r
+ if (_url !== _undefined) {\r
+ oOptions = {\r
+ 'id': oOptions,\r
+ 'url': _url\r
+ };\r
+ }\r
+ options = mixin(oOptions);\r
+ options.url = parseURL(options.url);\r
+ if (options.id === _undefined) {\r
+ options.id = sm2.setupOptions.idPrefix + (idCounter++);\r
+ }\r
+ if (idCheck(options.id, true)) {\r
+ return sm2.sounds[options.id];\r
+ }\r
+ function make() {\r
+ options = loopFix(options);\r
+ sm2.sounds[options.id] = new SMSound(options);\r
+ sm2.soundIDs.push(options.id);\r
+ return sm2.sounds[options.id];\r
+ }\r
+ if (html5OK(options)) {\r
+ oSound = make();\r
+ oSound._setup_html5(options);\r
+ } else {\r
+ if (sm2.html5Only) {\r
+ return make();\r
+ }\r
+ if (sm2.html5.usingFlash && options.url && options.url.match(/data\:/i)) {\r
+ return make();\r
+ }\r
+ if (fV > 8) {\r
+ if (options.isMovieStar === null) {\r
+ options.isMovieStar = !!(options.serverURL || (options.type ? options.type.match(netStreamMimeTypes) : false) || (options.url && options.url.match(netStreamPattern)));\r
+ }\r
+ }\r
+ options = policyFix(options, cs);\r
+ oSound = make();\r
+ if (fV === 8) {\r
+ flash._createSound(options.id, options.loops || 1, options.usePolicyFile);\r
+ } else {\r
+ flash._createSound(options.id, options.url, options.usePeakData, options.useWaveformData, options.useEQData, options.isMovieStar, (options.isMovieStar ? options.bufferTime : false), options.loops || 1, options.serverURL, options.duration || null, options.autoPlay, true, options.autoLoad, options.usePolicyFile);\r
+ if (!options.serverURL) {\r
+ oSound.connected = true;\r
+ if (options.onconnect) {\r
+ options.onconnect.apply(oSound);\r
+ }\r
+ }\r
+ }\r
+ if (!options.serverURL && (options.autoLoad || options.autoPlay)) {\r
+ oSound.load(options);\r
+ }\r
+ }\r
+ if (!options.serverURL && options.autoPlay) {\r
+ oSound.play();\r
+ }\r
+ return oSound;\r
+ };\r
+ this.destroySound = function(sID, _bFromSound) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ var oS = sm2.sounds[sID], i;\r
+ oS.stop();\r
+ oS._iO = {};\r
+ oS.unload();\r
+ for (i = 0; i < sm2.soundIDs.length; i++) {\r
+ if (sm2.soundIDs[i] === sID) {\r
+ sm2.soundIDs.splice(i, 1);\r
+ break;\r
+ }\r
+ }\r
+ if (!_bFromSound) {\r
+ oS.destruct(true);\r
+ }\r
+ oS = null;\r
+ delete sm2.sounds[sID];\r
+ return true;\r
+ };\r
+ this.load = function(sID, oOptions) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].load(oOptions);\r
+ };\r
+ this.unload = function(sID) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].unload();\r
+ };\r
+ this.onPosition = function(sID, nPosition, oMethod, oScope) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].onposition(nPosition, oMethod, oScope);\r
+ };\r
+ this.onposition = this.onPosition;\r
+ this.clearOnPosition = function(sID, nPosition, oMethod) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].clearOnPosition(nPosition, oMethod);\r
+ };\r
+ this.play = function(sID, oOptions) {\r
+ var result = null,\r
+ overloaded = (oOptions && !(oOptions instanceof Object));\r
+ if (!didInit || !sm2.ok()) {\r
+ return false;\r
+ }\r
+ if (!idCheck(sID, overloaded)) {\r
+ if (!overloaded) {\r
+ return false;\r
+ }\r
+ if (overloaded) {\r
+ oOptions = {\r
+ url: oOptions\r
+ };\r
+ }\r
+ if (oOptions && oOptions.url) {\r
+ oOptions.id = sID;\r
+ result = sm2.createSound(oOptions).play();\r
+ }\r
+ } else if (overloaded) {\r
+ oOptions = {\r
+ url: oOptions\r
+ };\r
+ }\r
+ if (result === null) {\r
+ result = sm2.sounds[sID].play(oOptions);\r
+ }\r
+ return result;\r
+ };\r
+ this.start = this.play;\r
+ this.setPosition = function(sID, nMsecOffset) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].setPosition(nMsecOffset);\r
+ };\r
+ this.stop = function(sID) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].stop();\r
+ };\r
+ this.stopAll = function() {\r
+ var oSound;\r
+ for (oSound in sm2.sounds) {\r
+ if (sm2.sounds.hasOwnProperty(oSound)) {\r
+ sm2.sounds[oSound].stop();\r
+ }\r
+ }\r
+ };\r
+ this.pause = function(sID) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].pause();\r
+ };\r
+ this.pauseAll = function() {\r
+ var i;\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].pause();\r
+ }\r
+ };\r
+ this.resume = function(sID) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].resume();\r
+ };\r
+ this.resumeAll = function() {\r
+ var i;\r
+ for (i = sm2.soundIDs.length- 1 ; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].resume();\r
+ }\r
+ };\r
+ this.togglePause = function(sID) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].togglePause();\r
+ };\r
+ this.setPan = function(sID, nPan) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].setPan(nPan);\r
+ };\r
+ this.setVolume = function(sID, nVol) {\r
+ var i, j;\r
+ if (sID !== _undefined && !isNaN(sID) && nVol === _undefined) {\r
+ for (i = 0, j = sm2.soundIDs.length; i < j; i++) {\r
+ sm2.sounds[sm2.soundIDs[i]].setVolume(sID);\r
+ }\r
+ return;\r
+ }\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].setVolume(nVol);\r
+ };\r
+ this.mute = function(sID) {\r
+ var i = 0;\r
+ if (sID instanceof String) {\r
+ sID = null;\r
+ }\r
+ if (!sID) {\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].mute();\r
+ }\r
+ sm2.muted = true;\r
+ } else {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].mute();\r
+ }\r
+ return true;\r
+ };\r
+ this.muteAll = function() {\r
+ sm2.mute();\r
+ };\r
+ this.unmute = function(sID) {\r
+ var i;\r
+ if (sID instanceof String) {\r
+ sID = null;\r
+ }\r
+ if (!sID) {\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].unmute();\r
+ }\r
+ sm2.muted = false;\r
+ } else {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].unmute();\r
+ }\r
+ return true;\r
+ };\r
+ this.unmuteAll = function() {\r
+ sm2.unmute();\r
+ };\r
+ this.toggleMute = function(sID) {\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].toggleMute();\r
+ };\r
+ this.getMemoryUse = function() {\r
+ var ram = 0;\r
+ if (flash && fV !== 8) {\r
+ ram = parseInt(flash._getMemoryUse(), 10);\r
+ }\r
+ return ram;\r
+ };\r
+ this.disable = function(bNoDisable) {\r
+ var i;\r
+ if (bNoDisable === _undefined) {\r
+ bNoDisable = false;\r
+ }\r
+ if (disabled) {\r
+ return false;\r
+ }\r
+ disabled = true;\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+ disableObject(sm2.sounds[sm2.soundIDs[i]]);\r
+ }\r
+ initComplete(bNoDisable);\r
+ event.remove(window, 'load', initUserOnload);\r
+ return true;\r
+ };\r
+ this.canPlayMIME = function(sMIME) {\r
+ var result;\r
+ if (sm2.hasHTML5) {\r
+ result = html5CanPlay({\r
+ type: sMIME\r
+ });\r
+ }\r
+ if (!result && needsFlash) {\r
+ result = (sMIME && sm2.ok() ? !!((fV > 8 ? sMIME.match(netStreamMimeTypes) : null) || sMIME.match(sm2.mimePattern)) : null);\r
+ }\r
+ return result;\r
+ };\r
+ this.canPlayURL = function(sURL) {\r
+ var result;\r
+ if (sm2.hasHTML5) {\r
+ result = html5CanPlay({\r
+ url: sURL\r
+ });\r
+ }\r
+ if (!result && needsFlash) {\r
+ result = (sURL && sm2.ok() ? !!(sURL.match(sm2.filePattern)) : null);\r
+ }\r
+ return result;\r
+ };\r
+ this.canPlayLink = function(oLink) {\r
+ if (oLink.type !== _undefined && oLink.type) {\r
+ if (sm2.canPlayMIME(oLink.type)) {\r
+ return true;\r
+ }\r
+ }\r
+ return sm2.canPlayURL(oLink.href);\r
+ };\r
+ this.getSoundById = function(sID, _suppressDebug) {\r
+ if (!sID) {\r
+ return null;\r
+ }\r
+ var result = sm2.sounds[sID];\r
+ return result;\r
+ };\r
+ this.onready = function(oMethod, oScope) {\r
+ var sType = 'onready',\r
+ result = false;\r
+ if (typeof oMethod === 'function') {\r
+ if (!oScope) {\r
+ oScope = window;\r
+ }\r
+ addOnEvent(sType, oMethod, oScope);\r
+ processOnEvents();\r
+ result = true;\r
+ } else {\r
+ throw str('needFunction', sType);\r
+ }\r
+ return result;\r
+ };\r
+ this.ontimeout = function(oMethod, oScope) {\r
+ var sType = 'ontimeout',\r
+ result = false;\r
+ if (typeof oMethod === 'function') {\r
+ if (!oScope) {\r
+ oScope = window;\r
+ }\r
+ addOnEvent(sType, oMethod, oScope);\r
+ processOnEvents({type:sType});\r
+ result = true;\r
+ } else {\r
+ throw str('needFunction', sType);\r
+ }\r
+ return result;\r
+ };\r
+ this._writeDebug = function(sText, sTypeOrObject) {\r
+ return true;\r
+ };\r
+ this._wD = this._writeDebug;\r
+ this._debug = function() {\r
+ };\r
+ this.reboot = function(resetEvents, excludeInit) {\r
+ var i, j, k;\r
+ for (i = sm2.soundIDs.length- 1 ; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].destruct();\r
+ }\r
+ if (flash) {\r
+ try {\r
+ if (isIE) {\r
+ oRemovedHTML = flash.innerHTML;\r
+ }\r
+ oRemoved = flash.parentNode.removeChild(flash);\r
+ } catch(e) {\r
+ }\r
+ }\r
+ oRemovedHTML = oRemoved = needsFlash = flash = null;\r
+ sm2.enabled = didDCLoaded = didInit = waitingForEI = initPending = didAppend = appendSuccess = disabled = useGlobalHTML5Audio = sm2.swfLoaded = false;\r
+ sm2.soundIDs = [];\r
+ sm2.sounds = {};\r
+ idCounter = 0;\r
+ didSetup = false;\r
+ if (!resetEvents) {\r
+ for (i in on_queue) {\r
+ if (on_queue.hasOwnProperty(i)) {\r
+ for (j = 0, k = on_queue[i].length; j < k; j++) {\r
+ on_queue[i][j].fired = false;\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ on_queue = [];\r
+ }\r
+ sm2.html5 = {\r
+ 'usingFlash': null\r
+ };\r
+ sm2.flash = {};\r
+ sm2.html5Only = false;\r
+ sm2.ignoreFlash = false;\r
+ window.setTimeout(function() {\r
+ if (!excludeInit) {\r
+ sm2.beginDelayedInit();\r
+ }\r
+ }, 20);\r
+ return sm2;\r
+ };\r
+ this.reset = function() {\r
+ return sm2.reboot(true, true);\r
+ };\r
+ this.getMoviePercent = function() {\r
+ return (flash && 'PercentLoaded' in flash ? flash.PercentLoaded() : null);\r
+ };\r
+ this.beginDelayedInit = function() {\r
+ windowLoaded = true;\r
+ domContentLoaded();\r
+ setTimeout(function() {\r
+ if (initPending) {\r
+ return false;\r
+ }\r
+ createMovie();\r
+ initMovie();\r
+ initPending = true;\r
+ return true;\r
+ }, 20);\r
+ delayWaitForEI();\r
+ };\r
+ this.destruct = function() {\r
+ sm2.disable(true);\r
+ };\r
+ SMSound = function(oOptions) {\r
+ var s = 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, urlOmitted;\r
+ lastHTML5State = {\r
+ duration: null,\r
+ time: null\r
+ };\r
+ this.id = oOptions.id;\r
+ this.sID = this.id;\r
+ this.url = oOptions.url;\r
+ this.options = mixin(oOptions);\r
+ this.instanceOptions = this.options;\r
+ this._iO = this.instanceOptions;\r
+ this.pan = this.options.pan;\r
+ this.volume = this.options.volume;\r
+ this.isHTML5 = false;\r
+ this._a = null;\r
+ urlOmitted = (this.url ? false : true);\r
+ this.id3 = {};\r
+ this._debug = function() {\r
+ };\r
+ this.load = function(oOptions) {\r
+ var oSound = null, instanceOptions;\r
+ if (oOptions !== _undefined) {\r
+ s._iO = mixin(oOptions, s.options);\r
+ } else {\r
+ oOptions = s.options;\r
+ s._iO = oOptions;\r
+ if (lastURL && lastURL !== s.url) {\r
+ s._iO.url = s.url;\r
+ s.url = null;\r
+ }\r
+ }\r
+ if (!s._iO.url) {\r
+ s._iO.url = s.url;\r
+ }\r
+ s._iO.url = parseURL(s._iO.url);\r
+ s.instanceOptions = s._iO;\r
+ instanceOptions = s._iO;\r
+ if (!instanceOptions.url && !s.url) {\r
+ return s;\r
+ }\r
+ if (instanceOptions.url === s.url && s.readyState !== 0 && s.readyState !== 2) {\r
+ if (s.readyState === 3 && instanceOptions.onload) {\r
+ wrapCallback(s, function() {\r
+ instanceOptions.onload.apply(s, [(!!s.duration)]);\r
+ });\r
+ }\r
+ return s;\r
+ }\r
+ s.loaded = false;\r
+ s.readyState = 1;\r
+ s.playState = 0;\r
+ s.id3 = {};\r
+ if (html5OK(instanceOptions)) {\r
+ oSound = s._setup_html5(instanceOptions);\r
+ if (!oSound._called_load) {\r
+ s._html5_canplay = false;\r
+ if (s.url !== instanceOptions.url) {\r
+ s._a.src = instanceOptions.url;\r
+ s.setPosition(0);\r
+ }\r
+ s._a.autobuffer = 'auto';\r
+ s._a.preload = 'auto';\r
+ s._a._called_load = true;\r
+ } else {\r
+ }\r
+ } else {\r
+ if (sm2.html5Only) {\r
+ return s;\r
+ }\r
+ if (s._iO.url && s._iO.url.match(/data\:/i)) {\r
+ return s;\r
+ }\r
+ try {\r
+ s.isHTML5 = false;\r
+ s._iO = policyFix(loopFix(instanceOptions));\r
+ if (s._iO.autoPlay && (s._iO.position || s._iO.from)) {\r
+ s._iO.autoPlay = false;\r
+ }\r
+ instanceOptions = s._iO;\r
+ if (fV === 8) {\r
+ flash._load(s.id, instanceOptions.url, instanceOptions.stream, instanceOptions.autoPlay, instanceOptions.usePolicyFile);\r
+ } else {\r
+ flash._load(s.id, instanceOptions.url, !!(instanceOptions.stream), !!(instanceOptions.autoPlay), instanceOptions.loops || 1, !!(instanceOptions.autoLoad), instanceOptions.usePolicyFile);\r
+ }\r
+ } catch(e) {\r
+ catchError({\r
+ type: 'SMSOUND_LOAD_JS_EXCEPTION',\r
+ fatal: true\r
+ });\r
+ }\r
+ }\r
+ s.url = instanceOptions.url;\r
+ return s;\r
+ };\r
+ this.unload = function() {\r
+ if (s.readyState !== 0) {\r
+ if (!s.isHTML5) {\r
+ if (fV === 8) {\r
+ flash._unload(s.id, emptyURL);\r
+ } else {\r
+ flash._unload(s.id);\r
+ }\r
+ } else {\r
+ stop_html5_timer();\r
+ if (s._a) {\r
+ s._a.pause();\r
+ lastURL = html5Unload(s._a);\r
+ }\r
+ }\r
+ resetProperties();\r
+ }\r
+ return s;\r
+ };\r
+ this.destruct = function(_bFromSM) {\r
+ if (!s.isHTML5) {\r
+ s._iO.onfailure = null;\r
+ flash._destroySound(s.id);\r
+ } else {\r
+ stop_html5_timer();\r
+ if (s._a) {\r
+ s._a.pause();\r
+ html5Unload(s._a);\r
+ if (!useGlobalHTML5Audio) {\r
+ remove_html5_events();\r
+ }\r
+ s._a._s = null;\r
+ s._a = null;\r
+ }\r
+ }\r
+ if (!_bFromSM) {\r
+ sm2.destroySound(s.id, true);\r
+ }\r
+ };\r
+ this.play = function(oOptions, _updatePlayState) {\r
+ var fN, allowMulti, a, onready,\r
+ audioClone, onended, oncanplay,\r
+ startOK = true,\r
+ exit = null;\r
+ _updatePlayState = (_updatePlayState === _undefined ? true : _updatePlayState);\r
+ if (!oOptions) {\r
+ oOptions = {};\r
+ }\r
+ if (s.url) {\r
+ s._iO.url = s.url;\r
+ }\r
+ s._iO = mixin(s._iO, s.options);\r
+ s._iO = mixin(oOptions, s._iO);\r
+ s._iO.url = parseURL(s._iO.url);\r
+ s.instanceOptions = s._iO;\r
+ if (!s.isHTML5 && s._iO.serverURL && !s.connected) {\r
+ if (!s.getAutoPlay()) {\r
+ s.setAutoPlay(true);\r
+ }\r
+ return s;\r
+ }\r
+ if (html5OK(s._iO)) {\r
+ s._setup_html5(s._iO);\r
+ start_html5_timer();\r
+ }\r
+ if (s.playState === 1 && !s.paused) {\r
+ allowMulti = s._iO.multiShot;\r
+ if (!allowMulti) {\r
+ if (s.isHTML5) {\r
+ s.setPosition(s._iO.position);\r
+ }\r
+ exit = s;\r
+ } else {\r
+ }\r
+ }\r
+ if (exit !== null) {\r
+ return exit;\r
+ }\r
+ if (oOptions.url && oOptions.url !== s.url) {\r
+ if (!s.readyState && !s.isHTML5 && fV === 8 && urlOmitted) {\r
+ urlOmitted = false;\r
+ } else {\r
+ s.load(s._iO);\r
+ }\r
+ }\r
+ if (!s.loaded) {\r
+ if (s.readyState === 0) {\r
+ if (!s.isHTML5 && !sm2.html5Only) {\r
+ s._iO.autoPlay = true;\r
+ s.load(s._iO);\r
+ } else if (s.isHTML5) {\r
+ s.load(s._iO);\r
+ } else {\r
+ exit = s;\r
+ }\r
+ s.instanceOptions = s._iO;\r
+ } else if (s.readyState === 2) {\r
+ exit = s;\r
+ } else {\r
+ }\r
+ } else {\r
+ }\r
+ if (exit !== null) {\r
+ return exit;\r
+ }\r
+ if (!s.isHTML5 && fV === 9 && s.position > 0 && s.position === s.duration) {\r
+ oOptions.position = 0;\r
+ }\r
+ if (s.paused && s.position >= 0 && (!s._iO.serverURL || s.position > 0)) {\r
+ s.resume();\r
+ } else {\r
+ s._iO = mixin(oOptions, s._iO);\r
+ if (((!s.isHTML5 && s._iO.position !== null && s._iO.position > 0) || (s._iO.from !== null && s._iO.from > 0) || s._iO.to !== null) && s.instanceCount === 0 && s.playState === 0 && !s._iO.serverURL) {\r
+ onready = function() {\r
+ s._iO = mixin(oOptions, s._iO);\r
+ s.play(s._iO);\r
+ };\r
+ if (s.isHTML5 && !s._html5_canplay) {\r
+ s.load({\r
+ _oncanplay: onready\r
+ });\r
+ exit = false;\r
+ } else if (!s.isHTML5 && !s.loaded && (!s.readyState || s.readyState !== 2)) {\r
+ s.load({\r
+ onload: onready\r
+ });\r
+ exit = false;\r
+ }\r
+ if (exit !== null) {\r
+ return exit;\r
+ }\r
+ s._iO = applyFromTo();\r
+ }\r
+ if (!s.instanceCount || s._iO.multiShotEvents || (s.isHTML5 && s._iO.multiShot && !useGlobalHTML5Audio) || (!s.isHTML5 && fV > 8 && !s.getAutoPlay())) {\r
+ s.instanceCount++;\r
+ }\r
+ if (s._iO.onposition && s.playState === 0) {\r
+ attachOnPosition(s);\r
+ }\r
+ s.playState = 1;\r
+ s.paused = false;\r
+ s.position = (s._iO.position !== _undefined && !isNaN(s._iO.position) ? s._iO.position : 0);\r
+ if (!s.isHTML5) {\r
+ s._iO = policyFix(loopFix(s._iO));\r
+ }\r
+ if (s._iO.onplay && _updatePlayState) {\r
+ s._iO.onplay.apply(s);\r
+ onplay_called = true;\r
+ }\r
+ s.setVolume(s._iO.volume, true);\r
+ s.setPan(s._iO.pan, true);\r
+ if (!s.isHTML5) {\r
+ startOK = flash._start(s.id, s._iO.loops || 1, (fV === 9 ? s.position : s.position / msecScale), s._iO.multiShot || false);\r
+ if (fV === 9 && !startOK) {\r
+ if (s._iO.onplayerror) {\r
+ s._iO.onplayerror.apply(s);\r
+ }\r
+ }\r
+ } else {\r
+ if (s.instanceCount < 2) {\r
+ start_html5_timer();\r
+ a = s._setup_html5();\r
+ s.setPosition(s._iO.position);\r
+ a.play();\r
+ } else {\r
+ audioClone = new Audio(s._iO.url);\r
+ onended = function() {\r
+ event.remove(audioClone, 'ended', onended);\r
+ s._onfinish(s);\r
+ html5Unload(audioClone);\r
+ audioClone = null;\r
+ };\r
+ oncanplay = function() {\r
+ event.remove(audioClone, 'canplay', oncanplay);\r
+ try {\r
+ audioClone.currentTime = s._iO.position/msecScale;\r
+ } catch(err) {\r
+ }\r
+ audioClone.play();\r
+ };\r
+ event.add(audioClone, 'ended', onended);\r
+ if (s._iO.volume !== _undefined) {\r
+ audioClone.volume = Math.max(0, Math.min(1, s._iO.volume/100));\r
+ }\r
+ if (s.muted) {\r
+ audioClone.muted = true;\r
+ }\r
+ if (s._iO.position) {\r
+ event.add(audioClone, 'canplay', oncanplay);\r
+ } else {\r
+ audioClone.play();\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return s;\r
+ };\r
+ this.start = this.play;\r
+ this.stop = function(bAll) {\r
+ var instanceOptions = s._iO,\r
+ originalPosition;\r
+ if (s.playState === 1) {\r
+ s._onbufferchange(0);\r
+ s._resetOnPosition(0);\r
+ s.paused = false;\r
+ if (!s.isHTML5) {\r
+ s.playState = 0;\r
+ }\r
+ detachOnPosition();\r
+ if (instanceOptions.to) {\r
+ s.clearOnPosition(instanceOptions.to);\r
+ }\r
+ if (!s.isHTML5) {\r
+ flash._stop(s.id, bAll);\r
+ if (instanceOptions.serverURL) {\r
+ s.unload();\r
+ }\r
+ } else {\r
+ if (s._a) {\r
+ originalPosition = s.position;\r
+ s.setPosition(0);\r
+ s.position = originalPosition;\r
+ s._a.pause();\r
+ s.playState = 0;\r
+ s._onTimer();\r
+ stop_html5_timer();\r
+ }\r
+ }\r
+ s.instanceCount = 0;\r
+ s._iO = {};\r
+ if (instanceOptions.onstop) {\r
+ instanceOptions.onstop.apply(s);\r
+ }\r
+ }\r
+ return s;\r
+ };\r
+ this.setAutoPlay = function(autoPlay) {\r
+ s._iO.autoPlay = autoPlay;\r
+ if (!s.isHTML5) {\r
+ flash._setAutoPlay(s.id, autoPlay);\r
+ if (autoPlay) {\r
+ if (!s.instanceCount && s.readyState === 1) {\r
+ s.instanceCount++;\r
+ }\r
+ }\r
+ }\r
+ };\r
+ this.getAutoPlay = function() {\r
+ return s._iO.autoPlay;\r
+ };\r
+ this.setPosition = function(nMsecOffset) {\r
+ if (nMsecOffset === _undefined) {\r
+ nMsecOffset = 0;\r
+ }\r
+ var position, position1K,\r
+ offset = (s.isHTML5 ? Math.max(nMsecOffset, 0) : Math.min(s.duration || s._iO.duration, Math.max(nMsecOffset, 0)));\r
+ s.position = offset;\r
+ position1K = s.position/msecScale;\r
+ s._resetOnPosition(s.position);\r
+ s._iO.position = offset;\r
+ if (!s.isHTML5) {\r
+ position = (fV === 9 ? s.position : position1K);\r
+ if (s.readyState && s.readyState !== 2) {\r
+ flash._setPosition(s.id, position, (s.paused || !s.playState), s._iO.multiShot);\r
+ }\r
+ } else if (s._a) {\r
+ if (s._html5_canplay) {\r
+ if (s._a.currentTime !== position1K) {\r
+ try {\r
+ s._a.currentTime = position1K;\r
+ if (s.playState === 0 || s.paused) {\r
+ s._a.pause();\r
+ }\r
+ } catch(e) {\r
+ }\r
+ }\r
+ } else if (position1K) {\r
+ return s;\r
+ }\r
+ if (s.paused) {\r
+ s._onTimer(true);\r
+ }\r
+ }\r
+ return s;\r
+ };\r
+ this.pause = function(_bCallFlash) {\r
+ if (s.paused || (s.playState === 0 && s.readyState !== 1)) {\r
+ return s;\r
+ }\r
+ s.paused = true;\r
+ if (!s.isHTML5) {\r
+ if (_bCallFlash || _bCallFlash === _undefined) {\r
+ flash._pause(s.id, s._iO.multiShot);\r
+ }\r
+ } else {\r
+ s._setup_html5().pause();\r
+ stop_html5_timer();\r
+ }\r
+ if (s._iO.onpause) {\r
+ s._iO.onpause.apply(s);\r
+ }\r
+ return s;\r
+ };\r
+ this.resume = function() {\r
+ var instanceOptions = s._iO;\r
+ if (!s.paused) {\r
+ return s;\r
+ }\r
+ s.paused = false;\r
+ s.playState = 1;\r
+ if (!s.isHTML5) {\r
+ if (instanceOptions.isMovieStar && !instanceOptions.serverURL) {\r
+ s.setPosition(s.position);\r
+ }\r
+ flash._pause(s.id, instanceOptions.multiShot);\r
+ } else {\r
+ s._setup_html5().play();\r
+ start_html5_timer();\r
+ }\r
+ if (!onplay_called && instanceOptions.onplay) {\r
+ instanceOptions.onplay.apply(s);\r
+ onplay_called = true;\r
+ } else if (instanceOptions.onresume) {\r
+ instanceOptions.onresume.apply(s);\r
+ }\r
+ return s;\r
+ };\r
+ this.togglePause = function() {\r
+ if (s.playState === 0) {\r
+ s.play({\r
+ position: (fV === 9 && !s.isHTML5 ? s.position : s.position / msecScale)\r
+ });\r
+ return s;\r
+ }\r
+ if (s.paused) {\r
+ s.resume();\r
+ } else {\r
+ s.pause();\r
+ }\r
+ return s;\r
+ };\r
+ this.setPan = function(nPan, bInstanceOnly) {\r
+ if (nPan === _undefined) {\r
+ nPan = 0;\r
+ }\r
+ if (bInstanceOnly === _undefined) {\r
+ bInstanceOnly = false;\r
+ }\r
+ if (!s.isHTML5) {\r
+ flash._setPan(s.id, nPan);\r
+ }\r
+ s._iO.pan = nPan;\r
+ if (!bInstanceOnly) {\r
+ s.pan = nPan;\r
+ s.options.pan = nPan;\r
+ }\r
+ return s;\r
+ };\r
+ this.setVolume = function(nVol, _bInstanceOnly) {\r
+ if (nVol === _undefined) {\r
+ nVol = 100;\r
+ }\r
+ if (_bInstanceOnly === _undefined) {\r
+ _bInstanceOnly = false;\r
+ }\r
+ if (!s.isHTML5) {\r
+ flash._setVolume(s.id, (sm2.muted && !s.muted) || s.muted ? 0 : nVol);\r
+ } else if (s._a) {\r
+ if (sm2.muted && !s.muted) {\r
+ s.muted = true;\r
+ s._a.muted = true;\r
+ }\r
+ s._a.volume = Math.max(0, Math.min(1, nVol/100));\r
+ }\r
+ s._iO.volume = nVol;\r
+ if (!_bInstanceOnly) {\r
+ s.volume = nVol;\r
+ s.options.volume = nVol;\r
+ }\r
+ return s;\r
+ };\r
+ this.mute = function() {\r
+ s.muted = true;\r
+ if (!s.isHTML5) {\r
+ flash._setVolume(s.id, 0);\r
+ } else if (s._a) {\r
+ s._a.muted = true;\r
+ }\r
+ return s;\r
+ };\r
+ this.unmute = function() {\r
+ s.muted = false;\r
+ var hasIO = (s._iO.volume !== _undefined);\r
+ if (!s.isHTML5) {\r
+ flash._setVolume(s.id, hasIO ? s._iO.volume : s.options.volume);\r
+ } else if (s._a) {\r
+ s._a.muted = false;\r
+ }\r
+ return s;\r
+ };\r
+ this.toggleMute = function() {\r
+ return (s.muted ? s.unmute() : s.mute());\r
+ };\r
+ this.onPosition = function(nPosition, oMethod, oScope) {\r
+ onPositionItems.push({\r
+ position: parseInt(nPosition, 10),\r
+ method: oMethod,\r
+ scope: (oScope !== _undefined ? oScope : s),\r
+ fired: false\r
+ });\r
+ return s;\r
+ };\r
+ this.onposition = this.onPosition;\r
+ this.clearOnPosition = function(nPosition, oMethod) {\r
+ var i;\r
+ nPosition = parseInt(nPosition, 10);\r
+ if (isNaN(nPosition)) {\r
+ return false;\r
+ }\r
+ for (i=0; i < onPositionItems.length; i++) {\r
+ if (nPosition === onPositionItems[i].position) {\r
+ if (!oMethod || (oMethod === onPositionItems[i].method)) {\r
+ if (onPositionItems[i].fired) {\r
+ onPositionFired--;\r
+ }\r
+ onPositionItems.splice(i, 1);\r
+ }\r
+ }\r
+ }\r
+ };\r
+ this._processOnPosition = function() {\r
+ var i, item, j = onPositionItems.length;\r
+ if (!j || !s.playState || onPositionFired >= j) {\r
+ return false;\r
+ }\r
+ for (i = j - 1; i >= 0; i--) {\r
+ item = onPositionItems[i];\r
+ if (!item.fired && s.position >= item.position) {\r
+ item.fired = true;\r
+ onPositionFired++;\r
+ item.method.apply(item.scope, [item.position]);\r
+ j = onPositionItems.length;\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+ this._resetOnPosition = function(nPosition) {\r
+ var i, item, j = onPositionItems.length;\r
+ if (!j) {\r
+ return false;\r
+ }\r
+ for (i = j - 1; i >= 0; i--) {\r
+ item = onPositionItems[i];\r
+ if (item.fired && nPosition <= item.position) {\r
+ item.fired = false;\r
+ onPositionFired--;\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+ applyFromTo = function() {\r
+ var instanceOptions = s._iO,\r
+ f = instanceOptions.from,\r
+ t = instanceOptions.to,\r
+ start, end;\r
+ end = function() {\r
+ s.clearOnPosition(t, end);\r
+ s.stop();\r
+ };\r
+ start = function() {\r
+ if (t !== null && !isNaN(t)) {\r
+ s.onPosition(t, end);\r
+ }\r
+ };\r
+ if (f !== null && !isNaN(f)) {\r
+ instanceOptions.position = f;\r
+ instanceOptions.multiShot = false;\r
+ start();\r
+ }\r
+ return instanceOptions;\r
+ };\r
+ attachOnPosition = function() {\r
+ var item,\r
+ op = s._iO.onposition;\r
+ if (op) {\r
+ for (item in op) {\r
+ if (op.hasOwnProperty(item)) {\r
+ s.onPosition(parseInt(item, 10), op[item]);\r
+ }\r
+ }\r
+ }\r
+ };\r
+ detachOnPosition = function() {\r
+ var item,\r
+ op = s._iO.onposition;\r
+ if (op) {\r
+ for (item in op) {\r
+ if (op.hasOwnProperty(item)) {\r
+ s.clearOnPosition(parseInt(item, 10));\r
+ }\r
+ }\r
+ }\r
+ };\r
+ start_html5_timer = function() {\r
+ if (s.isHTML5) {\r
+ startTimer(s);\r
+ }\r
+ };\r
+ stop_html5_timer = function() {\r
+ if (s.isHTML5) {\r
+ stopTimer(s);\r
+ }\r
+ };\r
+ resetProperties = function(retainPosition) {\r
+ if (!retainPosition) {\r
+ onPositionItems = [];\r
+ onPositionFired = 0;\r
+ }\r
+ onplay_called = false;\r
+ s._hasTimer = null;\r
+ s._a = null;\r
+ s._html5_canplay = false;\r
+ s.bytesLoaded = null;\r
+ s.bytesTotal = null;\r
+ s.duration = (s._iO && s._iO.duration ? s._iO.duration : null);\r
+ s.durationEstimate = null;\r
+ s.buffered = [];\r
+ s.eqData = [];\r
+ s.eqData.left = [];\r
+ s.eqData.right = [];\r
+ s.failures = 0;\r
+ s.isBuffering = false;\r
+ s.instanceOptions = {};\r
+ s.instanceCount = 0;\r
+ s.loaded = false;\r
+ s.metadata = {};\r
+ s.readyState = 0;\r
+ s.muted = false;\r
+ s.paused = false;\r
+ s.peakData = {\r
+ left: 0,\r
+ right: 0\r
+ };\r
+ s.waveformData = {\r
+ left: [],\r
+ right: []\r
+ };\r
+ s.playState = 0;\r
+ s.position = null;\r
+ s.id3 = {};\r
+ };\r
+ resetProperties();\r
+ this._onTimer = function(bForce) {\r
+ var duration, isNew = false, time, x = {};\r
+ if (s._hasTimer || bForce) {\r
+ if (s._a && (bForce || ((s.playState > 0 || s.readyState === 1) && !s.paused))) {\r
+ duration = s._get_html5_duration();\r
+ if (duration !== lastHTML5State.duration) {\r
+ lastHTML5State.duration = duration;\r
+ s.duration = duration;\r
+ isNew = true;\r
+ }\r
+ s.durationEstimate = s.duration;\r
+ time = (s._a.currentTime * msecScale || 0);\r
+ if (time !== lastHTML5State.time) {\r
+ lastHTML5State.time = time;\r
+ isNew = true;\r
+ }\r
+ if (isNew || bForce) {\r
+ s._whileplaying(time, x, x, x, x);\r
+ }\r
+ }\r
+ return isNew;\r
+ }\r
+ };\r
+ this._get_html5_duration = function() {\r
+ var instanceOptions = s._iO,\r
+ d = (s._a && s._a.duration ? s._a.duration * msecScale : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : null)),\r
+ result = (d && !isNaN(d) && d !== Infinity ? d : null);\r
+ return result;\r
+ };\r
+ this._apply_loop = function(a, nLoops) {\r
+ a.loop = (nLoops > 1 ? 'loop' : '');\r
+ };\r
+ this._setup_html5 = function(oOptions) {\r
+ var instanceOptions = mixin(s._iO, oOptions),\r
+ a = useGlobalHTML5Audio ? globalHTML5Audio : s._a,\r
+ dURL = decodeURI(instanceOptions.url),\r
+ sameURL;\r
+ if (useGlobalHTML5Audio) {\r
+ if (dURL === decodeURI(lastGlobalHTML5URL)) {\r
+ sameURL = true;\r
+ }\r
+ } else if (dURL === decodeURI(lastURL)) {\r
+ sameURL = true;\r
+ }\r
+ if (a) {\r
+ if (a._s) {\r
+ if (useGlobalHTML5Audio) {\r
+ if (a._s && a._s.playState && !sameURL) {\r
+ a._s.stop();\r
+ }\r
+ } else if (!useGlobalHTML5Audio && dURL === decodeURI(lastURL)) {\r
+ s._apply_loop(a, instanceOptions.loops);\r
+ return a;\r
+ }\r
+ }\r
+ if (!sameURL) {\r
+ if (lastURL) {\r
+ resetProperties(false);\r
+ }\r
+ a.src = instanceOptions.url;\r
+ s.url = instanceOptions.url;\r
+ lastURL = instanceOptions.url;\r
+ lastGlobalHTML5URL = instanceOptions.url;\r
+ a._called_load = false;\r
+ }\r
+ } else {\r
+ if (instanceOptions.autoLoad || instanceOptions.autoPlay) {\r
+ s._a = new Audio(instanceOptions.url);\r
+ s._a.load();\r
+ } else {\r
+ s._a = (isOpera && opera.version() < 10 ? new Audio(null) : new Audio());\r
+ }\r
+ a = s._a;\r
+ a._called_load = false;\r
+ if (useGlobalHTML5Audio) {\r
+ globalHTML5Audio = a;\r
+ }\r
+ }\r
+ s.isHTML5 = true;\r
+ s._a = a;\r
+ a._s = s;\r
+ add_html5_events();\r
+ s._apply_loop(a, instanceOptions.loops);\r
+ if (instanceOptions.autoLoad || instanceOptions.autoPlay) {\r
+ s.load();\r
+ } else {\r
+ a.autobuffer = false;\r
+ a.preload = 'auto';\r
+ }\r
+ return a;\r
+ };\r
+ add_html5_events = function() {\r
+ if (s._a._added_events) {\r
+ return false;\r
+ }\r
+ var f;\r
+ function add(oEvt, oFn, bCapture) {\r
+ return s._a ? s._a.addEventListener(oEvt, oFn, bCapture || false) : null;\r
+ }\r
+ s._a._added_events = true;\r
+ for (f in html5_events) {\r
+ if (html5_events.hasOwnProperty(f)) {\r
+ add(f, html5_events[f]);\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+ remove_html5_events = function() {\r
+ var f;\r
+ function remove(oEvt, oFn, bCapture) {\r
+ return (s._a ? s._a.removeEventListener(oEvt, oFn, bCapture || false) : null);\r
+ }\r
+ s._a._added_events = false;\r
+ for (f in html5_events) {\r
+ if (html5_events.hasOwnProperty(f)) {\r
+ remove(f, html5_events[f]);\r
+ }\r
+ }\r
+ };\r
+ this._onload = function(nSuccess) {\r
+ var fN,\r
+ loadOK = !!nSuccess || (!s.isHTML5 && fV === 8 && s.duration);\r
+ s.loaded = loadOK;\r
+ s.readyState = (loadOK ? 3 : 2);\r
+ s._onbufferchange(0);\r
+ if (s._iO.onload) {\r
+ wrapCallback(s, function() {\r
+ s._iO.onload.apply(s, [loadOK]);\r
+ });\r
+ }\r
+ return true;\r
+ };\r
+ this._onbufferchange = function(nIsBuffering) {\r
+ if (s.playState === 0) {\r
+ return false;\r
+ }\r
+ if ((nIsBuffering && s.isBuffering) || (!nIsBuffering && !s.isBuffering)) {\r
+ return false;\r
+ }\r
+ s.isBuffering = (nIsBuffering === 1);\r
+ if (s._iO.onbufferchange) {\r
+ s._iO.onbufferchange.apply(s, [nIsBuffering]);\r
+ }\r
+ return true;\r
+ };\r
+ this._onsuspend = function() {\r
+ if (s._iO.onsuspend) {\r
+ s._iO.onsuspend.apply(s);\r
+ }\r
+ return true;\r
+ };\r
+ this._onfailure = function(msg, level, code) {\r
+ s.failures++;\r
+ if (s._iO.onfailure && s.failures === 1) {\r
+ s._iO.onfailure(msg, level, code);\r
+ } else {\r
+ }\r
+ };\r
+ this._onwarning = function(msg, level, code) {\r
+ if (s._iO.onwarning) {\r
+ s._iO.onwarning(msg, level, code);\r
+ }\r
+ };\r
+ this._onfinish = function() {\r
+ var io_onfinish = s._iO.onfinish;\r
+ s._onbufferchange(0);\r
+ s._resetOnPosition(0);\r
+ if (s.instanceCount) {\r
+ s.instanceCount--;\r
+ if (!s.instanceCount) {\r
+ detachOnPosition();\r
+ s.playState = 0;\r
+ s.paused = false;\r
+ s.instanceCount = 0;\r
+ s.instanceOptions = {};\r
+ s._iO = {};\r
+ stop_html5_timer();\r
+ if (s.isHTML5) {\r
+ s.position = 0;\r
+ }\r
+ }\r
+ if (!s.instanceCount || s._iO.multiShotEvents) {\r
+ if (io_onfinish) {\r
+ wrapCallback(s, function() {\r
+ io_onfinish.apply(s);\r
+ });\r
+ }\r
+ }\r
+ }\r
+ };\r
+ this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) {\r
+ var instanceOptions = s._iO;\r
+ s.bytesLoaded = nBytesLoaded;\r
+ s.bytesTotal = nBytesTotal;\r
+ s.duration = Math.floor(nDuration);\r
+ s.bufferLength = nBufferLength;\r
+ if (!s.isHTML5 && !instanceOptions.isMovieStar) {\r
+ if (instanceOptions.duration) {\r
+ s.durationEstimate = (s.duration > instanceOptions.duration) ? s.duration : instanceOptions.duration;\r
+ } else {\r
+ s.durationEstimate = parseInt((s.bytesTotal / s.bytesLoaded) * s.duration, 10);\r
+ }\r
+ } else {\r
+ s.durationEstimate = s.duration;\r
+ }\r
+ if (!s.isHTML5) {\r
+ s.buffered = [{\r
+ 'start': 0,\r
+ 'end': s.duration\r
+ }];\r
+ }\r
+ if ((s.readyState !== 3 || s.isHTML5) && instanceOptions.whileloading) {\r
+ instanceOptions.whileloading.apply(s);\r
+ }\r
+ };\r
+ this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) {\r
+ var instanceOptions = s._iO,\r
+ eqLeft;\r
+ if (isNaN(nPosition) || nPosition === null) {\r
+ return false;\r
+ }\r
+ s.position = Math.max(0, nPosition);\r
+ s._processOnPosition();\r
+ if (!s.isHTML5 && fV > 8) {\r
+ if (instanceOptions.usePeakData && oPeakData !== _undefined && oPeakData) {\r
+ s.peakData = {\r
+ left: oPeakData.leftPeak,\r
+ right: oPeakData.rightPeak\r
+ };\r
+ }\r
+ if (instanceOptions.useWaveformData && oWaveformDataLeft !== _undefined && oWaveformDataLeft) {\r
+ s.waveformData = {\r
+ left: oWaveformDataLeft.split(','),\r
+ right: oWaveformDataRight.split(',')\r
+ };\r
+ }\r
+ if (instanceOptions.useEQData) {\r
+ if (oEQData !== _undefined && oEQData && oEQData.leftEQ) {\r
+ eqLeft = oEQData.leftEQ.split(',');\r
+ s.eqData = eqLeft;\r
+ s.eqData.left = eqLeft;\r
+ if (oEQData.rightEQ !== _undefined && oEQData.rightEQ) {\r
+ s.eqData.right = oEQData.rightEQ.split(',');\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (s.playState === 1) {\r
+ if (!s.isHTML5 && fV === 8 && !s.position && s.isBuffering) {\r
+ s._onbufferchange(0);\r
+ }\r
+ if (instanceOptions.whileplaying) {\r
+ instanceOptions.whileplaying.apply(s);\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+ this._oncaptiondata = function(oData) {\r
+ s.captiondata = oData;\r
+ if (s._iO.oncaptiondata) {\r
+ s._iO.oncaptiondata.apply(s, [oData]);\r
+ }\r
+ };\r
+ this._onmetadata = function(oMDProps, oMDData) {\r
+ var oData = {}, i, j;\r
+ for (i = 0, j = oMDProps.length; i < j; i++) {\r
+ oData[oMDProps[i]] = oMDData[i];\r
+ }\r
+ s.metadata = oData;\r
+ if (s._iO.onmetadata) {\r
+ s._iO.onmetadata.call(s, s.metadata);\r
+ }\r
+ };\r
+ this._onid3 = function(oID3Props, oID3Data) {\r
+ var oData = [], i, j;\r
+ for (i = 0, j = oID3Props.length; i < j; i++) {\r
+ oData[oID3Props[i]] = oID3Data[i];\r
+ }\r
+ s.id3 = mixin(s.id3, oData);\r
+ if (s._iO.onid3) {\r
+ s._iO.onid3.apply(s);\r
+ }\r
+ };\r
+ this._onconnect = function(bSuccess) {\r
+ bSuccess = (bSuccess === 1);\r
+ s.connected = bSuccess;\r
+ if (bSuccess) {\r
+ s.failures = 0;\r
+ if (idCheck(s.id)) {\r
+ if (s.getAutoPlay()) {\r
+ s.play(_undefined, s.getAutoPlay());\r
+ } else if (s._iO.autoLoad) {\r
+ s.load();\r
+ }\r
+ }\r
+ if (s._iO.onconnect) {\r
+ s._iO.onconnect.apply(s, [bSuccess]);\r
+ }\r
+ }\r
+ };\r
+ this._ondataerror = function(sError) {\r
+ if (s.playState > 0) {\r
+ if (s._iO.ondataerror) {\r
+ s._iO.ondataerror.apply(s);\r
+ }\r
+ }\r
+ };\r
+ };\r
+ getDocument = function() {\r
+ return (doc.body || doc.getElementsByTagName('div')[0]);\r
+ };\r
+ id = function(sID) {\r
+ return doc.getElementById(sID);\r
+ };\r
+ mixin = function(oMain, oAdd) {\r
+ var o1 = (oMain || {}), o2, o;\r
+ o2 = (oAdd === _undefined ? sm2.defaultOptions : oAdd);\r
+ for (o in o2) {\r
+ if (o2.hasOwnProperty(o) && o1[o] === _undefined) {\r
+ if (typeof o2[o] !== 'object' || o2[o] === null) {\r
+ o1[o] = o2[o];\r
+ } else {\r
+ o1[o] = mixin(o1[o], o2[o]);\r
+ }\r
+ }\r
+ }\r
+ return o1;\r
+ };\r
+ wrapCallback = function(oSound, callback) {\r
+ if (!oSound.isHTML5 && fV === 8) {\r
+ window.setTimeout(callback, 0);\r
+ } else {\r
+ callback();\r
+ }\r
+ };\r
+ extraOptions = {\r
+ 'onready': 1,\r
+ 'ontimeout': 1,\r
+ 'defaultOptions': 1,\r
+ 'flash9Options': 1,\r
+ 'movieStarOptions': 1\r
+ };\r
+ assign = function(o, oParent) {\r
+ var i,\r
+ result = true,\r
+ hasParent = (oParent !== _undefined),\r
+ setupOptions = sm2.setupOptions,\r
+ bonusOptions = extraOptions;\r
+ for (i in o) {\r
+ if (o.hasOwnProperty(i)) {\r
+ if (typeof o[i] !== 'object' || o[i] === null || o[i] instanceof Array || o[i] instanceof RegExp) {\r
+ if (hasParent && bonusOptions[oParent] !== _undefined) {\r
+ sm2[oParent][i] = o[i];\r
+ } else if (setupOptions[i] !== _undefined) {\r
+ sm2.setupOptions[i] = o[i];\r
+ sm2[i] = o[i];\r
+ } else if (bonusOptions[i] === _undefined) {\r
+ result = false;\r
+ } else {\r
+ if (sm2[i] instanceof Function) {\r
+ sm2[i].apply(sm2, (o[i] instanceof Array ? o[i] : [o[i]]));\r
+ } else {\r
+ sm2[i] = o[i];\r
+ }\r
+ }\r
+ } else {\r
+ if (bonusOptions[i] === _undefined) {\r
+ result = false;\r
+ } else {\r
+ return assign(o[i], i);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return result;\r
+ };\r
+ function preferFlashCheck(kind) {\r
+ return (sm2.preferFlash && hasFlash && !sm2.ignoreFlash && (sm2.flash[kind] !== _undefined && sm2.flash[kind]));\r
+ }\r
+ event = (function() {\r
+ var old = (window.attachEvent),\r
+ evt = {\r
+ add: (old ? 'attachEvent' : 'addEventListener'),\r
+ remove: (old ? 'detachEvent' : 'removeEventListener')\r
+ };\r
+ function getArgs(oArgs) {\r
+ var args = slice.call(oArgs),\r
+ len = args.length;\r
+ if (old) {\r
+ args[1] = 'on' + args[1];\r
+ if (len > 3) {\r
+ args.pop();\r
+ }\r
+ } else if (len === 3) {\r
+ args.push(false);\r
+ }\r
+ return args;\r
+ }\r
+ function apply(args, sType) {\r
+ var element = args.shift(),\r
+ method = [evt[sType]];\r
+ if (old) {\r
+ element[method](args[0], args[1]);\r
+ } else {\r
+ element[method].apply(element, args);\r
+ }\r
+ }\r
+ function add() {\r
+ apply(getArgs(arguments), 'add');\r
+ }\r
+ function remove() {\r
+ apply(getArgs(arguments), 'remove');\r
+ }\r
+ return {\r
+ 'add': add,\r
+ 'remove': remove\r
+ };\r
+ }());\r
+ function html5_event(oFn) {\r
+ return function(e) {\r
+ var s = this._s,\r
+ result;\r
+ if (!s || !s._a) {\r
+ result = null;\r
+ } else {\r
+ result = oFn.call(this, e);\r
+ }\r
+ return result;\r
+ };\r
+ }\r
+ html5_events = {\r
+ abort: html5_event(function() {\r
+ }),\r
+ canplay: html5_event(function() {\r
+ var s = this._s,\r
+ position1K;\r
+ if (s._html5_canplay) {\r
+ return true;\r
+ }\r
+ s._html5_canplay = true;\r
+ s._onbufferchange(0);\r
+ position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position) ? s._iO.position/msecScale : null);\r
+ if (this.currentTime !== position1K) {\r
+ try {\r
+ this.currentTime = position1K;\r
+ } catch(ee) {\r
+ }\r
+ }\r
+ if (s._iO._oncanplay) {\r
+ s._iO._oncanplay();\r
+ }\r
+ }),\r
+ canplaythrough: html5_event(function() {\r
+ var s = this._s;\r
+ if (!s.loaded) {\r
+ s._onbufferchange(0);\r
+ s._whileloading(s.bytesLoaded, s.bytesTotal, s._get_html5_duration());\r
+ s._onload(true);\r
+ }\r
+ }),\r
+ durationchange: html5_event(function() {\r
+ var s = this._s,\r
+ duration;\r
+ duration = s._get_html5_duration();\r
+ if (!isNaN(duration) && duration !== s.duration) {\r
+ s.durationEstimate = s.duration = duration;\r
+ }\r
+ }),\r
+ ended: html5_event(function() {\r
+ var s = this._s;\r
+ s._onfinish();\r
+ }),\r
+ error: html5_event(function() {\r
+ this._s._onload(false);\r
+ }),\r
+ loadeddata: html5_event(function() {\r
+ var s = this._s;\r
+ if (!s._loaded && !isSafari) {\r
+ s.duration = s._get_html5_duration();\r
+ }\r
+ }),\r
+ loadedmetadata: html5_event(function() {\r
+ }),\r
+ loadstart: html5_event(function() {\r
+ this._s._onbufferchange(1);\r
+ }),\r
+ play: html5_event(function() {\r
+ this._s._onbufferchange(0);\r
+ }),\r
+ playing: html5_event(function() {\r
+ this._s._onbufferchange(0);\r
+ }),\r
+ progress: html5_event(function(e) {\r
+ var s = this._s,\r
+ i, j, progStr, buffered = 0,\r
+ isProgress = (e.type === 'progress'),\r
+ ranges = e.target.buffered,\r
+ loaded = (e.loaded || 0),\r
+ total = (e.total || 1);\r
+ s.buffered = [];\r
+ if (ranges && ranges.length) {\r
+ for (i = 0, j = ranges.length; i < j; i++) {\r
+ s.buffered.push({\r
+ 'start': ranges.start(i) * msecScale,\r
+ 'end': ranges.end(i) * msecScale\r
+ });\r
+ }\r
+ buffered = (ranges.end(0) - ranges.start(0)) * msecScale;\r
+ loaded = Math.min(1, buffered / (e.target.duration * msecScale));\r
+ }\r
+ if (!isNaN(loaded)) {\r
+ s._whileloading(loaded, total, s._get_html5_duration());\r
+ if (loaded && total && loaded === total) {\r
+ html5_events.canplaythrough.call(this, e);\r
+ }\r
+ }\r
+ }),\r
+ ratechange: html5_event(function() {\r
+ }),\r
+ suspend: html5_event(function(e) {\r
+ var s = this._s;\r
+ html5_events.progress.call(this, e);\r
+ s._onsuspend();\r
+ }),\r
+ stalled: html5_event(function() {\r
+ }),\r
+ timeupdate: html5_event(function() {\r
+ this._s._onTimer();\r
+ }),\r
+ waiting: html5_event(function() {\r
+ var s = this._s;\r
+ s._onbufferchange(1);\r
+ })\r
+ };\r
+ html5OK = function(iO) {\r
+ var result;\r
+ if (!iO || (!iO.type && !iO.url && !iO.serverURL)) {\r
+ result = false;\r
+ } else if (iO.serverURL || (iO.type && preferFlashCheck(iO.type))) {\r
+ result = false;\r
+ } else {\r
+ result = ((iO.type ? html5CanPlay({type:iO.type}) : html5CanPlay({url:iO.url}) || sm2.html5Only || iO.url.match(/data\:/i)));\r
+ }\r
+ return result;\r
+ };\r
+ html5Unload = function(oAudio) {\r
+ var url;\r
+ if (oAudio) {\r
+ url = (isSafari ? emptyURL : (sm2.html5.canPlayType('audio/wav') ? emptyWAV : emptyURL));\r
+ oAudio.src = url;\r
+ if (oAudio._called_unload !== _undefined) {\r
+ oAudio._called_load = false;\r
+ }\r
+ }\r
+ if (useGlobalHTML5Audio) {\r
+ lastGlobalHTML5URL = null;\r
+ }\r
+ return url;\r
+ };\r
+ html5CanPlay = function(o) {\r
+ if (!sm2.useHTML5Audio || !sm2.hasHTML5) {\r
+ return false;\r
+ }\r
+ var url = (o.url || null),\r
+ mime = (o.type || null),\r
+ aF = sm2.audioFormats,\r
+ result,\r
+ offset,\r
+ fileExt,\r
+ item;\r
+ if (mime && sm2.html5[mime] !== _undefined) {\r
+ return (sm2.html5[mime] && !preferFlashCheck(mime));\r
+ }\r
+ if (!html5Ext) {\r
+ html5Ext = [];\r
+ for (item in aF) {\r
+ if (aF.hasOwnProperty(item)) {\r
+ html5Ext.push(item);\r
+ if (aF[item].related) {\r
+ html5Ext = html5Ext.concat(aF[item].related);\r
+ }\r
+ }\r
+ }\r
+ html5Ext = new RegExp('\\.('+html5Ext.join('|')+')(\\?.*)?$','i');\r
+ }\r
+ fileExt = (url ? url.toLowerCase().match(html5Ext) : null);\r
+ if (!fileExt || !fileExt.length) {\r
+ if (!mime) {\r
+ result = false;\r
+ } else {\r
+ offset = mime.indexOf(';');\r
+ fileExt = (offset !== -1 ? mime.substr(0,offset) : mime).substr(6);\r
+ }\r
+ } else {\r
+ fileExt = fileExt[1];\r
+ }\r
+ if (fileExt && sm2.html5[fileExt] !== _undefined) {\r
+ result = (sm2.html5[fileExt] && !preferFlashCheck(fileExt));\r
+ } else {\r
+ mime = 'audio/' + fileExt;\r
+ result = sm2.html5.canPlayType({type:mime});\r
+ sm2.html5[fileExt] = result;\r
+ result = (result && sm2.html5[mime] && !preferFlashCheck(mime));\r
+ }\r
+ return result;\r
+ };\r
+ testHTML5 = function() {\r
+ if (!sm2.useHTML5Audio || !sm2.hasHTML5) {\r
+ sm2.html5.usingFlash = true;\r
+ needsFlash = true;\r
+ return false;\r
+ }\r
+ var a = (Audio !== _undefined ? (isOpera && opera.version() < 10 ? new Audio(null) : new Audio()) : null),\r
+ item, lookup, support = {}, aF, i;\r
+ function cp(m) {\r
+ var canPlay, j,\r
+ result = false,\r
+ isOK = false;\r
+ if (!a || typeof a.canPlayType !== 'function') {\r
+ return result;\r
+ }\r
+ if (m instanceof Array) {\r
+ for (i = 0, j = m.length; i < j; i++) {\r
+ if (sm2.html5[m[i]] || a.canPlayType(m[i]).match(sm2.html5Test)) {\r
+ isOK = true;\r
+ sm2.html5[m[i]] = true;\r
+ sm2.flash[m[i]] = !!(m[i].match(flashMIME));\r
+ }\r
+ }\r
+ result = isOK;\r
+ } else {\r
+ canPlay = (a && typeof a.canPlayType === 'function' ? a.canPlayType(m) : false);\r
+ result = !!(canPlay && (canPlay.match(sm2.html5Test)));\r
+ }\r
+ return result;\r
+ }\r
+ aF = sm2.audioFormats;\r
+ for (item in aF) {\r
+ if (aF.hasOwnProperty(item)) {\r
+ lookup = 'audio/' + item;\r
+ support[item] = cp(aF[item].type);\r
+ support[lookup] = support[item];\r
+ if (item.match(flashMIME)) {\r
+ sm2.flash[item] = true;\r
+ sm2.flash[lookup] = true;\r
+ } else {\r
+ sm2.flash[item] = false;\r
+ sm2.flash[lookup] = false;\r
+ }\r
+ if (aF[item] && aF[item].related) {\r
+ for (i = aF[item].related.length - 1; i >= 0; i--) {\r
+ support['audio/' + aF[item].related[i]] = support[item];\r
+ sm2.html5[aF[item].related[i]] = support[item];\r
+ sm2.flash[aF[item].related[i]] = support[item];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ support.canPlayType = (a ? cp : null);\r
+ sm2.html5 = mixin(sm2.html5, support);\r
+ sm2.html5.usingFlash = featureCheck();\r
+ needsFlash = sm2.html5.usingFlash;\r
+ return true;\r
+ };\r
+ strings = {\r
+ };\r
+ str = function() {\r
+ };\r
+ loopFix = function(sOpt) {\r
+ if (fV === 8 && sOpt.loops > 1 && sOpt.stream) {\r
+ sOpt.stream = false;\r
+ }\r
+ return sOpt;\r
+ };\r
+ policyFix = function(sOpt, sPre) {\r
+ if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) {\r
+ sOpt.usePolicyFile = true;\r
+ }\r
+ return sOpt;\r
+ };\r
+ complain = function(sMsg) {\r
+ };\r
+ doNothing = function() {\r
+ return false;\r
+ };\r
+ disableObject = function(o) {\r
+ var oProp;\r
+ for (oProp in o) {\r
+ if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') {\r
+ o[oProp] = doNothing;\r
+ }\r
+ }\r
+ oProp = null;\r
+ };\r
+ failSafely = function(bNoDisable) {\r
+ if (bNoDisable === _undefined) {\r
+ bNoDisable = false;\r
+ }\r
+ if (disabled || bNoDisable) {\r
+ sm2.disable(bNoDisable);\r
+ }\r
+ };\r
+ normalizeMovieURL = function(smURL) {\r
+ var urlParams = null, url;\r
+ if (smURL) {\r
+ if (smURL.match(/\.swf(\?.*)?$/i)) {\r
+ urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4);\r
+ if (urlParams) {\r
+ return smURL;\r
+ }\r
+ } else if (smURL.lastIndexOf('/') !== smURL.length - 1) {\r
+ smURL += '/';\r
+ }\r
+ }\r
+ url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + sm2.movieURL;\r
+ if (sm2.noSWFCache) {\r
+ url += ('?ts=' + new Date().getTime());\r
+ }\r
+ return url;\r
+ };\r
+ setVersionInfo = function() {\r
+ fV = parseInt(sm2.flashVersion, 10);\r
+ if (fV !== 8 && fV !== 9) {\r
+ sm2.flashVersion = fV = defaultFlashVersion;\r
+ }\r
+ var isDebug = (sm2.debugMode || sm2.debugFlash ? '_debug.swf' : '.swf');\r
+ if (sm2.useHTML5Audio && !sm2.html5Only && sm2.audioFormats.mp4.required && fV < 9) {\r
+ sm2.flashVersion = fV = 9;\r
+ }\r
+ sm2.version = sm2.versionNumber + (sm2.html5Only ? ' (HTML5-only mode)' : (fV === 9 ? ' (AS3/Flash 9)' : ' (AS2/Flash 8)'));\r
+ if (fV > 8) {\r
+ sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.flash9Options);\r
+ sm2.features.buffering = true;\r
+ sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.movieStarOptions);\r
+ sm2.filePatterns.flash9 = new RegExp('\\.(mp3|' + netStreamTypes.join('|') + ')(\\?.*)?$', 'i');\r
+ sm2.features.movieStar = true;\r
+ } else {\r
+ sm2.features.movieStar = false;\r
+ }\r
+ sm2.filePattern = sm2.filePatterns[(fV !== 8 ? 'flash9' : 'flash8')];\r
+ sm2.movieURL = (fV === 8 ? 'soundmanager2.swf' : 'soundmanager2_flash9.swf').replace('.swf', isDebug);\r
+ sm2.features.peakData = sm2.features.waveformData = sm2.features.eqData = (fV > 8);\r
+ };\r
+ setPolling = function(bPolling, bHighPerformance) {\r
+ if (!flash) {\r
+ return false;\r
+ }\r
+ flash._setPolling(bPolling, bHighPerformance);\r
+ };\r
+ initDebug = function() {\r
+ };\r
+ idCheck = this.getSoundById;\r
+ getSWFCSS = function() {\r
+ var css = [];\r
+ if (sm2.debugMode) {\r
+ css.push(swfCSS.sm2Debug);\r
+ }\r
+ if (sm2.debugFlash) {\r
+ css.push(swfCSS.flashDebug);\r
+ }\r
+ if (sm2.useHighPerformance) {\r
+ css.push(swfCSS.highPerf);\r
+ }\r
+ return css.join(' ');\r
+ };\r
+ flashBlockHandler = function() {\r
+ var name = str('fbHandler'),\r
+ p = sm2.getMoviePercent(),\r
+ css = swfCSS,\r
+ error = {\r
+ type:'FLASHBLOCK'\r
+ };\r
+ if (sm2.html5Only) {\r
+ return false;\r
+ }\r
+ if (!sm2.ok()) {\r
+ if (needsFlash) {\r
+ sm2.oMC.className = getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null ? css.swfTimedout : css.swfError);\r
+ }\r
+ sm2.didFlashBlock = true;\r
+ processOnEvents({\r
+ type: 'ontimeout',\r
+ ignoreInit: true,\r
+ error: error\r
+ });\r
+ catchError(error);\r
+ } else {\r
+ if (sm2.oMC) {\r
+ sm2.oMC.className = [getSWFCSS(), css.swfDefault, css.swfLoaded + (sm2.didFlashBlock ? ' ' + css.swfUnblocked : '')].join(' ');\r
+ }\r
+ }\r
+ };\r
+ addOnEvent = function(sType, oMethod, oScope) {\r
+ if (on_queue[sType] === _undefined) {\r
+ on_queue[sType] = [];\r
+ }\r
+ on_queue[sType].push({\r
+ 'method': oMethod,\r
+ 'scope': (oScope || null),\r
+ 'fired': false\r
+ });\r
+ };\r
+ processOnEvents = function(oOptions) {\r
+ if (!oOptions) {\r
+ oOptions = {\r
+ type: (sm2.ok() ? 'onready' : 'ontimeout')\r
+ };\r
+ }\r
+ if (!didInit && oOptions && !oOptions.ignoreInit) {\r
+ return false;\r
+ }\r
+ if (oOptions.type === 'ontimeout' && (sm2.ok() || (disabled && !oOptions.ignoreInit))) {\r
+ return false;\r
+ }\r
+ var status = {\r
+ success: (oOptions && oOptions.ignoreInit ? sm2.ok() : !disabled)\r
+ },\r
+ srcQueue = (oOptions && oOptions.type ? on_queue[oOptions.type] || [] : []),\r
+ queue = [], i, j,\r
+ args = [status],\r
+ canRetry = (needsFlash && !sm2.ok());\r
+ if (oOptions.error) {\r
+ args[0].error = oOptions.error;\r
+ }\r
+ for (i = 0, j = srcQueue.length; i < j; i++) {\r
+ if (srcQueue[i].fired !== true) {\r
+ queue.push(srcQueue[i]);\r
+ }\r
+ }\r
+ if (queue.length) {\r
+ for (i = 0, j = queue.length; i < j; i++) {\r
+ if (queue[i].scope) {\r
+ queue[i].method.apply(queue[i].scope, args);\r
+ } else {\r
+ queue[i].method.apply(this, args);\r
+ }\r
+ if (!canRetry) {\r
+ queue[i].fired = true;\r
+ }\r
+ }\r
+ }\r
+ return true;\r
+ };\r
+ initUserOnload = function() {\r
+ window.setTimeout(function() {\r
+ if (sm2.useFlashBlock) {\r
+ flashBlockHandler();\r
+ }\r
+ processOnEvents();\r
+ if (typeof sm2.onload === 'function') {\r
+ sm2.onload.apply(window);\r
+ }\r
+ if (sm2.waitForWindowLoad) {\r
+ event.add(window, 'load', initUserOnload);\r
+ }\r
+ }, 1);\r
+ };\r
+ detectFlash = function() {\r
+ if (hasFlash !== _undefined) {\r
+ return hasFlash;\r
+ }\r
+ var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = window.ActiveXObject;\r
+ if (nP && nP.length) {\r
+ type = 'application/x-shockwave-flash';\r
+ types = n.mimeTypes;\r
+ if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) {\r
+ hasPlugin = true;\r
+ }\r
+ } else if (AX !== _undefined && !ua.match(/MSAppHost/i)) {\r
+ try {\r
+ obj = new AX('ShockwaveFlash.ShockwaveFlash');\r
+ } catch(e) {\r
+ obj = null;\r
+ }\r
+ hasPlugin = (!!obj);\r
+ obj = null;\r
+ }\r
+ hasFlash = hasPlugin;\r
+ return hasPlugin;\r
+ };\r
+featureCheck = function() {\r
+ var flashNeeded,\r
+ item,\r
+ formats = sm2.audioFormats,\r
+ isSpecial = (is_iDevice && !!(ua.match(/os (1|2|3_0|3_1)\s/i)));\r
+ if (isSpecial) {\r
+ sm2.hasHTML5 = false;\r
+ sm2.html5Only = true;\r
+ if (sm2.oMC) {\r
+ sm2.oMC.style.display = 'none';\r
+ }\r
+ } else {\r
+ if (sm2.useHTML5Audio) {\r
+ if (!sm2.html5 || !sm2.html5.canPlayType) {\r
+ sm2.hasHTML5 = false;\r
+ }\r
+ }\r
+ }\r
+ if (sm2.useHTML5Audio && sm2.hasHTML5) {\r
+ canIgnoreFlash = true;\r
+ for (item in formats) {\r
+ if (formats.hasOwnProperty(item)) {\r
+ if (formats[item].required) {\r
+ if (!sm2.html5.canPlayType(formats[item].type)) {\r
+ canIgnoreFlash = false;\r
+ flashNeeded = true;\r
+ } else if (sm2.preferFlash && (sm2.flash[item] || sm2.flash[formats[item].type])) {\r
+ flashNeeded = true;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (sm2.ignoreFlash) {\r
+ flashNeeded = false;\r
+ canIgnoreFlash = true;\r
+ }\r
+ sm2.html5Only = (sm2.hasHTML5 && sm2.useHTML5Audio && !flashNeeded);\r
+ return (!sm2.html5Only);\r
+ };\r
+ parseURL = function(url) {\r
+ var i, j, urlResult = 0, result;\r
+ if (url instanceof Array) {\r
+ for (i = 0, j = url.length; i < j; i++) {\r
+ if (url[i] instanceof Object) {\r
+ if (sm2.canPlayMIME(url[i].type)) {\r
+ urlResult = i;\r
+ break;\r
+ }\r
+ } else if (sm2.canPlayURL(url[i])) {\r
+ urlResult = i;\r
+ break;\r
+ }\r
+ }\r
+ if (url[urlResult].url) {\r
+ url[urlResult] = url[urlResult].url;\r
+ }\r
+ result = url[urlResult];\r
+ } else {\r
+ result = url;\r
+ }\r
+ return result;\r
+ };\r
+ startTimer = function(oSound) {\r
+ if (!oSound._hasTimer) {\r
+ oSound._hasTimer = true;\r
+ if (!mobileHTML5 && sm2.html5PollingInterval) {\r
+ if (h5IntervalTimer === null && h5TimerCount === 0) {\r
+ h5IntervalTimer = setInterval(timerExecute, sm2.html5PollingInterval);\r
+ }\r
+ h5TimerCount++;\r
+ }\r
+ }\r
+ };\r
+ stopTimer = function(oSound) {\r
+ if (oSound._hasTimer) {\r
+ oSound._hasTimer = false;\r
+ if (!mobileHTML5 && sm2.html5PollingInterval) {\r
+ h5TimerCount--;\r
+ }\r
+ }\r
+ };\r
+ timerExecute = function() {\r
+ var i;\r
+ if (h5IntervalTimer !== null && !h5TimerCount) {\r
+ clearInterval(h5IntervalTimer);\r
+ h5IntervalTimer = null;\r
+ return false;\r
+ }\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+ if (sm2.sounds[sm2.soundIDs[i]].isHTML5 && sm2.sounds[sm2.soundIDs[i]]._hasTimer) {\r
+ sm2.sounds[sm2.soundIDs[i]]._onTimer();\r
+ }\r
+ }\r
+ };\r
+ catchError = function(options) {\r
+ options = (options !== _undefined ? options : {});\r
+ if (typeof sm2.onerror === 'function') {\r
+ sm2.onerror.apply(window, [{\r
+ type: (options.type !== _undefined ? options.type : null)\r
+ }]);\r
+ }\r
+ if (options.fatal !== _undefined && options.fatal) {\r
+ sm2.disable();\r
+ }\r
+ };\r
+ badSafariFix = function() {\r
+ if (!isBadSafari || !detectFlash()) {\r
+ return false;\r
+ }\r
+ var aF = sm2.audioFormats, i, item;\r
+ for (item in aF) {\r
+ if (aF.hasOwnProperty(item)) {\r
+ if (item === 'mp3' || item === 'mp4') {\r
+ sm2.html5[item] = false;\r
+ if (aF[item] && aF[item].related) {\r
+ for (i = aF[item].related.length - 1; i >= 0; i--) {\r
+ sm2.html5[aF[item].related[i]] = false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ };\r
+ this._setSandboxType = function(sandboxType) {\r
+ };\r
+ this._externalInterfaceOK = function(swfVersion) {\r
+ if (sm2.swfLoaded) {\r
+ return false;\r
+ }\r
+ var e;\r
+ sm2.swfLoaded = true;\r
+ tryInitOnFocus = false;\r
+ if (isBadSafari) {\r
+ badSafariFix();\r
+ }\r
+ setTimeout(init, isIE ? 100 : 1);\r
+ };\r
+ createMovie = function(smID, smURL) {\r
+ if (didAppend && appendSuccess) {\r
+ return false;\r
+ }\r
+ function initMsg() {\r
+ }\r
+ if (sm2.html5Only) {\r
+ setVersionInfo();\r
+ initMsg();\r
+ sm2.oMC = id(sm2.movieID);\r
+ init();\r
+ didAppend = true;\r
+ appendSuccess = true;\r
+ return false;\r
+ }\r
+ var remoteURL = (smURL || sm2.url),\r
+ localURL = (sm2.altURL || remoteURL),\r
+ swfTitle = 'JS/Flash audio component (SoundManager 2)',\r
+ oTarget = getDocument(),\r
+ extraClass = getSWFCSS(),\r
+ isRTL = null,\r
+ html = doc.getElementsByTagName('html')[0],\r
+ oEmbed, oMovie, tmp, movieHTML, oEl, s, x, sClass;\r
+ isRTL = (html && html.dir && html.dir.match(/rtl/i));\r
+ smID = (smID === _undefined ? sm2.id : smID);\r
+ function param(name, value) {\r
+ return '<param name="' + name + '" value="' + value + '" />';\r
+ }\r
+ setVersionInfo();\r
+ sm2.url = normalizeMovieURL(overHTTP ? remoteURL : localURL);\r
+ smURL = sm2.url;\r
+ sm2.wmode = (!sm2.wmode && sm2.useHighPerformance ? 'transparent' : sm2.wmode);\r
+ if (sm2.wmode !== null && (ua.match(/msie 8/i) || (!isIE && !sm2.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) {\r
+ messages.push(strings.spcWmode);\r
+ sm2.wmode = null;\r
+ }\r
+ oEmbed = {\r
+ 'name': smID,\r
+ 'id': smID,\r
+ 'src': smURL,\r
+ 'quality': 'high',\r
+ 'allowScriptAccess': sm2.allowScriptAccess,\r
+ 'bgcolor': sm2.bgColor,\r
+ 'pluginspage': http + 'www.macromedia.com/go/getflashplayer',\r
+ 'title': swfTitle,\r
+ 'type': 'application/x-shockwave-flash',\r
+ 'wmode': sm2.wmode,\r
+ 'hasPriority': 'true'\r
+ };\r
+ if (sm2.debugFlash) {\r
+ oEmbed.FlashVars = 'debug=1';\r
+ }\r
+ if (!sm2.wmode) {\r
+ delete oEmbed.wmode;\r
+ }\r
+ if (isIE) {\r
+ oMovie = doc.createElement('div');\r
+ movieHTML = [\r
+ '<object id="' + smID + '" data="' + smURL + '" type="' + oEmbed.type + '" title="' + oEmbed.title +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">',\r
+ param('movie', smURL),\r
+ param('AllowScriptAccess', sm2.allowScriptAccess),\r
+ param('quality', oEmbed.quality),\r
+ (sm2.wmode? param('wmode', sm2.wmode): ''),\r
+ param('bgcolor', sm2.bgColor),\r
+ param('hasPriority', 'true'),\r
+ (sm2.debugFlash ? param('FlashVars', oEmbed.FlashVars) : ''),\r
+ '</object>'\r
+ ].join('');\r
+ } else {\r
+ oMovie = doc.createElement('embed');\r
+ for (tmp in oEmbed) {\r
+ if (oEmbed.hasOwnProperty(tmp)) {\r
+ oMovie.setAttribute(tmp, oEmbed[tmp]);\r
+ }\r
+ }\r
+ }\r
+ initDebug();\r
+ extraClass = getSWFCSS();\r
+ oTarget = getDocument();\r
+ if (oTarget) {\r
+ sm2.oMC = (id(sm2.movieID) || doc.createElement('div'));\r
+ if (!sm2.oMC.id) {\r
+ sm2.oMC.id = sm2.movieID;\r
+ sm2.oMC.className = swfCSS.swfDefault + ' ' + extraClass;\r
+ s = null;\r
+ oEl = null;\r
+ if (!sm2.useFlashBlock) {\r
+ if (sm2.useHighPerformance) {\r
+ s = {\r
+ 'position': 'fixed',\r
+ 'width': '8px',\r
+ 'height': '8px',\r
+ 'bottom': '0px',\r
+ 'left': '0px',\r
+ 'overflow': 'hidden'\r
+ };\r
+ } else {\r
+ s = {\r
+ 'position': 'absolute',\r
+ 'width': '6px',\r
+ 'height': '6px',\r
+ 'top': '-9999px',\r
+ 'left': '-9999px'\r
+ };\r
+ if (isRTL) {\r
+ s.left = Math.abs(parseInt(s.left, 10)) + 'px';\r
+ }\r
+ }\r
+ }\r
+ if (isWebkit) {\r
+ sm2.oMC.style.zIndex = 10000;\r
+ }\r
+ if (!sm2.debugFlash) {\r
+ for (x in s) {\r
+ if (s.hasOwnProperty(x)) {\r
+ sm2.oMC.style[x] = s[x];\r
+ }\r
+ }\r
+ }\r
+ try {\r
+ if (!isIE) {\r
+ sm2.oMC.appendChild(oMovie);\r
+ }\r
+ oTarget.appendChild(sm2.oMC);\r
+ if (isIE) {\r
+ oEl = sm2.oMC.appendChild(doc.createElement('div'));\r
+ oEl.className = swfCSS.swfBox;\r
+ oEl.innerHTML = movieHTML;\r
+ }\r
+ appendSuccess = true;\r
+ } catch(e) {\r
+ throw new Error(str('domError') + ' \n' + e.toString());\r
+ }\r
+ } else {\r
+ sClass = sm2.oMC.className;\r
+ sm2.oMC.className = (sClass ? sClass + ' ' : swfCSS.swfDefault) + (extraClass ? ' ' + extraClass : '');\r
+ sm2.oMC.appendChild(oMovie);\r
+ if (isIE) {\r
+ oEl = sm2.oMC.appendChild(doc.createElement('div'));\r
+ oEl.className = swfCSS.swfBox;\r
+ oEl.innerHTML = movieHTML;\r
+ }\r
+ appendSuccess = true;\r
+ }\r
+ }\r
+ didAppend = true;\r
+ initMsg();\r
+ return true;\r
+ };\r
+ initMovie = function() {\r
+ if (sm2.html5Only) {\r
+ createMovie();\r
+ return false;\r
+ }\r
+ if (flash) {\r
+ return false;\r
+ }\r
+ if (!sm2.url) {\r
+ return false;\r
+ }\r
+ flash = sm2.getMovie(sm2.id);\r
+ if (!flash) {\r
+ if (!oRemoved) {\r
+ createMovie(sm2.id, sm2.url);\r
+ } else {\r
+ if (!isIE) {\r
+ sm2.oMC.appendChild(oRemoved);\r
+ } else {\r
+ sm2.oMC.innerHTML = oRemovedHTML;\r
+ }\r
+ oRemoved = null;\r
+ didAppend = true;\r
+ }\r
+ flash = sm2.getMovie(sm2.id);\r
+ }\r
+ if (typeof sm2.oninitmovie === 'function') {\r
+ setTimeout(sm2.oninitmovie, 1);\r
+ }\r
+ return true;\r
+ };\r
+ delayWaitForEI = function() {\r
+ setTimeout(waitForEI, 1000);\r
+ };\r
+ rebootIntoHTML5 = function() {\r
+ window.setTimeout(function() {\r
+ sm2.setup({\r
+ preferFlash: false\r
+ }).reboot();\r
+ sm2.didFlashBlock = true;\r
+ sm2.beginDelayedInit();\r
+ }, 1);\r
+ };\r
+ waitForEI = function() {\r
+ var p,\r
+ loadIncomplete = false;\r
+ if (!sm2.url) {\r
+ return false;\r
+ }\r
+ if (waitingForEI) {\r
+ return false;\r
+ }\r
+ waitingForEI = true;\r
+ event.remove(window, 'load', delayWaitForEI);\r
+ if (hasFlash && tryInitOnFocus && !isFocused) {\r
+ return false;\r
+ }\r
+ if (!didInit) {\r
+ p = sm2.getMoviePercent();\r
+ if (p > 0 && p < 100) {\r
+ loadIncomplete = true;\r
+ }\r
+ }\r
+ setTimeout(function() {\r
+ p = sm2.getMoviePercent();\r
+ if (loadIncomplete) {\r
+ waitingForEI = false;\r
+ window.setTimeout(delayWaitForEI, 1);\r
+ return false;\r
+ }\r
+ if (!didInit && okToDisable) {\r
+ if (p === null) {\r
+ if (sm2.useFlashBlock || sm2.flashLoadTimeout === 0) {\r
+ if (sm2.useFlashBlock) {\r
+ flashBlockHandler();\r
+ }\r
+ } else {\r
+ if (!sm2.useFlashBlock && canIgnoreFlash) {\r
+ rebootIntoHTML5();\r
+ } else {\r
+ processOnEvents({\r
+ type: 'ontimeout',\r
+ ignoreInit: true,\r
+ error: {\r
+ type: 'INIT_FLASHBLOCK'\r
+ }\r
+ });\r
+ }\r
+ }\r
+ } else {\r
+ if (sm2.flashLoadTimeout === 0) {\r
+ } else {\r
+ if (!sm2.useFlashBlock && canIgnoreFlash) {\r
+ rebootIntoHTML5();\r
+ } else {\r
+ failSafely(true);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }, sm2.flashLoadTimeout);\r
+ };\r
+ handleFocus = function() {\r
+ function cleanup() {\r
+ event.remove(window, 'focus', handleFocus);\r
+ }\r
+ if (isFocused || !tryInitOnFocus) {\r
+ cleanup();\r
+ return true;\r
+ }\r
+ okToDisable = true;\r
+ isFocused = true;\r
+ waitingForEI = false;\r
+ delayWaitForEI();\r
+ cleanup();\r
+ return true;\r
+ };\r
+ flushMessages = function() {\r
+ };\r
+ showSupport = function() {\r
+ };\r
+ initComplete = function(bNoDisable) {\r
+ if (didInit) {\r
+ return false;\r
+ }\r
+ if (sm2.html5Only) {\r
+ didInit = true;\r
+ initUserOnload();\r
+ return true;\r
+ }\r
+ var wasTimeout = (sm2.useFlashBlock && sm2.flashLoadTimeout && !sm2.getMoviePercent()),\r
+ result = true,\r
+ error;\r
+ if (!wasTimeout) {\r
+ didInit = true;\r
+ }\r
+ error = {\r
+ type: (!hasFlash && needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')\r
+ };\r
+ if (disabled || bNoDisable) {\r
+ if (sm2.useFlashBlock && sm2.oMC) {\r
+ sm2.oMC.className = getSWFCSS() + ' ' + (sm2.getMoviePercent() === null ? swfCSS.swfTimedout : swfCSS.swfError);\r
+ }\r
+ processOnEvents({\r
+ type: 'ontimeout',\r
+ error: error,\r
+ ignoreInit: true\r
+ });\r
+ catchError(error);\r
+ result = false;\r
+ } else {\r
+ }\r
+ if (!disabled) {\r
+ if (sm2.waitForWindowLoad && !windowLoaded) {\r
+ event.add(window, 'load', initUserOnload);\r
+ } else {\r
+ initUserOnload();\r
+ }\r
+ }\r
+ return result;\r
+ };\r
+ setProperties = function() {\r
+ var i,\r
+ o = sm2.setupOptions;\r
+ for (i in o) {\r
+ if (o.hasOwnProperty(i)) {\r
+ if (sm2[i] === _undefined) {\r
+ sm2[i] = o[i];\r
+ } else if (sm2[i] !== o[i]) {\r
+ sm2.setupOptions[i] = sm2[i];\r
+ }\r
+ }\r
+ }\r
+ };\r
+ init = function() {\r
+ if (didInit) {\r
+ return false;\r
+ }\r
+ function cleanup() {\r
+ event.remove(window, 'load', sm2.beginDelayedInit);\r
+ }\r
+ if (sm2.html5Only) {\r
+ if (!didInit) {\r
+ cleanup();\r
+ sm2.enabled = true;\r
+ initComplete();\r
+ }\r
+ return true;\r
+ }\r
+ initMovie();\r
+ try {\r
+ flash._externalInterfaceTest(false);\r
+ setPolling(true, (sm2.flashPollingInterval || (sm2.useHighPerformance ? 10 : 50)));\r
+ if (!sm2.debugMode) {\r
+ flash._disableDebug();\r
+ }\r
+ sm2.enabled = true;\r
+ if (!sm2.html5Only) {\r
+ event.add(window, 'unload', doNothing);\r
+ }\r
+ } catch(e) {\r
+ catchError({\r
+ type: 'JS_TO_FLASH_EXCEPTION',\r
+ fatal: true\r
+ });\r
+ failSafely(true);\r
+ initComplete();\r
+ return false;\r
+ }\r
+ initComplete();\r
+ cleanup();\r
+ return true;\r
+ };\r
+ domContentLoaded = function() {\r
+ if (didDCLoaded) {\r
+ return false;\r
+ }\r
+ didDCLoaded = true;\r
+ setProperties();\r
+ initDebug();\r
+ if (!hasFlash && sm2.hasHTML5) {\r
+ sm2.setup({\r
+ 'useHTML5Audio': true,\r
+ 'preferFlash': false\r
+ });\r
+ }\r
+ testHTML5();\r
+ if (!hasFlash && needsFlash) {\r
+ messages.push(strings.needFlash);\r
+ sm2.setup({\r
+ 'flashLoadTimeout': 1\r
+ });\r
+ }\r
+ if (doc.removeEventListener) {\r
+ doc.removeEventListener('DOMContentLoaded', domContentLoaded, false);\r
+ }\r
+ initMovie();\r
+ return true;\r
+ };\r
+ domContentLoadedIE = function() {\r
+ if (doc.readyState === 'complete') {\r
+ domContentLoaded();\r
+ doc.detachEvent('onreadystatechange', domContentLoadedIE);\r
+ }\r
+ return true;\r
+ };\r
+ winOnLoad = function() {\r
+ windowLoaded = true;\r
+ domContentLoaded();\r
+ event.remove(window, 'load', winOnLoad);\r
+ };\r
+ detectFlash();\r
+ event.add(window, 'focus', handleFocus);\r
+ event.add(window, 'load', delayWaitForEI);\r
+ event.add(window, 'load', winOnLoad);\r
+ if (doc.addEventListener) {\r
+ doc.addEventListener('DOMContentLoaded', domContentLoaded, false);\r
+ } else if (doc.attachEvent) {\r
+ doc.attachEvent('onreadystatechange', domContentLoadedIE);\r
+ } else {\r
+ catchError({\r
+ type: 'NO_DOM2_EVENTS',\r
+ fatal: true\r
+ });\r
+ }\r
+}\r
+// SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading\r
+if (window.SM2_DEFER === _undefined || !SM2_DEFER) {\r
+ soundManager = new SoundManager();\r
+}\r
+if (typeof module === 'object' && module && typeof module.exports === 'object') {\r
+ module.exports.SoundManager = SoundManager;\r
+ module.exports.soundManager = soundManager;\r
+} else if (typeof define === 'function' && define.amd) {\r
+ define(function() {\r
+ function getInstance(smBuilder) {\r
+ if (!window.soundManager && smBuilder instanceof Function) {\r
+ var instance = smBuilder(SoundManager);\r
+ if (instance instanceof SoundManager) {\r
+ window.soundManager = instance;\r
+ }\r
+ }\r
+ return window.soundManager;\r
+ }\r
+ return {\r
+ constructor: SoundManager,\r
+ getInstance: getInstance\r
+ }\r
+ });\r
+}\r
+// standard browser case\r
+// constructor\r
+window.SoundManager = SoundManager;\r
+// public API, flash callbacks etc.\r
+window.soundManager = soundManager;\r
+}(window));\r
--- /dev/null
+/** @license\r
+ *\r
+ * SoundManager 2: JavaScript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code provided under the BSD License:\r
+ * http://schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * V2.97a.20150601\r
+ */\r
+\r
+/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio, opera, module, define */\r
+/*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true, todo: true */\r
+\r
+/**\r
+ * About this file\r
+ * -------------------------------------------------------------------------------------\r
+ * This is the fully-commented source version of the SoundManager 2 API,\r
+ * recommended for use during development and testing.\r
+ *\r
+ * See soundmanager2-nodebug-jsmin.js for an optimized build (~11KB with gzip.)\r
+ * http://schillmania.com/projects/soundmanager2/doc/getstarted/#basic-inclusion\r
+ * Alternately, serve this file with gzip for 75% compression savings (~30KB over HTTP.)\r
+ *\r
+ * You may notice <d> and </d> comments in this source; these are delimiters for\r
+ * debug blocks which are removed in the -nodebug builds, further optimizing code size.\r
+ *\r
+ * Also, as you may note: Whoa, reliable cross-platform/device audio support is hard! ;)\r
+ */\r
+\r
+(function(window, _undefined) {\r
+\r
+"use strict";\r
+\r
+if (!window || !window.document) {\r
+\r
+ // Don't cross the [environment] streams. SM2 expects to be running in a browser, not under node.js etc.\r
+ // Additionally, if a browser somehow manages to fail this test, as Egon said: "It would be bad."\r
+\r
+ throw new Error('SoundManager requires a browser with window and document objects.');\r
+\r
+}\r
+\r
+var soundManager = null;\r
+\r
+/**\r
+ * The SoundManager constructor.\r
+ *\r
+ * @constructor\r
+ * @param {string} smURL Optional: Path to SWF files\r
+ * @param {string} smID Optional: The ID to use for the SWF container element\r
+ * @this {SoundManager}\r
+ * @return {SoundManager} The new SoundManager instance\r
+ */\r
+\r
+function SoundManager(smURL, smID) {\r
+\r
+ /**\r
+ * soundManager configuration options list\r
+ * defines top-level configuration properties to be applied to the soundManager instance (eg. soundManager.flashVersion)\r
+ * to set these properties, use the setup() method - eg., soundManager.setup({url: '/swf/', flashVersion: 9})\r
+ */\r
+\r
+ this.setupOptions = {\r
+\r
+ 'url': (smURL || null), // path (directory) where SoundManager 2 SWFs exist, eg., /path/to/swfs/\r
+ 'flashVersion': 8, // flash build to use (8 or 9.) Some API features require 9.\r
+ 'debugMode': true, // enable debugging output (console.log() with HTML fallback)\r
+ 'debugFlash': false, // enable debugging output inside SWF, troubleshoot Flash/browser issues\r
+ 'useConsole': true, // use console.log() if available (otherwise, writes to #soundmanager-debug element)\r
+ 'consoleOnly': true, // if console is being used, do not create/write to #soundmanager-debug\r
+ 'waitForWindowLoad': false, // force SM2 to wait for window.onload() before trying to call soundManager.onload()\r
+ 'bgColor': '#ffffff', // SWF background color. N/A when wmode = 'transparent'\r
+ 'useHighPerformance': false, // position:fixed flash movie can help increase js/flash speed, minimize lag\r
+ 'flashPollingInterval': null, // msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used.\r
+ 'html5PollingInterval': null, // msec affecting whileplaying() for HTML5 audio, excluding mobile devices. If null, native HTML5 update events are used.\r
+ 'flashLoadTimeout': 1000, // msec to wait for flash movie to load before failing (0 = infinity)\r
+ 'wmode': null, // flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index to work)\r
+ 'allowScriptAccess': 'always', // for scripting the SWF (object/embed property), 'always' or 'sameDomain'\r
+ 'useFlashBlock': false, // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable.\r
+ 'useHTML5Audio': true, // use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (MP3/MP4 support varies.) Ideally, transparent vs. Flash API where possible.\r
+ 'forceUseGlobalHTML5Audio': false, // if true, a single Audio() object is used for all sounds - and only one can play at a time.\r
+ 'ignoreMobileRestrictions': false, // if true, SM2 will not apply global HTML5 audio rules to mobile UAs. iOS > 7 and WebViews may allow multiple Audio() instances.\r
+ 'html5Test': /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.\r
+ 'preferFlash': false, // overrides useHTML5audio, will use Flash for MP3/MP4/AAC if present. Potential option if HTML5 playback with these formats is quirky.\r
+ 'noSWFCache': false, // if true, appends ?ts={date} to break aggressive SWF caching.\r
+ 'idPrefix': 'sound' // if an id is not provided to createSound(), this prefix is used for generated IDs - 'sound0', 'sound1' etc.\r
+\r
+ };\r
+\r
+ this.defaultOptions = {\r
+\r
+ /**\r
+ * the default configuration for sound objects made with createSound() and related methods\r
+ * eg., volume, auto-load behaviour and so forth\r
+ */\r
+\r
+ '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)\r
+ 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true)\r
+ 'from': null, // position to start playback within a sound (msec), default = beginning\r
+ 'loops': 1, // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0)\r
+ 'onid3': null, // callback function for "ID3 data is added/available"\r
+ 'onload': null, // callback function for "load finished"\r
+ 'whileloading': null, // callback function for "download progress update" (X of Y bytes received)\r
+ 'onplay': null, // callback for "play" start\r
+ 'onpause': null, // callback for "pause"\r
+ 'onresume': null, // callback for "resume" (pause toggle)\r
+ 'whileplaying': null, // callback during play (position update)\r
+ 'onposition': null, // object containing times and function callbacks for positions of interest\r
+ 'onstop': null, // callback for "user stop"\r
+ 'onfailure': null, // callback function for when playing fails\r
+ 'onfinish': null, // callback function for "sound finished playing"\r
+ 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time\r
+ 'multiShotEvents': false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled\r
+ 'position': null, // offset (milliseconds) to seek to within loaded sound data.\r
+ 'pan': 0, // "pan" settings, left-to-right, -100 to 100\r
+ 'stream': true, // allows playing before entire file has loaded (recommended)\r
+ 'to': null, // position to end playback within a sound (msec), default = end\r
+ 'type': null, // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3\r
+ 'usePolicyFile': false, // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access)\r
+ 'volume': 100 // self-explanatory. 0-100, the latter being the max.\r
+\r
+ };\r
+\r
+ this.flash9Options = {\r
+\r
+ /**\r
+ * flash 9-only options,\r
+ * merged into defaultOptions if flash 9 is being used\r
+ */\r
+\r
+ 'isMovieStar': null, // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL\r
+ 'usePeakData': false, // enable left/right channel peak (level) data\r
+ 'useWaveformData': false, // enable sound spectrum (raw waveform data) - NOTE: May increase CPU load.\r
+ 'useEQData': false, // enable sound EQ (frequency spectrum data) - NOTE: May increase CPU load.\r
+ 'onbufferchange': null, // callback for "isBuffering" property change\r
+ 'ondataerror': null // callback for waveform/eq data access error (flash playing audio in other tabs/domains)\r
+\r
+ };\r
+\r
+ this.movieStarOptions = {\r
+\r
+ /**\r
+ * flash 9.0r115+ MPEG4 audio options,\r
+ * merged into defaultOptions if flash 9+movieStar mode is enabled\r
+ */\r
+\r
+ 'bufferTime': 3, // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.)\r
+ 'serverURL': null, // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants\r
+ 'onconnect': null, // rtmp: callback for connection to flash media server\r
+ 'duration': null // rtmp: song duration (msec)\r
+\r
+ };\r
+\r
+ this.audioFormats = {\r
+\r
+ /**\r
+ * determines HTML5 support + flash requirements.\r
+ * if no support (via flash and/or HTML5) for a "required" format, SM2 will fail to start.\r
+ * flash fallback is used for MP3 or MP4 if HTML5 can't play it (or if preferFlash = true)\r
+ */\r
+\r
+ 'mp3': {\r
+ 'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'],\r
+ 'required': true\r
+ },\r
+\r
+ 'mp4': {\r
+ 'related': ['aac','m4a','m4b'], // additional formats under the MP4 container\r
+ 'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'],\r
+ 'required': false\r
+ },\r
+\r
+ 'ogg': {\r
+ 'type': ['audio/ogg; codecs=vorbis'],\r
+ 'required': false\r
+ },\r
+\r
+ 'opus': {\r
+ 'type': ['audio/ogg; codecs=opus', 'audio/opus'],\r
+ 'required': false\r
+ },\r
+\r
+ 'wav': {\r
+ 'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'],\r
+ 'required': false\r
+ }\r
+\r
+ };\r
+\r
+ // HTML attributes (id + class names) for the SWF container\r
+\r
+ this.movieID = 'sm2-container';\r
+ this.id = (smID || 'sm2movie');\r
+\r
+ this.debugID = 'soundmanager-debug';\r
+ this.debugURLParam = /([#?&])debug=1/i;\r
+\r
+ // dynamic attributes\r
+\r
+ this.versionNumber = 'V2.97a.20150601';\r
+ this.version = null;\r
+ this.movieURL = null;\r
+ this.altURL = null;\r
+ this.swfLoaded = false;\r
+ this.enabled = false;\r
+ this.oMC = null;\r
+ this.sounds = {};\r
+ this.soundIDs = [];\r
+ this.muted = false;\r
+ this.didFlashBlock = false;\r
+ this.filePattern = null;\r
+\r
+ this.filePatterns = {\r
+ 'flash8': /\.mp3(\?.*)?$/i,\r
+ 'flash9': /\.mp3(\?.*)?$/i\r
+ };\r
+\r
+ // support indicators, set at init\r
+\r
+ this.features = {\r
+ 'buffering': false,\r
+ 'peakData': false,\r
+ 'waveformData': false,\r
+ 'eqData': false,\r
+ 'movieStar': false\r
+ };\r
+\r
+ // flash sandbox info, used primarily in troubleshooting\r
+\r
+ this.sandbox = {\r
+ // <d>\r
+ 'type': null,\r
+ 'types': {\r
+ 'remote': 'remote (domain-based) rules',\r
+ 'localWithFile': 'local with file access (no internet access)',\r
+ 'localWithNetwork': 'local with network (internet access only, no local access)',\r
+ 'localTrusted': 'local, trusted (local+internet access)'\r
+ },\r
+ 'description': null,\r
+ 'noRemote': null,\r
+ 'noLocal': null\r
+ // </d>\r
+ };\r
+\r
+ /**\r
+ * format support (html5/flash)\r
+ * stores canPlayType() results based on audioFormats.\r
+ * eg. { mp3: boolean, mp4: boolean }\r
+ * treat as read-only.\r
+ */\r
+\r
+ this.html5 = {\r
+ 'usingFlash': null // set if/when flash fallback is needed\r
+ };\r
+\r
+ // file type support hash\r
+ this.flash = {};\r
+\r
+ // determined at init time\r
+ this.html5Only = false;\r
+\r
+ // used for special cases (eg. iPad/iPhone/palm OS?)\r
+ this.ignoreFlash = false;\r
+\r
+ /**\r
+ * a few private internals (OK, a lot. :D)\r
+ */\r
+\r
+ var SMSound,\r
+ sm2 = this, globalHTML5Audio = null, flash = null, sm = 'soundManager', smc = sm + ': ', h5 = 'HTML5::', id, ua = navigator.userAgent, wl = window.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, rebootIntoHTML5, 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, messages = [],\r
+ canIgnoreFlash, needsFlash = null, featureCheck, html5OK, html5CanPlay, html5Ext, html5Unload, domContentLoadedIE, testHTML5, event, slice = Array.prototype.slice, useGlobalHTML5Audio = false, lastGlobalHTML5URL, hasFlash, detectFlash, badSafariFix, html5_events, showSupport, flushMessages, wrapCallback, idCounter = 0, didSetup, msecScale = 1000,\r
+ is_iDevice = ua.match(/(ipad|iphone|ipod)/i), isAndroid = ua.match(/android/i), isIE = ua.match(/msie/i),\r
+ isWebkit = ua.match(/webkit/i),\r
+ isSafari = (ua.match(/safari/i) && !ua.match(/chrome/i)),\r
+ isOpera = (ua.match(/opera/i)),\r
+ mobileHTML5 = (ua.match(/(mobile|pre\/|xoom)/i) || is_iDevice || isAndroid),\r
+ 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\r
+ hasConsole = (window.console !== _undefined && console.log !== _undefined),\r
+ isFocused = (doc.hasFocus !== _undefined ? doc.hasFocus() : null),\r
+ tryInitOnFocus = (isSafari && (doc.hasFocus === _undefined || !doc.hasFocus())),\r
+ okToDisable = !tryInitOnFocus,\r
+ flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i,\r
+ emptyURL = 'about:blank', // safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs)\r
+ emptyWAV = 'data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w==', // tiny WAV for HTML5 unloading\r
+ overHTTP = (doc.location ? doc.location.protocol.match(/http/i) : null),\r
+ http = (!overHTTP ? 'http:/'+'/' : ''),\r
+ // mp3, mp4, aac etc.\r
+ netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,\r
+ // Flash v9.0r115+ "moviestar" formats\r
+ netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'm4b', 'mp4v', '3gp', '3g2'],\r
+ netStreamPattern = new RegExp('\\.(' + netStreamTypes.join('|') + ')(\\?.*)?$', 'i');\r
+\r
+ this.mimePattern = /^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i; // default mp3 set\r
+\r
+ // use altURL if not "online"\r
+ this.useAltURL = !overHTTP;\r
+\r
+ swfCSS = {\r
+ 'swfBox': 'sm2-object-box',\r
+ 'swfDefault': 'movieContainer',\r
+ 'swfError': 'swf_error', // SWF loaded, but SM2 couldn't start (other error)\r
+ 'swfTimedout': 'swf_timedout',\r
+ 'swfLoaded': 'swf_loaded',\r
+ 'swfUnblocked': 'swf_unblocked', // or loaded OK\r
+ 'sm2Debug': 'sm2_debug',\r
+ 'highPerf': 'high_performance',\r
+ 'flashDebug': 'flash_debug'\r
+ };\r
+\r
+ /**\r
+ * basic HTML5 Audio() support test\r
+ * try...catch because of IE 9 "not implemented" nonsense\r
+ * https://github.com/Modernizr/Modernizr/issues/224\r
+ */\r
+\r
+ this.hasHTML5 = (function() {\r
+ try {\r
+ // new Audio(null) for stupid Opera 9.64 case, which throws not_enough_arguments exception otherwise.\r
+ return (Audio !== _undefined && (isOpera && opera !== _undefined && opera.version() < 10 ? new Audio(null) : new Audio()).canPlayType !== _undefined);\r
+ } catch(e) {\r
+ return false;\r
+ }\r
+ }());\r
+\r
+ /**\r
+ * Public SoundManager API\r
+ * -----------------------\r
+ */\r
+\r
+ /**\r
+ * Configures top-level soundManager properties.\r
+ *\r
+ * @param {object} options Option parameters, eg. { flashVersion: 9, url: '/path/to/swfs/' }\r
+ * onready and ontimeout are also accepted parameters. call soundManager.setup() to see the full list.\r
+ */\r
+\r
+ this.setup = function(options) {\r
+\r
+ var noURL = (!sm2.url);\r
+\r
+ // warn if flash options have already been applied\r
+\r
+ if (options !== _undefined && didInit && needsFlash && sm2.ok() && (options.flashVersion !== _undefined || options.url !== _undefined || options.html5Test !== _undefined)) {\r
+ complain(str('setupLate'));\r
+ }\r
+\r
+ // TODO: defer: true?\r
+\r
+ assign(options);\r
+\r
+ if (!useGlobalHTML5Audio) {\r
+\r
+ if (mobileHTML5) {\r
+\r
+ // force the singleton HTML5 pattern on mobile, by default.\r
+ if (!sm2.setupOptions.ignoreMobileRestrictions || sm2.setupOptions.forceUseGlobalHTML5Audio) {\r
+ messages.push(strings.globalHTML5);\r
+ useGlobalHTML5Audio = true;\r
+ }\r
+\r
+ } else {\r
+\r
+ // only apply singleton HTML5 on desktop if forced.\r
+ if (sm2.setupOptions.forceUseGlobalHTML5Audio) {\r
+ messages.push(strings.globalHTML5);\r
+ useGlobalHTML5Audio = true;\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ if (!didSetup && mobileHTML5) {\r
+\r
+ if (sm2.setupOptions.ignoreMobileRestrictions) {\r
+ \r
+ messages.push(strings.ignoreMobile);\r
+ \r
+ } else {\r
+\r
+ // prefer HTML5 for mobile + tablet-like devices, probably more reliable vs. flash at this point.\r
+\r
+ // <d>\r
+ if (!sm2.setupOptions.useHTML5Audio || sm2.setupOptions.preferFlash) {\r
+ // notify that defaults are being changed.\r
+ sm2._wD(strings.mobileUA);\r
+ }\r
+ // </d>\r
+\r
+ sm2.setupOptions.useHTML5Audio = true;\r
+ sm2.setupOptions.preferFlash = false;\r
+\r
+ if (is_iDevice) {\r
+\r
+ // no flash here.\r
+ sm2.ignoreFlash = true;\r
+\r
+ } else if ((isAndroid && !ua.match(/android\s2\.3/i)) || !isAndroid) {\r
+ \r
+ /**\r
+ * Android devices tend to work better with a single audio instance, specifically for chained playback of sounds in sequence.\r
+ * Common use case: exiting sound onfinish() -> createSound() -> play()\r
+ * Presuming similar restrictions for other mobile, non-Android, non-iOS devices.\r
+ */\r
+\r
+ // <d>\r
+ sm2._wD(strings.globalHTML5);\r
+ // </d>\r
+\r
+ useGlobalHTML5Audio = true;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ // 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.\r
+\r
+ if (options) {\r
+\r
+ if (noURL && didDCLoaded && options.url !== _undefined) {\r
+ sm2.beginDelayedInit();\r
+ }\r
+\r
+ // special case 2: If lazy-loading SM2 (DOMContentLoaded has already happened) and user calls setup() with url: parameter, try to init ASAP.\r
+\r
+ if (!didDCLoaded && options.url !== _undefined && doc.readyState === 'complete') {\r
+ setTimeout(domContentLoaded, 1);\r
+ }\r
+\r
+ }\r
+\r
+ didSetup = true;\r
+\r
+ return sm2;\r
+\r
+ };\r
+\r
+ this.ok = function() {\r
+\r
+ return (needsFlash ? (didInit && !disabled) : (sm2.useHTML5Audio && sm2.hasHTML5));\r
+\r
+ };\r
+\r
+ this.supported = this.ok; // legacy\r
+\r
+ this.getMovie = function(smID) {\r
+\r
+ // safety net: some old browsers differ on SWF references, possibly related to ExternalInterface / flash version\r
+ return id(smID) || doc[smID] || window[smID];\r
+\r
+ };\r
+\r
+ /**\r
+ * Creates a SMSound sound object instance. Can also be overloaded, e.g., createSound('mySound', '/some.mp3');\r
+ *\r
+ * @param {object} oOptions Sound options (at minimum, url parameter is required.)\r
+ * @return {object} SMSound The new SMSound object.\r
+ */\r
+\r
+ this.createSound = function(oOptions, _url) {\r
+\r
+ var cs, cs_string, options, oSound = null;\r
+\r
+ // <d>\r
+ cs = sm + '.createSound(): ';\r
+ cs_string = cs + str(!didInit ? 'notReady' : 'notOK');\r
+ // </d>\r
+\r
+ if (!didInit || !sm2.ok()) {\r
+ complain(cs_string);\r
+ return false;\r
+ }\r
+\r
+ if (_url !== _undefined) {\r
+ // function overloading in JS! :) ... assume simple createSound(id, url) use case.\r
+ oOptions = {\r
+ 'id': oOptions,\r
+ 'url': _url\r
+ };\r
+ }\r
+\r
+ // inherit from defaultOptions\r
+ options = mixin(oOptions);\r
+\r
+ options.url = parseURL(options.url);\r
+\r
+ // generate an id, if needed.\r
+ if (options.id === _undefined) {\r
+ options.id = sm2.setupOptions.idPrefix + (idCounter++);\r
+ }\r
+\r
+ // <d>\r
+ if (options.id.toString().charAt(0).match(/^[0-9]$/)) {\r
+ sm2._wD(cs + str('badID', options.id), 2);\r
+ }\r
+\r
+ sm2._wD(cs + options.id + (options.url ? ' (' + options.url + ')' : ''), 1);\r
+ // </d>\r
+\r
+ if (idCheck(options.id, true)) {\r
+ sm2._wD(cs + options.id + ' exists', 1);\r
+ return sm2.sounds[options.id];\r
+ }\r
+\r
+ function make() {\r
+\r
+ options = loopFix(options);\r
+ sm2.sounds[options.id] = new SMSound(options);\r
+ sm2.soundIDs.push(options.id);\r
+ return sm2.sounds[options.id];\r
+\r
+ }\r
+\r
+ if (html5OK(options)) {\r
+\r
+ oSound = make();\r
+ // <d>\r
+ if (!sm2.html5Only) {\r
+ sm2._wD(options.id + ': Using HTML5');\r
+ }\r
+ // </d>\r
+ oSound._setup_html5(options);\r
+\r
+ } else {\r
+\r
+ if (sm2.html5Only) {\r
+ sm2._wD(options.id + ': No HTML5 support for this sound, and no Flash. Exiting.');\r
+ return make();\r
+ }\r
+\r
+ // TODO: Move HTML5/flash checks into generic URL parsing/handling function.\r
+\r
+ if (sm2.html5.usingFlash && options.url && options.url.match(/data\:/i)) {\r
+ // data: URIs not supported by Flash, either.\r
+ sm2._wD(options.id + ': data: URIs not supported via Flash. Exiting.');\r
+ return make();\r
+ }\r
+\r
+ if (fV > 8) {\r
+ if (options.isMovieStar === null) {\r
+ // attempt to detect MPEG-4 formats\r
+ options.isMovieStar = !!(options.serverURL || (options.type ? options.type.match(netStreamMimeTypes) : false) || (options.url && options.url.match(netStreamPattern)));\r
+ }\r
+ // <d>\r
+ if (options.isMovieStar) {\r
+ sm2._wD(cs + 'using MovieStar handling');\r
+ if (options.loops > 1) {\r
+ _wDS('noNSLoop');\r
+ }\r
+ }\r
+ // </d>\r
+ }\r
+\r
+ options = policyFix(options, cs);\r
+ oSound = make();\r
+\r
+ if (fV === 8) {\r
+ flash._createSound(options.id, options.loops || 1, options.usePolicyFile);\r
+ } else {\r
+ flash._createSound(options.id, options.url, options.usePeakData, options.useWaveformData, options.useEQData, options.isMovieStar, (options.isMovieStar ? options.bufferTime : false), options.loops || 1, options.serverURL, options.duration || null, options.autoPlay, true, options.autoLoad, options.usePolicyFile);\r
+ if (!options.serverURL) {\r
+ // We are connected immediately\r
+ oSound.connected = true;\r
+ if (options.onconnect) {\r
+ options.onconnect.apply(oSound);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!options.serverURL && (options.autoLoad || options.autoPlay)) {\r
+ // call load for non-rtmp streams\r
+ oSound.load(options);\r
+ }\r
+\r
+ }\r
+\r
+ // rtmp will play in onconnect\r
+ if (!options.serverURL && options.autoPlay) {\r
+ oSound.play();\r
+ }\r
+\r
+ return oSound;\r
+\r
+ };\r
+\r
+ /**\r
+ * Destroys a SMSound sound object instance.\r
+ *\r
+ * @param {string} sID The ID of the sound to destroy\r
+ */\r
+\r
+ this.destroySound = function(sID, _bFromSound) {\r
+\r
+ // explicitly destroy a sound before normal page unload, etc.\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+\r
+ var oS = sm2.sounds[sID], i;\r
+\r
+ oS.stop();\r
+ \r
+ // Disable all callbacks after stop(), when the sound is being destroyed\r
+ oS._iO = {};\r
+ \r
+ oS.unload();\r
+\r
+ for (i = 0; i < sm2.soundIDs.length; i++) {\r
+ if (sm2.soundIDs[i] === sID) {\r
+ sm2.soundIDs.splice(i, 1);\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!_bFromSound) {\r
+ // ignore if being called from SMSound instance\r
+ oS.destruct(true);\r
+ }\r
+\r
+ oS = null;\r
+ delete sm2.sounds[sID];\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the load() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {object} oOptions Optional: Sound options\r
+ */\r
+\r
+ this.load = function(sID, oOptions) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].load(oOptions);\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the unload() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ */\r
+\r
+ this.unload = function(sID) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].unload();\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the onPosition() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nPosition The position to watch for\r
+ * @param {function} oMethod The relevant callback to fire\r
+ * @param {object} oScope Optional: The scope to apply the callback to\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.onPosition = function(sID, nPosition, oMethod, oScope) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].onposition(nPosition, oMethod, oScope);\r
+\r
+ };\r
+\r
+ // legacy/backwards-compability: lower-case method name\r
+ this.onposition = this.onPosition;\r
+\r
+ /**\r
+ * Calls the clearOnPosition() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nPosition The position to watch for\r
+ * @param {function} oMethod Optional: The relevant callback to fire\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.clearOnPosition = function(sID, nPosition, oMethod) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].clearOnPosition(nPosition, oMethod);\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the play() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {object} oOptions Optional: Sound options\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.play = function(sID, oOptions) {\r
+\r
+ var result = null,\r
+ // legacy function-overloading use case: play('mySound', '/path/to/some.mp3');\r
+ overloaded = (oOptions && !(oOptions instanceof Object));\r
+\r
+ if (!didInit || !sm2.ok()) {\r
+ complain(sm + '.play(): ' + str(!didInit?'notReady':'notOK'));\r
+ return false;\r
+ }\r
+\r
+ if (!idCheck(sID, overloaded)) {\r
+\r
+ if (!overloaded) {\r
+ // no sound found for the given ID. Bail.\r
+ return false;\r
+ }\r
+\r
+ if (overloaded) {\r
+ oOptions = {\r
+ url: oOptions\r
+ };\r
+ }\r
+\r
+ if (oOptions && oOptions.url) {\r
+ // overloading use case, create+play: .play('someID', {url:'/path/to.mp3'});\r
+ sm2._wD(sm + '.play(): Attempting to create "' + sID + '"', 1);\r
+ oOptions.id = sID;\r
+ result = sm2.createSound(oOptions).play();\r
+ }\r
+\r
+ } else if (overloaded) {\r
+\r
+ // existing sound object case\r
+ oOptions = {\r
+ url: oOptions\r
+ };\r
+\r
+ }\r
+\r
+ if (result === null) {\r
+ // default case\r
+ result = sm2.sounds[sID].play(oOptions);\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ // just for convenience\r
+ this.start = this.play;\r
+\r
+ /**\r
+ * Calls the setPosition() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nMsecOffset Position (milliseconds)\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.setPosition = function(sID, nMsecOffset) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].setPosition(nMsecOffset);\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the stop() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.stop = function(sID) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+\r
+ sm2._wD(sm + '.stop(' + sID + ')', 1);\r
+ return sm2.sounds[sID].stop();\r
+\r
+ };\r
+\r
+ /**\r
+ * Stops all currently-playing sounds.\r
+ */\r
+\r
+ this.stopAll = function() {\r
+\r
+ var oSound;\r
+ sm2._wD(sm + '.stopAll()', 1);\r
+\r
+ for (oSound in sm2.sounds) {\r
+ if (sm2.sounds.hasOwnProperty(oSound)) {\r
+ // apply only to sound objects\r
+ sm2.sounds[oSound].stop();\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the pause() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.pause = function(sID) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].pause();\r
+\r
+ };\r
+\r
+ /**\r
+ * Pauses all currently-playing sounds.\r
+ */\r
+\r
+ this.pauseAll = function() {\r
+\r
+ var i;\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].pause();\r
+ }\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the resume() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.resume = function(sID) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].resume();\r
+\r
+ };\r
+\r
+ /**\r
+ * Resumes all currently-paused sounds.\r
+ */\r
+\r
+ this.resumeAll = function() {\r
+\r
+ var i;\r
+ for (i = sm2.soundIDs.length- 1 ; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].resume();\r
+ }\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the togglePause() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.togglePause = function(sID) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].togglePause();\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the setPan() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nPan The pan value (-100 to 100)\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.setPan = function(sID, nPan) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].setPan(nPan);\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the setVolume() method of a SMSound object by ID\r
+ * Overloaded case: pass only volume argument eg., setVolume(50) to apply to all sounds.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @param {number} nVol The volume value (0 to 100)\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.setVolume = function(sID, nVol) {\r
+\r
+ // setVolume(50) function overloading case - apply to all sounds\r
+\r
+ var i, j;\r
+\r
+ if (sID !== _undefined && !isNaN(sID) && nVol === _undefined) {\r
+ for (i = 0, j = sm2.soundIDs.length; i < j; i++) {\r
+ sm2.sounds[sm2.soundIDs[i]].setVolume(sID);\r
+ }\r
+ return;\r
+ }\r
+\r
+ // setVolume('mySound', 50) case\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+\r
+ return sm2.sounds[sID].setVolume(nVol);\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the mute() method of either a single SMSound object by ID, or all sound objects.\r
+ *\r
+ * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.)\r
+ */\r
+\r
+ this.mute = function(sID) {\r
+\r
+ var i = 0;\r
+\r
+ if (sID instanceof String) {\r
+ sID = null;\r
+ }\r
+\r
+ if (!sID) {\r
+\r
+ sm2._wD(sm + '.mute(): Muting all sounds');\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].mute();\r
+ }\r
+ sm2.muted = true;\r
+\r
+ } else {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ sm2._wD(sm + '.mute(): Muting "' + sID + '"');\r
+ return sm2.sounds[sID].mute();\r
+\r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ /**\r
+ * Mutes all sounds.\r
+ */\r
+\r
+ this.muteAll = function() {\r
+\r
+ sm2.mute();\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the unmute() method of either a single SMSound object by ID, or all sound objects.\r
+ *\r
+ * @param {string} sID Optional: The ID of the sound (if omitted, all sounds will be used.)\r
+ */\r
+\r
+ this.unmute = function(sID) {\r
+\r
+ var i;\r
+\r
+ if (sID instanceof String) {\r
+ sID = null;\r
+ }\r
+\r
+ if (!sID) {\r
+\r
+ sm2._wD(sm + '.unmute(): Unmuting all sounds');\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].unmute();\r
+ }\r
+ sm2.muted = false;\r
+\r
+ } else {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ sm2._wD(sm + '.unmute(): Unmuting "' + sID + '"');\r
+ return sm2.sounds[sID].unmute();\r
+\r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ /**\r
+ * Unmutes all sounds.\r
+ */\r
+\r
+ this.unmuteAll = function() {\r
+\r
+ sm2.unmute();\r
+\r
+ };\r
+\r
+ /**\r
+ * Calls the toggleMute() method of a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.toggleMute = function(sID) {\r
+\r
+ if (!idCheck(sID)) {\r
+ return false;\r
+ }\r
+ return sm2.sounds[sID].toggleMute();\r
+\r
+ };\r
+\r
+ /**\r
+ * Retrieves the memory used by the flash plugin.\r
+ *\r
+ * @return {number} The amount of memory in use\r
+ */\r
+\r
+ this.getMemoryUse = function() {\r
+\r
+ // flash-only\r
+ var ram = 0;\r
+\r
+ if (flash && fV !== 8) {\r
+ ram = parseInt(flash._getMemoryUse(), 10);\r
+ }\r
+\r
+ return ram;\r
+\r
+ };\r
+\r
+ /**\r
+ * Undocumented: NOPs soundManager and all SMSound objects.\r
+ */\r
+\r
+ this.disable = function(bNoDisable) {\r
+\r
+ // destroy all functions\r
+ var i;\r
+\r
+ if (bNoDisable === _undefined) {\r
+ bNoDisable = false;\r
+ }\r
+\r
+ if (disabled) {\r
+ return false;\r
+ }\r
+\r
+ disabled = true;\r
+ _wDS('shutdown', 1);\r
+\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+ disableObject(sm2.sounds[sm2.soundIDs[i]]);\r
+ }\r
+\r
+ // fire "complete", despite fail\r
+ initComplete(bNoDisable);\r
+ event.remove(window, 'load', initUserOnload);\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ /**\r
+ * Determines playability of a MIME type, eg. 'audio/mp3'.\r
+ */\r
+\r
+ this.canPlayMIME = function(sMIME) {\r
+\r
+ var result;\r
+\r
+ if (sm2.hasHTML5) {\r
+ result = html5CanPlay({\r
+ type: sMIME\r
+ });\r
+ }\r
+\r
+ if (!result && needsFlash) {\r
+ // if flash 9, test netStream (movieStar) types as well.\r
+ result = (sMIME && sm2.ok() ? !!((fV > 8 ? sMIME.match(netStreamMimeTypes) : null) || sMIME.match(sm2.mimePattern)) : null); // TODO: make less "weird" (per JSLint)\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ /**\r
+ * Determines playability of a URL based on audio support.\r
+ *\r
+ * @param {string} sURL The URL to test\r
+ * @return {boolean} URL playability\r
+ */\r
+\r
+ this.canPlayURL = function(sURL) {\r
+\r
+ var result;\r
+\r
+ if (sm2.hasHTML5) {\r
+ result = html5CanPlay({\r
+ url: sURL\r
+ });\r
+ }\r
+\r
+ if (!result && needsFlash) {\r
+ result = (sURL && sm2.ok() ? !!(sURL.match(sm2.filePattern)) : null);\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ /**\r
+ * Determines playability of an HTML DOM <a> object (or similar object literal) based on audio support.\r
+ *\r
+ * @param {object} oLink an HTML DOM <a> object or object literal including href and/or type attributes\r
+ * @return {boolean} URL playability\r
+ */\r
+\r
+ this.canPlayLink = function(oLink) {\r
+\r
+ if (oLink.type !== _undefined && oLink.type) {\r
+ if (sm2.canPlayMIME(oLink.type)) {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ return sm2.canPlayURL(oLink.href);\r
+\r
+ };\r
+\r
+ /**\r
+ * Retrieves a SMSound object by ID.\r
+ *\r
+ * @param {string} sID The ID of the sound\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.getSoundById = function(sID, _suppressDebug) {\r
+\r
+ if (!sID) {\r
+ return null;\r
+ }\r
+\r
+ var result = sm2.sounds[sID];\r
+\r
+ // <d>\r
+ if (!result && !_suppressDebug) {\r
+ sm2._wD(sm + '.getSoundById(): Sound "' + sID + '" not found.', 2);\r
+ }\r
+ // </d>\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ /**\r
+ * Queues a callback for execution when SoundManager has successfully initialized.\r
+ *\r
+ * @param {function} oMethod The callback method to fire\r
+ * @param {object} oScope Optional: The scope to apply to the callback\r
+ */\r
+\r
+ this.onready = function(oMethod, oScope) {\r
+\r
+ var sType = 'onready',\r
+ result = false;\r
+\r
+ if (typeof oMethod === 'function') {\r
+\r
+ // <d>\r
+ if (didInit) {\r
+ sm2._wD(str('queue', sType));\r
+ }\r
+ // </d>\r
+\r
+ if (!oScope) {\r
+ oScope = window;\r
+ }\r
+\r
+ addOnEvent(sType, oMethod, oScope);\r
+ processOnEvents();\r
+\r
+ result = true;\r
+\r
+ } else {\r
+\r
+ throw str('needFunction', sType);\r
+\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ /**\r
+ * Queues a callback for execution when SoundManager has failed to initialize.\r
+ *\r
+ * @param {function} oMethod The callback method to fire\r
+ * @param {object} oScope Optional: The scope to apply to the callback\r
+ */\r
+\r
+ this.ontimeout = function(oMethod, oScope) {\r
+\r
+ var sType = 'ontimeout',\r
+ result = false;\r
+\r
+ if (typeof oMethod === 'function') {\r
+\r
+ // <d>\r
+ if (didInit) {\r
+ sm2._wD(str('queue', sType));\r
+ }\r
+ // </d>\r
+\r
+ if (!oScope) {\r
+ oScope = window;\r
+ }\r
+\r
+ addOnEvent(sType, oMethod, oScope);\r
+ processOnEvents({type:sType});\r
+\r
+ result = true;\r
+\r
+ } else {\r
+\r
+ throw str('needFunction', sType);\r
+\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ /**\r
+ * Writes console.log()-style debug output to a console or in-browser element.\r
+ * Applies when debugMode = true\r
+ *\r
+ * @param {string} sText The console message\r
+ * @param {object} nType Optional log level (number), or object. Number case: Log type/style where 0 = 'info', 1 = 'warn', 2 = 'error'. Object case: Object to be dumped.\r
+ */\r
+\r
+ this._writeDebug = function(sText, sTypeOrObject) {\r
+\r
+ // pseudo-private console.log()-style output\r
+ // <d>\r
+\r
+ var sDID = 'soundmanager-debug', o, oItem;\r
+\r
+ if (!sm2.setupOptions.debugMode) {\r
+ return false;\r
+ }\r
+\r
+ if (hasConsole && sm2.useConsole) {\r
+ if (sTypeOrObject && typeof sTypeOrObject === 'object') {\r
+ // object passed; dump to console.\r
+ console.log(sText, sTypeOrObject);\r
+ } else if (debugLevels[sTypeOrObject] !== _undefined) {\r
+ console[debugLevels[sTypeOrObject]](sText);\r
+ } else {\r
+ console.log(sText);\r
+ }\r
+ if (sm2.consoleOnly) {\r
+ return true;\r
+ }\r
+ }\r
+\r
+ o = id(sDID);\r
+\r
+ if (!o) {\r
+ return false;\r
+ }\r
+\r
+ oItem = doc.createElement('div');\r
+\r
+ if (++wdCount % 2 === 0) {\r
+ oItem.className = 'sm2-alt';\r
+ }\r
+\r
+ if (sTypeOrObject === _undefined) {\r
+ sTypeOrObject = 0;\r
+ } else {\r
+ sTypeOrObject = parseInt(sTypeOrObject, 10);\r
+ }\r
+\r
+ oItem.appendChild(doc.createTextNode(sText));\r
+\r
+ if (sTypeOrObject) {\r
+ if (sTypeOrObject >= 2) {\r
+ oItem.style.fontWeight = 'bold';\r
+ }\r
+ if (sTypeOrObject === 3) {\r
+ oItem.style.color = '#ff3333';\r
+ }\r
+ }\r
+\r
+ // top-to-bottom\r
+ // o.appendChild(oItem);\r
+\r
+ // bottom-to-top\r
+ o.insertBefore(oItem, o.firstChild);\r
+\r
+ o = null;\r
+ // </d>\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ // <d>\r
+ // last-resort debugging option\r
+ if (wl.indexOf('sm2-debug=alert') !== -1) {\r
+ this._writeDebug = function(sText) {\r
+ window.alert(sText);\r
+ };\r
+ }\r
+ // </d>\r
+\r
+ // alias\r
+ this._wD = this._writeDebug;\r
+\r
+ /**\r
+ * Provides debug / state information on all SMSound objects.\r
+ */\r
+\r
+ this._debug = function() {\r
+\r
+ // <d>\r
+ var i, j;\r
+ _wDS('currentObj', 1);\r
+\r
+ for (i = 0, j = sm2.soundIDs.length; i < j; i++) {\r
+ sm2.sounds[sm2.soundIDs[i]]._debug();\r
+ }\r
+ // </d>\r
+\r
+ };\r
+\r
+ /**\r
+ * Restarts and re-initializes the SoundManager instance.\r
+ *\r
+ * @param {boolean} resetEvents Optional: When true, removes all registered onready and ontimeout event callbacks.\r
+ * @param {boolean} excludeInit Options: When true, does not call beginDelayedInit() (which would restart SM2).\r
+ * @return {object} soundManager The soundManager instance.\r
+ */\r
+\r
+ this.reboot = function(resetEvents, excludeInit) {\r
+\r
+ // reset some (or all) state, and re-init unless otherwise specified.\r
+\r
+ // <d>\r
+ if (sm2.soundIDs.length) {\r
+ sm2._wD('Destroying ' + sm2.soundIDs.length + ' SMSound object' + (sm2.soundIDs.length !== 1 ? 's' : '') + '...');\r
+ }\r
+ // </d>\r
+\r
+ var i, j, k;\r
+\r
+ for (i = sm2.soundIDs.length- 1 ; i >= 0; i--) {\r
+ sm2.sounds[sm2.soundIDs[i]].destruct();\r
+ }\r
+\r
+ // trash ze flash (remove from the DOM)\r
+\r
+ if (flash) {\r
+\r
+ try {\r
+\r
+ if (isIE) {\r
+ oRemovedHTML = flash.innerHTML;\r
+ }\r
+\r
+ oRemoved = flash.parentNode.removeChild(flash);\r
+\r
+ } catch(e) {\r
+\r
+ // Remove failed? May be due to flash blockers silently removing the SWF object/embed node from the DOM. Warn and continue.\r
+\r
+ _wDS('badRemove', 2);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ // actually, force recreate of movie.\r
+\r
+ oRemovedHTML = oRemoved = needsFlash = flash = null;\r
+\r
+ sm2.enabled = didDCLoaded = didInit = waitingForEI = initPending = didAppend = appendSuccess = disabled = useGlobalHTML5Audio = sm2.swfLoaded = false;\r
+\r
+ sm2.soundIDs = [];\r
+ sm2.sounds = {};\r
+\r
+ idCounter = 0;\r
+ didSetup = false;\r
+\r
+ if (!resetEvents) {\r
+ // reset callbacks for onready, ontimeout etc. so that they will fire again on re-init\r
+ for (i in on_queue) {\r
+ if (on_queue.hasOwnProperty(i)) {\r
+ for (j = 0, k = on_queue[i].length; j < k; j++) {\r
+ on_queue[i][j].fired = false;\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ // remove all callbacks entirely\r
+ on_queue = [];\r
+ }\r
+\r
+ // <d>\r
+ if (!excludeInit) {\r
+ sm2._wD(sm + ': Rebooting...');\r
+ }\r
+ // </d>\r
+\r
+ // reset HTML5 and flash canPlay test results\r
+\r
+ sm2.html5 = {\r
+ 'usingFlash': null\r
+ };\r
+\r
+ sm2.flash = {};\r
+\r
+ // reset device-specific HTML/flash mode switches\r
+\r
+ sm2.html5Only = false;\r
+ sm2.ignoreFlash = false;\r
+\r
+ window.setTimeout(function() {\r
+\r
+ // by default, re-init\r
+\r
+ if (!excludeInit) {\r
+ sm2.beginDelayedInit();\r
+ }\r
+\r
+ }, 20);\r
+\r
+ return sm2;\r
+\r
+ };\r
+\r
+ this.reset = function() {\r
+\r
+ /**\r
+ * Shuts down and restores the SoundManager instance to its original loaded state, without an explicit reboot. All onready/ontimeout handlers are removed.\r
+ * After this call, SM2 may be re-initialized via soundManager.beginDelayedInit().\r
+ * @return {object} soundManager The soundManager instance.\r
+ */\r
+\r
+ _wDS('reset');\r
+ return sm2.reboot(true, true);\r
+\r
+ };\r
+\r
+ /**\r
+ * Undocumented: Determines the SM2 flash movie's load progress.\r
+ *\r
+ * @return {number or null} Percent loaded, or if invalid/unsupported, null.\r
+ */\r
+\r
+ this.getMoviePercent = function() {\r
+\r
+ /**\r
+ * Interesting syntax notes...\r
+ * Flash/ExternalInterface (ActiveX/NPAPI) bridge methods are not typeof "function" nor instanceof Function, but are still valid.\r
+ * Additionally, JSLint dislikes ('PercentLoaded' in flash)-style syntax and recommends hasOwnProperty(), which does not work in this case.\r
+ * Furthermore, using (flash && flash.PercentLoaded) causes IE to throw "object doesn't support this property or method".\r
+ * Thus, 'in' syntax must be used.\r
+ */\r
+\r
+ return (flash && 'PercentLoaded' in flash ? flash.PercentLoaded() : null); // Yes, JSLint. See nearby comment in source for explanation.\r
+\r
+ };\r
+\r
+ /**\r
+ * Additional helper for manually invoking SM2's init process after DOM Ready / window.onload().\r
+ */\r
+\r
+ this.beginDelayedInit = function() {\r
+\r
+ windowLoaded = true;\r
+ domContentLoaded();\r
+\r
+ setTimeout(function() {\r
+\r
+ if (initPending) {\r
+ return false;\r
+ }\r
+\r
+ createMovie();\r
+ initMovie();\r
+ initPending = true;\r
+\r
+ return true;\r
+\r
+ }, 20);\r
+\r
+ delayWaitForEI();\r
+\r
+ };\r
+\r
+ /**\r
+ * Destroys the SoundManager instance and all SMSound instances.\r
+ */\r
+\r
+ this.destruct = function() {\r
+\r
+ sm2._wD(sm + '.destruct()');\r
+ sm2.disable(true);\r
+\r
+ };\r
+\r
+ /**\r
+ * SMSound() (sound object) constructor\r
+ * ------------------------------------\r
+ *\r
+ * @param {object} oOptions Sound options (id and url are required attributes)\r
+ * @return {SMSound} The new SMSound object\r
+ */\r
+\r
+ SMSound = function(oOptions) {\r
+\r
+ var s = 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, urlOmitted;\r
+\r
+ lastHTML5State = {\r
+ // tracks duration + position (time)\r
+ duration: null,\r
+ time: null\r
+ };\r
+\r
+ this.id = oOptions.id;\r
+\r
+ // legacy\r
+ this.sID = this.id;\r
+\r
+ this.url = oOptions.url;\r
+ this.options = mixin(oOptions);\r
+\r
+ // per-play-instance-specific options\r
+ this.instanceOptions = this.options;\r
+\r
+ // short alias\r
+ this._iO = this.instanceOptions;\r
+\r
+ // assign property defaults\r
+ this.pan = this.options.pan;\r
+ this.volume = this.options.volume;\r
+\r
+ // whether or not this object is using HTML5\r
+ this.isHTML5 = false;\r
+\r
+ // internal HTML5 Audio() object reference\r
+ this._a = null;\r
+\r
+ // for flash 8 special-case createSound() without url, followed by load/play with url case\r
+ urlOmitted = (this.url ? false : true);\r
+\r
+ /**\r
+ * SMSound() public methods\r
+ * ------------------------\r
+ */\r
+\r
+ this.id3 = {};\r
+\r
+ /**\r
+ * Writes SMSound object parameters to debug console\r
+ */\r
+\r
+ this._debug = function() {\r
+\r
+ // <d>\r
+ sm2._wD(s.id + ': Merged options:', s.options);\r
+ // </d>\r
+\r
+ };\r
+\r
+ /**\r
+ * Begins loading a sound per its *url*.\r
+ *\r
+ * @param {object} oOptions Optional: Sound options\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.load = function(oOptions) {\r
+\r
+ var oSound = null, instanceOptions;\r
+\r
+ if (oOptions !== _undefined) {\r
+ s._iO = mixin(oOptions, s.options);\r
+ } else {\r
+ oOptions = s.options;\r
+ s._iO = oOptions;\r
+ if (lastURL && lastURL !== s.url) {\r
+ _wDS('manURL');\r
+ s._iO.url = s.url;\r
+ s.url = null;\r
+ }\r
+ }\r
+\r
+ if (!s._iO.url) {\r
+ s._iO.url = s.url;\r
+ }\r
+\r
+ s._iO.url = parseURL(s._iO.url);\r
+\r
+ // ensure we're in sync\r
+ s.instanceOptions = s._iO;\r
+\r
+ // local shortcut\r
+ instanceOptions = s._iO;\r
+\r
+ sm2._wD(s.id + ': load (' + instanceOptions.url + ')');\r
+\r
+ if (!instanceOptions.url && !s.url) {\r
+ sm2._wD(s.id + ': load(): url is unassigned. Exiting.', 2);\r
+ return s;\r
+ }\r
+\r
+ // <d>\r
+ if (!s.isHTML5 && fV === 8 && !s.url && !instanceOptions.autoPlay) {\r
+ // flash 8 load() -> play() won't work before onload has fired.\r
+ sm2._wD(s.id + ': Flash 8 load() limitation: Wait for onload() before calling play().', 1);\r
+ }\r
+ // </d>\r
+\r
+ if (instanceOptions.url === s.url && s.readyState !== 0 && s.readyState !== 2) {\r
+ _wDS('onURL', 1);\r
+ // if loaded and an onload() exists, fire immediately.\r
+ if (s.readyState === 3 && instanceOptions.onload) {\r
+ // assume success based on truthy duration.\r
+ wrapCallback(s, function() {\r
+ instanceOptions.onload.apply(s, [(!!s.duration)]);\r
+ });\r
+ }\r
+ return s;\r
+ }\r
+\r
+ // reset a few state properties\r
+\r
+ s.loaded = false;\r
+ s.readyState = 1;\r
+ s.playState = 0;\r
+ s.id3 = {};\r
+\r
+ // TODO: If switching from HTML5 -> flash (or vice versa), stop currently-playing audio.\r
+\r
+ if (html5OK(instanceOptions)) {\r
+\r
+ oSound = s._setup_html5(instanceOptions);\r
+\r
+ if (!oSound._called_load) {\r
+\r
+ s._html5_canplay = false;\r
+\r
+ // TODO: review called_load / html5_canplay logic\r
+\r
+ // if url provided directly to load(), assign it here.\r
+\r
+ if (s.url !== instanceOptions.url) {\r
+\r
+ sm2._wD(_wDS('manURL') + ': ' + instanceOptions.url);\r
+\r
+ s._a.src = instanceOptions.url;\r
+\r
+ // TODO: review / re-apply all relevant options (volume, loop, onposition etc.)\r
+\r
+ // reset position for new URL\r
+ s.setPosition(0);\r
+\r
+ }\r
+\r
+ // given explicit load call, try to preload.\r
+\r
+ // early HTML5 implementation (non-standard)\r
+ s._a.autobuffer = 'auto';\r
+\r
+ // standard property, values: none / metadata / auto\r
+ // reference: http://msdn.microsoft.com/en-us/library/ie/ff974759%28v=vs.85%29.aspx\r
+ s._a.preload = 'auto';\r
+\r
+ s._a._called_load = true;\r
+\r
+ } else {\r
+\r
+ sm2._wD(s.id + ': Ignoring request to load again');\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ if (sm2.html5Only) {\r
+ sm2._wD(s.id + ': No flash support. Exiting.');\r
+ return s;\r
+ }\r
+\r
+ if (s._iO.url && s._iO.url.match(/data\:/i)) {\r
+ // data: URIs not supported by Flash, either.\r
+ sm2._wD(s.id + ': data: URIs not supported via Flash. Exiting.');\r
+ return s;\r
+ }\r
+\r
+ try {\r
+ s.isHTML5 = false;\r
+ s._iO = policyFix(loopFix(instanceOptions));\r
+ // if we have "position", disable auto-play as we'll be seeking to that position at onload().\r
+ if (s._iO.autoPlay && (s._iO.position || s._iO.from)) {\r
+ sm2._wD(s.id + ': Disabling autoPlay because of non-zero offset case');\r
+ s._iO.autoPlay = false;\r
+ }\r
+ // re-assign local shortcut\r
+ instanceOptions = s._iO;\r
+ if (fV === 8) {\r
+ flash._load(s.id, instanceOptions.url, instanceOptions.stream, instanceOptions.autoPlay, instanceOptions.usePolicyFile);\r
+ } else {\r
+ flash._load(s.id, instanceOptions.url, !!(instanceOptions.stream), !!(instanceOptions.autoPlay), instanceOptions.loops || 1, !!(instanceOptions.autoLoad), instanceOptions.usePolicyFile);\r
+ }\r
+ } catch(e) {\r
+ _wDS('smError', 2);\r
+ debugTS('onload', false);\r
+ catchError({\r
+ type: 'SMSOUND_LOAD_JS_EXCEPTION',\r
+ fatal: true\r
+ });\r
+ }\r
+\r
+ }\r
+\r
+ // after all of this, ensure sound url is up to date.\r
+ s.url = instanceOptions.url;\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Unloads a sound, canceling any open HTTP requests.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.unload = function() {\r
+\r
+ // Flash 8/AS2 can't "close" a stream - fake it by loading an empty URL\r
+ // Flash 9/AS3: Close stream, preventing further load\r
+ // HTML5: Most UAs will use empty URL\r
+\r
+ if (s.readyState !== 0) {\r
+\r
+ sm2._wD(s.id + ': unload()');\r
+\r
+ if (!s.isHTML5) {\r
+\r
+ if (fV === 8) {\r
+ flash._unload(s.id, emptyURL);\r
+ } else {\r
+ flash._unload(s.id);\r
+ }\r
+\r
+ } else {\r
+\r
+ stop_html5_timer();\r
+\r
+ if (s._a) {\r
+\r
+ s._a.pause();\r
+\r
+ // update empty URL, too\r
+ lastURL = html5Unload(s._a);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ // reset load/status flags\r
+ resetProperties();\r
+\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Unloads and destroys a sound.\r
+ */\r
+\r
+ this.destruct = function(_bFromSM) {\r
+\r
+ sm2._wD(s.id + ': Destruct');\r
+\r
+ if (!s.isHTML5) {\r
+\r
+ // kill sound within Flash\r
+ // Disable the onfailure handler\r
+ s._iO.onfailure = null;\r
+ flash._destroySound(s.id);\r
+\r
+ } else {\r
+\r
+ stop_html5_timer();\r
+\r
+ if (s._a) {\r
+ s._a.pause();\r
+ html5Unload(s._a);\r
+ if (!useGlobalHTML5Audio) {\r
+ remove_html5_events();\r
+ }\r
+ // break obvious circular reference\r
+ s._a._s = null;\r
+ s._a = null;\r
+ }\r
+\r
+ }\r
+\r
+ if (!_bFromSM) {\r
+ // ensure deletion from controller\r
+ sm2.destroySound(s.id, true);\r
+ }\r
+\r
+ };\r
+\r
+ /**\r
+ * Begins playing a sound.\r
+ *\r
+ * @param {object} oOptions Optional: Sound options\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.play = function(oOptions, _updatePlayState) {\r
+\r
+ var fN, allowMulti, a, onready,\r
+ audioClone, onended, oncanplay,\r
+ startOK = true,\r
+ exit = null;\r
+\r
+ // <d>\r
+ fN = s.id + ': play(): ';\r
+ // </d>\r
+\r
+ // default to true\r
+ _updatePlayState = (_updatePlayState === _undefined ? true : _updatePlayState);\r
+\r
+ if (!oOptions) {\r
+ oOptions = {};\r
+ }\r
+\r
+ // first, use local URL (if specified)\r
+ if (s.url) {\r
+ s._iO.url = s.url;\r
+ }\r
+\r
+ // mix in any options defined at createSound()\r
+ s._iO = mixin(s._iO, s.options);\r
+\r
+ // mix in any options specific to this method\r
+ s._iO = mixin(oOptions, s._iO);\r
+\r
+ s._iO.url = parseURL(s._iO.url);\r
+\r
+ s.instanceOptions = s._iO;\r
+\r
+ // RTMP-only\r
+ if (!s.isHTML5 && s._iO.serverURL && !s.connected) {\r
+ if (!s.getAutoPlay()) {\r
+ sm2._wD(fN +' Netstream not connected yet - setting autoPlay');\r
+ s.setAutoPlay(true);\r
+ }\r
+ // play will be called in onconnect()\r
+ return s;\r
+ }\r
+\r
+ if (html5OK(s._iO)) {\r
+ s._setup_html5(s._iO);\r
+ start_html5_timer();\r
+ }\r
+\r
+ if (s.playState === 1 && !s.paused) {\r
+\r
+ allowMulti = s._iO.multiShot;\r
+\r
+ if (!allowMulti) {\r
+\r
+ sm2._wD(fN + 'Already playing (one-shot)', 1);\r
+\r
+ if (s.isHTML5) {\r
+ // go back to original position.\r
+ s.setPosition(s._iO.position);\r
+ }\r
+\r
+ exit = s;\r
+\r
+ } else {\r
+ sm2._wD(fN + 'Already playing (multi-shot)', 1);\r
+ }\r
+\r
+ }\r
+\r
+ if (exit !== null) {\r
+ return exit;\r
+ }\r
+\r
+ // edge case: play() with explicit URL parameter\r
+ if (oOptions.url && oOptions.url !== s.url) {\r
+\r
+ // special case for createSound() followed by load() / play() with url; avoid double-load case.\r
+ if (!s.readyState && !s.isHTML5 && fV === 8 && urlOmitted) {\r
+\r
+ urlOmitted = false;\r
+\r
+ } else {\r
+\r
+ // load using merged options\r
+ s.load(s._iO);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ if (!s.loaded) {\r
+\r
+ if (s.readyState === 0) {\r
+\r
+ sm2._wD(fN + 'Attempting to load');\r
+\r
+ // try to get this sound playing ASAP\r
+ if (!s.isHTML5 && !sm2.html5Only) {\r
+\r
+ // flash: assign directly because setAutoPlay() increments the instanceCount\r
+ s._iO.autoPlay = true;\r
+ s.load(s._iO);\r
+\r
+ } else if (s.isHTML5) {\r
+\r
+ // iOS needs this when recycling sounds, loading a new URL on an existing object.\r
+ s.load(s._iO);\r
+\r
+ } else {\r
+\r
+ sm2._wD(fN + 'Unsupported type. Exiting.');\r
+ exit = s;\r
+\r
+ }\r
+\r
+ // HTML5 hack - re-set instanceOptions?\r
+ s.instanceOptions = s._iO;\r
+\r
+ } else if (s.readyState === 2) {\r
+\r
+ sm2._wD(fN + 'Could not load - exiting', 2);\r
+ exit = s;\r
+\r
+ } else {\r
+\r
+ sm2._wD(fN + 'Loading - attempting to play...');\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ // "play()"\r
+ sm2._wD(fN.substr(0, fN.lastIndexOf(':')));\r
+\r
+ }\r
+\r
+ if (exit !== null) {\r
+ return exit;\r
+ }\r
+\r
+ if (!s.isHTML5 && fV === 9 && s.position > 0 && s.position === s.duration) {\r
+ // flash 9 needs a position reset if play() is called while at the end of a sound.\r
+ sm2._wD(fN + 'Sound at end, resetting to position: 0');\r
+ oOptions.position = 0;\r
+ }\r
+\r
+ /**\r
+ * Streams will pause when their buffer is full if they are being loaded.\r
+ * In this case paused is true, but the song hasn't started playing yet.\r
+ * If we just call resume() the onplay() callback will never be called.\r
+ * So only call resume() if the position is > 0.\r
+ * Another reason is because options like volume won't have been applied yet.\r
+ * For normal sounds, just resume.\r
+ */\r
+\r
+ if (s.paused && s.position >= 0 && (!s._iO.serverURL || s.position > 0)) {\r
+\r
+ // https://gist.github.com/37b17df75cc4d7a90bf6\r
+ sm2._wD(fN + 'Resuming from paused state', 1);\r
+ s.resume();\r
+\r
+ } else {\r
+\r
+ s._iO = mixin(oOptions, s._iO);\r
+\r
+ /**\r
+ * Preload in the event of play() with position under Flash,\r
+ * or from/to parameters and non-RTMP case\r
+ */\r
+ if (((!s.isHTML5 && s._iO.position !== null && s._iO.position > 0) || (s._iO.from !== null && s._iO.from > 0) || s._iO.to !== null) && s.instanceCount === 0 && s.playState === 0 && !s._iO.serverURL) {\r
+\r
+ onready = function() {\r
+ // sound "canplay" or onload()\r
+ // re-apply position/from/to to instance options, and start playback\r
+ s._iO = mixin(oOptions, s._iO);\r
+ s.play(s._iO);\r
+ };\r
+\r
+ // HTML5 needs to at least have "canplay" fired before seeking.\r
+ if (s.isHTML5 && !s._html5_canplay) {\r
+\r
+ // this hasn't been loaded yet. load it first, and then do this again.\r
+ sm2._wD(fN + 'Beginning load for non-zero offset case');\r
+\r
+ s.load({\r
+ // note: custom HTML5-only event added for from/to implementation.\r
+ _oncanplay: onready\r
+ });\r
+\r
+ exit = false;\r
+\r
+ } else if (!s.isHTML5 && !s.loaded && (!s.readyState || s.readyState !== 2)) {\r
+\r
+ // to be safe, preload the whole thing in Flash.\r
+\r
+ sm2._wD(fN + 'Preloading for non-zero offset case');\r
+\r
+ s.load({\r
+ onload: onready\r
+ });\r
+\r
+ exit = false;\r
+\r
+ }\r
+\r
+ if (exit !== null) {\r
+ return exit;\r
+ }\r
+\r
+ // otherwise, we're ready to go. re-apply local options, and continue\r
+\r
+ s._iO = applyFromTo();\r
+\r
+ }\r
+\r
+ // sm2._wD(fN + 'Starting to play');\r
+\r
+ // increment instance counter, where enabled + supported\r
+ if (!s.instanceCount || s._iO.multiShotEvents || (s.isHTML5 && s._iO.multiShot && !useGlobalHTML5Audio) || (!s.isHTML5 && fV > 8 && !s.getAutoPlay())) {\r
+ s.instanceCount++;\r
+ }\r
+\r
+ // if first play and onposition parameters exist, apply them now\r
+ if (s._iO.onposition && s.playState === 0) {\r
+ attachOnPosition(s);\r
+ }\r
+\r
+ s.playState = 1;\r
+ s.paused = false;\r
+\r
+ s.position = (s._iO.position !== _undefined && !isNaN(s._iO.position) ? s._iO.position : 0);\r
+\r
+ if (!s.isHTML5) {\r
+ s._iO = policyFix(loopFix(s._iO));\r
+ }\r
+\r
+ if (s._iO.onplay && _updatePlayState) {\r
+ s._iO.onplay.apply(s);\r
+ onplay_called = true;\r
+ }\r
+\r
+ s.setVolume(s._iO.volume, true);\r
+ s.setPan(s._iO.pan, true);\r
+\r
+ if (!s.isHTML5) {\r
+\r
+ startOK = flash._start(s.id, s._iO.loops || 1, (fV === 9 ? s.position : s.position / msecScale), s._iO.multiShot || false);\r
+\r
+ if (fV === 9 && !startOK) {\r
+ // edge case: no sound hardware, or 32-channel flash ceiling hit.\r
+ // applies only to Flash 9, non-NetStream/MovieStar sounds.\r
+ // http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29\r
+ sm2._wD(fN + 'No sound hardware, or 32-sound ceiling hit', 2);\r
+ if (s._iO.onplayerror) {\r
+ s._iO.onplayerror.apply(s);\r
+ }\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ if (s.instanceCount < 2) {\r
+\r
+ // HTML5 single-instance case\r
+\r
+ start_html5_timer();\r
+\r
+ a = s._setup_html5();\r
+\r
+ s.setPosition(s._iO.position);\r
+\r
+ a.play();\r
+\r
+ } else {\r
+\r
+ // HTML5 multi-shot case\r
+\r
+ sm2._wD(s.id + ': Cloning Audio() for instance #' + s.instanceCount + '...');\r
+\r
+ audioClone = new Audio(s._iO.url);\r
+\r
+ onended = function() {\r
+ event.remove(audioClone, 'ended', onended);\r
+ s._onfinish(s);\r
+ // cleanup\r
+ html5Unload(audioClone);\r
+ audioClone = null;\r
+ };\r
+\r
+ oncanplay = function() {\r
+ event.remove(audioClone, 'canplay', oncanplay);\r
+ try {\r
+ audioClone.currentTime = s._iO.position/msecScale;\r
+ } catch(err) {\r
+ complain(s.id + ': multiShot play() failed to apply position of ' + (s._iO.position/msecScale));\r
+ }\r
+ audioClone.play();\r
+ };\r
+\r
+ event.add(audioClone, 'ended', onended);\r
+\r
+ // apply volume to clones, too\r
+ if (s._iO.volume !== _undefined) {\r
+ audioClone.volume = Math.max(0, Math.min(1, s._iO.volume/100));\r
+ }\r
+\r
+ // playing multiple muted sounds? if you do this, you're weird ;) - but let's cover it.\r
+ if (s.muted) {\r
+ audioClone.muted = true;\r
+ }\r
+\r
+ if (s._iO.position) {\r
+ // HTML5 audio can't seek before onplay() event has fired.\r
+ // wait for canplay, then seek to position and start playback.\r
+ event.add(audioClone, 'canplay', oncanplay);\r
+ } else {\r
+ // begin playback at currentTime: 0\r
+ audioClone.play();\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ // just for convenience\r
+ this.start = this.play;\r
+\r
+ /**\r
+ * Stops playing a sound (and optionally, all sounds)\r
+ *\r
+ * @param {boolean} bAll Optional: Whether to stop all sounds\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.stop = function(bAll) {\r
+\r
+ var instanceOptions = s._iO,\r
+ originalPosition;\r
+\r
+ if (s.playState === 1) {\r
+\r
+ sm2._wD(s.id + ': stop()');\r
+\r
+ s._onbufferchange(0);\r
+ s._resetOnPosition(0);\r
+ s.paused = false;\r
+\r
+ if (!s.isHTML5) {\r
+ s.playState = 0;\r
+ }\r
+\r
+ // remove onPosition listeners, if any\r
+ detachOnPosition();\r
+\r
+ // and "to" position, if set\r
+ if (instanceOptions.to) {\r
+ s.clearOnPosition(instanceOptions.to);\r
+ }\r
+\r
+ if (!s.isHTML5) {\r
+\r
+ flash._stop(s.id, bAll);\r
+\r
+ // hack for netStream: just unload\r
+ if (instanceOptions.serverURL) {\r
+ s.unload();\r
+ }\r
+\r
+ } else {\r
+\r
+ if (s._a) {\r
+\r
+ originalPosition = s.position;\r
+\r
+ // act like Flash, though\r
+ s.setPosition(0);\r
+\r
+ // hack: reflect old position for onstop() (also like Flash)\r
+ s.position = originalPosition;\r
+\r
+ // html5 has no stop()\r
+ // NOTE: pausing means iOS requires interaction to resume.\r
+ s._a.pause();\r
+\r
+ s.playState = 0;\r
+\r
+ // and update UI\r
+ s._onTimer();\r
+\r
+ stop_html5_timer();\r
+\r
+ }\r
+\r
+ }\r
+\r
+ s.instanceCount = 0;\r
+ s._iO = {};\r
+\r
+ if (instanceOptions.onstop) {\r
+ instanceOptions.onstop.apply(s);\r
+ }\r
+\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Undocumented/internal: Sets autoPlay for RTMP.\r
+ *\r
+ * @param {boolean} autoPlay state\r
+ */\r
+\r
+ this.setAutoPlay = function(autoPlay) {\r
+\r
+ sm2._wD(s.id + ': Autoplay turned ' + (autoPlay ? 'on' : 'off'));\r
+ s._iO.autoPlay = autoPlay;\r
+\r
+ if (!s.isHTML5) {\r
+ flash._setAutoPlay(s.id, autoPlay);\r
+ if (autoPlay) {\r
+ // only increment the instanceCount if the sound isn't loaded (TODO: verify RTMP)\r
+ if (!s.instanceCount && s.readyState === 1) {\r
+ s.instanceCount++;\r
+ sm2._wD(s.id + ': Incremented instance count to '+s.instanceCount);\r
+ }\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ /**\r
+ * Undocumented/internal: Returns the autoPlay boolean.\r
+ *\r
+ * @return {boolean} The current autoPlay value\r
+ */\r
+\r
+ this.getAutoPlay = function() {\r
+\r
+ return s._iO.autoPlay;\r
+\r
+ };\r
+\r
+ /**\r
+ * Sets the position of a sound.\r
+ *\r
+ * @param {number} nMsecOffset Position (milliseconds)\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.setPosition = function(nMsecOffset) {\r
+\r
+ if (nMsecOffset === _undefined) {\r
+ nMsecOffset = 0;\r
+ }\r
+\r
+ var position, position1K,\r
+ // Use the duration from the instance options, if we don't have a track duration yet.\r
+ // position >= 0 and <= current available (loaded) duration\r
+ offset = (s.isHTML5 ? Math.max(nMsecOffset, 0) : Math.min(s.duration || s._iO.duration, Math.max(nMsecOffset, 0)));\r
+\r
+ s.position = offset;\r
+ position1K = s.position/msecScale;\r
+ s._resetOnPosition(s.position);\r
+ s._iO.position = offset;\r
+\r
+ if (!s.isHTML5) {\r
+\r
+ position = (fV === 9 ? s.position : position1K);\r
+\r
+ if (s.readyState && s.readyState !== 2) {\r
+ // if paused or not playing, will not resume (by playing)\r
+ flash._setPosition(s.id, position, (s.paused || !s.playState), s._iO.multiShot);\r
+ }\r
+\r
+ } else if (s._a) {\r
+\r
+ // Set the position in the canplay handler if the sound is not ready yet\r
+ if (s._html5_canplay) {\r
+\r
+ if (s._a.currentTime !== position1K) {\r
+\r
+ /**\r
+ * DOM/JS errors/exceptions to watch out for:\r
+ * if seek is beyond (loaded?) position, "DOM exception 11"\r
+ * "INDEX_SIZE_ERR": DOM exception 1\r
+ */\r
+ sm2._wD(s.id + ': setPosition(' + position1K + ')');\r
+\r
+ try {\r
+ s._a.currentTime = position1K;\r
+ if (s.playState === 0 || s.paused) {\r
+ // allow seek without auto-play/resume\r
+ s._a.pause();\r
+ }\r
+ } catch(e) {\r
+ sm2._wD(s.id + ': setPosition(' + position1K + ') failed: ' + e.message, 2);\r
+ }\r
+\r
+ }\r
+\r
+ } else if (position1K) {\r
+\r
+ // warn on non-zero seek attempts\r
+ sm2._wD(s.id + ': setPosition(' + position1K + '): Cannot seek yet, sound not ready', 2);\r
+ return s;\r
+\r
+ }\r
+\r
+ if (s.paused) {\r
+\r
+ // if paused, refresh UI right away by forcing update\r
+ s._onTimer(true);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Pauses sound playback.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.pause = function(_bCallFlash) {\r
+\r
+ if (s.paused || (s.playState === 0 && s.readyState !== 1)) {\r
+ return s;\r
+ }\r
+\r
+ sm2._wD(s.id + ': pause()');\r
+ s.paused = true;\r
+\r
+ if (!s.isHTML5) {\r
+ if (_bCallFlash || _bCallFlash === _undefined) {\r
+ flash._pause(s.id, s._iO.multiShot);\r
+ }\r
+ } else {\r
+ s._setup_html5().pause();\r
+ stop_html5_timer();\r
+ }\r
+\r
+ if (s._iO.onpause) {\r
+ s._iO.onpause.apply(s);\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Resumes sound playback.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ /**\r
+ * When auto-loaded streams pause on buffer full they have a playState of 0.\r
+ * We need to make sure that the playState is set to 1 when these streams "resume".\r
+ * When a paused stream is resumed, we need to trigger the onplay() callback if it\r
+ * hasn't been called already. In this case since the sound is being played for the\r
+ * first time, I think it's more appropriate to call onplay() rather than onresume().\r
+ */\r
+\r
+ this.resume = function() {\r
+\r
+ var instanceOptions = s._iO;\r
+\r
+ if (!s.paused) {\r
+ return s;\r
+ }\r
+\r
+ sm2._wD(s.id + ': resume()');\r
+ s.paused = false;\r
+ s.playState = 1;\r
+\r
+ if (!s.isHTML5) {\r
+\r
+ if (instanceOptions.isMovieStar && !instanceOptions.serverURL) {\r
+ // Bizarre Webkit bug (Chrome reported via 8tracks.com dudes): AAC content paused for 30+ seconds(?) will not resume without a reposition.\r
+ s.setPosition(s.position);\r
+ }\r
+\r
+ // flash method is toggle-based (pause/resume)\r
+ flash._pause(s.id, instanceOptions.multiShot);\r
+\r
+ } else {\r
+\r
+ s._setup_html5().play();\r
+ start_html5_timer();\r
+\r
+ }\r
+\r
+ if (!onplay_called && instanceOptions.onplay) {\r
+\r
+ instanceOptions.onplay.apply(s);\r
+ onplay_called = true;\r
+\r
+ } else if (instanceOptions.onresume) {\r
+\r
+ instanceOptions.onresume.apply(s);\r
+\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Toggles sound playback.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.togglePause = function() {\r
+\r
+ sm2._wD(s.id + ': togglePause()');\r
+\r
+ if (s.playState === 0) {\r
+ s.play({\r
+ position: (fV === 9 && !s.isHTML5 ? s.position : s.position / msecScale)\r
+ });\r
+ return s;\r
+ }\r
+\r
+ if (s.paused) {\r
+ s.resume();\r
+ } else {\r
+ s.pause();\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Sets the panning (L-R) effect.\r
+ *\r
+ * @param {number} nPan The pan value (-100 to 100)\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.setPan = function(nPan, bInstanceOnly) {\r
+\r
+ if (nPan === _undefined) {\r
+ nPan = 0;\r
+ }\r
+\r
+ if (bInstanceOnly === _undefined) {\r
+ bInstanceOnly = false;\r
+ }\r
+\r
+ if (!s.isHTML5) {\r
+ flash._setPan(s.id, nPan);\r
+ } // else { no HTML5 pan? }\r
+\r
+ s._iO.pan = nPan;\r
+\r
+ if (!bInstanceOnly) {\r
+ s.pan = nPan;\r
+ s.options.pan = nPan;\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Sets the volume.\r
+ *\r
+ * @param {number} nVol The volume value (0 to 100)\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.setVolume = function(nVol, _bInstanceOnly) {\r
+\r
+ /**\r
+ * Note: Setting volume has no effect on iOS "special snowflake" devices.\r
+ * Hardware volume control overrides software, and volume\r
+ * will always return 1 per Apple docs. (iOS 4 + 5.)\r
+ * http://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/AddingSoundtoCanvasAnimations/AddingSoundtoCanvasAnimations.html\r
+ */\r
+\r
+ if (nVol === _undefined) {\r
+ nVol = 100;\r
+ }\r
+\r
+ if (_bInstanceOnly === _undefined) {\r
+ _bInstanceOnly = false;\r
+ }\r
+\r
+ if (!s.isHTML5) {\r
+\r
+ flash._setVolume(s.id, (sm2.muted && !s.muted) || s.muted ? 0 : nVol);\r
+\r
+ } else if (s._a) {\r
+\r
+ if (sm2.muted && !s.muted) {\r
+ s.muted = true;\r
+ s._a.muted = true;\r
+ }\r
+\r
+ // valid range for native HTML5 Audio(): 0-1\r
+ s._a.volume = Math.max(0, Math.min(1, nVol/100));\r
+\r
+ }\r
+\r
+ s._iO.volume = nVol;\r
+\r
+ if (!_bInstanceOnly) {\r
+ s.volume = nVol;\r
+ s.options.volume = nVol;\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Mutes the sound.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.mute = function() {\r
+\r
+ s.muted = true;\r
+\r
+ if (!s.isHTML5) {\r
+ flash._setVolume(s.id, 0);\r
+ } else if (s._a) {\r
+ s._a.muted = true;\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Unmutes the sound.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.unmute = function() {\r
+\r
+ s.muted = false;\r
+ var hasIO = (s._iO.volume !== _undefined);\r
+\r
+ if (!s.isHTML5) {\r
+ flash._setVolume(s.id, hasIO ? s._iO.volume : s.options.volume);\r
+ } else if (s._a) {\r
+ s._a.muted = false;\r
+ }\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ /**\r
+ * Toggles the muted state of a sound.\r
+ *\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.toggleMute = function() {\r
+\r
+ return (s.muted ? s.unmute() : s.mute());\r
+\r
+ };\r
+\r
+ /**\r
+ * Registers a callback to be fired when a sound reaches a given position during playback.\r
+ *\r
+ * @param {number} nPosition The position to watch for\r
+ * @param {function} oMethod The relevant callback to fire\r
+ * @param {object} oScope Optional: The scope to apply the callback to\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.onPosition = function(nPosition, oMethod, oScope) {\r
+\r
+ // TODO: basic dupe checking?\r
+\r
+ onPositionItems.push({\r
+ position: parseInt(nPosition, 10),\r
+ method: oMethod,\r
+ scope: (oScope !== _undefined ? oScope : s),\r
+ fired: false\r
+ });\r
+\r
+ return s;\r
+\r
+ };\r
+\r
+ // legacy/backwards-compability: lower-case method name\r
+ this.onposition = this.onPosition;\r
+\r
+ /**\r
+ * Removes registered callback(s) from a sound, by position and/or callback.\r
+ *\r
+ * @param {number} nPosition The position to clear callback(s) for\r
+ * @param {function} oMethod Optional: Identify one callback to be removed when multiple listeners exist for one position\r
+ * @return {SMSound} The SMSound object\r
+ */\r
+\r
+ this.clearOnPosition = function(nPosition, oMethod) {\r
+\r
+ var i;\r
+\r
+ nPosition = parseInt(nPosition, 10);\r
+\r
+ if (isNaN(nPosition)) {\r
+ // safety check\r
+ return false;\r
+ }\r
+\r
+ for (i=0; i < onPositionItems.length; i++) {\r
+\r
+ if (nPosition === onPositionItems[i].position) {\r
+ // remove this item if no method was specified, or, if the method matches\r
+ \r
+ if (!oMethod || (oMethod === onPositionItems[i].method)) {\r
+ \r
+ if (onPositionItems[i].fired) {\r
+ // decrement "fired" counter, too\r
+ onPositionFired--;\r
+ }\r
+ \r
+ onPositionItems.splice(i, 1);\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ this._processOnPosition = function() {\r
+\r
+ var i, item, j = onPositionItems.length;\r
+\r
+ if (!j || !s.playState || onPositionFired >= j) {\r
+ return false;\r
+ }\r
+\r
+ for (i = j - 1; i >= 0; i--) {\r
+ \r
+ item = onPositionItems[i];\r
+ \r
+ if (!item.fired && s.position >= item.position) {\r
+ \r
+ item.fired = true;\r
+ onPositionFired++;\r
+ item.method.apply(item.scope, [item.position]);\r
+ \r
+ // reset j -- onPositionItems.length can be changed in the item callback above... occasionally breaking the loop.\r
+ j = onPositionItems.length;\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ this._resetOnPosition = function(nPosition) {\r
+\r
+ // reset "fired" for items interested in this position\r
+ var i, item, j = onPositionItems.length;\r
+\r
+ if (!j) {\r
+ return false;\r
+ }\r
+\r
+ for (i = j - 1; i >= 0; i--) {\r
+ \r
+ item = onPositionItems[i];\r
+ \r
+ if (item.fired && nPosition <= item.position) {\r
+ item.fired = false;\r
+ onPositionFired--;\r
+ }\r
+ \r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ /**\r
+ * SMSound() private internals\r
+ * --------------------------------\r
+ */\r
+\r
+ applyFromTo = function() {\r
+\r
+ var instanceOptions = s._iO,\r
+ f = instanceOptions.from,\r
+ t = instanceOptions.to,\r
+ start, end;\r
+\r
+ end = function() {\r
+\r
+ // end has been reached.\r
+ sm2._wD(s.id + ': "To" time of ' + t + ' reached.');\r
+\r
+ // detach listener\r
+ s.clearOnPosition(t, end);\r
+\r
+ // stop should clear this, too\r
+ s.stop();\r
+\r
+ };\r
+\r
+ start = function() {\r
+\r
+ sm2._wD(s.id + ': Playing "from" ' + f);\r
+\r
+ // add listener for end\r
+ if (t !== null && !isNaN(t)) {\r
+ s.onPosition(t, end);\r
+ }\r
+\r
+ };\r
+\r
+ if (f !== null && !isNaN(f)) {\r
+\r
+ // apply to instance options, guaranteeing correct start position.\r
+ instanceOptions.position = f;\r
+\r
+ // multiShot timing can't be tracked, so prevent that.\r
+ instanceOptions.multiShot = false;\r
+\r
+ start();\r
+\r
+ }\r
+\r
+ // return updated instanceOptions including starting position\r
+ return instanceOptions;\r
+\r
+ };\r
+\r
+ attachOnPosition = function() {\r
+\r
+ var item,\r
+ op = s._iO.onposition;\r
+\r
+ // attach onposition things, if any, now.\r
+\r
+ if (op) {\r
+\r
+ for (item in op) {\r
+ if (op.hasOwnProperty(item)) {\r
+ s.onPosition(parseInt(item, 10), op[item]);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ detachOnPosition = function() {\r
+\r
+ var item,\r
+ op = s._iO.onposition;\r
+\r
+ // detach any onposition()-style listeners.\r
+\r
+ if (op) {\r
+\r
+ for (item in op) {\r
+ if (op.hasOwnProperty(item)) {\r
+ s.clearOnPosition(parseInt(item, 10));\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ start_html5_timer = function() {\r
+\r
+ if (s.isHTML5) {\r
+ startTimer(s);\r
+ }\r
+\r
+ };\r
+\r
+ stop_html5_timer = function() {\r
+\r
+ if (s.isHTML5) {\r
+ stopTimer(s);\r
+ }\r
+\r
+ };\r
+\r
+ resetProperties = function(retainPosition) {\r
+\r
+ if (!retainPosition) {\r
+ onPositionItems = [];\r
+ onPositionFired = 0;\r
+ }\r
+\r
+ onplay_called = false;\r
+\r
+ s._hasTimer = null;\r
+ s._a = null;\r
+ s._html5_canplay = false;\r
+ s.bytesLoaded = null;\r
+ s.bytesTotal = null;\r
+ s.duration = (s._iO && s._iO.duration ? s._iO.duration : null);\r
+ s.durationEstimate = null;\r
+ s.buffered = [];\r
+\r
+ // legacy: 1D array\r
+ s.eqData = [];\r
+\r
+ s.eqData.left = [];\r
+ s.eqData.right = [];\r
+\r
+ s.failures = 0;\r
+ s.isBuffering = false;\r
+ s.instanceOptions = {};\r
+ s.instanceCount = 0;\r
+ s.loaded = false;\r
+ s.metadata = {};\r
+\r
+ // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success\r
+ s.readyState = 0;\r
+\r
+ s.muted = false;\r
+ s.paused = false;\r
+\r
+ s.peakData = {\r
+ left: 0,\r
+ right: 0\r
+ };\r
+\r
+ s.waveformData = {\r
+ left: [],\r
+ right: []\r
+ };\r
+\r
+ s.playState = 0;\r
+ s.position = null;\r
+\r
+ s.id3 = {};\r
+\r
+ };\r
+\r
+ resetProperties();\r
+\r
+ /**\r
+ * Pseudo-private SMSound internals\r
+ * --------------------------------\r
+ */\r
+\r
+ this._onTimer = function(bForce) {\r
+\r
+ /**\r
+ * HTML5-only _whileplaying() etc.\r
+ * called from both HTML5 native events, and polling/interval-based timers\r
+ * mimics flash and fires only when time/duration change, so as to be polling-friendly\r
+ */\r
+\r
+ var duration, isNew = false, time, x = {};\r
+\r
+ if (s._hasTimer || bForce) {\r
+\r
+ // TODO: May not need to track readyState (1 = loading)\r
+\r
+ if (s._a && (bForce || ((s.playState > 0 || s.readyState === 1) && !s.paused))) {\r
+\r
+ duration = s._get_html5_duration();\r
+\r
+ if (duration !== lastHTML5State.duration) {\r
+\r
+ lastHTML5State.duration = duration;\r
+ s.duration = duration;\r
+ isNew = true;\r
+\r
+ }\r
+\r
+ // TODO: investigate why this goes wack if not set/re-set each time.\r
+ s.durationEstimate = s.duration;\r
+\r
+ time = (s._a.currentTime * msecScale || 0);\r
+\r
+ if (time !== lastHTML5State.time) {\r
+\r
+ lastHTML5State.time = time;\r
+ isNew = true;\r
+\r
+ }\r
+\r
+ if (isNew || bForce) {\r
+\r
+ s._whileplaying(time, x, x, x, x);\r
+\r
+ }\r
+\r
+ }/* else {\r
+\r
+ // sm2._wD('_onTimer: Warn for "'+s.id+'": '+(!s._a?'Could not find element. ':'')+(s.playState === 0?'playState bad, 0?':'playState = '+s.playState+', OK'));\r
+\r
+ return false;\r
+\r
+ }*/\r
+\r
+ return isNew;\r
+\r
+ }\r
+\r
+ };\r
+\r
+ this._get_html5_duration = function() {\r
+\r
+ var instanceOptions = s._iO,\r
+ // if audio object exists, use its duration - else, instance option duration (if provided - it's a hack, really, and should be retired) OR null\r
+ d = (s._a && s._a.duration ? s._a.duration * msecScale : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : null)),\r
+ result = (d && !isNaN(d) && d !== Infinity ? d : null);\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ this._apply_loop = function(a, nLoops) {\r
+\r
+ /**\r
+ * boolean instead of "loop", for webkit? - spec says string. http://www.w3.org/TR/html-markup/audio.html#audio.attrs.loop\r
+ * note that loop is either off or infinite under HTML5, unlike Flash which allows arbitrary loop counts to be specified.\r
+ */\r
+\r
+ // <d>\r
+ if (!a.loop && nLoops > 1) {\r
+ sm2._wD('Note: Native HTML5 looping is infinite.', 1);\r
+ }\r
+ // </d>\r
+\r
+ a.loop = (nLoops > 1 ? 'loop' : '');\r
+\r
+ };\r
+\r
+ this._setup_html5 = function(oOptions) {\r
+\r
+ var instanceOptions = mixin(s._iO, oOptions),\r
+ a = useGlobalHTML5Audio ? globalHTML5Audio : s._a,\r
+ dURL = decodeURI(instanceOptions.url),\r
+ sameURL;\r
+\r
+ /**\r
+ * "First things first, I, Poppa..." (reset the previous state of the old sound, if playing)\r
+ * Fixes case with devices that can only play one sound at a time\r
+ * Otherwise, other sounds in mid-play will be terminated without warning and in a stuck state\r
+ */\r
+\r
+ if (useGlobalHTML5Audio) {\r
+\r
+ if (dURL === decodeURI(lastGlobalHTML5URL)) {\r
+ // global HTML5 audio: re-use of URL\r
+ sameURL = true;\r
+ }\r
+\r
+ } else if (dURL === decodeURI(lastURL)) {\r
+\r
+ // options URL is the same as the "last" URL, and we used (loaded) it\r
+ sameURL = true;\r
+\r
+ }\r
+\r
+ if (a) {\r
+\r
+ if (a._s) {\r
+\r
+ if (useGlobalHTML5Audio) {\r
+\r
+ if (a._s && a._s.playState && !sameURL) {\r
+\r
+ // global HTML5 audio case, and loading a new URL. stop the currently-playing one.\r
+ a._s.stop();\r
+\r
+ }\r
+\r
+ } else if (!useGlobalHTML5Audio && dURL === decodeURI(lastURL)) {\r
+\r
+ // non-global HTML5 reuse case: same url, ignore request\r
+ s._apply_loop(a, instanceOptions.loops);\r
+\r
+ return a;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ if (!sameURL) {\r
+\r
+ // don't retain onPosition() stuff with new URLs.\r
+\r
+ if (lastURL) {\r
+ resetProperties(false);\r
+ }\r
+\r
+ // assign new HTML5 URL\r
+\r
+ a.src = instanceOptions.url;\r
+\r
+ s.url = instanceOptions.url;\r
+\r
+ lastURL = instanceOptions.url;\r
+\r
+ lastGlobalHTML5URL = instanceOptions.url;\r
+\r
+ a._called_load = false;\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ if (instanceOptions.autoLoad || instanceOptions.autoPlay) {\r
+\r
+ s._a = new Audio(instanceOptions.url);\r
+ s._a.load();\r
+\r
+ } else {\r
+\r
+ // null for stupid Opera 9.64 case\r
+ s._a = (isOpera && opera.version() < 10 ? new Audio(null) : new Audio());\r
+\r
+ }\r
+\r
+ // assign local reference\r
+ a = s._a;\r
+\r
+ a._called_load = false;\r
+\r
+ if (useGlobalHTML5Audio) {\r
+\r
+ globalHTML5Audio = a;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ s.isHTML5 = true;\r
+\r
+ // store a ref on the track\r
+ s._a = a;\r
+\r
+ // store a ref on the audio\r
+ a._s = s;\r
+\r
+ add_html5_events();\r
+\r
+ s._apply_loop(a, instanceOptions.loops);\r
+\r
+ if (instanceOptions.autoLoad || instanceOptions.autoPlay) {\r
+\r
+ s.load();\r
+\r
+ } else {\r
+\r
+ // early HTML5 implementation (non-standard)\r
+ a.autobuffer = false;\r
+\r
+ // standard ('none' is also an option.)\r
+ a.preload = 'auto';\r
+\r
+ }\r
+\r
+ return a;\r
+\r
+ };\r
+\r
+ add_html5_events = function() {\r
+\r
+ if (s._a._added_events) {\r
+ return false;\r
+ }\r
+\r
+ var f;\r
+\r
+ function add(oEvt, oFn, bCapture) {\r
+ return s._a ? s._a.addEventListener(oEvt, oFn, bCapture || false) : null;\r
+ }\r
+\r
+ s._a._added_events = true;\r
+\r
+ for (f in html5_events) {\r
+ if (html5_events.hasOwnProperty(f)) {\r
+ add(f, html5_events[f]);\r
+ }\r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ remove_html5_events = function() {\r
+\r
+ // Remove event listeners\r
+\r
+ var f;\r
+\r
+ function remove(oEvt, oFn, bCapture) {\r
+ return (s._a ? s._a.removeEventListener(oEvt, oFn, bCapture || false) : null);\r
+ }\r
+\r
+ sm2._wD(s.id + ': Removing event listeners');\r
+ s._a._added_events = false;\r
+\r
+ for (f in html5_events) {\r
+ if (html5_events.hasOwnProperty(f)) {\r
+ remove(f, html5_events[f]);\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ /**\r
+ * Pseudo-private event internals\r
+ * ------------------------------\r
+ */\r
+\r
+ this._onload = function(nSuccess) {\r
+\r
+ var fN,\r
+ // check for duration to prevent false positives from flash 8 when loading from cache.\r
+ loadOK = !!nSuccess || (!s.isHTML5 && fV === 8 && s.duration);\r
+\r
+ // <d>\r
+ fN = s.id + ': ';\r
+ sm2._wD(fN + (loadOK ? 'onload()' : 'Failed to load / invalid sound?' + (!s.duration ? ' Zero-length duration reported.' : ' -') + ' (' + s.url + ')'), (loadOK ? 1 : 2));\r
+\r
+ if (!loadOK && !s.isHTML5) {\r
+ if (sm2.sandbox.noRemote === true) {\r
+ sm2._wD(fN + str('noNet'), 1);\r
+ }\r
+ if (sm2.sandbox.noLocal === true) {\r
+ sm2._wD(fN + str('noLocal'), 1);\r
+ }\r
+ }\r
+ // </d>\r
+\r
+ s.loaded = loadOK;\r
+ s.readyState = (loadOK ? 3 : 2);\r
+ s._onbufferchange(0);\r
+\r
+ if (s._iO.onload) {\r
+ wrapCallback(s, function() {\r
+ s._iO.onload.apply(s, [loadOK]);\r
+ });\r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ this._onbufferchange = function(nIsBuffering) {\r
+\r
+ if (s.playState === 0) {\r
+ // ignore if not playing\r
+ return false;\r
+ }\r
+\r
+ if ((nIsBuffering && s.isBuffering) || (!nIsBuffering && !s.isBuffering)) {\r
+ return false;\r
+ }\r
+\r
+ s.isBuffering = (nIsBuffering === 1);\r
+ \r
+ if (s._iO.onbufferchange) {\r
+ sm2._wD(s.id + ': Buffer state change: ' + nIsBuffering);\r
+ s._iO.onbufferchange.apply(s, [nIsBuffering]);\r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ /**\r
+ * Playback may have stopped due to buffering, or related reason.\r
+ * This state can be encountered on iOS < 6 when auto-play is blocked.\r
+ */\r
+\r
+ this._onsuspend = function() {\r
+\r
+ if (s._iO.onsuspend) {\r
+ sm2._wD(s.id + ': Playback suspended');\r
+ s._iO.onsuspend.apply(s);\r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ /**\r
+ * flash 9/movieStar + RTMP-only method, should fire only once at most\r
+ * at this point we just recreate failed sounds rather than trying to reconnect\r
+ */\r
+\r
+ this._onfailure = function(msg, level, code) {\r
+\r
+ s.failures++;\r
+ sm2._wD(s.id + ': Failure (' + s.failures + '): ' + msg);\r
+\r
+ if (s._iO.onfailure && s.failures === 1) {\r
+ s._iO.onfailure(msg, level, code);\r
+ } else {\r
+ sm2._wD(s.id + ': Ignoring failure');\r
+ }\r
+\r
+ };\r
+\r
+ /**\r
+ * flash 9/movieStar + RTMP-only method for unhandled warnings/exceptions from Flash\r
+ * e.g., RTMP "method missing" warning (non-fatal) for getStreamLength on server\r
+ */\r
+\r
+ this._onwarning = function(msg, level, code) {\r
+\r
+ if (s._iO.onwarning) {\r
+ s._iO.onwarning(msg, level, code);\r
+ }\r
+\r
+ };\r
+\r
+ this._onfinish = function() {\r
+\r
+ // store local copy before it gets trashed...\r
+ var io_onfinish = s._iO.onfinish;\r
+\r
+ s._onbufferchange(0);\r
+ s._resetOnPosition(0);\r
+\r
+ // reset some state items\r
+ if (s.instanceCount) {\r
+\r
+ s.instanceCount--;\r
+\r
+ if (!s.instanceCount) {\r
+\r
+ // remove onPosition listeners, if any\r
+ detachOnPosition();\r
+\r
+ // reset instance options\r
+ s.playState = 0;\r
+ s.paused = false;\r
+ s.instanceCount = 0;\r
+ s.instanceOptions = {};\r
+ s._iO = {};\r
+ stop_html5_timer();\r
+\r
+ // reset position, too\r
+ if (s.isHTML5) {\r
+ s.position = 0;\r
+ }\r
+\r
+ }\r
+\r
+ if (!s.instanceCount || s._iO.multiShotEvents) {\r
+ // fire onfinish for last, or every instance\r
+ if (io_onfinish) {\r
+ sm2._wD(s.id + ': onfinish()');\r
+ wrapCallback(s, function() {\r
+ io_onfinish.apply(s);\r
+ });\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration, nBufferLength) {\r
+\r
+ var instanceOptions = s._iO;\r
+\r
+ s.bytesLoaded = nBytesLoaded;\r
+ s.bytesTotal = nBytesTotal;\r
+ s.duration = Math.floor(nDuration);\r
+ s.bufferLength = nBufferLength;\r
+\r
+ if (!s.isHTML5 && !instanceOptions.isMovieStar) {\r
+\r
+ if (instanceOptions.duration) {\r
+ // use duration from options, if specified and larger. nobody should be specifying duration in options, actually, and it should be retired.\r
+ s.durationEstimate = (s.duration > instanceOptions.duration) ? s.duration : instanceOptions.duration;\r
+ } else {\r
+ s.durationEstimate = parseInt((s.bytesTotal / s.bytesLoaded) * s.duration, 10);\r
+ }\r
+\r
+ } else {\r
+\r
+ s.durationEstimate = s.duration;\r
+\r
+ }\r
+\r
+ // for flash, reflect sequential-load-style buffering\r
+ if (!s.isHTML5) {\r
+ s.buffered = [{\r
+ 'start': 0,\r
+ 'end': s.duration\r
+ }];\r
+ }\r
+\r
+ // allow whileloading to fire even if "load" fired under HTML5, due to HTTP range/partials\r
+ if ((s.readyState !== 3 || s.isHTML5) && instanceOptions.whileloading) {\r
+ instanceOptions.whileloading.apply(s);\r
+ }\r
+\r
+ };\r
+\r
+ this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) {\r
+\r
+ var instanceOptions = s._iO,\r
+ eqLeft;\r
+\r
+ if (isNaN(nPosition) || nPosition === null) {\r
+ // flash safety net\r
+ return false;\r
+ }\r
+\r
+ // 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.\r
+ s.position = Math.max(0, nPosition);\r
+\r
+ s._processOnPosition();\r
+\r
+ if (!s.isHTML5 && fV > 8) {\r
+\r
+ if (instanceOptions.usePeakData && oPeakData !== _undefined && oPeakData) {\r
+ s.peakData = {\r
+ left: oPeakData.leftPeak,\r
+ right: oPeakData.rightPeak\r
+ };\r
+ }\r
+\r
+ if (instanceOptions.useWaveformData && oWaveformDataLeft !== _undefined && oWaveformDataLeft) {\r
+ s.waveformData = {\r
+ left: oWaveformDataLeft.split(','),\r
+ right: oWaveformDataRight.split(',')\r
+ };\r
+ }\r
+\r
+ if (instanceOptions.useEQData) {\r
+ if (oEQData !== _undefined && oEQData && oEQData.leftEQ) {\r
+ eqLeft = oEQData.leftEQ.split(',');\r
+ s.eqData = eqLeft;\r
+ s.eqData.left = eqLeft;\r
+ if (oEQData.rightEQ !== _undefined && oEQData.rightEQ) {\r
+ s.eqData.right = oEQData.rightEQ.split(',');\r
+ }\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ if (s.playState === 1) {\r
+\r
+ // special case/hack: ensure buffering is false if loading from cache (and not yet started)\r
+ if (!s.isHTML5 && fV === 8 && !s.position && s.isBuffering) {\r
+ s._onbufferchange(0);\r
+ }\r
+\r
+ if (instanceOptions.whileplaying) {\r
+ // flash may call after actual finish\r
+ instanceOptions.whileplaying.apply(s);\r
+ }\r
+\r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ this._oncaptiondata = function(oData) {\r
+\r
+ /**\r
+ * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature\r
+ *\r
+ * @param {object} oData\r
+ */\r
+\r
+ sm2._wD(s.id + ': Caption data received.');\r
+\r
+ s.captiondata = oData;\r
+\r
+ if (s._iO.oncaptiondata) {\r
+ s._iO.oncaptiondata.apply(s, [oData]);\r
+ }\r
+\r
+ };\r
+\r
+ this._onmetadata = function(oMDProps, oMDData) {\r
+\r
+ /**\r
+ * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature\r
+ * RTMP may include song title, MovieStar content may include encoding info\r
+ *\r
+ * @param {array} oMDProps (names)\r
+ * @param {array} oMDData (values)\r
+ */\r
+\r
+ sm2._wD(s.id + ': Metadata received.');\r
+\r
+ var oData = {}, i, j;\r
+\r
+ for (i = 0, j = oMDProps.length; i < j; i++) {\r
+ oData[oMDProps[i]] = oMDData[i];\r
+ }\r
+\r
+ s.metadata = oData;\r
+\r
+ if (s._iO.onmetadata) {\r
+ s._iO.onmetadata.call(s, s.metadata);\r
+ }\r
+\r
+ };\r
+\r
+ this._onid3 = function(oID3Props, oID3Data) {\r
+\r
+ /**\r
+ * internal: flash 8 + flash 9 ID3 feature\r
+ * may include artist, song title etc.\r
+ *\r
+ * @param {array} oID3Props (names)\r
+ * @param {array} oID3Data (values)\r
+ */\r
+\r
+ sm2._wD(s.id + ': ID3 data received.');\r
+\r
+ var oData = [], i, j;\r
+\r
+ for (i = 0, j = oID3Props.length; i < j; i++) {\r
+ oData[oID3Props[i]] = oID3Data[i];\r
+ }\r
+\r
+ s.id3 = mixin(s.id3, oData);\r
+\r
+ if (s._iO.onid3) {\r
+ s._iO.onid3.apply(s);\r
+ }\r
+\r
+ };\r
+\r
+ // flash/RTMP-only\r
+\r
+ this._onconnect = function(bSuccess) {\r
+\r
+ bSuccess = (bSuccess === 1);\r
+ sm2._wD(s.id + ': ' + (bSuccess ? 'Connected.' : 'Failed to connect? - ' + s.url), (bSuccess ? 1 : 2));\r
+ s.connected = bSuccess;\r
+\r
+ if (bSuccess) {\r
+\r
+ s.failures = 0;\r
+\r
+ if (idCheck(s.id)) {\r
+ if (s.getAutoPlay()) {\r
+ // only update the play state if auto playing\r
+ s.play(_undefined, s.getAutoPlay());\r
+ } else if (s._iO.autoLoad) {\r
+ s.load();\r
+ }\r
+ }\r
+\r
+ if (s._iO.onconnect) {\r
+ s._iO.onconnect.apply(s, [bSuccess]);\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ this._ondataerror = function(sError) {\r
+\r
+ // flash 9 wave/eq data handler\r
+ // hack: called at start, and end from flash at/after onfinish()\r
+ if (s.playState > 0) {\r
+ sm2._wD(s.id + ': Data error: ' + sError);\r
+ if (s._iO.ondataerror) {\r
+ s._iO.ondataerror.apply(s);\r
+ }\r
+ }\r
+\r
+ };\r
+\r
+ // <d>\r
+ this._debug();\r
+ // </d>\r
+\r
+ }; // SMSound()\r
+\r
+ /**\r
+ * Private SoundManager internals\r
+ * ------------------------------\r
+ */\r
+\r
+ getDocument = function() {\r
+\r
+ return (doc.body || doc.getElementsByTagName('div')[0]);\r
+\r
+ };\r
+\r
+ id = function(sID) {\r
+\r
+ return doc.getElementById(sID);\r
+\r
+ };\r
+\r
+ mixin = function(oMain, oAdd) {\r
+\r
+ // non-destructive merge\r
+ var o1 = (oMain || {}), o2, o;\r
+\r
+ // if unspecified, o2 is the default options object\r
+ o2 = (oAdd === _undefined ? sm2.defaultOptions : oAdd);\r
+\r
+ for (o in o2) {\r
+\r
+ if (o2.hasOwnProperty(o) && o1[o] === _undefined) {\r
+\r
+ if (typeof o2[o] !== 'object' || o2[o] === null) {\r
+\r
+ // assign directly\r
+ o1[o] = o2[o];\r
+\r
+ } else {\r
+\r
+ // recurse through o2\r
+ o1[o] = mixin(o1[o], o2[o]);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ return o1;\r
+\r
+ };\r
+\r
+ wrapCallback = function(oSound, callback) {\r
+\r
+ /**\r
+ * 03/03/2013: Fix for Flash Player 11.6.602.171 + Flash 8 (flashVersion = 8) SWF issue\r
+ * setTimeout() fix for certain SMSound callbacks like onload() and onfinish(), where subsequent calls like play() and load() fail when Flash Player 11.6.602.171 is installed, and using soundManager with flashVersion = 8 (which is the default).\r
+ * Not sure of exact cause. Suspect race condition and/or invalid (NaN-style) position argument trickling down to the next JS -> Flash _start() call, in the play() case.\r
+ * Fix: setTimeout() to yield, plus safer null / NaN checking on position argument provided to Flash.\r
+ * https://getsatisfaction.com/schillmania/topics/recent_chrome_update_seems_to_have_broken_my_sm2_audio_player\r
+ */\r
+ if (!oSound.isHTML5 && fV === 8) {\r
+ window.setTimeout(callback, 0);\r
+ } else {\r
+ callback();\r
+ }\r
+\r
+ };\r
+\r
+ // additional soundManager properties that soundManager.setup() will accept\r
+\r
+ extraOptions = {\r
+ 'onready': 1,\r
+ 'ontimeout': 1,\r
+ 'defaultOptions': 1,\r
+ 'flash9Options': 1,\r
+ 'movieStarOptions': 1\r
+ };\r
+\r
+ assign = function(o, oParent) {\r
+\r
+ /**\r
+ * recursive assignment of properties, soundManager.setup() helper\r
+ * allows property assignment based on whitelist\r
+ */\r
+\r
+ var i,\r
+ result = true,\r
+ hasParent = (oParent !== _undefined),\r
+ setupOptions = sm2.setupOptions,\r
+ bonusOptions = extraOptions;\r
+\r
+ // <d>\r
+\r
+ // if soundManager.setup() called, show accepted parameters.\r
+\r
+ if (o === _undefined) {\r
+\r
+ result = [];\r
+\r
+ for (i in setupOptions) {\r
+\r
+ if (setupOptions.hasOwnProperty(i)) {\r
+ result.push(i);\r
+ }\r
+\r
+ }\r
+\r
+ for (i in bonusOptions) {\r
+\r
+ if (bonusOptions.hasOwnProperty(i)) {\r
+\r
+ if (typeof sm2[i] === 'object') {\r
+ result.push(i + ': {...}');\r
+ } else if (sm2[i] instanceof Function) {\r
+ result.push(i + ': function() {...}');\r
+ } else {\r
+ result.push(i);\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ sm2._wD(str('setup', result.join(', ')));\r
+\r
+ return false;\r
+\r
+ }\r
+\r
+ // </d>\r
+\r
+ for (i in o) {\r
+\r
+ if (o.hasOwnProperty(i)) {\r
+\r
+ // if not an {object} we want to recurse through...\r
+\r
+ if (typeof o[i] !== 'object' || o[i] === null || o[i] instanceof Array || o[i] instanceof RegExp) {\r
+\r
+ // check "allowed" options\r
+\r
+ if (hasParent && bonusOptions[oParent] !== _undefined) {\r
+\r
+ // valid recursive / nested object option, eg., { defaultOptions: { volume: 50 } }\r
+ sm2[oParent][i] = o[i];\r
+\r
+ } else if (setupOptions[i] !== _undefined) {\r
+\r
+ // special case: assign to setupOptions object, which soundManager property references\r
+ sm2.setupOptions[i] = o[i];\r
+\r
+ // assign directly to soundManager, too\r
+ sm2[i] = o[i];\r
+\r
+ } else if (bonusOptions[i] === _undefined) {\r
+\r
+ // invalid or disallowed parameter. complain.\r
+ complain(str((sm2[i] === _undefined ? 'setupUndef' : 'setupError'), i), 2);\r
+\r
+ result = false;\r
+\r
+ } else {\r
+\r
+ /**\r
+ * valid extraOptions (bonusOptions) parameter.\r
+ * is it a method, like onready/ontimeout? call it.\r
+ * multiple parameters should be in an array, eg. soundManager.setup({onready: [myHandler, myScope]});\r
+ */\r
+\r
+ if (sm2[i] instanceof Function) {\r
+\r
+ sm2[i].apply(sm2, (o[i] instanceof Array ? o[i] : [o[i]]));\r
+\r
+ } else {\r
+\r
+ // good old-fashioned direct assignment\r
+ sm2[i] = o[i];\r
+\r
+ }\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ // recursion case, eg., { defaultOptions: { ... } }\r
+\r
+ if (bonusOptions[i] === _undefined) {\r
+\r
+ // invalid or disallowed parameter. complain.\r
+ complain(str((sm2[i] === _undefined ? 'setupUndef' : 'setupError'), i), 2);\r
+\r
+ result = false;\r
+\r
+ } else {\r
+\r
+ // recurse through object\r
+ return assign(o[i], i);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ function preferFlashCheck(kind) {\r
+\r
+ // whether flash should play a given type\r
+ return (sm2.preferFlash && hasFlash && !sm2.ignoreFlash && (sm2.flash[kind] !== _undefined && sm2.flash[kind]));\r
+\r
+ }\r
+\r
+ /**\r
+ * Internal DOM2-level event helpers\r
+ * ---------------------------------\r
+ */\r
+\r
+ event = (function() {\r
+\r
+ // normalize event methods\r
+ var old = (window.attachEvent),\r
+ evt = {\r
+ add: (old ? 'attachEvent' : 'addEventListener'),\r
+ remove: (old ? 'detachEvent' : 'removeEventListener')\r
+ };\r
+\r
+ // normalize "on" event prefix, optional capture argument\r
+ function getArgs(oArgs) {\r
+\r
+ var args = slice.call(oArgs),\r
+ len = args.length;\r
+\r
+ if (old) {\r
+ // prefix\r
+ args[1] = 'on' + args[1];\r
+ if (len > 3) {\r
+ // no capture\r
+ args.pop();\r
+ }\r
+ } else if (len === 3) {\r
+ args.push(false);\r
+ }\r
+\r
+ return args;\r
+\r
+ }\r
+\r
+ function apply(args, sType) {\r
+\r
+ // normalize and call the event method, with the proper arguments\r
+ var element = args.shift(),\r
+ method = [evt[sType]];\r
+\r
+ if (old) {\r
+ // old IE can't do apply().\r
+ element[method](args[0], args[1]);\r
+ } else {\r
+ element[method].apply(element, args);\r
+ }\r
+\r
+ }\r
+\r
+ function add() {\r
+ apply(getArgs(arguments), 'add');\r
+ }\r
+\r
+ function remove() {\r
+ apply(getArgs(arguments), 'remove');\r
+ }\r
+\r
+ return {\r
+ 'add': add,\r
+ 'remove': remove\r
+ };\r
+\r
+ }());\r
+\r
+ /**\r
+ * Internal HTML5 event handling\r
+ * -----------------------------\r
+ */\r
+\r
+ function html5_event(oFn) {\r
+\r
+ // wrap html5 event handlers so we don't call them on destroyed and/or unloaded sounds\r
+\r
+ return function(e) {\r
+\r
+ var s = this._s,\r
+ result;\r
+\r
+ if (!s || !s._a) {\r
+ // <d>\r
+ if (s && s.id) {\r
+ sm2._wD(s.id + ': Ignoring ' + e.type);\r
+ } else {\r
+ sm2._wD(h5 + 'Ignoring ' + e.type);\r
+ }\r
+ // </d>\r
+ result = null;\r
+ } else {\r
+ result = oFn.call(this, e);\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ }\r
+\r
+ html5_events = {\r
+\r
+ // HTML5 event-name-to-handler map\r
+\r
+ abort: html5_event(function() {\r
+\r
+ sm2._wD(this._s.id + ': abort');\r
+\r
+ }),\r
+\r
+ // enough has loaded to play\r
+\r
+ canplay: html5_event(function() {\r
+\r
+ var s = this._s,\r
+ position1K;\r
+\r
+ if (s._html5_canplay) {\r
+ // this event has already fired. ignore.\r
+ return true;\r
+ }\r
+\r
+ s._html5_canplay = true;\r
+ sm2._wD(s.id + ': canplay');\r
+ s._onbufferchange(0);\r
+\r
+ // position according to instance options\r
+ position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position) ? s._iO.position/msecScale : null);\r
+\r
+ // set the position if position was provided before the sound loaded\r
+ if (this.currentTime !== position1K) {\r
+ sm2._wD(s.id + ': canplay: Setting position to ' + position1K);\r
+ try {\r
+ this.currentTime = position1K;\r
+ } catch(ee) {\r
+ sm2._wD(s.id + ': canplay: Setting position of ' + position1K + ' failed: ' + ee.message, 2);\r
+ }\r
+ }\r
+\r
+ // hack for HTML5 from/to case\r
+ if (s._iO._oncanplay) {\r
+ s._iO._oncanplay();\r
+ }\r
+\r
+ }),\r
+\r
+ canplaythrough: html5_event(function() {\r
+\r
+ var s = this._s;\r
+\r
+ if (!s.loaded) {\r
+ s._onbufferchange(0);\r
+ s._whileloading(s.bytesLoaded, s.bytesTotal, s._get_html5_duration());\r
+ s._onload(true);\r
+ }\r
+\r
+ }),\r
+\r
+ durationchange: html5_event(function() {\r
+\r
+ // durationchange may fire at various times, probably the safest way to capture accurate/final duration.\r
+\r
+ var s = this._s,\r
+ duration;\r
+\r
+ duration = s._get_html5_duration();\r
+\r
+ if (!isNaN(duration) && duration !== s.duration) {\r
+\r
+ sm2._wD(this._s.id + ': durationchange (' + duration + ')' + (s.duration ? ', previously ' + s.duration : ''));\r
+\r
+ s.durationEstimate = s.duration = duration;\r
+\r
+ }\r
+\r
+ }),\r
+\r
+ // TODO: Reserved for potential use\r
+ /*\r
+ emptied: html5_event(function() {\r
+\r
+ sm2._wD(this._s.id + ': emptied');\r
+\r
+ }),\r
+ */\r
+\r
+ ended: html5_event(function() {\r
+\r
+ var s = this._s;\r
+\r
+ sm2._wD(s.id + ': ended');\r
+\r
+ s._onfinish();\r
+\r
+ }),\r
+\r
+ error: html5_event(function() {\r
+\r
+ sm2._wD(this._s.id + ': HTML5 error, code ' + this.error.code);\r
+ /**\r
+ * HTML5 error codes, per W3C\r
+ * Error 1: Client aborted download at user's request.\r
+ * Error 2: Network error after load started.\r
+ * Error 3: Decoding issue.\r
+ * Error 4: Media (audio file) not supported.\r
+ * Reference: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#error-codes\r
+ */\r
+ // call load with error state?\r
+ this._s._onload(false);\r
+\r
+ }),\r
+\r
+ loadeddata: html5_event(function() {\r
+\r
+ var s = this._s;\r
+\r
+ sm2._wD(s.id + ': loadeddata');\r
+\r
+ // safari seems to nicely report progress events, eventually totalling 100%\r
+ if (!s._loaded && !isSafari) {\r
+ s.duration = s._get_html5_duration();\r
+ }\r
+\r
+ }),\r
+\r
+ loadedmetadata: html5_event(function() {\r
+\r
+ sm2._wD(this._s.id + ': loadedmetadata');\r
+\r
+ }),\r
+\r
+ loadstart: html5_event(function() {\r
+\r
+ sm2._wD(this._s.id + ': loadstart');\r
+ // assume buffering at first\r
+ this._s._onbufferchange(1);\r
+\r
+ }),\r
+\r
+ play: html5_event(function() {\r
+\r
+ // sm2._wD(this._s.id + ': play()');\r
+ // once play starts, no buffering\r
+ this._s._onbufferchange(0);\r
+\r
+ }),\r
+\r
+ playing: html5_event(function() {\r
+\r
+ sm2._wD(this._s.id + ': playing ' + String.fromCharCode(9835));\r
+ // once play starts, no buffering\r
+ this._s._onbufferchange(0);\r
+\r
+ }),\r
+\r
+ progress: html5_event(function(e) {\r
+\r
+ // note: can fire repeatedly after "loaded" event, due to use of HTTP range/partials\r
+\r
+ var s = this._s,\r
+ i, j, progStr, buffered = 0,\r
+ isProgress = (e.type === 'progress'),\r
+ ranges = e.target.buffered,\r
+ // firefox 3.6 implements e.loaded/total (bytes)\r
+ loaded = (e.loaded || 0),\r
+ total = (e.total || 1);\r
+\r
+ // reset the "buffered" (loaded byte ranges) array\r
+ s.buffered = [];\r
+\r
+ if (ranges && ranges.length) {\r
+\r
+ // if loaded is 0, try TimeRanges implementation as % of load\r
+ // https://developer.mozilla.org/en/DOM/TimeRanges\r
+\r
+ // re-build "buffered" array\r
+ // HTML5 returns seconds. SM2 API uses msec for setPosition() etc., whether Flash or HTML5.\r
+ for (i = 0, j = ranges.length; i < j; i++) {\r
+ s.buffered.push({\r
+ 'start': ranges.start(i) * msecScale,\r
+ 'end': ranges.end(i) * msecScale\r
+ });\r
+ }\r
+\r
+ // use the last value locally\r
+ buffered = (ranges.end(0) - ranges.start(0)) * msecScale;\r
+\r
+ // linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges\r
+ loaded = Math.min(1, buffered / (e.target.duration * msecScale));\r
+\r
+ // <d>\r
+ if (isProgress && ranges.length > 1) {\r
+ progStr = [];\r
+ j = ranges.length;\r
+ for (i = 0; i < j; i++) {\r
+ progStr.push((e.target.buffered.start(i) * msecScale) + '-' + (e.target.buffered.end(i) * msecScale));\r
+ }\r
+ sm2._wD(this._s.id + ': progress, timeRanges: ' + progStr.join(', '));\r
+ }\r
+\r
+ if (isProgress && !isNaN(loaded)) {\r
+ sm2._wD(this._s.id + ': progress, ' + Math.floor(loaded * 100) + '% loaded');\r
+ }\r
+ // </d>\r
+\r
+ }\r
+\r
+ if (!isNaN(loaded)) {\r
+\r
+ // TODO: prevent calls with duplicate values.\r
+ s._whileloading(loaded, total, s._get_html5_duration());\r
+ if (loaded && total && loaded === total) {\r
+ // in case "onload" doesn't fire (eg. gecko 1.9.2)\r
+ html5_events.canplaythrough.call(this, e);\r
+ }\r
+\r
+ }\r
+\r
+ }),\r
+\r
+ ratechange: html5_event(function() {\r
+\r
+ sm2._wD(this._s.id + ': ratechange');\r
+\r
+ }),\r
+\r
+ suspend: html5_event(function(e) {\r
+\r
+ // download paused/stopped, may have finished (eg. onload)\r
+ var s = this._s;\r
+\r
+ sm2._wD(this._s.id + ': suspend');\r
+ html5_events.progress.call(this, e);\r
+ s._onsuspend();\r
+\r
+ }),\r
+\r
+ stalled: html5_event(function() {\r
+\r
+ sm2._wD(this._s.id + ': stalled');\r
+\r
+ }),\r
+\r
+ timeupdate: html5_event(function() {\r
+\r
+ this._s._onTimer();\r
+\r
+ }),\r
+\r
+ waiting: html5_event(function() {\r
+\r
+ var s = this._s;\r
+\r
+ // see also: seeking\r
+ sm2._wD(this._s.id + ': waiting');\r
+\r
+ // playback faster than download rate, etc.\r
+ s._onbufferchange(1);\r
+\r
+ })\r
+\r
+ };\r
+\r
+ html5OK = function(iO) {\r
+\r
+ // playability test based on URL or MIME type\r
+\r
+ var result;\r
+\r
+ if (!iO || (!iO.type && !iO.url && !iO.serverURL)) {\r
+\r
+ // nothing to check\r
+ result = false;\r
+\r
+ } else if (iO.serverURL || (iO.type && preferFlashCheck(iO.type))) {\r
+\r
+ // RTMP, or preferring flash\r
+ result = false;\r
+\r
+ } else {\r
+\r
+ // Use type, if specified. Pass data: URIs to HTML5. If HTML5-only mode, no other options, so just give 'er\r
+ result = ((iO.type ? html5CanPlay({type:iO.type}) : html5CanPlay({url:iO.url}) || sm2.html5Only || iO.url.match(/data\:/i)));\r
+\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ html5Unload = function(oAudio) {\r
+\r
+ /**\r
+ * Internal method: Unload media, and cancel any current/pending network requests.\r
+ * Firefox can load an empty URL, which allegedly destroys the decoder and stops the download.\r
+ * https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox#Stopping_the_download_of_media\r
+ * However, Firefox has been seen loading a relative URL from '' and thus requesting the hosting page on unload.\r
+ * Other UA behaviour is unclear, so everyone else gets an about:blank-style URL.\r
+ */\r
+\r
+ var url;\r
+\r
+ if (oAudio) {\r
+\r
+ // Firefox and Chrome accept short WAVe data: URIs. Chome dislikes audio/wav, but accepts audio/wav for data: MIME.\r
+ // Desktop Safari complains / fails on data: URI, so it gets about:blank.\r
+ url = (isSafari ? emptyURL : (sm2.html5.canPlayType('audio/wav') ? emptyWAV : emptyURL));\r
+\r
+ oAudio.src = url;\r
+\r
+ // reset some state, too\r
+ if (oAudio._called_unload !== _undefined) {\r
+ oAudio._called_load = false;\r
+ }\r
+\r
+ }\r
+\r
+ if (useGlobalHTML5Audio) {\r
+\r
+ // ensure URL state is trashed, also\r
+ lastGlobalHTML5URL = null;\r
+\r
+ }\r
+\r
+ return url;\r
+\r
+ };\r
+\r
+ html5CanPlay = function(o) {\r
+\r
+ /**\r
+ * Try to find MIME, test and return truthiness\r
+ * o = {\r
+ * url: '/path/to/an.mp3',\r
+ * type: 'audio/mp3'\r
+ * }\r
+ */\r
+\r
+ if (!sm2.useHTML5Audio || !sm2.hasHTML5) {\r
+ return false;\r
+ }\r
+\r
+ var url = (o.url || null),\r
+ mime = (o.type || null),\r
+ aF = sm2.audioFormats,\r
+ result,\r
+ offset,\r
+ fileExt,\r
+ item;\r
+\r
+ // account for known cases like audio/mp3\r
+\r
+ if (mime && sm2.html5[mime] !== _undefined) {\r
+ return (sm2.html5[mime] && !preferFlashCheck(mime));\r
+ }\r
+\r
+ if (!html5Ext) {\r
+ \r
+ html5Ext = [];\r
+ \r
+ for (item in aF) {\r
+ \r
+ if (aF.hasOwnProperty(item)) {\r
+ \r
+ html5Ext.push(item);\r
+ \r
+ if (aF[item].related) {\r
+ html5Ext = html5Ext.concat(aF[item].related);\r
+ }\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ html5Ext = new RegExp('\\.('+html5Ext.join('|')+')(\\?.*)?$','i');\r
+ \r
+ }\r
+\r
+ // TODO: Strip URL queries, etc.\r
+ fileExt = (url ? url.toLowerCase().match(html5Ext) : null);\r
+\r
+ if (!fileExt || !fileExt.length) {\r
+ \r
+ if (!mime) {\r
+ \r
+ result = false;\r
+ \r
+ } else {\r
+ \r
+ // audio/mp3 -> mp3, result should be known\r
+ offset = mime.indexOf(';');\r
+ \r
+ // strip "audio/X; codecs..."\r
+ fileExt = (offset !== -1 ? mime.substr(0,offset) : mime).substr(6);\r
+ \r
+ }\r
+ \r
+ } else {\r
+ \r
+ // match the raw extension name - "mp3", for example\r
+ fileExt = fileExt[1];\r
+ \r
+ }\r
+\r
+ if (fileExt && sm2.html5[fileExt] !== _undefined) {\r
+ \r
+ // result known\r
+ result = (sm2.html5[fileExt] && !preferFlashCheck(fileExt));\r
+ \r
+ } else {\r
+ \r
+ mime = 'audio/' + fileExt;\r
+ result = sm2.html5.canPlayType({type:mime});\r
+ \r
+ sm2.html5[fileExt] = result;\r
+ \r
+ // sm2._wD('canPlayType, found result: ' + result);\r
+ result = (result && sm2.html5[mime] && !preferFlashCheck(mime));\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ testHTML5 = function() {\r
+\r
+ /**\r
+ * Internal: Iterates over audioFormats, determining support eg. audio/mp3, audio/mpeg and so on\r
+ * assigns results to html5[] and flash[].\r
+ */\r
+\r
+ if (!sm2.useHTML5Audio || !sm2.hasHTML5) {\r
+ \r
+ // without HTML5, we need Flash.\r
+ sm2.html5.usingFlash = true;\r
+ needsFlash = true;\r
+ \r
+ return false;\r
+ \r
+ }\r
+\r
+ // 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. :/\r
+ var a = (Audio !== _undefined ? (isOpera && opera.version() < 10 ? new Audio(null) : new Audio()) : null),\r
+ item, lookup, support = {}, aF, i;\r
+\r
+ function cp(m) {\r
+\r
+ var canPlay, j,\r
+ result = false,\r
+ isOK = false;\r
+\r
+ if (!a || typeof a.canPlayType !== 'function') {\r
+ return result;\r
+ }\r
+\r
+ if (m instanceof Array) {\r
+ \r
+ // iterate through all mime types, return any successes\r
+ \r
+ for (i = 0, j = m.length; i < j; i++) {\r
+ \r
+ if (sm2.html5[m[i]] || a.canPlayType(m[i]).match(sm2.html5Test)) {\r
+ \r
+ isOK = true;\r
+ sm2.html5[m[i]] = true;\r
+ \r
+ // note flash support, too\r
+ sm2.flash[m[i]] = !!(m[i].match(flashMIME));\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ result = isOK;\r
+ \r
+ } else {\r
+ \r
+ canPlay = (a && typeof a.canPlayType === 'function' ? a.canPlayType(m) : false);\r
+ result = !!(canPlay && (canPlay.match(sm2.html5Test)));\r
+ \r
+ }\r
+\r
+ return result;\r
+\r
+ }\r
+\r
+ // test all registered formats + codecs\r
+\r
+ aF = sm2.audioFormats;\r
+\r
+ for (item in aF) {\r
+\r
+ if (aF.hasOwnProperty(item)) {\r
+\r
+ lookup = 'audio/' + item;\r
+\r
+ support[item] = cp(aF[item].type);\r
+\r
+ // write back generic type too, eg. audio/mp3\r
+ support[lookup] = support[item];\r
+\r
+ // assign flash\r
+ if (item.match(flashMIME)) {\r
+\r
+ sm2.flash[item] = true;\r
+ sm2.flash[lookup] = true;\r
+\r
+ } else {\r
+\r
+ sm2.flash[item] = false;\r
+ sm2.flash[lookup] = false;\r
+\r
+ }\r
+\r
+ // assign result to related formats, too\r
+\r
+ if (aF[item] && aF[item].related) {\r
+\r
+ for (i = aF[item].related.length - 1; i >= 0; i--) {\r
+\r
+ // eg. audio/m4a\r
+ support['audio/' + aF[item].related[i]] = support[item];\r
+ sm2.html5[aF[item].related[i]] = support[item];\r
+ sm2.flash[aF[item].related[i]] = support[item];\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ support.canPlayType = (a ? cp : null);\r
+ sm2.html5 = mixin(sm2.html5, support);\r
+\r
+ sm2.html5.usingFlash = featureCheck();\r
+ needsFlash = sm2.html5.usingFlash;\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ strings = {\r
+\r
+ // <d>\r
+ notReady: 'Unavailable - wait until onready() has fired.',\r
+ notOK: 'Audio support is not available.',\r
+ domError: sm + 'exception caught while appending SWF to DOM.',\r
+ spcWmode: 'Removing wmode, preventing known SWF loading issue(s)',\r
+ swf404: smc + 'Verify that %s is a valid path.',\r
+ tryDebug: 'Try ' + sm + '.debugFlash = true for more security details (output goes to SWF.)',\r
+ checkSWF: 'See SWF output for more debug info.',\r
+ localFail: smc + '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/',\r
+ waitFocus: smc + 'Special case: Waiting for SWF to load with window focus...',\r
+ waitForever: smc + 'Waiting indefinitely for Flash (will recover if unblocked)...',\r
+ waitSWF: smc + 'Waiting for 100% SWF load...',\r
+ needFunction: smc + 'Function object expected for %s',\r
+ badID: 'Sound ID "%s" should be a string, starting with a non-numeric character',\r
+ currentObj: smc + '_debug(): Current sound objects',\r
+ waitOnload: smc + 'Waiting for window.onload()',\r
+ docLoaded: smc + 'Document already loaded',\r
+ onload: smc + 'initComplete(): calling soundManager.onload()',\r
+ onloadOK: sm + '.onload() complete',\r
+ didInit: smc + 'init(): Already called?',\r
+ 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',\r
+ badRemove: smc + 'Failed to remove Flash node.',\r
+ shutdown: sm + '.disable(): Shutting down',\r
+ queue: smc + 'Queueing %s handler',\r
+ smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.',\r
+ fbTimeout: 'No flash response, applying .' + swfCSS.swfTimedout + ' CSS...',\r
+ fbLoaded: 'Flash loaded',\r
+ fbHandler: smc + 'flashBlockHandler()',\r
+ manURL: 'SMSound.load(): Using manually-assigned URL',\r
+ onURL: sm + '.load(): current URL already assigned.',\r
+ badFV: sm + '.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',\r
+ as2loop: 'Note: Setting stream:false so looping can work (flash 8 limitation)',\r
+ noNSLoop: 'Note: Looping not implemented for MovieStar formats',\r
+ needfl9: 'Note: Switching to flash 9, required for MP4 formats.',\r
+ mfTimeout: 'Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case',\r
+ needFlash: smc + 'Fatal error: Flash is needed to play some required formats, but is not available.',\r
+ gotFocus: smc + 'Got window focus.',\r
+ policy: 'Enabling usePolicyFile for data access',\r
+ setup: sm + '.setup(): allowed parameters: %s',\r
+ setupError: sm + '.setup(): "%s" cannot be assigned with this method.',\r
+ setupUndef: sm + '.setup(): Could not find option "%s"',\r
+ setupLate: sm + '.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().',\r
+ noURL: smc + 'Flash URL required. Call soundManager.setup({url:...}) to get started.',\r
+ sm2Loaded: 'SoundManager 2: Ready. ' + String.fromCharCode(10003),\r
+ reset: sm + '.reset(): Removing event callbacks',\r
+ mobileUA: 'Mobile UA detected, preferring HTML5 by default.',\r
+ globalHTML5: 'Using singleton HTML5 Audio() pattern for this device.',\r
+ ignoreMobile: 'Ignoring mobile restrictions for this device.'\r
+ // </d>\r
+\r
+ };\r
+\r
+ str = function() {\r
+\r
+ // internal string replace helper.\r
+ // arguments: o [,items to replace]\r
+ // <d>\r
+\r
+ var args,\r
+ i, j, o,\r
+ sstr;\r
+\r
+ // real array, please\r
+ args = slice.call(arguments);\r
+\r
+ // first argument\r
+ o = args.shift();\r
+\r
+ sstr = (strings && strings[o] ? strings[o] : '');\r
+\r
+ if (sstr && args && args.length) {\r
+ for (i = 0, j = args.length; i < j; i++) {\r
+ sstr = sstr.replace('%s', args[i]);\r
+ }\r
+ }\r
+\r
+ return sstr;\r
+ // </d>\r
+\r
+ };\r
+\r
+ loopFix = function(sOpt) {\r
+\r
+ // flash 8 requires stream = false for looping to work\r
+ if (fV === 8 && sOpt.loops > 1 && sOpt.stream) {\r
+ _wDS('as2loop');\r
+ sOpt.stream = false;\r
+ }\r
+\r
+ return sOpt;\r
+\r
+ };\r
+\r
+ policyFix = function(sOpt, sPre) {\r
+\r
+ if (sOpt && !sOpt.usePolicyFile && (sOpt.onid3 || sOpt.usePeakData || sOpt.useWaveformData || sOpt.useEQData)) {\r
+ sm2._wD((sPre || '') + str('policy'));\r
+ sOpt.usePolicyFile = true;\r
+ }\r
+\r
+ return sOpt;\r
+\r
+ };\r
+\r
+ complain = function(sMsg) {\r
+\r
+ // <d>\r
+ if (hasConsole && console.warn !== _undefined) {\r
+ console.warn(sMsg);\r
+ } else {\r
+ sm2._wD(sMsg);\r
+ }\r
+ // </d>\r
+\r
+ };\r
+\r
+ doNothing = function() {\r
+\r
+ return false;\r
+\r
+ };\r
+\r
+ disableObject = function(o) {\r
+\r
+ var oProp;\r
+\r
+ for (oProp in o) {\r
+ if (o.hasOwnProperty(oProp) && typeof o[oProp] === 'function') {\r
+ o[oProp] = doNothing;\r
+ }\r
+ }\r
+\r
+ oProp = null;\r
+\r
+ };\r
+\r
+ failSafely = function(bNoDisable) {\r
+\r
+ // general failure exception handler\r
+\r
+ if (bNoDisable === _undefined) {\r
+ bNoDisable = false;\r
+ }\r
+\r
+ if (disabled || bNoDisable) {\r
+ sm2.disable(bNoDisable);\r
+ }\r
+\r
+ };\r
+\r
+ normalizeMovieURL = function(smURL) {\r
+\r
+ var urlParams = null, url;\r
+\r
+ if (smURL) {\r
+ \r
+ if (smURL.match(/\.swf(\?.*)?$/i)) {\r
+ \r
+ urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4);\r
+ \r
+ if (urlParams) {\r
+ // assume user knows what they're doing\r
+ return smURL;\r
+ }\r
+ \r
+ } else if (smURL.lastIndexOf('/') !== smURL.length - 1) {\r
+ \r
+ // append trailing slash, if needed\r
+ smURL += '/';\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + sm2.movieURL;\r
+\r
+ if (sm2.noSWFCache) {\r
+ url += ('?ts=' + new Date().getTime());\r
+ }\r
+\r
+ return url;\r
+\r
+ };\r
+\r
+ setVersionInfo = function() {\r
+\r
+ // short-hand for internal use\r
+\r
+ fV = parseInt(sm2.flashVersion, 10);\r
+\r
+ if (fV !== 8 && fV !== 9) {\r
+ sm2._wD(str('badFV', fV, defaultFlashVersion));\r
+ sm2.flashVersion = fV = defaultFlashVersion;\r
+ }\r
+\r
+ // debug flash movie, if applicable\r
+\r
+ var isDebug = (sm2.debugMode || sm2.debugFlash ? '_debug.swf' : '.swf');\r
+\r
+ if (sm2.useHTML5Audio && !sm2.html5Only && sm2.audioFormats.mp4.required && fV < 9) {\r
+ sm2._wD(str('needfl9'));\r
+ sm2.flashVersion = fV = 9;\r
+ }\r
+\r
+ sm2.version = sm2.versionNumber + (sm2.html5Only ? ' (HTML5-only mode)' : (fV === 9 ? ' (AS3/Flash 9)' : ' (AS2/Flash 8)'));\r
+\r
+ // set up default options\r
+ if (fV > 8) {\r
+ \r
+ // +flash 9 base options\r
+ sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.flash9Options);\r
+ sm2.features.buffering = true;\r
+ \r
+ // +moviestar support\r
+ sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.movieStarOptions);\r
+ sm2.filePatterns.flash9 = new RegExp('\\.(mp3|' + netStreamTypes.join('|') + ')(\\?.*)?$', 'i');\r
+ sm2.features.movieStar = true;\r
+ \r
+ } else {\r
+ \r
+ sm2.features.movieStar = false;\r
+ \r
+ }\r
+\r
+ // regExp for flash canPlay(), etc.\r
+ sm2.filePattern = sm2.filePatterns[(fV !== 8 ? 'flash9' : 'flash8')];\r
+\r
+ // if applicable, use _debug versions of SWFs\r
+ sm2.movieURL = (fV === 8 ? 'soundmanager2.swf' : 'soundmanager2_flash9.swf').replace('.swf', isDebug);\r
+\r
+ sm2.features.peakData = sm2.features.waveformData = sm2.features.eqData = (fV > 8);\r
+\r
+ };\r
+\r
+ setPolling = function(bPolling, bHighPerformance) {\r
+\r
+ if (!flash) {\r
+ return false;\r
+ }\r
+\r
+ flash._setPolling(bPolling, bHighPerformance);\r
+\r
+ };\r
+\r
+ initDebug = function() {\r
+\r
+ // starts debug mode, creating output <div> for UAs without console object\r
+\r
+ // allow force of debug mode via URL\r
+ // <d>\r
+ if (sm2.debugURLParam.test(wl)) {\r
+ sm2.setupOptions.debugMode = sm2.debugMode = true;\r
+ }\r
+\r
+ if (id(sm2.debugID)) {\r
+ return false;\r
+ }\r
+\r
+ var oD, oDebug, oTarget, oToggle, tmp;\r
+\r
+ if (sm2.debugMode && !id(sm2.debugID) && (!hasConsole || !sm2.useConsole || !sm2.consoleOnly)) {\r
+\r
+ oD = doc.createElement('div');\r
+ oD.id = sm2.debugID + '-toggle';\r
+\r
+ oToggle = {\r
+ 'position': 'fixed',\r
+ 'bottom': '0px',\r
+ 'right': '0px',\r
+ 'width': '1.2em',\r
+ 'height': '1.2em',\r
+ 'lineHeight': '1.2em',\r
+ 'margin': '2px',\r
+ 'textAlign': 'center',\r
+ 'border': '1px solid #999',\r
+ 'cursor': 'pointer',\r
+ 'background': '#fff',\r
+ 'color': '#333',\r
+ 'zIndex': 10001\r
+ };\r
+\r
+ oD.appendChild(doc.createTextNode('-'));\r
+ oD.onclick = toggleDebug;\r
+ oD.title = 'Toggle SM2 debug console';\r
+\r
+ if (ua.match(/msie 6/i)) {\r
+ oD.style.position = 'absolute';\r
+ oD.style.cursor = 'hand';\r
+ }\r
+\r
+ for (tmp in oToggle) {\r
+ if (oToggle.hasOwnProperty(tmp)) {\r
+ oD.style[tmp] = oToggle[tmp];\r
+ }\r
+ }\r
+\r
+ oDebug = doc.createElement('div');\r
+ oDebug.id = sm2.debugID;\r
+ oDebug.style.display = (sm2.debugMode ? 'block' : 'none');\r
+\r
+ if (sm2.debugMode && !id(oD.id)) {\r
+ try {\r
+ oTarget = getDocument();\r
+ oTarget.appendChild(oD);\r
+ } catch(e2) {\r
+ throw new Error(str('domError') + ' \n' + e2.toString());\r
+ }\r
+ oTarget.appendChild(oDebug);\r
+ }\r
+\r
+ }\r
+\r
+ oTarget = null;\r
+ // </d>\r
+\r
+ };\r
+\r
+ idCheck = this.getSoundById;\r
+\r
+ // <d>\r
+ _wDS = function(o, errorLevel) {\r
+\r
+ return (!o ? '' : sm2._wD(str(o), errorLevel));\r
+\r
+ };\r
+\r
+ toggleDebug = function() {\r
+\r
+ var o = id(sm2.debugID),\r
+ oT = id(sm2.debugID + '-toggle');\r
+\r
+ if (!o) {\r
+ return false;\r
+ }\r
+\r
+ if (debugOpen) {\r
+ // minimize\r
+ oT.innerHTML = '+';\r
+ o.style.display = 'none';\r
+ } else {\r
+ oT.innerHTML = '-';\r
+ o.style.display = 'block';\r
+ }\r
+\r
+ debugOpen = !debugOpen;\r
+\r
+ };\r
+\r
+ debugTS = function(sEventType, bSuccess, sMessage) {\r
+\r
+ // troubleshooter debug hooks\r
+\r
+ if (window.sm2Debugger !== _undefined) {\r
+ try {\r
+ sm2Debugger.handleEvent(sEventType, bSuccess, sMessage);\r
+ } catch(e) {\r
+ // oh well\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+ // </d>\r
+\r
+ getSWFCSS = function() {\r
+\r
+ var css = [];\r
+\r
+ if (sm2.debugMode) {\r
+ css.push(swfCSS.sm2Debug);\r
+ }\r
+\r
+ if (sm2.debugFlash) {\r
+ css.push(swfCSS.flashDebug);\r
+ }\r
+\r
+ if (sm2.useHighPerformance) {\r
+ css.push(swfCSS.highPerf);\r
+ }\r
+\r
+ return css.join(' ');\r
+\r
+ };\r
+\r
+ flashBlockHandler = function() {\r
+\r
+ // *possible* flash block situation.\r
+\r
+ var name = str('fbHandler'),\r
+ p = sm2.getMoviePercent(),\r
+ css = swfCSS,\r
+ error = {\r
+ type:'FLASHBLOCK'\r
+ };\r
+\r
+ if (sm2.html5Only) {\r
+ // no flash, or unused\r
+ return false;\r
+ }\r
+\r
+ if (!sm2.ok()) {\r
+\r
+ if (needsFlash) {\r
+ // make the movie more visible, so user can fix\r
+ sm2.oMC.className = getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null ? css.swfTimedout : css.swfError);\r
+ sm2._wD(name + ': ' + str('fbTimeout') + (p ? ' (' + str('fbLoaded') + ')' : ''));\r
+ }\r
+\r
+ sm2.didFlashBlock = true;\r
+\r
+ // fire onready(), complain lightly\r
+ processOnEvents({\r
+ type: 'ontimeout',\r
+ ignoreInit: true,\r
+ error: error\r
+ });\r
+\r
+ catchError(error);\r
+\r
+ } else {\r
+\r
+ // SM2 loaded OK (or recovered)\r
+\r
+ // <d>\r
+ if (sm2.didFlashBlock) {\r
+ sm2._wD(name + ': Unblocked');\r
+ }\r
+ // </d>\r
+\r
+ if (sm2.oMC) {\r
+ sm2.oMC.className = [getSWFCSS(), css.swfDefault, css.swfLoaded + (sm2.didFlashBlock ? ' ' + css.swfUnblocked : '')].join(' ');\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ addOnEvent = function(sType, oMethod, oScope) {\r
+\r
+ if (on_queue[sType] === _undefined) {\r
+ on_queue[sType] = [];\r
+ }\r
+\r
+ on_queue[sType].push({\r
+ 'method': oMethod,\r
+ 'scope': (oScope || null),\r
+ 'fired': false\r
+ });\r
+\r
+ };\r
+\r
+ processOnEvents = function(oOptions) {\r
+\r
+ // if unspecified, assume OK/error\r
+\r
+ if (!oOptions) {\r
+ oOptions = {\r
+ type: (sm2.ok() ? 'onready' : 'ontimeout')\r
+ };\r
+ }\r
+\r
+ if (!didInit && oOptions && !oOptions.ignoreInit) {\r
+ // not ready yet.\r
+ return false;\r
+ }\r
+\r
+ if (oOptions.type === 'ontimeout' && (sm2.ok() || (disabled && !oOptions.ignoreInit))) {\r
+ // invalid case\r
+ return false;\r
+ }\r
+\r
+ var status = {\r
+ success: (oOptions && oOptions.ignoreInit ? sm2.ok() : !disabled)\r
+ },\r
+\r
+ // queue specified by type, or none\r
+ srcQueue = (oOptions && oOptions.type ? on_queue[oOptions.type] || [] : []),\r
+\r
+ queue = [], i, j,\r
+ args = [status],\r
+ canRetry = (needsFlash && !sm2.ok());\r
+\r
+ if (oOptions.error) {\r
+ args[0].error = oOptions.error;\r
+ }\r
+\r
+ for (i = 0, j = srcQueue.length; i < j; i++) {\r
+ if (srcQueue[i].fired !== true) {\r
+ queue.push(srcQueue[i]);\r
+ }\r
+ }\r
+\r
+ if (queue.length) {\r
+ \r
+ // sm2._wD(sm + ': Firing ' + queue.length + ' ' + oOptions.type + '() item' + (queue.length === 1 ? '' : 's')); \r
+ for (i = 0, j = queue.length; i < j; i++) {\r
+ \r
+ if (queue[i].scope) {\r
+ queue[i].method.apply(queue[i].scope, args);\r
+ } else {\r
+ queue[i].method.apply(this, args);\r
+ }\r
+ \r
+ if (!canRetry) {\r
+ // useFlashBlock and SWF timeout case doesn't count here.\r
+ queue[i].fired = true;\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ initUserOnload = function() {\r
+\r
+ window.setTimeout(function() {\r
+\r
+ if (sm2.useFlashBlock) {\r
+ flashBlockHandler();\r
+ }\r
+\r
+ processOnEvents();\r
+\r
+ // call user-defined "onload", scoped to window\r
+\r
+ if (typeof sm2.onload === 'function') {\r
+ _wDS('onload', 1);\r
+ sm2.onload.apply(window);\r
+ _wDS('onloadOK', 1);\r
+ }\r
+\r
+ if (sm2.waitForWindowLoad) {\r
+ event.add(window, 'load', initUserOnload);\r
+ }\r
+\r
+ }, 1);\r
+\r
+ };\r
+\r
+ detectFlash = function() {\r
+\r
+ /**\r
+ * Hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau\r
+ * http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt\r
+ */\r
+\r
+ if (hasFlash !== _undefined) {\r
+ // this work has already been done.\r
+ return hasFlash;\r
+ }\r
+\r
+ var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = window.ActiveXObject;\r
+\r
+ if (nP && nP.length) {\r
+ \r
+ type = 'application/x-shockwave-flash';\r
+ types = n.mimeTypes;\r
+ \r
+ if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) {\r
+ hasPlugin = true;\r
+ }\r
+ \r
+ } else if (AX !== _undefined && !ua.match(/MSAppHost/i)) {\r
+ \r
+ // Windows 8 Store Apps (MSAppHost) are weird (compatibility?) and won't complain here, but will barf if Flash/ActiveX object is appended to the DOM.\r
+ try {\r
+ obj = new AX('ShockwaveFlash.ShockwaveFlash');\r
+ } catch(e) {\r
+ // oh well\r
+ obj = null;\r
+ }\r
+ \r
+ hasPlugin = (!!obj);\r
+ \r
+ // cleanup, because it is ActiveX after all\r
+ obj = null;\r
+ \r
+ }\r
+\r
+ hasFlash = hasPlugin;\r
+\r
+ return hasPlugin;\r
+\r
+ };\r
+\r
+featureCheck = function() {\r
+\r
+ var flashNeeded,\r
+ item,\r
+ formats = sm2.audioFormats,\r
+ // iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (original iPad) + iOS4 works.\r
+ isSpecial = (is_iDevice && !!(ua.match(/os (1|2|3_0|3_1)\s/i)));\r
+\r
+ if (isSpecial) {\r
+\r
+ // has Audio(), but is broken; let it load links directly.\r
+ sm2.hasHTML5 = false;\r
+\r
+ // ignore flash case, however\r
+ sm2.html5Only = true;\r
+\r
+ // hide the SWF, if present\r
+ if (sm2.oMC) {\r
+ sm2.oMC.style.display = 'none';\r
+ }\r
+\r
+ } else {\r
+\r
+ if (sm2.useHTML5Audio) {\r
+\r
+ if (!sm2.html5 || !sm2.html5.canPlayType) {\r
+ sm2._wD('SoundManager: No HTML5 Audio() support detected.');\r
+ sm2.hasHTML5 = false;\r
+ }\r
+\r
+ // <d>\r
+ if (isBadSafari) {\r
+ sm2._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);\r
+ }\r
+ // </d>\r
+\r
+ }\r
+\r
+ }\r
+\r
+ if (sm2.useHTML5Audio && sm2.hasHTML5) {\r
+\r
+ // sort out whether flash is optional, required or can be ignored.\r
+\r
+ // innocent until proven guilty.\r
+ canIgnoreFlash = true;\r
+\r
+ for (item in formats) {\r
+ \r
+ if (formats.hasOwnProperty(item)) {\r
+ \r
+ if (formats[item].required) {\r
+ \r
+ if (!sm2.html5.canPlayType(formats[item].type)) {\r
+ \r
+ // 100% HTML5 mode is not possible.\r
+ canIgnoreFlash = false;\r
+ flashNeeded = true;\r
+ \r
+ } else if (sm2.preferFlash && (sm2.flash[item] || sm2.flash[formats[item].type])) {\r
+ \r
+ // flash may be required, or preferred for this format.\r
+ flashNeeded = true;\r
+ \r
+ }\r
+ \r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ // sanity check...\r
+ if (sm2.ignoreFlash) {\r
+ flashNeeded = false;\r
+ canIgnoreFlash = true;\r
+ }\r
+\r
+ sm2.html5Only = (sm2.hasHTML5 && sm2.useHTML5Audio && !flashNeeded);\r
+\r
+ return (!sm2.html5Only);\r
+\r
+ };\r
+\r
+ parseURL = function(url) {\r
+\r
+ /**\r
+ * Internal: Finds and returns the first playable URL (or failing that, the first URL.)\r
+ * @param {string or array} url A single URL string, OR, an array of URL strings or {url:'/path/to/resource', type:'audio/mp3'} objects.\r
+ */\r
+\r
+ var i, j, urlResult = 0, result;\r
+\r
+ if (url instanceof Array) {\r
+\r
+ // find the first good one\r
+ for (i = 0, j = url.length; i < j; i++) {\r
+\r
+ if (url[i] instanceof Object) {\r
+\r
+ // MIME check\r
+ if (sm2.canPlayMIME(url[i].type)) {\r
+ urlResult = i;\r
+ break;\r
+ }\r
+\r
+ } else if (sm2.canPlayURL(url[i])) {\r
+\r
+ // URL string check\r
+ urlResult = i;\r
+ break;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ // normalize to string\r
+ if (url[urlResult].url) {\r
+ url[urlResult] = url[urlResult].url;\r
+ }\r
+\r
+ result = url[urlResult];\r
+\r
+ } else {\r
+\r
+ // single URL case\r
+ result = url;\r
+\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+\r
+ startTimer = function(oSound) {\r
+\r
+ /**\r
+ * attach a timer to this sound, and start an interval if needed\r
+ */\r
+\r
+ if (!oSound._hasTimer) {\r
+\r
+ oSound._hasTimer = true;\r
+\r
+ if (!mobileHTML5 && sm2.html5PollingInterval) {\r
+\r
+ if (h5IntervalTimer === null && h5TimerCount === 0) {\r
+\r
+ h5IntervalTimer = setInterval(timerExecute, sm2.html5PollingInterval);\r
+\r
+ }\r
+\r
+ h5TimerCount++;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ stopTimer = function(oSound) {\r
+\r
+ /**\r
+ * detach a timer\r
+ */\r
+\r
+ if (oSound._hasTimer) {\r
+\r
+ oSound._hasTimer = false;\r
+\r
+ if (!mobileHTML5 && sm2.html5PollingInterval) {\r
+\r
+ // interval will stop itself at next execution.\r
+\r
+ h5TimerCount--;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ timerExecute = function() {\r
+\r
+ /**\r
+ * manual polling for HTML5 progress events, ie., whileplaying()\r
+ * (can achieve greater precision than conservative default HTML5 interval)\r
+ */\r
+\r
+ var i;\r
+\r
+ if (h5IntervalTimer !== null && !h5TimerCount) {\r
+\r
+ // no active timers, stop polling interval.\r
+\r
+ clearInterval(h5IntervalTimer);\r
+\r
+ h5IntervalTimer = null;\r
+\r
+ return false;\r
+\r
+ }\r
+\r
+ // check all HTML5 sounds with timers\r
+\r
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {\r
+\r
+ if (sm2.sounds[sm2.soundIDs[i]].isHTML5 && sm2.sounds[sm2.soundIDs[i]]._hasTimer) {\r
+ sm2.sounds[sm2.soundIDs[i]]._onTimer();\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ catchError = function(options) {\r
+\r
+ options = (options !== _undefined ? options : {});\r
+\r
+ if (typeof sm2.onerror === 'function') {\r
+ sm2.onerror.apply(window, [{\r
+ type: (options.type !== _undefined ? options.type : null)\r
+ }]);\r
+ }\r
+\r
+ if (options.fatal !== _undefined && options.fatal) {\r
+ sm2.disable();\r
+ }\r
+\r
+ };\r
+\r
+ badSafariFix = function() {\r
+\r
+ // special case: "bad" Safari (OS X 10.3 - 10.7) must fall back to flash for MP3/MP4\r
+ if (!isBadSafari || !detectFlash()) {\r
+ // doesn't apply\r
+ return false;\r
+ }\r
+\r
+ var aF = sm2.audioFormats, i, item;\r
+\r
+ for (item in aF) {\r
+\r
+ if (aF.hasOwnProperty(item)) {\r
+\r
+ if (item === 'mp3' || item === 'mp4') {\r
+\r
+ sm2._wD(sm + ': Using flash fallback for ' + item + ' format');\r
+ sm2.html5[item] = false;\r
+\r
+ // assign result to related formats, too\r
+ if (aF[item] && aF[item].related) {\r
+ for (i = aF[item].related.length - 1; i >= 0; i--) {\r
+ sm2.html5[aF[item].related[i]] = false;\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+ /**\r
+ * Pseudo-private flash/ExternalInterface methods\r
+ * ----------------------------------------------\r
+ */\r
+\r
+ this._setSandboxType = function(sandboxType) {\r
+\r
+ // <d>\r
+ // Security sandbox according to Flash plugin\r
+ var sb = sm2.sandbox;\r
+\r
+ sb.type = sandboxType;\r
+ sb.description = sb.types[(sb.types[sandboxType] !== _undefined?sandboxType : 'unknown')];\r
+\r
+ if (sb.type === 'localWithFile') {\r
+\r
+ sb.noRemote = true;\r
+ sb.noLocal = false;\r
+ _wDS('secNote', 2);\r
+\r
+ } else if (sb.type === 'localWithNetwork') {\r
+\r
+ sb.noRemote = false;\r
+ sb.noLocal = true;\r
+\r
+ } else if (sb.type === 'localTrusted') {\r
+\r
+ sb.noRemote = false;\r
+ sb.noLocal = false;\r
+\r
+ }\r
+ // </d>\r
+\r
+ };\r
+\r
+ this._externalInterfaceOK = function(swfVersion) {\r
+\r
+ // flash callback confirming flash loaded, EI working etc.\r
+ // swfVersion: SWF build string\r
+\r
+ if (sm2.swfLoaded) {\r
+ return false;\r
+ }\r
+\r
+ var e;\r
+\r
+ debugTS('swf', true);\r
+ debugTS('flashtojs', true);\r
+ sm2.swfLoaded = true;\r
+ tryInitOnFocus = false;\r
+\r
+ if (isBadSafari) {\r
+ badSafariFix();\r
+ }\r
+\r
+ // complain if JS + SWF build/version strings don't match, excluding +DEV builds\r
+ // <d>\r
+ if (!swfVersion || swfVersion.replace(/\+dev/i,'') !== sm2.versionNumber.replace(/\+dev/i, '')) {\r
+\r
+ e = sm + ': Fatal: JavaScript file build "' + sm2.versionNumber + '" does not match Flash SWF build "' + swfVersion + '" at ' + sm2.url + '. Ensure both are up-to-date.';\r
+\r
+ // escape flash -> JS stack so this error fires in window.\r
+ setTimeout(function versionMismatch() {\r
+ throw new Error(e);\r
+ }, 0);\r
+\r
+ // exit, init will fail with timeout\r
+ return false;\r
+\r
+ }\r
+ // </d>\r
+\r
+ // IE needs a larger timeout\r
+ setTimeout(init, isIE ? 100 : 1);\r
+\r
+ };\r
+\r
+ /**\r
+ * Private initialization helpers\r
+ * ------------------------------\r
+ */\r
+\r
+ createMovie = function(smID, smURL) {\r
+\r
+ if (didAppend && appendSuccess) {\r
+ // ignore if already succeeded\r
+ return false;\r
+ }\r
+\r
+ function initMsg() {\r
+\r
+ // <d>\r
+\r
+ var options = [],\r
+ title,\r
+ msg = [],\r
+ delimiter = ' + ';\r
+\r
+ title = 'SoundManager ' + sm2.version + (!sm2.html5Only && sm2.useHTML5Audio ? (sm2.hasHTML5 ? ' + HTML5 audio' : ', no HTML5 audio support') : '');\r
+\r
+ if (!sm2.html5Only) {\r
+\r
+ if (sm2.preferFlash) {\r
+ options.push('preferFlash');\r
+ }\r
+\r
+ if (sm2.useHighPerformance) {\r
+ options.push('useHighPerformance');\r
+ }\r
+\r
+ if (sm2.flashPollingInterval) {\r
+ options.push('flashPollingInterval (' + sm2.flashPollingInterval + 'ms)');\r
+ }\r
+\r
+ if (sm2.html5PollingInterval) {\r
+ options.push('html5PollingInterval (' + sm2.html5PollingInterval + 'ms)');\r
+ }\r
+\r
+ if (sm2.wmode) {\r
+ options.push('wmode (' + sm2.wmode + ')');\r
+ }\r
+\r
+ if (sm2.debugFlash) {\r
+ options.push('debugFlash');\r
+ }\r
+\r
+ if (sm2.useFlashBlock) {\r
+ options.push('flashBlock');\r
+ }\r
+\r
+ } else {\r
+\r
+ if (sm2.html5PollingInterval) {\r
+ options.push('html5PollingInterval (' + sm2.html5PollingInterval + 'ms)');\r
+ }\r
+\r
+ }\r
+\r
+ if (options.length) {\r
+ msg = msg.concat([options.join(delimiter)]);\r
+ }\r
+\r
+ sm2._wD(title + (msg.length ? delimiter + msg.join(', ') : ''), 1);\r
+\r
+ showSupport();\r
+\r
+ // </d>\r
+\r
+ }\r
+\r
+ if (sm2.html5Only) {\r
+\r
+ // 100% HTML5 mode\r
+ setVersionInfo();\r
+\r
+ initMsg();\r
+ sm2.oMC = id(sm2.movieID);\r
+ init();\r
+\r
+ // prevent multiple init attempts\r
+ didAppend = true;\r
+\r
+ appendSuccess = true;\r
+\r
+ return false;\r
+\r
+ }\r
+\r
+ // flash path\r
+ var remoteURL = (smURL || sm2.url),\r
+ localURL = (sm2.altURL || remoteURL),\r
+ swfTitle = 'JS/Flash audio component (SoundManager 2)',\r
+ oTarget = getDocument(),\r
+ extraClass = getSWFCSS(),\r
+ isRTL = null,\r
+ html = doc.getElementsByTagName('html')[0],\r
+ oEmbed, oMovie, tmp, movieHTML, oEl, s, x, sClass;\r
+\r
+ isRTL = (html && html.dir && html.dir.match(/rtl/i));\r
+ smID = (smID === _undefined ? sm2.id : smID);\r
+\r
+ function param(name, value) {\r
+ return '<param name="' + name + '" value="' + value + '" />';\r
+ }\r
+\r
+ // safety check for legacy (change to Flash 9 URL)\r
+ setVersionInfo();\r
+ sm2.url = normalizeMovieURL(overHTTP ? remoteURL : localURL);\r
+ smURL = sm2.url;\r
+\r
+ sm2.wmode = (!sm2.wmode && sm2.useHighPerformance ? 'transparent' : sm2.wmode);\r
+\r
+ if (sm2.wmode !== null && (ua.match(/msie 8/i) || (!isIE && !sm2.useHighPerformance)) && navigator.platform.match(/win32|win64/i)) {\r
+ /**\r
+ * extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here\r
+ * does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout\r
+ * wmode breaks IE 8 on Vista + Win7 too in some cases, as of January 2011 (?)\r
+ */\r
+ messages.push(strings.spcWmode);\r
+ sm2.wmode = null;\r
+ }\r
+\r
+ oEmbed = {\r
+ 'name': smID,\r
+ 'id': smID,\r
+ 'src': smURL,\r
+ 'quality': 'high',\r
+ 'allowScriptAccess': sm2.allowScriptAccess,\r
+ 'bgcolor': sm2.bgColor,\r
+ 'pluginspage': http + 'www.macromedia.com/go/getflashplayer',\r
+ 'title': swfTitle,\r
+ 'type': 'application/x-shockwave-flash',\r
+ 'wmode': sm2.wmode,\r
+ // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html\r
+ 'hasPriority': 'true'\r
+ };\r
+\r
+ if (sm2.debugFlash) {\r
+ oEmbed.FlashVars = 'debug=1';\r
+ }\r
+\r
+ if (!sm2.wmode) {\r
+ // don't write empty attribute\r
+ delete oEmbed.wmode;\r
+ }\r
+\r
+ if (isIE) {\r
+\r
+ // IE is "special".\r
+ oMovie = doc.createElement('div');\r
+ movieHTML = [\r
+ '<object id="' + smID + '" data="' + smURL + '" type="' + oEmbed.type + '" title="' + oEmbed.title +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">',\r
+ param('movie', smURL),\r
+ param('AllowScriptAccess', sm2.allowScriptAccess),\r
+ param('quality', oEmbed.quality),\r
+ (sm2.wmode? param('wmode', sm2.wmode): ''),\r
+ param('bgcolor', sm2.bgColor),\r
+ param('hasPriority', 'true'),\r
+ (sm2.debugFlash ? param('FlashVars', oEmbed.FlashVars) : ''),\r
+ '</object>'\r
+ ].join('');\r
+\r
+ } else {\r
+\r
+ oMovie = doc.createElement('embed');\r
+ for (tmp in oEmbed) {\r
+ if (oEmbed.hasOwnProperty(tmp)) {\r
+ oMovie.setAttribute(tmp, oEmbed[tmp]);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ initDebug();\r
+ extraClass = getSWFCSS();\r
+ oTarget = getDocument();\r
+\r
+ if (oTarget) {\r
+\r
+ sm2.oMC = (id(sm2.movieID) || doc.createElement('div'));\r
+\r
+ if (!sm2.oMC.id) {\r
+\r
+ sm2.oMC.id = sm2.movieID;\r
+ sm2.oMC.className = swfCSS.swfDefault + ' ' + extraClass;\r
+ s = null;\r
+ oEl = null;\r
+\r
+ if (!sm2.useFlashBlock) {\r
+ if (sm2.useHighPerformance) {\r
+ // on-screen at all times\r
+ s = {\r
+ 'position': 'fixed',\r
+ 'width': '8px',\r
+ 'height': '8px',\r
+ // >= 6px for flash to run fast, >= 8px to start up under Firefox/win32 in some cases. odd? yes.\r
+ 'bottom': '0px',\r
+ 'left': '0px',\r
+ 'overflow': 'hidden'\r
+ };\r
+ } else {\r
+ // hide off-screen, lower priority\r
+ s = {\r
+ 'position': 'absolute',\r
+ 'width': '6px',\r
+ 'height': '6px',\r
+ 'top': '-9999px',\r
+ 'left': '-9999px'\r
+ };\r
+ if (isRTL) {\r
+ s.left = Math.abs(parseInt(s.left, 10)) + 'px';\r
+ }\r
+ }\r
+ }\r
+\r
+ if (isWebkit) {\r
+ // soundcloud-reported render/crash fix, safari 5\r
+ sm2.oMC.style.zIndex = 10000;\r
+ }\r
+\r
+ if (!sm2.debugFlash) {\r
+ for (x in s) {\r
+ if (s.hasOwnProperty(x)) {\r
+ sm2.oMC.style[x] = s[x];\r
+ }\r
+ }\r
+ }\r
+\r
+ try {\r
+\r
+ if (!isIE) {\r
+ sm2.oMC.appendChild(oMovie);\r
+ }\r
+\r
+ oTarget.appendChild(sm2.oMC);\r
+\r
+ if (isIE) {\r
+ oEl = sm2.oMC.appendChild(doc.createElement('div'));\r
+ oEl.className = swfCSS.swfBox;\r
+ oEl.innerHTML = movieHTML;\r
+ }\r
+\r
+ appendSuccess = true;\r
+\r
+ } catch(e) {\r
+\r
+ throw new Error(str('domError') + ' \n' + e.toString());\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ // SM2 container is already in the document (eg. flashblock use case)\r
+ sClass = sm2.oMC.className;\r
+ sm2.oMC.className = (sClass ? sClass + ' ' : swfCSS.swfDefault) + (extraClass ? ' ' + extraClass : '');\r
+ sm2.oMC.appendChild(oMovie);\r
+\r
+ if (isIE) {\r
+ oEl = sm2.oMC.appendChild(doc.createElement('div'));\r
+ oEl.className = swfCSS.swfBox;\r
+ oEl.innerHTML = movieHTML;\r
+ }\r
+\r
+ appendSuccess = true;\r
+\r
+ }\r
+\r
+ }\r
+\r
+ didAppend = true;\r
+\r
+ initMsg();\r
+\r
+ // sm2._wD(sm + ': Trying to load ' + smURL + (!overHTTP && sm2.altURL ? ' (alternate URL)' : ''), 1);\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ initMovie = function() {\r
+\r
+ if (sm2.html5Only) {\r
+ createMovie();\r
+ return false;\r
+ }\r
+\r
+ // attempt to get, or create, movie (may already exist)\r
+ if (flash) {\r
+ return false;\r
+ }\r
+\r
+ if (!sm2.url) {\r
+\r
+ /**\r
+ * Something isn't right - we've reached init, but the soundManager url property has not been set.\r
+ * User has not called setup({url: ...}), or has not set soundManager.url (legacy use case) directly before init time.\r
+ * Notify and exit. If user calls setup() with a url: property, init will be restarted as in the deferred loading case.\r
+ */\r
+\r
+ _wDS('noURL');\r
+ return false;\r
+\r
+ }\r
+\r
+ // inline markup case\r
+ flash = sm2.getMovie(sm2.id);\r
+\r
+ if (!flash) {\r
+\r
+ if (!oRemoved) {\r
+\r
+ // try to create\r
+ createMovie(sm2.id, sm2.url);\r
+\r
+ } else {\r
+\r
+ // try to re-append removed movie after reboot()\r
+ if (!isIE) {\r
+ sm2.oMC.appendChild(oRemoved);\r
+ } else {\r
+ sm2.oMC.innerHTML = oRemovedHTML;\r
+ }\r
+\r
+ oRemoved = null;\r
+ didAppend = true;\r
+\r
+ }\r
+\r
+ flash = sm2.getMovie(sm2.id);\r
+\r
+ }\r
+\r
+ if (typeof sm2.oninitmovie === 'function') {\r
+ setTimeout(sm2.oninitmovie, 1);\r
+ }\r
+\r
+ // <d>\r
+ flushMessages();\r
+ // </d>\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ delayWaitForEI = function() {\r
+\r
+ setTimeout(waitForEI, 1000);\r
+\r
+ };\r
+\r
+ rebootIntoHTML5 = function() {\r
+\r
+ // special case: try for a reboot with preferFlash: false, if 100% HTML5 mode is possible and useFlashBlock is not enabled.\r
+\r
+ window.setTimeout(function() {\r
+\r
+ complain(smc + 'useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...');\r
+\r
+ sm2.setup({\r
+ preferFlash: false\r
+ }).reboot();\r
+\r
+ // if for some reason you want to detect this case, use an ontimeout() callback and look for html5Only and didFlashBlock == true.\r
+ sm2.didFlashBlock = true;\r
+\r
+ sm2.beginDelayedInit();\r
+\r
+ }, 1);\r
+\r
+ };\r
+\r
+ waitForEI = function() {\r
+\r
+ var p,\r
+ loadIncomplete = false;\r
+\r
+ if (!sm2.url) {\r
+ // No SWF url to load (noURL case) - exit for now. Will be retried when url is set.\r
+ return false;\r
+ }\r
+\r
+ if (waitingForEI) {\r
+ return false;\r
+ }\r
+\r
+ waitingForEI = true;\r
+ event.remove(window, 'load', delayWaitForEI);\r
+\r
+ if (hasFlash && tryInitOnFocus && !isFocused) {\r
+ // Safari won't load flash in background tabs, only when focused.\r
+ _wDS('waitFocus');\r
+ return false;\r
+ }\r
+\r
+ if (!didInit) {\r
+ p = sm2.getMoviePercent();\r
+ if (p > 0 && p < 100) {\r
+ loadIncomplete = true;\r
+ }\r
+ }\r
+\r
+ setTimeout(function() {\r
+\r
+ p = sm2.getMoviePercent();\r
+\r
+ if (loadIncomplete) {\r
+ // special case: if movie *partially* loaded, retry until it's 100% before assuming failure.\r
+ waitingForEI = false;\r
+ sm2._wD(str('waitSWF'));\r
+ window.setTimeout(delayWaitForEI, 1);\r
+ return false;\r
+ }\r
+\r
+ // <d>\r
+ if (!didInit) {\r
+\r
+ sm2._wD(sm + ': No Flash response within expected time. Likely causes: ' + (p === 0 ? 'SWF load failed, ' : '') + 'Flash blocked or JS-Flash security error.' + (sm2.debugFlash ? ' ' + str('checkSWF') : ''), 2);\r
+\r
+ if (!overHTTP && p) {\r
+\r
+ _wDS('localFail', 2);\r
+\r
+ if (!sm2.debugFlash) {\r
+ _wDS('tryDebug', 2);\r
+ }\r
+\r
+ }\r
+\r
+ if (p === 0) {\r
+\r
+ // if 0 (not null), probably a 404.\r
+ sm2._wD(str('swf404', sm2.url), 1);\r
+\r
+ }\r
+\r
+ debugTS('flashtojs', false, ': Timed out' + (overHTTP ? ' (Check flash security or flash blockers)':' (No plugin/missing SWF?)'));\r
+\r
+ }\r
+ // </d>\r
+\r
+ // give up / time-out, depending\r
+\r
+ if (!didInit && okToDisable) {\r
+\r
+ if (p === null) {\r
+\r
+ // SWF failed to report load progress. Possibly blocked.\r
+\r
+ if (sm2.useFlashBlock || sm2.flashLoadTimeout === 0) {\r
+\r
+ if (sm2.useFlashBlock) {\r
+\r
+ flashBlockHandler();\r
+\r
+ }\r
+\r
+ _wDS('waitForever');\r
+\r
+ } else {\r
+\r
+ // no custom flash block handling, but SWF has timed out. Will recover if user unblocks / allows SWF load.\r
+\r
+ if (!sm2.useFlashBlock && canIgnoreFlash) {\r
+\r
+ rebootIntoHTML5();\r
+\r
+ } else {\r
+\r
+ _wDS('waitForever');\r
+\r
+ // fire any regular registered ontimeout() listeners.\r
+ processOnEvents({\r
+ type: 'ontimeout',\r
+ ignoreInit: true,\r
+ error: {\r
+ type: 'INIT_FLASHBLOCK'\r
+ }\r
+ });\r
+\r
+ }\r
+\r
+ }\r
+\r
+ } else {\r
+\r
+ // SWF loaded? Shouldn't be a blocking issue, then.\r
+\r
+ if (sm2.flashLoadTimeout === 0) {\r
+\r
+ _wDS('waitForever');\r
+\r
+ } else {\r
+\r
+ if (!sm2.useFlashBlock && canIgnoreFlash) {\r
+\r
+ rebootIntoHTML5();\r
+\r
+ } else {\r
+\r
+ failSafely(true);\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }, sm2.flashLoadTimeout);\r
+\r
+ };\r
+\r
+ handleFocus = function() {\r
+\r
+ function cleanup() {\r
+ event.remove(window, 'focus', handleFocus);\r
+ }\r
+\r
+ if (isFocused || !tryInitOnFocus) {\r
+ // already focused, or not special Safari background tab case\r
+ cleanup();\r
+ return true;\r
+ }\r
+\r
+ okToDisable = true;\r
+ isFocused = true;\r
+ _wDS('gotFocus');\r
+\r
+ // allow init to restart\r
+ waitingForEI = false;\r
+\r
+ // kick off ExternalInterface timeout, now that the SWF has started\r
+ delayWaitForEI();\r
+\r
+ cleanup();\r
+ return true;\r
+\r
+ };\r
+\r
+ flushMessages = function() {\r
+\r
+ // <d>\r
+\r
+ // SM2 pre-init debug messages\r
+ if (messages.length) {\r
+ sm2._wD('SoundManager 2: ' + messages.join(' '), 1);\r
+ messages = [];\r
+ }\r
+\r
+ // </d>\r
+\r
+ };\r
+\r
+ showSupport = function() {\r
+\r
+ // <d>\r
+\r
+ flushMessages();\r
+\r
+ var item, tests = [];\r
+\r
+ if (sm2.useHTML5Audio && sm2.hasHTML5) {\r
+ for (item in sm2.audioFormats) {\r
+ if (sm2.audioFormats.hasOwnProperty(item)) {\r
+ tests.push(item + ' = ' + sm2.html5[item] + (!sm2.html5[item] && needsFlash && sm2.flash[item] ? ' (using flash)' : (sm2.preferFlash && sm2.flash[item] && needsFlash ? ' (preferring flash)' : (!sm2.html5[item] ? ' (' + (sm2.audioFormats[item].required ? 'required, ' : '') + 'and no flash support)' : ''))));\r
+ }\r
+ }\r
+ sm2._wD('SoundManager 2 HTML5 support: ' + tests.join(', '), 1);\r
+ }\r
+\r
+ // </d>\r
+\r
+ };\r
+\r
+ initComplete = function(bNoDisable) {\r
+\r
+ if (didInit) {\r
+ return false;\r
+ }\r
+\r
+ if (sm2.html5Only) {\r
+ // all good.\r
+ _wDS('sm2Loaded', 1);\r
+ didInit = true;\r
+ initUserOnload();\r
+ debugTS('onload', true);\r
+ return true;\r
+ }\r
+\r
+ var wasTimeout = (sm2.useFlashBlock && sm2.flashLoadTimeout && !sm2.getMoviePercent()),\r
+ result = true,\r
+ error;\r
+\r
+ if (!wasTimeout) {\r
+ didInit = true;\r
+ }\r
+\r
+ error = {\r
+ type: (!hasFlash && needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')\r
+ };\r
+\r
+ sm2._wD('SoundManager 2 ' + (disabled ? 'failed to load' : 'loaded') + ' (' + (disabled ? 'Flash security/load error' : 'OK') + ') ' + String.fromCharCode(disabled ? 10006 : 10003), disabled ? 2: 1);\r
+\r
+ if (disabled || bNoDisable) {\r
+\r
+ if (sm2.useFlashBlock && sm2.oMC) {\r
+ sm2.oMC.className = getSWFCSS() + ' ' + (sm2.getMoviePercent() === null ? swfCSS.swfTimedout : swfCSS.swfError);\r
+ }\r
+\r
+ processOnEvents({\r
+ type: 'ontimeout',\r
+ error: error,\r
+ ignoreInit: true\r
+ });\r
+\r
+ debugTS('onload', false);\r
+ catchError(error);\r
+\r
+ result = false;\r
+\r
+ } else {\r
+\r
+ debugTS('onload', true);\r
+\r
+ }\r
+\r
+ if (!disabled) {\r
+\r
+ if (sm2.waitForWindowLoad && !windowLoaded) {\r
+\r
+ _wDS('waitOnload');\r
+ event.add(window, 'load', initUserOnload);\r
+\r
+ } else {\r
+\r
+ // <d>\r
+ if (sm2.waitForWindowLoad && windowLoaded) {\r
+ _wDS('docLoaded');\r
+ }\r
+ // </d>\r
+\r
+ initUserOnload();\r
+\r
+ }\r
+\r
+ }\r
+\r
+ return result;\r
+\r
+ };\r
+\r
+ /**\r
+ * apply top-level setupOptions object as local properties, eg., this.setupOptions.flashVersion -> this.flashVersion (soundManager.flashVersion)\r
+ * this maintains backward compatibility, and allows properties to be defined separately for use by soundManager.setup().\r
+ */\r
+\r
+ setProperties = function() {\r
+\r
+ var i,\r
+ o = sm2.setupOptions;\r
+\r
+ for (i in o) {\r
+\r
+ if (o.hasOwnProperty(i)) {\r
+\r
+ // assign local property if not already defined\r
+\r
+ if (sm2[i] === _undefined) {\r
+\r
+ sm2[i] = o[i];\r
+\r
+ } else if (sm2[i] !== o[i]) {\r
+\r
+ // legacy support: write manually-assigned property (eg., soundManager.url) back to setupOptions to keep things in sync\r
+ sm2.setupOptions[i] = sm2[i];\r
+\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ };\r
+\r
+\r
+ init = function() {\r
+\r
+ // called after onload()\r
+\r
+ if (didInit) {\r
+ _wDS('didInit');\r
+ return false;\r
+ }\r
+\r
+ function cleanup() {\r
+ event.remove(window, 'load', sm2.beginDelayedInit);\r
+ }\r
+\r
+ if (sm2.html5Only) {\r
+\r
+ if (!didInit) {\r
+ // we don't need no steenking flash!\r
+ cleanup();\r
+ sm2.enabled = true;\r
+ initComplete();\r
+ }\r
+\r
+ return true;\r
+\r
+ }\r
+\r
+ // flash path\r
+ initMovie();\r
+\r
+ try {\r
+\r
+ // attempt to talk to Flash\r
+ flash._externalInterfaceTest(false);\r
+\r
+ /**\r
+ * Apply user-specified polling interval, OR, if "high performance" set, faster vs. default polling\r
+ * (determines frequency of whileloading/whileplaying callbacks, effectively driving UI framerates)\r
+ */\r
+ setPolling(true, (sm2.flashPollingInterval || (sm2.useHighPerformance ? 10 : 50)));\r
+\r
+ if (!sm2.debugMode) {\r
+ // stop the SWF from making debug output calls to JS\r
+ flash._disableDebug();\r
+ }\r
+\r
+ sm2.enabled = true;\r
+ debugTS('jstoflash', true);\r
+\r
+ if (!sm2.html5Only) {\r
+ // prevent browser from showing cached page state (or rather, restoring "suspended" page state) via back button, because flash may be dead\r
+ // http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/\r
+ event.add(window, 'unload', doNothing);\r
+ }\r
+\r
+ } catch(e) {\r
+\r
+ sm2._wD('js/flash exception: ' + e.toString());\r
+\r
+ debugTS('jstoflash', false);\r
+\r
+ catchError({\r
+ type: 'JS_TO_FLASH_EXCEPTION',\r
+ fatal: true\r
+ });\r
+\r
+ // don't disable, for reboot()\r
+ failSafely(true);\r
+\r
+ initComplete();\r
+\r
+ return false;\r
+\r
+ }\r
+\r
+ initComplete();\r
+\r
+ // disconnect events\r
+ cleanup();\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ domContentLoaded = function() {\r
+\r
+ if (didDCLoaded) {\r
+ return false;\r
+ }\r
+\r
+ didDCLoaded = true;\r
+\r
+ // assign top-level soundManager properties eg. soundManager.url\r
+ setProperties();\r
+\r
+ initDebug();\r
+\r
+ if (!hasFlash && sm2.hasHTML5) {\r
+\r
+ sm2._wD('SoundManager 2: No Flash detected' + (!sm2.useHTML5Audio ? ', enabling HTML5.' : '. Trying HTML5-only mode.'), 1);\r
+\r
+ sm2.setup({\r
+ 'useHTML5Audio': true,\r
+ // make sure we aren't preferring flash, either\r
+ // TODO: preferFlash should not matter if flash is not installed. Currently, stuff breaks without the below tweak.\r
+ 'preferFlash': false\r
+ });\r
+\r
+ }\r
+\r
+ testHTML5();\r
+\r
+ if (!hasFlash && needsFlash) {\r
+\r
+ messages.push(strings.needFlash);\r
+\r
+ // TODO: Fatal here vs. timeout approach, etc.\r
+ // hack: fail sooner.\r
+ sm2.setup({\r
+ 'flashLoadTimeout': 1\r
+ });\r
+\r
+ }\r
+\r
+ if (doc.removeEventListener) {\r
+ doc.removeEventListener('DOMContentLoaded', domContentLoaded, false);\r
+ }\r
+\r
+ initMovie();\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ domContentLoadedIE = function() {\r
+\r
+ if (doc.readyState === 'complete') {\r
+ domContentLoaded();\r
+ doc.detachEvent('onreadystatechange', domContentLoadedIE);\r
+ }\r
+\r
+ return true;\r
+\r
+ };\r
+\r
+ winOnLoad = function() {\r
+\r
+ // catch edge case of initComplete() firing after window.load()\r
+ windowLoaded = true;\r
+\r
+ // catch case where DOMContentLoaded has been sent, but we're still in doc.readyState = 'interactive'\r
+ domContentLoaded();\r
+\r
+ event.remove(window, 'load', winOnLoad);\r
+\r
+ };\r
+\r
+ // sniff up-front\r
+ detectFlash();\r
+\r
+ // focus and window load, init (primarily flash-driven)\r
+ event.add(window, 'focus', handleFocus);\r
+ event.add(window, 'load', delayWaitForEI);\r
+ event.add(window, 'load', winOnLoad);\r
+\r
+ if (doc.addEventListener) {\r
+\r
+ doc.addEventListener('DOMContentLoaded', domContentLoaded, false);\r
+\r
+ } else if (doc.attachEvent) {\r
+\r
+ doc.attachEvent('onreadystatechange', domContentLoadedIE);\r
+\r
+ } else {\r
+\r
+ // no add/attachevent support - safe to assume no JS -> Flash either\r
+ debugTS('onload', false);\r
+ catchError({\r
+ type: 'NO_DOM2_EVENTS',\r
+ fatal: true\r
+ });\r
+\r
+ }\r
+\r
+} // SoundManager()\r
+\r
+// SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading\r
+\r
+if (window.SM2_DEFER === _undefined || !SM2_DEFER) {\r
+ soundManager = new SoundManager();\r
+}\r
+\r
+/**\r
+ * SoundManager public interfaces\r
+ * ------------------------------\r
+ */\r
+\r
+if (typeof module === 'object' && module && typeof module.exports === 'object') {\r
+\r
+ /**\r
+ * commonJS module\r
+ */\r
+\r
+ module.exports.SoundManager = SoundManager;\r
+ module.exports.soundManager = soundManager;\r
+\r
+} else if (typeof define === 'function' && define.amd) {\r
+\r
+ /**\r
+ * AMD - requireJS\r
+ * basic usage:\r
+ * require(["/path/to/soundmanager2.js"], function(SoundManager) {\r
+ * SoundManager.getInstance().setup({\r
+ * url: '/swf/',\r
+ * onready: function() { ... }\r
+ * })\r
+ * });\r
+ *\r
+ * SM2_DEFER usage:\r
+ * window.SM2_DEFER = true;\r
+ * require(["/path/to/soundmanager2.js"], function(SoundManager) {\r
+ * SoundManager.getInstance(function() {\r
+ * var soundManager = new SoundManager.constructor();\r
+ * soundManager.setup({\r
+ * url: '/swf/',\r
+ * ...\r
+ * });\r
+ * ...\r
+ * soundManager.beginDelayedInit();\r
+ * return soundManager;\r
+ * })\r
+ * }); \r
+ */\r
+\r
+ define(function() {\r
+ /**\r
+ * Retrieve the global instance of SoundManager.\r
+ * If a global instance does not exist it can be created using a callback.\r
+ *\r
+ * @param {Function} smBuilder Optional: Callback used to create a new SoundManager instance\r
+ * @return {SoundManager} The global SoundManager instance\r
+ */\r
+ function getInstance(smBuilder) {\r
+ if (!window.soundManager && smBuilder instanceof Function) {\r
+ var instance = smBuilder(SoundManager);\r
+ if (instance instanceof SoundManager) {\r
+ window.soundManager = instance;\r
+ }\r
+ }\r
+ return window.soundManager;\r
+ }\r
+ return {\r
+ constructor: SoundManager,\r
+ getInstance: getInstance\r
+ }\r
+ });\r
+\r
+}\r
+\r
+// standard browser case\r
+\r
+// constructor\r
+window.SoundManager = SoundManager;\r
+\r
+/**\r
+ * note: SM2 requires a window global due to Flash, which makes calls to window.soundManager.\r
+ * Flash may not always be needed, but this is not known until async init and SM2 may even "reboot" into Flash mode.\r
+ */\r
+\r
+// public API, flash callbacks etc.\r
+window.soundManager = soundManager;\r
+\r
+}(window));\r
--- /dev/null
+/**\r
+ * SoundManager 2: Javascript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code licensed under the BSD License:\r
+ * http://www.schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * Flash 8 / ActionScript 2 version\r
+ *\r
+ * Compiling AS to Flash 8 SWF using MTASC (free compiler - http://www.mtasc.org/):\r
+ * mtasc -swf soundmanager2.swf -main -header 16:16:30 SoundManager2.as -version 8\r
+ *\r
+ * ActionScript Sound class reference (Macromedia), documentation download:\r
+ * http://livedocs.macromedia.com/flash/8/\r
+ * Previously-live URL:\r
+ * http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002668.html\r
+ *\r
+ * *** NOTE ON LOCAL FILE SYSTEM ACCESS ***\r
+ *\r
+ * Flash security allows local OR network access, but not both\r
+ * unless explicitly whitelisted/allowed by the flash player's\r
+ * security settings.\r
+ *\r
+ * To enable in-flash messaging for troubleshooting, pass debug=1 in FlashVars (within object/embed code)\r
+ * SM2 will do this by default when soundManager.debugFlash = true.\r
+ *\r
+ */\r
+\r
+import flash.external.ExternalInterface; // woo\r
+\r
+class SoundManager2 {\r
+\r
+ static var app: SoundManager2;\r
+\r
+ function SoundManager2() {\r
+\r
+ var version = "V2.97a.20150601";\r
+ var version_as = "(AS2/Flash 8)";\r
+\r
+ /**\r
+ * Cross-domain security options\r
+ * HTML on foo.com loading .swf hosted on bar.com? Define your "HTML domain" here to allow JS+Flash communication to work.\r
+ * // allow_xdomain_scripting = true;\r
+ * // xdomain = "foo.com";\r
+ * For all domains (possible security risk?), use xdomain = "*"; which ends up as System.security.allowDomain("*");\r
+ * When loading from HTTPS, use System.security.allowInsecureDomain();\r
+ * See "allowDomain (security.allowDomain method)" in Flash 8/AS2 liveDocs documentation (AS2 reference -> classes -> security)\r
+ * download from http://livedocs.macromedia.com/flash/8/\r
+ * Related AS3 documentation: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/Security.html#allowDomain%28%29\r
+ */\r
+\r
+ var allow_xdomain_scripting = false;\r
+ var xdomain = "*";\r
+\r
+ if (allow_xdomain_scripting && xdomain) {\r
+ System.security.allowDomain(xdomain);\r
+ version_as += ' - cross-domain enabled';\r
+ }\r
+\r
+ // externalInterface references (for Javascript callbacks)\r
+ var baseJSController = "soundManager";\r
+ var baseJSObject = baseJSController + ".sounds";\r
+\r
+ // internal objects\r
+ var sounds = []; // indexed string array\r
+ var soundObjects = []; // associative Sound() object array\r
+ var timer = null;\r
+ var pollingEnabled = false; // polling (timer) flag - disabled by default, enabled by JS->Flash call\r
+ var debugEnabled = true; // Flash debug output enabled by default, disabled by JS call\r
+ var flashDebugEnabled = false; // debug output to flash movie, off by default\r
+ var didSandboxMessage = false;\r
+ var caughtFatal = false;\r
+\r
+ // for flash text output, debugging etc.\r
+ var _messages = [];\r
+ var _messageObj = null;\r
+ flashDebugEnabled = (_root.debug == 1);\r
+\r
+ // display stuffs\r
+ Stage.scaleMode = 'noScale';\r
+ Stage.align = 'TL';\r
+\r
+ // context menu item with version info\r
+\r
+ var doNothing = function() {}\r
+\r
+ var sm2Menu:ContextMenu = new ContextMenu();\r
+ var sm2MenuItem:ContextMenuItem = new ContextMenuItem('SoundManager ' + version + ' ' + version_as, doNothing);\r
+ sm2MenuItem.enabled = false;\r
+ sm2Menu.customItems.push(sm2MenuItem);\r
+ _root.menu = sm2Menu;\r
+\r
+ var writeDebug = function(s, logLevel) {\r
+ // <d>\r
+ if (!debugEnabled) return false;\r
+ ExternalInterface.call(baseJSController + "['_writeDebug']", "(Flash): " + s, (logLevel || 0));\r
+ // </d>\r
+ }\r
+\r
+ var flashDebug = function(messageText) {\r
+ // <d>\r
+ _messages.push(messageText);\r
+ if (!flashDebugEnabled) {\r
+ return false;\r
+ }\r
+ var sans = new TextFormat();\r
+ sans.size = 12;\r
+ sans.font = "Arial";\r
+\r
+ // 320x240 if no stage dimensions (happens in IE, apparently 0 before stage resize event fires.)\r
+ var w = Stage.width?Stage.width:320;\r
+ var h = Stage.height?Stage.height:240;\r
+ if (!_messageObj) {\r
+ _messageObj = _root.createTextField("_messageObj", 0, 0, 0, w, h);\r
+ _messageObj.x = 0;\r
+ _messageObj.y = 0;\r
+ _messageObj.multiline = true;\r
+ _messageObj.html = true;\r
+ _messageObj.wordWrap = true;\r
+ _messageObj.align = 'left';\r
+ _messageObj.autoSize = false;\r
+ }\r
+ _messageObj.htmlText = _messages.join('\n');\r
+ _messageObj.setTextFormat(sans);\r
+ _messageObj.width = w;\r
+ _messageObj.height = h;\r
+ // </d>\r
+ }\r
+\r
+ var _externalInterfaceTest = function(isFirstCall) {\r
+ var sandboxType = System.security['sandboxType'];\r
+ try {\r
+ if (isFirstCall) {\r
+ flashDebug('Testing Flash -> JS...')\r
+ if (!didSandboxMessage && sandboxType != 'remote' && sandboxType != 'localTrusted') {\r
+ didSandboxMessage = true;\r
+ flashDebug('<br><b>Fatal: Security sandbox error: Got "' + sandboxType + '", expected "remote" or "localTrusted".<br>Additional security permissions need to be granted.<br>See <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html">flash security settings panel</a> for non-HTTP, eg. file:// use.</b><br>http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html<br><br>You may also be able to right-click this movie and choose from the menu: <br>"Global Settings" -> "Advanced" tab -> "Trusted Location Settings"<br>');\r
+ }\r
+ ExternalInterface.call(baseJSController + "._externalInterfaceOK", version);\r
+ if (!didSandboxMessage) {\r
+ flashDebug('Flash -> JS OK');\r
+ flashDebug('Waiting for JS -> Flash...');\r
+ }\r
+ } else {\r
+ // writeDebug('SM2 SWF ' + version + ' ' + version_as, 1);\r
+ ExternalInterface.call(baseJSController + "._setSandboxType", sandboxType);\r
+ flashDebug('JS -> Flash OK');\r
+ }\r
+ } catch(e) {\r
+ flashDebug(e.toString());\r
+ if (!caughtFatal) {\r
+ caughtFatal = true;\r
+ }\r
+ return false;\r
+ }\r
+ return true; // to verify that a call from JS to here, works. (eg. JS receives "true", thus OK.)\r
+ }\r
+\r
+ var _disableDebug = function() {\r
+ // prevent future debug calls from Flash going to client (maybe improve performance)\r
+ writeDebug('_disableDebug()');\r
+ debugEnabled = false;\r
+ }\r
+\r
+ var checkProgress = function() {\r
+ var bL = 0;\r
+ var bT = 0;\r
+ var nD = 0;\r
+ var nP = 0;\r
+ var oSound = null;\r
+ for (var i = 0, j = sounds.length; i < j; i++) {\r
+ oSound = soundObjects[sounds[i]];\r
+ bL = oSound.getBytesLoaded();\r
+ bT = oSound.getBytesTotal();\r
+ nD = oSound.duration || 0; // can sometimes be null with short MP3s? Wack.\r
+ nP = oSound.position;\r
+ if (bL && bT && bL != oSound.lastValues.bytes) {\r
+ oSound.lastValues.bytes = bL;\r
+ ExternalInterface.call(baseJSObject + "['" + oSound.sID + "']._whileloading", bL, bT, nD);\r
+ }\r
+ if (typeof nP != 'undefined' && nP != oSound.lastValues.position) {\r
+ oSound.lastValues.position = nP;\r
+ ExternalInterface.call(baseJSObject + "['" + oSound.sID + "']._whileplaying", nP);\r
+ // if position changed, check for near-end\r
+ }\r
+ }\r
+ }\r
+\r
+ var onLoad = function(bSuccess) {\r
+ checkProgress(); // ensure progress stats are up-to-date\r
+ // force duration update (doesn't seem to be always accurate)\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._whileloading", this.getBytesLoaded(), this.getBytesTotal(), this.duration);\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onload", this.duration > 0 ? 1 : 0); // bSuccess doesn't always seem to work, so check MP3 duration instead.\r
+ }\r
+\r
+ var onID3 = function() {\r
+ // --- NOTE: BUGGY? ---\r
+ // --------------------\r
+ // TODO: Investigate holes in ID3 parsing - for some reason, Album will be populated with Date if empty and date is provided. (?)\r
+ // ID3V1 seem to parse OK, but "holes" / blanks in ID3V2 data seem to get messed up (eg. missing album gets filled with date.)\r
+ // iTunes issues: onID3 was not called with a test MP3 encoded with iTunes 7.01, and what appeared to be valid ID3V2 data.\r
+ // May be related to thumbnails for album art included in MP3 file by iTunes. See http://mabblog.com/blog/?p=33\r
+ var id3Data = [];\r
+ var id3Props = [];\r
+ for (var prop in this.id3) {\r
+ id3Props.push(prop);\r
+ id3Data.push(this.id3[prop]);\r
+ // writeDebug('id3['+prop+']: '+this.id3[prop]);\r
+ }\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onid3", id3Props, id3Data);\r
+ // unhook own event handler, prevent second call (can fire twice as data is received - ID3V2 at beginning, ID3V1 at end.)\r
+ // Therefore if ID3V2 data is received, ID3V1 is ignored.\r
+ soundObjects[this.sID].onID3 = null;\r
+ }\r
+\r
+ var registerOnComplete = function(sID) {\r
+ soundObjects[sID].onSoundComplete = function() {\r
+ checkProgress();\r
+ ExternalInterface.call(baseJSObject + "['" + sID + "']._onfinish");\r
+ }\r
+ }\r
+\r
+ var _setPosition = function(sID, nSecOffset, isPaused, _allowMultiShot) {\r
+ // note: multiShot is Flash 9-only; retained so JS/Flash function signatures are identical.\r
+ var s = soundObjects[sID];\r
+ // writeDebug('_setPosition()');\r
+ s.lastValues.position = s.position;\r
+ if (s.lastValues.loops > 1 && nSecOffset != 0) {\r
+ writeDebug('Warning: Looping functionality being disabled due to Flash limitation.', 240);\r
+ s.lastValues.loops = 1;\r
+ }\r
+ s.start(nSecOffset, s.lastValues.nLoops || 1); // start playing at new position\r
+ if (isPaused) {\r
+ s.stop();\r
+ }\r
+ }\r
+\r
+ var _load = function(sID, sURL, bStream, bAutoPlay, bCheckPolicyFile) {\r
+ // writeDebug('_load(): '+sID+', '+sURL+', '+bStream+', '+bAutoPlay+', '+bCheckPolicyFile);\r
+ if (typeof bAutoPlay == 'undefined') {\r
+ bAutoPlay = false;\r
+ }\r
+ if (typeof bStream == 'undefined') {\r
+ bStream = true;\r
+ }\r
+ if (typeof bCheckPolicyFile == 'undefined') {\r
+ bCheckPolicyFile = false;\r
+ }\r
+ // writeDebug('bStream: '+bStream);\r
+ // writeDebug('bAutoPlay: '+bAutoPlay);\r
+ // checkProgress();\r
+ var s = soundObjects[sID];\r
+ s.onID3 = onID3;\r
+ s.onLoad = onLoad;\r
+ s.loaded = true;\r
+ s.checkPolicyFile = bCheckPolicyFile;\r
+ s.loadSound(sURL, bStream);\r
+ if (bAutoPlay != true) {\r
+ s.stop(); // prevent default auto-play behaviour\r
+ } else {\r
+ writeDebug('auto-play allowed');\r
+ }\r
+ registerOnComplete(sID);\r
+ }\r
+\r
+ var _unload = function(sID, sURL) {\r
+ // effectively "stop" loading by loading a tiny MP3\r
+ var s = soundObjects[sID];\r
+ s.onID3 = null;\r
+ s.onLoad = null;\r
+ s.loaded = false;\r
+ // ensure position is reset, if unload fails\r
+ s.start(0,1);\r
+ s.stop();\r
+ s.loadSound(sURL, true);\r
+ s.stop(); // prevent auto-play\r
+ }\r
+\r
+ var _createSound = function(sID, loops, checkPolicyFile) {\r
+ var s = new Sound();\r
+ if (!soundObjects[sID]) {\r
+ sounds.push(sID);\r
+ }\r
+ soundObjects[sID] = s;\r
+ s.setVolume(100);\r
+ s.sID = sID;\r
+ s.paused = false;\r
+ s.loaded = false;\r
+ s.checkPolicyFile = checkPolicyFile;\r
+ s.lastValues = {\r
+ bytes: 0,\r
+ position: 0,\r
+ nLoops: loops||1\r
+ };\r
+ }\r
+\r
+ var _destroySound = function(sID) {\r
+ // for the power of garbage collection! .. er, Greyskull!\r
+ var s = (soundObjects[sID] || null);\r
+ if (!s) {\r
+ return false;\r
+ }\r
+ for (var i = 0; i < sounds.length; i++) {\r
+ if (sounds[i] == sID) {\r
+ sounds.splice(i, 1);\r
+ break;\r
+ }\r
+ }\r
+ s = null;\r
+ delete soundObjects[sID];\r
+ }\r
+\r
+ var _stop = function(sID, bStopAll) {\r
+ // stop this particular instance (or "all", based on parameter)\r
+ if (bStopAll) {\r
+ _root.stop();\r
+ } else {\r
+ soundObjects[sID].stop();\r
+ soundObjects[sID].paused = false;\r
+ }\r
+ }\r
+\r
+ var _start = function(sID, nLoops, nMsecOffset, _allowMultiShot) {\r
+ // note: multiShot is Flash 9-only; retained so JS/Flash function signatures are identical.\r
+ // writeDebug('_start: ' + sID + ', loops: ' + nLoops + ', nMsecOffset: ' + nMsecOffset);\r
+ registerOnComplete();\r
+ var s = soundObjects[sID];\r
+ s.lastValues.paused = false; // reset pause if applicable\r
+ s.lastValues.nLoops = (nLoops || 1);\r
+ s.start(nMsecOffset, nLoops);\r
+ return true;\r
+ }\r
+\r
+ var _pause = function(sID, _allowMultiShot) {\r
+ // note: multiShot is Flash 9-only; retained so JS/Flash function signatures are identical.\r
+ // writeDebug('_pause()');\r
+ var s = soundObjects[sID];\r
+ if (!s.paused) {\r
+ // reference current position, stop sound\r
+ s.paused = true;\r
+ s.lastValues.position = s.position;\r
+ // writeDebug('_pause(): position: '+s.lastValues.position);\r
+ s.stop();\r
+ } else {\r
+ // resume playing from last position\r
+ // writeDebug('resuming - playing at '+s.lastValues.position+', '+s.lastValues.nLoops+' times');\r
+ s.paused = false;\r
+ s.start(s.lastValues.position / 1000, s.lastValues.nLoops);\r
+ }\r
+ }\r
+\r
+ var _setPan = function(sID, nPan) {\r
+ soundObjects[sID].setPan(nPan);\r
+ }\r
+\r
+ var _setVolume = function(sID, nVol) {\r
+ soundObjects[sID].setVolume(nVol);\r
+ }\r
+\r
+ var _setPolling = function(bPolling, timerInterval) {\r
+ if (typeof timerInterval === 'undefined') {\r
+ timerInterval = 50;\r
+ }\r
+ pollingEnabled = bPolling;\r
+ if (timer == null && pollingEnabled) {\r
+ flashDebug('Enabling polling, ' + timerInterval + ' ms interval');\r
+ timer = setInterval(checkProgress, timerInterval);\r
+ } else if (timer && !pollingEnabled) {\r
+ flashDebug('Disabling polling');\r
+ clearInterval(timer);\r
+ timer = null;\r
+ }\r
+ }\r
+\r
+ var _init = function() {\r
+\r
+ // OK now stuff should be available\r
+ try {\r
+ flashDebug('Adding ExternalInterface callbacks...');\r
+ ExternalInterface.addCallback('_load', this, _load);\r
+ ExternalInterface.addCallback('_unload', this, _unload);\r
+ ExternalInterface.addCallback('_stop', this, _stop);\r
+ ExternalInterface.addCallback('_start', this, _start);\r
+ ExternalInterface.addCallback('_pause', this, _pause);\r
+ ExternalInterface.addCallback('_setPosition', this, _setPosition);\r
+ ExternalInterface.addCallback('_setPan', this, _setPan);\r
+ ExternalInterface.addCallback('_setVolume', this, _setVolume);\r
+ ExternalInterface.addCallback('_setPolling', this, _setPolling);\r
+ ExternalInterface.addCallback('_externalInterfaceTest', this, _externalInterfaceTest);\r
+ ExternalInterface.addCallback('_disableDebug', this, _disableDebug);\r
+ ExternalInterface.addCallback('_createSound', this, _createSound);\r
+ ExternalInterface.addCallback('_destroySound', this, _destroySound);\r
+ } catch(e) {\r
+ flashDebug('Fatal: ExternalInterface error: ' + e.toString());\r
+ }\r
+ // try to talk to JS, do init etc.\r
+ _externalInterfaceTest(true);\r
+ // flashDebug('Init OK');\r
+ }\r
+\r
+ flashDebug('SM2 SWF ' + version + ' ' + version_as);\r
+\r
+ if (ExternalInterface.available) {\r
+ flashDebug('ExternalInterface available');\r
+ _init();\r
+ } else {\r
+ // d'oh! - may be from a corrupt install, ancient (pre-Netscape 6?) browser etc.\r
+ flashDebug('Fatal: ExternalInterface (Flash <-> JS) not available');\r
+ }\r
+\r
+\r
+ } // SoundManager2()\r
+\r
+ // entry point\r
+ static function main(mc) {\r
+ app = new SoundManager2();\r
+ }\r
+\r
+}
\ No newline at end of file
--- /dev/null
+/**\r
+ * SoundManager 2: Javascript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code licensed under the BSD License:\r
+ * http://www.schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * Flash 9 / ActionScript 3 version\r
+ */\r
+\r
+package {\r
+\r
+ import flash.display.Sprite;\r
+ import flash.events.Event;\r
+ import flash.events.IOErrorEvent;\r
+ import flash.events.MouseEvent;\r
+ import flash.events.SecurityErrorEvent;\r
+ import flash.events.AsyncErrorEvent;\r
+ import flash.events.NetStatusEvent;\r
+ import flash.events.TimerEvent;\r
+ import flash.external.ExternalInterface; // woo\r
+ import flash.media.Sound;\r
+ import flash.media.SoundChannel;\r
+ import flash.media.SoundMixer;\r
+ import flash.net.URLLoader;\r
+ import flash.net.URLRequest;\r
+ import flash.system.Security;\r
+ import flash.system.System;\r
+ import flash.text.TextField;\r
+ import flash.text.TextFormat;\r
+ import flash.text.TextFieldAutoSize;\r
+ import flash.ui.ContextMenu;\r
+ import flash.ui.ContextMenuItem;\r
+ import flash.utils.setInterval;\r
+ import flash.utils.clearInterval;\r
+ import flash.utils.Dictionary;\r
+ import flash.utils.Timer;\r
+\r
+ public class SoundManager2_AS3 extends Sprite {\r
+\r
+ public var version:String = "V2.97a.20150601";\r
+ public var version_as:String = "(AS3/Flash 9)";\r
+\r
+ /**\r
+ * Cross-domain security options\r
+ * HTML on foo.com loading .swf hosted on bar.com? Define your "HTML domain" here to allow JS+Flash communication to work.\r
+ * // allow_xdomain_scripting = true;\r
+ * // xdomain = "foo.com";\r
+ * For all domains (possible security risk?), use xdomain = "*"; which ends up as System.security.allowDomain("*");\r
+ * When loading from HTTPS, use System.security.allowInsecureDomain();\r
+ * See http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/Security.html#allowDomain()\r
+ */\r
+ public var allow_xdomain_scripting:Boolean = false;\r
+ public var xdomain:String = "*";\r
+\r
+ // externalInterface references (for Javascript callbacks)\r
+ public var baseJSController:String = "soundManager";\r
+ public var baseJSObject:String = baseJSController + ".sounds";\r
+\r
+ // internal objects\r
+ public var sounds:Array = []; // indexed string array\r
+ public var soundObjects: Dictionary = new Dictionary(); // associative Sound() object Dictionary type\r
+ public var timer: Timer = null;\r
+ public var pollingEnabled: Boolean = false; // polling (timer) flag - disabled by default, enabled by JS->Flash call\r
+ public var debugEnabled: Boolean = true; // Flash debug output enabled by default, disabled by JS call\r
+ public var flashDebugEnabled: Boolean = false; // Flash internal debug output (write to visible SWF in browser)\r
+ public var loaded: Boolean = false;\r
+ public var currentObject: SoundManager2_SMSound_AS3 = null;\r
+ public var paramList:Object = null;\r
+ public var messages:Array = [];\r
+ public var textField: TextField = null;\r
+ public var textStyle: TextFormat = new TextFormat();\r
+ public var didSandboxMessage: Boolean = false;\r
+ public var caughtFatal: Boolean = false;\r
+\r
+ public function SoundManager2_AS3() {\r
+\r
+ if (allow_xdomain_scripting && xdomain) {\r
+ Security.allowDomain(xdomain);\r
+ version_as += ' - cross-domain enabled';\r
+ }\r
+\r
+ this.paramList = this.root.loaderInfo.parameters;\r
+\r
+ // <d>\r
+ if (this.paramList['debug'] == 1) {\r
+ this.flashDebugEnabled = true;\r
+ }\r
+\r
+ if (this.flashDebugEnabled) {\r
+ var canvas: Sprite = new Sprite();\r
+ canvas.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);\r
+ addChild(canvas);\r
+ }\r
+ // </d>\r
+\r
+ flashDebug('SM2 SWF ' + version + ' ' + version_as);\r
+\r
+ // context menu item with version info\r
+\r
+ var sm2Menu:ContextMenu = new ContextMenu();\r
+ var sm2MenuItem:ContextMenuItem = new ContextMenuItem('SoundManager ' + version + ' ' + version_as);\r
+ sm2MenuItem.enabled = false;\r
+ sm2Menu.customItems.push(sm2MenuItem);\r
+ contextMenu = sm2Menu;\r
+\r
+ if (ExternalInterface.available) {\r
+ flashDebug('ExternalInterface available');\r
+ try {\r
+ flashDebug('Adding ExternalInterface callbacks...');\r
+ ExternalInterface.addCallback('_load', _load);\r
+ ExternalInterface.addCallback('_unload', _unload);\r
+ ExternalInterface.addCallback('_stop', _stop);\r
+ ExternalInterface.addCallback('_start', _start);\r
+ ExternalInterface.addCallback('_pause', _pause);\r
+ ExternalInterface.addCallback('_setPosition', _setPosition);\r
+ ExternalInterface.addCallback('_setPan', _setPan);\r
+ ExternalInterface.addCallback('_setVolume', _setVolume);\r
+ ExternalInterface.addCallback('_setPolling', _setPolling);\r
+ ExternalInterface.addCallback('_externalInterfaceTest', _externalInterfaceTest);\r
+ ExternalInterface.addCallback('_disableDebug', _disableDebug);\r
+ ExternalInterface.addCallback('_getMemoryUse', _getMemoryUse);\r
+ ExternalInterface.addCallback('_createSound', _createSound);\r
+ ExternalInterface.addCallback('_destroySound', _destroySound);\r
+ ExternalInterface.addCallback('_setAutoPlay', _setAutoPlay);\r
+ } catch(e: Error) {\r
+ flashDebug('Fatal: ExternalInterface error: ' + e.toString());\r
+ }\r
+ } else {\r
+ flashDebug('Fatal: ExternalInterface (Flash <-> JS) not available');\r
+ };\r
+\r
+ // call after delay, to be safe (ensure callbacks are registered by the time JS is called below)\r
+ var timer: Timer = new Timer(20, 0);\r
+ timer.addEventListener(TimerEvent.TIMER, function() : void {\r
+ timer.reset();\r
+ _externalInterfaceTest(true);\r
+ // timer.reset();\r
+ // flashDebug('Init OK');\r
+ });\r
+ timer.start();\r
+ // delayed, see above\r
+ // _externalInterfaceTest(true);\r
+ } // SoundManager2()\r
+\r
+ public function flashDebug (txt:String) : void {\r
+ // <d>\r
+ messages.push(txt);\r
+ if (this.flashDebugEnabled) {\r
+ var didCreate: Boolean = false;\r
+ textStyle.font = 'Arial';\r
+ textStyle.size = 12;\r
+ // 320x240 if no stage dimensions (happens in IE, apparently 0 before stage resize event fires.)\r
+ var w:Number = this.stage.width?this.stage.width:320;\r
+ var h:Number = this.stage.height?this.stage.height:240;\r
+ if (textField == null) {\r
+ didCreate = true;\r
+ textField = new TextField();\r
+ textField.autoSize = TextFieldAutoSize.LEFT;\r
+ textField.x = 0;\r
+ textField.y = 0;\r
+ textField.multiline = true;\r
+ textField.textColor = 0;\r
+ textField.wordWrap = true;\r
+ }\r
+ textField.htmlText = messages.join('\n');\r
+ textField.setTextFormat(textStyle);\r
+ textField.width = w;\r
+ textField.height = h;\r
+ if (didCreate) {\r
+ this.addChild(textField);\r
+ }\r
+ }\r
+ // </d>\r
+ }\r
+\r
+ public function _setAutoPlay(sID:String, autoPlay:Boolean) : void {\r
+ var s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ if (s) {\r
+ s.setAutoPlay(autoPlay);\r
+ }\r
+ }\r
+\r
+ // methods\r
+ // -----------------------------------\r
+\r
+ public function writeDebug (s:String, logLevel:Number = 0) : Boolean {\r
+ if (!debugEnabled) {\r
+ return false;\r
+ }\r
+ // <d>\r
+ ExternalInterface.call(baseJSController + "['_writeDebug']", "(Flash): " + s, null, logLevel);\r
+ // </d>\r
+ return true;\r
+ }\r
+\r
+ public function _externalInterfaceTest(isFirstCall: Boolean) : Boolean {\r
+ var sandboxType:String = flash.system.Security['sandboxType'];\r
+ if (!didSandboxMessage && sandboxType != 'localTrusted' && sandboxType != 'remote') {\r
+ didSandboxMessage = true;\r
+ flashDebug('<br><b>Fatal: Security sandbox error: Got "' + sandboxType + '", expected "remote" or "localTrusted".<br>Additional security permissions need to be granted.<br>See <a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html">flash security settings panel</a> for non-HTTP, eg., file:// use.</b><br>http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html<br><br>You may also be able to right-click this movie and choose from the menu: <br>"Global Settings" -> "Advanced" tab -> "Trusted Location Settings"<br>');\r
+ }\r
+ try {\r
+ if (isFirstCall == true) {\r
+ flashDebug('Testing Flash -> JS...');\r
+ ExternalInterface.call(baseJSController + "._externalInterfaceOK", version);\r
+ flashDebug('Flash -> JS OK');\r
+ flashDebug('Waiting for JS -> Flash...');\r
+ } else {\r
+ // writeDebug('SM2 SWF ' + version + ' ' + version_as, 1);\r
+ ExternalInterface.call(baseJSController + "._setSandboxType", sandboxType);\r
+ flashDebug('JS -> Flash OK');\r
+ }\r
+ } catch(e: Error) {\r
+ flashDebug('Fatal: Flash <-> JS error: ' + e.toString());\r
+ writeDebug('_externalInterfaceTest: Error: ' + e.toString(), 2);\r
+ if (!caughtFatal) {\r
+ caughtFatal = true;\r
+ }\r
+ return false;\r
+ }\r
+ return true; // to verify that a call from JS to here, works. (eg. JS receives "true", thus OK.)\r
+ }\r
+\r
+ public function _disableDebug() : void {\r
+ // prevent future debug calls from Flash going to client (maybe improve performance)\r
+ writeDebug('_disableDebug()');\r
+ debugEnabled = false;\r
+ }\r
+\r
+ public function checkLoadProgress(e: Event) : void {\r
+ try {\r
+ var oSound:Object = e.target;\r
+ var bL: int = oSound.bytesLoaded;\r
+ var bT: int = oSound.bytesTotal;\r
+ var nD: int = oSound.length || oSound.duration || 0;\r
+ var sMethod:String = baseJSObject + "['" + oSound.sID + "']._whileloading";\r
+ ExternalInterface.call(sMethod, bL, bT, nD);\r
+ if (bL && bT && bL != oSound.lastValues.bytes) {\r
+ oSound.lastValues.bytes = bL;\r
+ ExternalInterface.call(sMethod, bL, bT, nD);\r
+ }\r
+ } catch(e: Error) {\r
+ writeDebug('checkLoadProgress(): ' + e.toString());\r
+ }\r
+ }\r
+\r
+ public function checkSoundProgress(oSound:SoundManager2_SMSound_AS3, forceCheck:Boolean = false, forceEndCheck:Boolean = false) : void {\r
+ var bL: int = 0;\r
+ var bT: int = 0;\r
+ var nD: int = 0;\r
+ var nP: int = 0;\r
+ var bufferLength: int = 0;\r
+ var lP:Number = 0;\r
+ var rP:Number = 0;\r
+ var isBuffering:Object = null;\r
+ var oSoundChannel: flash.media.SoundChannel = null;\r
+ var sMethod:String = null;\r
+ var newPeakData: Boolean = false;\r
+ var newWaveformData: Boolean = false;\r
+ var newEQData: Boolean = false;\r
+ var areSoundsInaccessible: Boolean = SoundMixer.areSoundsInaccessible();\r
+ var isPlaying: Boolean = true; // special case for NetStream when ending\r
+ var hasNew:Boolean = false;\r
+ var hasNewLoaded:Boolean = false;\r
+\r
+ if (!oSound || !oSound.useEvents || oSound.failed || !oSound.connected) {\r
+ // edge cases for ignoring: if sounds are destructed within event handlers while checkProgress() is running, may be null\r
+ return;\r
+ }\r
+\r
+ sMethod = baseJSObject + "['" + oSound.sID + "']._whileloading";\r
+\r
+ if (oSound.useNetstream) {\r
+\r
+ // Don't do anything if there is no NetStream object yet\r
+ if (!oSound.ns) {\r
+ return;\r
+ }\r
+\r
+ // stream\r
+ bufferLength = oSound.ns.bufferLength;\r
+ bL = oSound.ns.bytesLoaded;\r
+ bT = oSound.ns.bytesTotal;\r
+ nD = int(oSound.duration || 0); // can sometimes be null with short MP3s? Wack.\r
+ nP = oSound.ns.time * 1000;\r
+\r
+ if (oSound.paused) {\r
+ // special case: paused netStreams don't update if setPosition() is called while they are paused.\r
+ // instead, return lastValues.position which should reflect setPosition() call.\r
+ // writeDebug('paused case, setting nP of '+nP+' to -1');\r
+ // writeDebug('lastValues: '+oSound.lastValues.position);\r
+ nP = oSound.lastValues.position;\r
+ }\r
+\r
+ if (nP >= 0 && nP != oSound.lastValues.position) {\r
+ oSound.lastValues.position = nP;\r
+ hasNew = true;\r
+ }\r
+ if (nD > oSound.lastValues.duration) {\r
+ oSound.lastValues.duration = nD;\r
+ hasNew = true;\r
+ }\r
+ if (bL > oSound.lastValues.bytesLoaded) {\r
+ oSound.lastValues.bytesLoaded = bL;\r
+ hasNew = true;\r
+ }\r
+ if (bT > oSound.lastValues.bytes) {\r
+ oSound.lastValues.bytes = bT;\r
+ hasNew = true;\r
+ }\r
+ if (bufferLength != oSound.lastValues.bufferLength) {\r
+ oSound.lastValues.bufferLength = bufferLength;\r
+ hasNew = true;\r
+ }\r
+\r
+ // Don't set loaded for streams because bytesLoaded and bytesTotal are always 0\r
+ // writeDebug('ns: time/duration, bytesloaded/total: '+nP+'/'+nD+', '+bL+'/'+bT);\r
+ if (oSound.loaded != true && nD > 0 && bL == bT && bL != 0 && bT != 0) {\r
+ // non-MP3 has loaded\r
+ oSound.loaded = true;\r
+ try {\r
+ ExternalInterface.call(sMethod, bL, bT, nD, bufferLength);\r
+ ExternalInterface.call(baseJSObject + "['" + oSound.sID + "']._onload", oSound.duration > 0 ? 1 : 0);\r
+ } catch(e: Error) {\r
+ writeDebug('_whileLoading/_onload error: ' + e.toString(), 2);\r
+ }\r
+ } else if (oSound.loaded != true && hasNew) {\r
+ ExternalInterface.call(sMethod, bL, bT, nD, bufferLength);\r
+ }\r
+\r
+ } else {\r
+\r
+ // MP3 sound\r
+ oSoundChannel = oSound.soundChannel;\r
+ bL = oSound.bytesLoaded;\r
+ bT = oSound.bytesTotal;\r
+ nD = int(oSound.length || 0); // can sometimes be null with short MP3s? Wack.\r
+ isBuffering = oSound.isBuffering;\r
+\r
+ if (oSoundChannel) {\r
+ nP = (oSoundChannel.position || 0);\r
+ if (oSound.lastValues.loops > 1 && nP > oSound.length) {\r
+ // round down to nearest loop\r
+ var playedLoops:Number = Math.floor(nP/oSound.length);\r
+ nP = nP - (oSound.length*playedLoops);\r
+ }\r
+ if (oSound.usePeakData) {\r
+ lP = int((oSoundChannel.leftPeak) * 1000) / 1000;\r
+ rP = int((oSoundChannel.rightPeak) * 1000) / 1000;\r
+ } else {\r
+ lP = 0;\r
+ rP = 0;\r
+ }\r
+ } else {\r
+ // stopped, not loaded or feature not used\r
+ nP = 0;\r
+ }\r
+\r
+ if (forceEndCheck) {\r
+ // sound finish case: Ensure position is at end (sound duration), as flash 9 does not always correctly match the two.\r
+ if (nP < nD) {\r
+ writeDebug('correcting sound ' + oSound.sID + ' end position ('+nP+') to length: '+ nD, 2);\r
+ nP = nD;\r
+ }\r
+ }\r
+\r
+ if (nP != oSound.lastValues.position && nP !== 0 && !oSound.didFinish) { // once "completed", sound is locked via didFinish so no more position-type events fire.\r
+ oSound.lastValues.position = nP;\r
+ hasNew = true;\r
+ }\r
+\r
+ if (nD > oSound.lastValues.duration) { // original sound duration * number of sound loops\r
+ oSound.lastValues.duration = nD;\r
+ hasNew = true;\r
+ }\r
+\r
+ if (bL > oSound.lastValues.bytesLoaded) {\r
+ oSound.lastValues.bytesLoaded = bL;\r
+ hasNew = true;\r
+ }\r
+\r
+ if (bT > oSound.lastValues.bytes) {\r
+ oSound.lastValues.bytes = bT;\r
+ hasNew = true;\r
+ hasNewLoaded = true;\r
+ }\r
+\r
+ // loading progress\r
+ if (hasNewLoaded) {\r
+ oSound.lastValues.bytes = bL;\r
+ ExternalInterface.call(sMethod, bL, bT, nD);\r
+ }\r
+\r
+ }\r
+\r
+ // peak data\r
+ if (oSoundChannel && oSound.usePeakData) {\r
+ if (lP != oSound.lastValues.leftPeak) {\r
+ oSound.lastValues.leftPeak = lP;\r
+ newPeakData = true;\r
+ }\r
+ if (rP != oSound.lastValues.rightPeak) {\r
+ oSound.lastValues.rightPeak = rP;\r
+ newPeakData = true;\r
+ }\r
+ }\r
+\r
+ var newDataError:Boolean = false;\r
+ var dataError:String;\r
+\r
+ // special case: Netstream may try to fire whileplaying() after finishing. check that stop hasn't fired.\r
+ isPlaying = (oSound.didLoad && !oSound.paused && (!oSound.useNetstream || (oSound.useNetstream && oSound.lastNetStatus != "NetStream.Play.Stop"))); // don't update if stream has ended\r
+\r
+ // raw waveform + EQ spectrum data\r
+ if (isPlaying && (oSoundChannel || oSound.useNetstream)) {\r
+\r
+ if (oSound.useWaveformData) {\r
+ if (!areSoundsInaccessible && !oSound.handledDataError && !oSound.ignoreDataError) {\r
+ try {\r
+ oSound.getWaveformData();\r
+ } catch(e: Error) {\r
+ if (!oSound.handledDataError) {\r
+ writeDebug('getWaveformData() (waveform data) '+e.toString());\r
+ }\r
+ // oSound.useWaveformData = false;\r
+ newDataError = true;\r
+ dataError = e.toString();\r
+ }\r
+ }\r
+ }\r
+\r
+ if (oSound.useEQData) {\r
+ if (!areSoundsInaccessible && !oSound.handledDataError && !oSound.ignoreDataError) {\r
+ try {\r
+ oSound.getEQData();\r
+ } catch(e: Error) {\r
+ if (!oSound.handledDataError) {\r
+ writeDebug('computeSpectrum() (EQ data) '+e.toString());\r
+ }\r
+ // oSound.useEQData = false;\r
+ newDataError = true;\r
+ dataError = e.toString();\r
+ }\r
+ }\r
+ }\r
+\r
+ if (oSound.waveformDataArray != oSound.lastValues.waveformDataArray) {\r
+ oSound.lastValues.waveformDataArray = oSound.waveformDataArray;\r
+ newWaveformData = true;\r
+ }\r
+\r
+ if (oSound.eqDataArray != oSound.lastValues.eqDataArray) {\r
+ oSound.lastValues.eqDataArray = oSound.eqDataArray;\r
+ newEQData = true;\r
+ }\r
+\r
+ if (newDataError && !oSound.handledDataError) {\r
+ sMethod = baseJSObject + "['" + oSound.sID + "']._ondataerror";\r
+ ExternalInterface.call(sMethod, 'data unavailable: ' + dataError);\r
+ oSound.handledDataError = true;\r
+ }\r
+\r
+ }\r
+\r
+ if (typeof nP != 'undefined' && (hasNew && (oSound.soundChannel || oSound.useNetstream || forceCheck || forceEndCheck))) { // && isPlaying - removed to allow updates while paused, eg. from setPosition() calls. Also be more liberal if we're using netStream.\r
+\r
+ // oSound.lastValues.position = nP;\r
+ sMethod = baseJSObject + "['" + oSound.sID + "']._whileplaying";\r
+ var waveDataLeft:String = (newWaveformData ? oSound.waveformDataArray.slice(0, 256).join(',') : null);\r
+ var waveDataRight:String = (newWaveformData ? oSound.waveformDataArray.slice(256).join(',') : null);\r
+ var eqDataLeft:String = (newEQData ? oSound.eqDataArray.slice(0, 256).join(',') : null);\r
+ var eqDataRight:String = (newEQData ? oSound.eqDataArray.slice(256).join(',') : null);\r
+ ExternalInterface.call(sMethod, nP, (newPeakData ? {\r
+ leftPeak: lP,\r
+ rightPeak: rP\r
+ } : null), waveDataLeft, waveDataRight, (newEQData ? {\r
+ leftEQ: eqDataLeft,\r
+ rightEQ: eqDataRight\r
+ } : null));\r
+ }\r
+\r
+ // check isBuffering\r
+ if (!oSound.useNetstream && oSound.isBuffering != oSound.lastValues.isBuffering) {\r
+ // property has changed\r
+ oSound.lastValues.isBuffering = oSound.isBuffering;\r
+ sMethod = baseJSObject + "['" + oSound.sID + "']._onbufferchange";\r
+ ExternalInterface.call(sMethod, oSound.isBuffering ? 1 : 0);\r
+ }\r
+\r
+ }\r
+\r
+ public function checkProgress() : void {\r
+ for (var i: int = 0, j: int = sounds.length; i < j; i++) {\r
+ checkSoundProgress(soundObjects[sounds[i]]);\r
+ }\r
+ }\r
+\r
+ public function onLoadError(oSound:Object) : void {\r
+ // something went wrong. 404, bad format etc.\r
+ ExternalInterface.call(baseJSObject + "['" + oSound.sID + "']._onload", 0);\r
+ }\r
+\r
+ public function onLoad(e: Event) : void {\r
+ var oSound:Object = e.target;\r
+ checkSoundProgress(soundObjects[oSound.sID]); // ensure progress stats are up-to-date\r
+ if (!oSound.useNetstream) { // FLV must also have metadata\r
+ oSound.loaded = true;\r
+ // force duration update (doesn't seem to be always accurate)\r
+ ExternalInterface.call(baseJSObject + "['" + oSound.sID + "']._whileloading", oSound.bytesLoaded, oSound.bytesTotal, oSound.length || oSound.duration);\r
+ // duration > 0 means a valid sound was loaded.\r
+ ExternalInterface.call(baseJSObject + "['" + oSound.sID + "']._onload", (oSound.length || oSound.duration ? 1 : 0));\r
+ }\r
+ }\r
+\r
+ public function onID3(e: Event) : void {\r
+\r
+ // --- NOTE: BUGGY (Flash 8 only? Haven't really checked 9 + 10.) ---\r
+ // TODO: Investigate holes in ID3 parsing - for some reason, Album will be populated with Date if empty and date is provided. (?)\r
+ // ID3V1 seem to parse OK, but "holes" / blanks in ID3V2 data seem to get messed up (eg. missing album gets filled with date.)\r
+ // iTunes issues: onID3 was not called with a test MP3 encoded with iTunes 7.01, and what appeared to be valid ID3V2 data.\r
+ // May be related to thumbnails for album art included in MP3 file by iTunes. See http://mabblog.com/blog/?p=33\r
+ try {\r
+ var oSound:Object = e.target;\r
+\r
+ var id3Data:Array = [];\r
+ var id3Props:Array = [];\r
+ for (var prop:String in oSound.id3) {\r
+ id3Props.push(prop);\r
+ id3Data.push(oSound.id3[prop]);\r
+ // writeDebug('id3['+prop+']: '+oSound.id3[prop]);\r
+ }\r
+ ExternalInterface.call(baseJSObject + "['" + oSound.sID + "']._onid3", id3Props, id3Data);\r
+ // unhook own event handler, prevent second call (can fire twice as data is received - ID3V2 at beginning, ID3V1 at end.)\r
+ // Therefore if ID3V2 data is received, ID3V1 is ignored.\r
+ // soundObjects[oSound.sID].onID3 = null;\r
+ } catch(e: Error) {\r
+ writeDebug('onID3(): Unable to get ID3 info for ' + oSound.sID + '.');\r
+ }\r
+ oSound.removeEventListener(Event.ID3, onID3);\r
+ }\r
+\r
+ public function registerOnComplete(sID:String) : void {\r
+ var oSound: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ if (oSound && oSound.soundChannel) {\r
+ oSound.didFinish = false; // reset this flag\r
+ oSound.soundChannel.addEventListener(Event.SOUND_COMPLETE, function() : void {\r
+ if (oSound) {\r
+ // force progress check, catching special end-of-sound case where position may not match duration.\r
+ checkSoundProgress(oSound, true, true);\r
+ try {\r
+ oSound.ignoreDataError = true; // workaround: avoid data error handling for this manual step..\r
+ // oSound.soundChannel.stop();\r
+ oSound.didFinish = true; // "lock" sound, prevent extra whileplaying() position-type updates\r
+ // call onfinish first (with end position)...\r
+ ExternalInterface.call(baseJSObject + "['" + sID + "']._onfinish");\r
+ // then reset sound so it can be played again.\r
+ // oSound.start(0, 1); // go back to 0\r
+ } catch(e: Error) {\r
+ writeDebug('Could not set position on ' + sID + ': ' + e.toString());\r
+ }\r
+ oSound.ignoreDataError = false; // ..and reset\r
+ oSound.handledDataError = false; // reset this flag\r
+ } else {\r
+ // safety net\r
+ ExternalInterface.call(baseJSObject + "['" + sID + "']._onfinish");\r
+ }\r
+ });\r
+ }\r
+ }\r
+\r
+ public function doSecurityError(oSound: SoundManager2_SMSound_AS3, e: SecurityErrorEvent) : void {\r
+ writeDebug('securityError: ' + e.text);\r
+ // when this happens, you don't have security rights on the server containing the FLV file\r
+ // a crossdomain.xml file would fix the problem easily\r
+ }\r
+\r
+ public function _setPosition(sID:String, nSecOffset:Number, isPaused: Boolean, allowMultiShot: Boolean) : void {\r
+ var s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ if (!s) return void;\r
+ // writeDebug('_setPosition()');\r
+\r
+ // stop current channel, start new one.\r
+ if (s.lastValues) {\r
+ s.lastValues.position = nSecOffset; // s.soundChannel.position;\r
+ }\r
+ if (s.useNetstream) {\r
+ // Minimize the buffer so playback starts ASAP\r
+ s.ns.bufferTime = s.bufferTime;\r
+ writeDebug('setPosition ('+ sID + '): setting buffer to '+s.ns.bufferTime+' secs');\r
+\r
+ nSecOffset = nSecOffset > 0 ? nSecOffset / 1000 : 0;\r
+ s.ns.seek(nSecOffset);\r
+ checkSoundProgress(s); // force UI update\r
+ } else {\r
+ if (s.soundChannel) {\r
+ s.soundChannel.stop();\r
+ }\r
+ writeDebug('setPosition ('+ sID + '): ' + nSecOffset); // +', '+(s.lastValues.loops?s.lastValues.loops:1));\r
+ if (s.lastValues.loops > 1 && nSecOffset != 0) {\r
+ writeDebug('Warning: Looping functionality being disabled due to Flash limitation.');\r
+ s.lastValues.loops = 1;\r
+ }\r
+ try {\r
+ s.start(nSecOffset, s.lastValues.loops || 1, allowMultiShot); // start playing at new position\r
+ } catch(e: Error) {\r
+ writeDebug('Warning: Could not set position on ' + sID + ': ' + e.toString());\r
+ }\r
+ checkSoundProgress(s); // force UI update\r
+ try {\r
+ registerOnComplete(sID);\r
+ } catch(e: Error) {\r
+ writeDebug('_setPosition(): Could not register onComplete');\r
+ }\r
+ if (isPaused && s.soundChannel) {\r
+ // writeDebug('_setPosition: stopping (paused) sound');\r
+ // writeDebug('last position: '+s.lastValues.position+' vs '+s.soundChannel.position);\r
+ s.soundChannel.stop();\r
+ }\r
+ }\r
+ }\r
+\r
+ public function _load(sID:String, sURL:String, bStream: Boolean, bAutoPlay: Boolean, nLoops: Number, bAutoLoad: Boolean, bCheckPolicyFile: Boolean) : void {\r
+ // writeDebug('_load()');\r
+ if (typeof bAutoPlay == 'undefined') bAutoPlay = false;\r
+ var s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ if (!s) return void;\r
+ var didRecreate: Boolean = false;\r
+ if (s.didLoad == true) {\r
+ // need to recreate sound\r
+ didRecreate = true;\r
+ writeDebug('recreating sound ' + sID + ' in order to load ' + sURL);\r
+ var ns:Object = new Object();\r
+ ns.sID = s.sID;\r
+ ns.loops = nLoops||1;\r
+ ns.usePeakData = s.usePeakData;\r
+ ns.useWaveformData = s.useWaveformData;\r
+ ns.useEQData = s.useEQData;\r
+ ns.useNetstream = s.useNetstream;\r
+ ns.bufferTime = s.bufferTime;\r
+ ns.serverUrl = s.serverUrl;\r
+ ns.duration = s.duration;\r
+ ns.checkPolicyFile = s.checkPolicyFile;\r
+ ns.useEvents = true;\r
+ _destroySound(s.sID);\r
+ _createSound(ns.sID, sURL, ns.usePeakData, ns.useWaveformData, ns.useEQData, ns.useNetstream, ns.bufferTime, ns.loops, ns.serverUrl, ns.duration, bAutoPlay, ns.useEvents, bAutoLoad, ns.checkPolicyFile);\r
+ s = soundObjects[sID];\r
+ // writeDebug('Sound object replaced');\r
+ }\r
+ checkSoundProgress(s);\r
+\r
+ if (!s.didLoad) {\r
+ try {\r
+ s.addEventListener(Event.ID3, onID3);\r
+ s.addEventListener(Event.COMPLETE, onLoad);\r
+ } catch(e: Error) {\r
+ writeDebug('_load(): could not assign ID3/complete event handlers');\r
+ }\r
+ }\r
+\r
+ // don't try to load if same request already made\r
+ s.sURL = sURL;\r
+\r
+ try {\r
+ if (!s.useNetstream) {\r
+ s.addEventListener(IOErrorEvent.IO_ERROR, function(e: IOErrorEvent) : void {\r
+ s.doIOError(e);\r
+ });\r
+ }\r
+ s.loadSound(sURL);\r
+ } catch(e: Error) {\r
+ // oh well\r
+ writeDebug('_load: Error loading ' + sURL + '. Flash error detail: ' + e.toString());\r
+ }\r
+\r
+ }\r
+\r
+ public function _unload(sID:String) : void {\r
+ var s: SoundManager2_SMSound_AS3 = (soundObjects[sID] || null);\r
+ if (!s) return void;\r
+ var sURL:String = s.sURL; // save existing sound URL for object recreation\r
+ try {\r
+ removeEventListener(Event.ID3, onID3);\r
+ removeEventListener(Event.COMPLETE, onLoad);\r
+ } catch(e: Error) {\r
+ writeDebug('_unload() warn: Could not remove ID3/complete events');\r
+ }\r
+ s.paused = false;\r
+ if (s.soundChannel) {\r
+ s.soundChannel.stop();\r
+ }\r
+ try {\r
+ if (s.didLoad && !s.loaded && !s.useNetstream) {\r
+ s.close(); // close stream only if still loading?\r
+ }\r
+ } catch(e: Error) {\r
+ // stream may already have closed if sound loaded, etc.\r
+ writeDebug(sID + '._unload(): Note: Unable to close stream: ' + e.toString());\r
+ // oh well\r
+ }\r
+ // destroy and recreate Flash sound object, try to reclaim memory\r
+ // writeDebug('sound._unload(): recreating sound '+sID+' to free memory');\r
+ if (s.useNetstream) {\r
+ // writeDebug('_unload(): closing netStream stuff');\r
+ try {\r
+ s.removeNetstreamEvents();\r
+ s.ns.close();\r
+ s.nc.close();\r
+ // s.nc = null;\r
+ // s.ns = null;\r
+ } catch(e: Error) {\r
+ // oh well\r
+ writeDebug('_unload(): caught exception during netConnection/netStream close');\r
+ }\r
+ }\r
+ var ns:Object = new Object();\r
+ ns.sID = s.sID;\r
+ ns.loops = s.loops;\r
+ ns.usePeakData = s.usePeakData;\r
+ ns.useWaveformData = s.useWaveformData;\r
+ ns.useEQData = s.useEQData;\r
+ ns.useNetstream = s.useNetstream;\r
+ ns.bufferTime = s.bufferTime;\r
+ ns.serverUrl = s.serverUrl;\r
+ ns.duration = s.duration;\r
+ ns.autoPlay = s.autoPlay;\r
+ ns.autoLoad = s.autoLoad;\r
+ ns.checkPolicyFile = s.checkPolicyFile;\r
+ _destroySound(s.sID);\r
+ _createSound(ns.sID, sURL, ns.usePeakData, ns.useWaveformData, ns.useEQData, ns.useNetstream, ns.bufferTime, ns.loops, ns.serverUrl, ns.duration, ns.autoPlay, false, ns.autoLoad, ns.checkPolicyFile); // false: don't allow events just yet\r
+ soundObjects[sID].connected = true; // fake it?\r
+ writeDebug(s.sID + '.unload(): ok');\r
+ }\r
+\r
+ public function _createSound(sID:String, sURL:String, usePeakData: Boolean, useWaveformData: Boolean, useEQData: Boolean, useNetstream: Boolean, bufferTime:Number, loops:Number, serverUrl:String, duration:Number, autoPlay:Boolean, useEvents:Boolean, autoLoad:Boolean, checkPolicyFile:Boolean) : void {\r
+ var s: SoundManager2_SMSound_AS3 = new SoundManager2_SMSound_AS3(this, sID, sURL, usePeakData, useWaveformData, useEQData, useNetstream, bufferTime, serverUrl, duration, autoPlay, useEvents, autoLoad, checkPolicyFile);\r
+ if (!soundObjects[sID]) {\r
+ sounds.push(sID);\r
+ }\r
+ soundObjects[sID] = s;\r
+ this.currentObject = s;\r
+ s.sID = sID;\r
+ s.sURL = sURL;\r
+ s.paused = false;\r
+ s.loaded = false;\r
+ s.checkPolicyFile = checkPolicyFile;\r
+ s.lastValues = {\r
+ bytes: 0,\r
+ duration: 0,\r
+ position: 0,\r
+ loops: loops||1,\r
+ leftPeak: 0,\r
+ rightPeak: 0,\r
+ bufferLength: 0\r
+ };\r
+ }\r
+\r
+ public function _destroySound(sID:String) : void {\r
+ // for the power of garbage collection! .. er, Greyskull!\r
+ var s: SoundManager2_SMSound_AS3 = (soundObjects[sID] || null);\r
+ if (!s) return void;\r
+ // try to unload the sound\r
+ for (var i: int = 0, j: int = sounds.length; i < j; i++) {\r
+ if (sounds[i] == sID) {\r
+ sounds.splice(i, 1);\r
+ break;\r
+ }\r
+ }\r
+ if (s.soundChannel) {\r
+ s.soundChannel.stop();\r
+ }\r
+ // if is a movie, remove that as well.\r
+ if (s.useNetstream) {\r
+ // s.nc.client = null;\r
+ try {\r
+ s.removeNetstreamEvents();\r
+ // s.nc.removeEventListener(NetStatusEvent.NET_STATUS, s.doNetStatus);\r
+ } catch(e: Error) {\r
+ writeDebug('_destroySound(): Events already removed from netStream/netConnection?');\r
+ }\r
+ if (s.didLoad) {\r
+ // TODO: figure out if stream is still open first, can't close an already-closed stream.\r
+ try {\r
+ s.ns.close();\r
+ s.nc.close();\r
+ } catch(e: Error) {\r
+ // oh well\r
+ writeDebug('_destroySound(): caught exception: '+e.toString());\r
+ }\r
+ }\r
+ } else if (s.didLoad) {\r
+ // non-netstream case\r
+ try {\r
+ s.close(); // close stream only if still loading?\r
+ } catch(e: Error) {\r
+ // oh well\r
+ }\r
+ }\r
+ s = null;\r
+ soundObjects[sID] = null;\r
+ delete soundObjects[sID];\r
+ }\r
+\r
+ public function _stop(sID:String, bStopAll: Boolean) : void {\r
+ // stop this particular instance (or "all", based on parameter)\r
+ if (bStopAll) {\r
+ SoundMixer.stopAll();\r
+ } else {\r
+ var s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ if (!s) return void;\r
+ if (s.useNetstream && s.ns) {\r
+ s.ns.pause();\r
+ } else if (s.soundChannel) {\r
+ s.soundChannel.stop();\r
+ }\r
+ s.paused = false;\r
+ }\r
+ }\r
+\r
+ public function _start(sID:String, nLoops: int, nMsecOffset: int, allowMultiShot: Boolean) : Boolean {\r
+ var s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ var result: Boolean;\r
+ if (!s) return true;\r
+ writeDebug('start (' + sID + '): ' + nMsecOffset + (nLoops > 1 ? ', loops: ' + nLoops : ''));\r
+ s.lastValues.paused = false; // reset pause if applicable\r
+ s.lastValues.loops = (nLoops || 1);\r
+ if (!s.useNetstream) {\r
+ s.lastValues.position = nMsecOffset;\r
+ }\r
+ s.handledDataError = false; // reset this flag\r
+ try {\r
+ result = s.start(nMsecOffset, nLoops, allowMultiShot);\r
+ } catch(e: Error) {\r
+ writeDebug('Could not start ' + sID + ': ' + e.toString());\r
+ }\r
+ try {\r
+ registerOnComplete(sID);\r
+ } catch(e: Error) {\r
+ writeDebug('_start(): registerOnComplete failed');\r
+ }\r
+ return result;\r
+ }\r
+\r
+ public function _pause(sID:String, allowMultiShot: Boolean) : void {\r
+ // writeDebug('_pause(): ' + sID);\r
+ var s: SoundManager2_SMSound_AS3 = soundObjects[sID];\r
+ if (!s) return void;\r
+ // writeDebug('s.paused: '+s.paused);\r
+ if (!s.paused) {\r
+ // reference current position, stop sound\r
+ s.paused = true;\r
+ // writeDebug('_pause(): position: '+s.lastValues.position);\r
+ if (s.useNetstream) {\r
+ if (s.ns) {\r
+ s.lastValues.position = s.ns.time*1000;\r
+ s.ns.pause();\r
+ } else if (s.autoPlay) {\r
+ s.setAutoPlay(false);\r
+ }\r
+ } else {\r
+ if (s.soundChannel) {\r
+ s.lastValues.position = s.soundChannel.position;\r
+ s.soundChannel.stop();\r
+ }\r
+ }\r
+ } else {\r
+ // resume playing from last position\r
+ // writeDebug('resuming - playing at '+s.lastValues.position+', '+s.lastValues.loops+' times');\r
+ s.paused = false;\r
+ if (s.useNetstream) {\r
+ s.ns.resume();\r
+ } else {\r
+ s.start(s.lastValues.position, s.lastValues.loops, allowMultiShot);\r
+ }\r
+ try {\r
+ registerOnComplete(sID);\r
+ } catch(e: Error) {\r
+ writeDebug('_pause(): registerOnComplete() failed');\r
+ }\r
+ }\r
+ }\r
+\r
+ public function _setPan(sID:String, nPan:Number) : void {\r
+ if (soundObjects[sID]) {\r
+ soundObjects[sID].setPan(nPan);\r
+ }\r
+ }\r
+\r
+ public function _setVolume(sID:String, nVol:Number) : void {\r
+ // writeDebug('_setVolume: '+nVol);\r
+ if (soundObjects[sID]) {\r
+ soundObjects[sID].setVolume(nVol);\r
+ }\r
+ }\r
+\r
+ public function _setPolling(bPolling: Boolean = false, nTimerInterval: uint = 50) : void {\r
+ pollingEnabled = bPolling;\r
+ if (timer == null && pollingEnabled) {\r
+ flashDebug('Enabling polling, ' + nTimerInterval + ' ms interval');\r
+ timer = new Timer(nTimerInterval, 0);\r
+ timer.addEventListener(TimerEvent.TIMER, function() : void {\r
+ checkProgress();\r
+ }); // direct reference eg. checkProgress doesn't work? .. odd.\r
+ timer.start();\r
+ } else if (timer && !pollingEnabled) {\r
+ flashDebug('Disabling polling');\r
+ // flash.utils.clearInterval(timer);\r
+ timer.reset();\r
+ }\r
+ }\r
+\r
+ public function _getMemoryUse() : String {\r
+ return System.totalMemory.toString();\r
+ }\r
+\r
+ // -----------------------------------\r
+ // end methods\r
+\r
+ }\r
+\r
+ // package\r
+\r
+}
\ No newline at end of file
--- /dev/null
+/**\r
+ * SoundManager 2: Javascript Sound for the Web\r
+ * ----------------------------------------------\r
+ * http://schillmania.com/projects/soundmanager2/\r
+ *\r
+ * Copyright (c) 2007, Scott Schiller. All rights reserved.\r
+ * Code licensed under the BSD License:\r
+ * http://www.schillmania.com/projects/soundmanager2/license.txt\r
+ *\r
+ * Flash 9 / ActionScript 3 version\r
+ */\r
+\r
+package {\r
+\r
+ import flash.external.*;\r
+ import flash.events.*;\r
+ import flash.media.Sound;\r
+ import flash.media.SoundChannel;\r
+ import flash.media.SoundLoaderContext;\r
+ import flash.media.SoundTransform;\r
+ import flash.media.SoundMixer;\r
+ import flash.net.URLRequest;\r
+ import flash.utils.ByteArray;\r
+ import flash.utils.getTimer;\r
+ import flash.net.NetConnection;\r
+ import flash.net.NetStream;\r
+ import flash.net.Responder;\r
+\r
+ public class SoundManager2_SMSound_AS3 extends Sound {\r
+\r
+ public var sm: SoundManager2_AS3 = null;\r
+ // externalInterface references (for Javascript callbacks)\r
+ public var baseJSController: String = "soundManager";\r
+ public var baseJSObject: String = baseJSController + ".sounds";\r
+ public var soundChannel: SoundChannel = new SoundChannel();\r
+ public var urlRequest: URLRequest;\r
+ public var soundLoaderContext: SoundLoaderContext;\r
+ public var waveformData: ByteArray = new ByteArray();\r
+ public var waveformDataArray: Array = [];\r
+ public var eqData: ByteArray = new ByteArray();\r
+ public var eqDataArray: Array = [];\r
+ public var usePeakData: Boolean = false;\r
+ public var useWaveformData: Boolean = false;\r
+ public var useEQData: Boolean = false;\r
+ public var sID: String;\r
+ public var sURL: String;\r
+ public var didFinish: Boolean;\r
+ public var loaded: Boolean;\r
+ public var connected: Boolean;\r
+ public var failed: Boolean;\r
+ public var paused: Boolean;\r
+ public var finished: Boolean;\r
+ public var duration: Number;\r
+ public var handledDataError: Boolean = false;\r
+ public var ignoreDataError: Boolean = false;\r
+ public var autoPlay: Boolean = false;\r
+ public var autoLoad: Boolean = false;\r
+ public var pauseOnBufferFull: Boolean = false; // only applies to RTMP\r
+ public var loops: Number = 1;\r
+ public var lastValues: Object = {\r
+ bytes: 0,\r
+ position: 0,\r
+ duration: 0,\r
+ volume: 100,\r
+ pan: 0,\r
+ loops: 1,\r
+ leftPeak: 0,\r
+ rightPeak: 0,\r
+ waveformDataArray: null,\r
+ eqDataArray: null,\r
+ isBuffering: null,\r
+ bufferLength: 0\r
+ };\r
+ public var didLoad: Boolean = false;\r
+ public var useEvents: Boolean = false;\r
+ public var sound: Sound = new Sound();\r
+\r
+ public var cc: Object;\r
+ public var nc: NetConnection;\r
+ public var ns: NetStream = null;\r
+ public var st: SoundTransform;\r
+ public var useNetstream: Boolean;\r
+ public var bufferTime: Number = 3; // previously 0.1\r
+ public var lastNetStatus: String = null;\r
+ public var serverUrl: String = null;\r
+\r
+ public var checkPolicyFile:Boolean = false;\r
+\r
+ public function SoundManager2_SMSound_AS3(oSoundManager: SoundManager2_AS3, sIDArg: String = null, sURLArg: String = null, usePeakData: Boolean = false, useWaveformData: Boolean = false, useEQData: Boolean = false, useNetstreamArg: Boolean = false, netStreamBufferTime: Number = 1, serverUrl: String = null, duration: Number = 0, autoPlay: Boolean = false, useEvents: Boolean = false, autoLoad: Boolean = false, checkPolicyFile: Boolean = false) {\r
+ this.sm = oSoundManager;\r
+ this.sID = sIDArg;\r
+ this.sURL = sURLArg;\r
+ this.usePeakData = usePeakData;\r
+ this.useWaveformData = useWaveformData;\r
+ this.useEQData = useEQData;\r
+ this.urlRequest = new URLRequest(sURLArg);\r
+ this.didFinish = false;\r
+ this.loaded = false;\r
+ this.connected = false;\r
+ this.failed = false;\r
+ this.finished = false;\r
+ this.soundChannel = null;\r
+ this.lastNetStatus = null;\r
+ this.useNetstream = useNetstreamArg;\r
+ this.serverUrl = serverUrl;\r
+ this.duration = duration;\r
+ this.useEvents = useEvents;\r
+ this.autoLoad = autoLoad;\r
+ if (netStreamBufferTime) {\r
+ this.bufferTime = netStreamBufferTime;\r
+ }\r
+ this.checkPolicyFile = checkPolicyFile;\r
+\r
+ writeDebug('SoundManager2_SMSound_AS3: Got duration: '+duration+', autoPlay: '+autoPlay);\r
+\r
+ if (this.useNetstream) {\r
+ // Pause on buffer full if auto-loading an RTMP stream\r
+ if (this.serverUrl && this.autoLoad) {\r
+ this.pauseOnBufferFull = true;\r
+ }\r
+\r
+ this.cc = new Object();\r
+ this.nc = new NetConnection();\r
+\r
+ // Handle FMS bandwidth check callback.\r
+ // @see onBWDone\r
+ // @see http://www.adobe.com/devnet/flashmediaserver/articles/dynamic_stream_switching_04.html\r
+ // @see http://www.johncblandii.com/index.php/2007/12/fms-a-quick-fix-for-missing-onbwdone-onfcsubscribe-etc.html\r
+ this.nc.client = this;\r
+\r
+ // TODO: security/IO error handling\r
+ // this.nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, doSecurityError);\r
+ nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);\r
+\r
+ if (this.serverUrl != null) {\r
+ writeDebug('SoundManager2_SMSound_AS3: NetConnection: connecting to server ' + this.serverUrl + '...');\r
+ }\r
+ this.nc.connect(serverUrl);\r
+ } else {\r
+ this.connected = true;\r
+ }\r
+\r
+ }\r
+\r
+ public function rtmpResponder(result:Object):void {\r
+ // callback from Flash Media Server (RTMP) for 'getStreamLength' server-side method - result should be a floating-point.\r
+ // http://help.adobe.com/en_US/FlashMediaServer/3.5_Deving/WS5b3ccc516d4fbf351e63e3d11a0773d117-7ffe.html\r
+ writeDebug('RTMP server getStreamLength() response: ' + result);\r
+ // we now know the duration. type cast to floating-point - this will update JS-land during whileloading() / whileplaying().\r
+ this.duration = Number(result) * 1000;\r
+ }\r
+\r
+ public function netStatusHandler(event:NetStatusEvent):void {\r
+\r
+ if (this.useEvents) {\r
+ writeDebug('netStatusHandler: '+event.info.code);\r
+ }\r
+\r
+ switch (event.info.code) {\r
+\r
+ case "NetConnection.Connect.Success":\r
+ try {\r
+ this.ns = new NetStream(this.nc);\r
+ this.ns.checkPolicyFile = this.checkPolicyFile;\r
+ // bufferTime reference: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/NetStream.html#bufferTime\r
+ this.ns.bufferTime = this.bufferTime; // set to 0.1 or higher. 0 is reported to cause playback issues with static files.\r
+ this.st = new SoundTransform();\r
+ this.cc.onMetaData = this.onMetaData;\r
+ this.cc.setCaption = this.captionHandler;\r
+ this.ns.client = this.cc;\r
+ this.ns.receiveAudio(true);\r
+ this.addNetstreamEvents();\r
+ this.connected = true;\r
+ // RTMP-only\r
+ if (this.serverUrl && this.useEvents) {\r
+ var responder:Responder = new Responder(rtmpResponder);\r
+ // call a method on server to get the length of the stream (like onMetaData, but Flash Media Server-specific)\r
+ // Red5 and other RTMP servers appear to provide duration via onMetaData event(s) in the stream.\r
+ // http://help.adobe.com/en_US/FlashMediaServer/3.5_Deving/WS5b3ccc516d4fbf351e63e3d11a0773d117-7ffe.html\r
+ nc.call('getStreamLength', responder, this.sURL);\r
+ writeDebug('NetConnection: connected');\r
+ writeDebug('firing _onconnect for '+this.sID);\r
+ ExternalInterface.call(this.sm.baseJSObject + "['" + this.sID + "']._onconnect", 1);\r
+ }\r
+ } catch(e: Error) {\r
+ this.failed = true;\r
+ writeDebug('netStream error: ' + e.toString());\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onfailure", 'Connection failed!', event.info.level, event.info.code);\r
+ }\r
+ break;\r
+\r
+ case "NetStream.Play.StreamNotFound":\r
+ this.failed = true;\r
+ writeDebug("NetConnection: Stream not found!");\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onfailure", 'Stream not found!', event.info.level, event.info.code);\r
+ break;\r
+\r
+ // This is triggered when the sound loses the connection with the server.\r
+ // In some cases one could just try to reconnect to the server and resume playback.\r
+ // However for streams protected by expiring tokens, I don't think that will work.\r
+ //\r
+ // Flash says that this is not an error code, but a status code...\r
+ // should this call the onFailure handler?\r
+ case "NetConnection.Connect.Closed":\r
+ this.failed = true;\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onfailure", 'Connection closed!', event.info.level, event.info.code);\r
+ writeDebug("NetConnection: Connection closed!");\r
+ break;\r
+\r
+ // Couldn't establish a connection with the server. Attempts to connect to the server\r
+ // can also fail if the permissible number of socket connections on either the client\r
+ // or the server computer is at its limit. This also happens when the internet\r
+ // connection is lost.\r
+ case "NetConnection.Connect.Failed":\r
+ this.failed = true;\r
+ writeDebug("NetConnection: Connection failed! Lost internet connection? Try again... Description: " + event.info.description);\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onfailure", 'Connection failed!', event.info.level, event.info.code);\r
+ break;\r
+\r
+ // A change has occurred to the network status. This could mean that the network\r
+ // connection is back, or it could mean that it has been lost...just try to resume\r
+ // playback.\r
+\r
+ // KJV: Can't use this yet because by the time you get your connection back the\r
+ // song has reached it's maximum retries, so it doesn't retry again. We need\r
+ // a new _ondisconnect handler.\r
+ //case "NetConnection.Connect.NetworkChange":\r
+ // this.failed = true;\r
+ // writeDebug("NetConnection: Network connection status changed");\r
+ // ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onfailure", 'Reconnecting...');\r
+ // break;\r
+\r
+ // Consider everything else a warning...\r
+ default:\r
+ // this.failed = true;\r
+ writeDebug("NetConnection: got unhandled code '" + event.info.code + "'. Description: " + event.info.description);\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onwarning", event.info.description, event.info.level, event.info.code);\r
+ break;\r
+ }\r
+\r
+ }\r
+\r
+ public function writeDebug (s: String, logLevel: Number = 0) : Boolean {\r
+ return this.sm.writeDebug (s,logLevel); // defined in main SM object\r
+ }\r
+\r
+ public function onMetaData(infoObject: Object) : void {\r
+ var prop:String;\r
+ if (sm.debugEnabled) {\r
+ var data:String = new String();\r
+ for (prop in infoObject) {\r
+ data += prop+': '+infoObject[prop]+' \n';\r
+ }\r
+ writeDebug('Metadata: '+data);\r
+ }\r
+ this.duration = infoObject.duration * 1000;\r
+ if (!this.loaded) {\r
+ // writeDebug('not loaded yet: '+this.ns.bytesLoaded+', '+this.ns.bytesTotal+', '+infoObject.duration*1000);\r
+ // TODO: investigate loaded/total values\r
+ // ExternalInterface.call(baseJSObject + "['" + this.sID + "']._whileloading", this.ns.bytesLoaded, this.ns.bytesTotal, infoObject.duration*1000);\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._whileloading", this.bytesLoaded, this.bytesTotal, (this.duration || infoObject.duration))\r
+ }\r
+ var metaData:Array = [];\r
+ var metaDataProps:Array = [];\r
+ for (prop in infoObject) {\r
+ metaData.push(prop);\r
+ metaDataProps.push(infoObject[prop]);\r
+ }\r
+ // pass infoObject to _onmetadata, too\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onmetadata", metaData, metaDataProps);\r
+writeDebug('waiting for next call...');\r
+ // this handler may fire multiple times, eg., when a song changes while playing an RTMP stream.\r
+ if (!this.serverUrl) {\r
+ // disconnect for non-RTMP cases, since multiple firings may mess up duration.\r
+ // this.cc.onMetaData = function(infoObject: Object) : void {}\r
+ }\r
+ }\r
+\r
+ public function captionHandler(infoObject: Object) : void {\r
+\r
+ if (sm.debugEnabled) {\r
+ var data:String = new String();\r
+ for (var prop:* in infoObject) {\r
+ data += prop+': '+infoObject[prop]+' \n';\r
+ }\r
+ writeDebug('Caption: '+data);\r
+ }\r
+\r
+ // null this out for the duration of this object's existence.\r
+ // it may be called multiple times.\r
+ // this.cc.setCaption = function(infoObject: Object) : void {}\r
+ \r
+ // writeDebug('Caption\n'+infoObject['dynamicMetadata']);\r
+ // writeDebug('firing _oncaptiondata for '+this.sID);\r
+\r
+ ExternalInterface.call(this.sm.baseJSObject + "['" + this.sID + "']._oncaptiondata", infoObject['dynamicMetadata']);\r
+\r
+ }\r
+\r
+ public function getWaveformData() : void {\r
+ // http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum()\r
+ SoundMixer.computeSpectrum(this.waveformData, false, 0); // sample wave data at 44.1 KHz\r
+ this.waveformDataArray = [];\r
+ for (var i: int = 0, j: int = this.waveformData.length / 4; i < j; i++) { // get all 512 values (256 per channel)\r
+ this.waveformDataArray.push(int(this.waveformData.readFloat() * 1000) / 1000);\r
+ }\r
+ }\r
+\r
+ public function getEQData() : void {\r
+ // http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundMixer.html#computeSpectrum()\r
+ SoundMixer.computeSpectrum(this.eqData, true, 0); // sample EQ data at 44.1 KHz\r
+ this.eqDataArray = [];\r
+ for (var i: int = 0, j: int = this.eqData.length / 4; i < j; i++) { // get all 512 values (256 per channel)\r
+ this.eqDataArray.push(int(this.eqData.readFloat() * 1000) / 1000);\r
+ }\r
+ }\r
+\r
+ public function start(nMsecOffset: int, nLoops: int, allowMultiShot:Boolean) : Boolean {\r
+\r
+ this.useEvents = true;\r
+\r
+ if (this.useNetstream) {\r
+\r
+ writeDebug("SMSound::start nMsecOffset "+ nMsecOffset+ ' nLoops '+nLoops + ' current bufferTime '+this.ns.bufferTime+' current bufferLength '+this.ns.bufferLength+ ' this.lastValues.position '+this.lastValues.position);\r
+\r
+ // mark for later Netstream.Play.Stop / sound completion\r
+ this.finished = false;\r
+\r
+ this.cc.onMetaData = this.onMetaData;\r
+\r
+ // Don't seek if we don't have to because it destroys the buffer\r
+ var set_position:Boolean = this.lastValues.position != null && this.lastValues.position != nMsecOffset;\r
+\r
+ if (set_position) {\r
+ // Minimize the buffer so playback starts ASAP\r
+ this.ns.bufferTime = this.bufferTime;\r
+ }\r
+\r
+ if (this.paused) {\r
+ writeDebug('start: resuming from paused state');\r
+ this.ns.resume(); // get the sound going again\r
+ if (!this.didLoad) {\r
+ this.didLoad = true;\r
+ }\r
+ this.paused = false;\r
+ } else if (!this.didLoad) {\r
+ writeDebug('start: !didLoad - playing '+this.sURL);\r
+ this.ns.play(this.sURL);\r
+ this.pauseOnBufferFull = false; // SAS: playing behaviour overrides buffering behaviour\r
+ this.didLoad = true;\r
+ this.paused = false;\r
+ } else {\r
+ // previously loaded, perhaps stopped/finished. play again?\r
+ writeDebug('playing again (not paused, didLoad = true)');\r
+ this.pauseOnBufferFull = false;\r
+ this.ns.play(this.sURL);\r
+ }\r
+\r
+ // KJV seek after calling play otherwise some streams get a NetStream.Seek.Failed\r
+ // Should only apply to the !didLoad case, but do it for all for simplicity.\r
+ // nMsecOffset is in milliseconds for streams but in seconds for progressive\r
+ // download.\r
+ if (set_position) {\r
+ this.ns.seek(this.serverUrl ? nMsecOffset / 1000 : nMsecOffset);\r
+ this.lastValues.position = nMsecOffset; // https://gist.github.com/1de8a3113cf33d0cff67\r
+ }\r
+\r
+ // this.ns.addEventListener(Event.SOUND_COMPLETE, _onfinish);\r
+ this.applyTransform();\r
+\r
+ } else {\r
+ // writeDebug('start: seeking to '+nMsecOffset+', '+nLoops+(nLoops==1?' loop':' loops'));\r
+ if (!this.soundChannel || allowMultiShot) {\r
+ this.soundChannel = this.play(nMsecOffset, nLoops);\r
+ this.addEventListener(Event.SOUND_COMPLETE, _onfinish);\r
+ this.applyTransform();\r
+ } else {\r
+ // writeDebug('start: was already playing, no-multishot case. Seeking to '+nMsecOffset+', '+nLoops+(nLoops==1?' loop':' loops'));\r
+ // already playing and no multi-shot allowed, so re-start and set position\r
+ if (this.soundChannel) {\r
+ this.soundChannel.stop();\r
+ }\r
+ this.soundChannel = this.play(nMsecOffset, nLoops); // start playing at new position\r
+ this.addEventListener(Event.SOUND_COMPLETE, _onfinish);\r
+ this.applyTransform();\r
+ }\r
+ }\r
+\r
+ // if soundChannel is null (and not a netStream), there is no sound card (or 32-channel ceiling has been hit.)\r
+ // http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29\r
+ return (!this.useNetstream && this.soundChannel === null ? false : true);\r
+\r
+ }\r
+\r
+ private function _onfinish() : void {\r
+ this.removeEventListener(Event.SOUND_COMPLETE, _onfinish);\r
+ }\r
+\r
+ public function loadSound(sURL: String) : void {\r
+ if (this.useNetstream) {\r
+ this.useEvents = true;\r
+ if (this.didLoad != true) {\r
+ this.ns.play(this.sURL); // load streams by playing them\r
+ if (!this.autoPlay) {\r
+ this.pauseOnBufferFull = true;\r
+ }\r
+ this.paused = false;\r
+ }\r
+ // this.addEventListener(Event.SOUND_COMPLETE, _onfinish);\r
+ this.applyTransform();\r
+ } else {\r
+ try {\r
+ this.didLoad = true;\r
+ this.urlRequest = new URLRequest(sURL);\r
+ this.soundLoaderContext = new SoundLoaderContext(1000, this.checkPolicyFile); // check for policy (crossdomain.xml) file on remote domains - http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/media/SoundLoaderContext.html\r
+ this.load(this.urlRequest, this.soundLoaderContext);\r
+ } catch(e: Error) {\r
+ writeDebug('error during loadSound(): ' + e.toString());\r
+ }\r
+ }\r
+ }\r
+\r
+ // Set the value of autoPlay\r
+ public function setAutoPlay(autoPlay: Boolean) : void {\r
+ if (!this.serverUrl) {\r
+ this.autoPlay = autoPlay;\r
+ } else {\r
+ this.autoPlay = autoPlay;\r
+ if (this.autoPlay) {\r
+ this.pauseOnBufferFull = false;\r
+ } else if (!this.autoPlay) {\r
+ this.pauseOnBufferFull = true;\r
+ }\r
+ }\r
+ }\r
+\r
+ public function setVolume(nVolume: Number) : void {\r
+ this.lastValues.volume = nVolume / 100;\r
+ this.applyTransform();\r
+ }\r
+\r
+ public function setPan(nPan: Number) : void {\r
+ this.lastValues.pan = nPan / 100;\r
+ this.applyTransform();\r
+ }\r
+\r
+ public function applyTransform() : void {\r
+ var st: SoundTransform = new SoundTransform(this.lastValues.volume, this.lastValues.pan);\r
+ if (this.useNetstream) {\r
+ if (this.ns) {\r
+ this.ns.soundTransform = st;\r
+ } else {\r
+ // writeDebug('applyTransform(): Note: No active netStream');\r
+ }\r
+ } else if (this.soundChannel) {\r
+ this.soundChannel.soundTransform = st; // new SoundTransform(this.lastValues.volume, this.lastValues.pan);\r
+ }\r
+ }\r
+\r
+ // Handle FMS bandwidth check callback.\r
+ // @see http://www.adobe.com/devnet/flashmediaserver/articles/dynamic_stream_switching_04.html\r
+ // @see http://www.johncblandii.com/index.php/2007/12/fms-a-quick-fix-for-missing-onbwdone-onfcsubscribe-etc.html\r
+ public function onBWDone() : void {\r
+ // writeDebug('onBWDone: called and ignored');\r
+ }\r
+\r
+ // NetStream client callback. Invoked when the song is complete.\r
+ public function onPlayStatus(info:Object):void {\r
+ writeDebug('onPlayStatus called with '+info);\r
+ switch(info.code) {\r
+ case "NetStream.Play.Complete":\r
+ writeDebug('Song has finished!');\r
+ break;\r
+ }\r
+ }\r
+\r
+ public function doIOError(e: IOErrorEvent) : void {\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onload", 0); // call onload, assume it failed.\r
+ // there was a connection drop, a loss of internet connection, or something else wrong. 404 error too.\r
+ }\r
+\r
+ public function doAsyncError(e: AsyncErrorEvent) : void {\r
+ writeDebug('asyncError: ' + e.text);\r
+ }\r
+\r
+ public function doNetStatus(e: NetStatusEvent) : void {\r
+\r
+ // Handle failures\r
+ if (e.info.code == "NetStream.Failed"\r
+ || e.info.code == "NetStream.Play.FileStructureInvalid"\r
+ || e.info.code == "NetStream.Play.StreamNotFound") {\r
+\r
+ this.lastNetStatus = e.info.code;\r
+ writeDebug('netStatusEvent: ' + e.info.code);\r
+ this.failed = true;\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onfailure", '', e.info.level, e.info.code);\r
+ return;\r
+ }\r
+\r
+ writeDebug('netStatusEvent: ' + e.info.code); // KJV we like to see all events\r
+\r
+ // When streaming, Stop is called when buffering stops, not when the stream is actually finished.\r
+ // @see http://www.actionscript.org/forums/archive/index.php3/t-159194.html\r
+ if (e.info.code == "NetStream.Play.Stop") {\r
+\r
+ if (!this.finished && (!this.useNetstream || !this.serverUrl)) {\r
+\r
+ // finished playing, and not RTMP\r
+ writeDebug('calling onfinish for a sound');\r
+ // reset the sound? Move back to position 0?\r
+ this.sm.checkProgress();\r
+ this.finished = true; // will be reset via JS callback\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onfinish");\r
+\r
+ }\r
+\r
+ } else if (e.info.code == "NetStream.Play.Start" || e.info.code == "NetStream.Buffer.Empty" || e.info.code == "NetStream.Buffer.Full") {\r
+\r
+ // RTMP case..\r
+ // We wait for the buffer to fill up before pausing the just-loaded song because only if the\r
+ // buffer is full will the song continue to buffer until the user hits play.\r
+ if (this.serverUrl && e.info.code == "NetStream.Buffer.Full" && this.pauseOnBufferFull) {\r
+ this.ns.pause();\r
+ this.paused = true;\r
+ this.pauseOnBufferFull = false;\r
+ // Call pause in JS. This will call back to us to pause again, but\r
+ // that should be harmless.\r
+ writeDebug('Pausing on buffer full');\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "'].pause", false);\r
+ }\r
+\r
+ var isNetstreamBuffering: Boolean = (e.info.code == "NetStream.Buffer.Empty" || e.info.code == "NetStream.Play.Start");\r
+ // assume buffering when we start playing, eg. initial load.\r
+ if (isNetstreamBuffering != this.lastValues.isBuffering) {\r
+ this.lastValues.isBuffering = isNetstreamBuffering;\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onbufferchange", this.lastValues.isBuffering ? 1 : 0);\r
+ }\r
+\r
+ // We can detect the end of the stream when Play.Stop is called followed by Buffer.Empty.\r
+ // However, if you pause and let the whole song buffer, Buffer.Flush is called followed by\r
+ // Buffer.Empty, so handle that case too.\r
+ //\r
+ // Ignore this event if we are more than 3 seconds from the end of the song.\r
+ if (e.info.code == "NetStream.Buffer.Empty" && (this.lastNetStatus == 'NetStream.Play.Stop' || this.lastNetStatus == 'NetStream.Buffer.Flush')) {\r
+ if (this.duration && (this.ns.time * 1000) < (this.duration - 3000)) {\r
+ writeDebug('Ignoring Buffer.Empty because this is too early to be the end of the stream! (sID: '+this.sID+', time: '+(this.ns.time*1000)+', duration: '+this.duration+')');\r
+ } else if (!this.finished) {\r
+ this.finished = true;\r
+ writeDebug('calling onfinish for sound '+this.sID);\r
+ this.sm.checkProgress();\r
+ ExternalInterface.call(baseJSObject + "['" + this.sID + "']._onfinish");\r
+ }\r
+\r
+ } else if (e.info.code == "NetStream.Buffer.Empty") {\r
+ // The buffer is empty. Start from the smallest buffer again.\r
+ this.ns.bufferTime = this.bufferTime;\r
+ }\r
+ }\r
+\r
+ // Remember the last NetStatus event\r
+ this.lastNetStatus = e.info.code;\r
+ }\r
+\r
+ // KJV The sound adds some of its own netstatus handlers so we don't need to do it here.\r
+ public function addNetstreamEvents() : void {\r
+ ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, doAsyncError);\r
+ ns.addEventListener(NetStatusEvent.NET_STATUS, doNetStatus);\r
+ ns.addEventListener(IOErrorEvent.IO_ERROR, doIOError);\r
+ }\r
+\r
+ public function removeNetstreamEvents() : void {\r
+ ns.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, doAsyncError);\r
+ ns.removeEventListener(NetStatusEvent.NET_STATUS, doNetStatus);\r
+ ns.addEventListener(NetStatusEvent.NET_STATUS, dummyNetStatusHandler);\r
+ ns.removeEventListener(IOErrorEvent.IO_ERROR, doIOError);\r
+ // KJV Stop listening for NetConnection events on the sound\r
+ nc.removeEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);\r
+ }\r
+\r
+ // Prevents possible 'Unhandled NetStatusEvent' condition if a sound is being\r
+ // destroyed and interacted with at the same time.\r
+ public function dummyNetStatusHandler(e: NetStatusEvent) : void {\r
+ // Don't do anything\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+@REM this builds the soundmanager 2 SWF from source
+
+mtasc -swf ../swf/soundmanager2_debug.swf -main -header 16:16:30 SoundManager2.as -version 8
+@pause
+
--- /dev/null
+#!/bin/bash
+/Applications/mtasc/mtasc -swf ../swf/soundmanager2_debug.swf -main -header 16:16:30 SoundManager2.as -version 8
--- /dev/null
+@REM this builds the soundmanager 2 SWF from source
+@REM using mxmlc from the Adobe open-source Flex SDK
+
+c:\progra~1\flexsdk\bin\mxmlc -debug=true -use-network=false -static-link-runtime-shared-libraries=true -optimize=true -o ../swf/soundmanager2_flash9_debug.swf -file-specs SoundManager2_AS3.as
--- /dev/null
+#!/bin/bash
+/Applications/flexsdk/bin/mxmlc -debug=true -static-link-runtime-shared-libraries=true -optimize=true -o ../swf/soundmanager2_flash9_debug.swf -file-specs SoundManager2_AS3.as
--- /dev/null
+/* SM2 troubleshooting CSS */\r
+\r
+#sm2-test {\r
+ position:relative;\r
+ background:#f6f6f6;\r
+ border:1px solid #eee;\r
+ padding:3px;\r
+}\r
+\r
+#sm2-test,\r
+#sm2-test ul.items {\r
+ border-radius:3px;\r
+}\r
+\r
+#sm2-test ul.items {\r
+ position:relative;\r
+ background:#fff;\r
+ list-style-type:none;\r
+ margin:0px;\r
+ padding:0px;\r
+ border:1px solid #ccc;\r
+}\r
+\r
+#sm2-test ul.items li {\r
+ position:relative;\r
+ margin-left:0.5em;\r
+ padding-left:0.5em;\r
+ margin-right:0.5em;\r
+ padding-right:0.5em;\r
+}\r
+\r
+#sm2-test ul.items li h3 {\r
+ padding-top:0.3em;\r
+ margin-top:0px;\r
+ border-bottom:1px solid #ccc;\r
+ border-top: none;\r
+}\r
+\r
+#sm2-test ul.items li:last-child h3 {\r
+ border-bottom:none;\r
+}\r
+\r
+#sm2-test ul.items li div.details {\r
+ border-bottom:1px solid #ccc;\r
+}\r
+\r
+#sm2-test ul.items li:hover div.details {\r
+ border-bottom:1px solid #ccc;\r
+}\r
+\r
+#sm2-test ul.items li.open:last-child h3,\r
+#sm2-test ul.items li.fail:last-child h3,\r
+#sm2-test ul.items li:last-child div.details:last-child {\r
+ border-bottom:1px solid #fff;\r
+}\r
+\r
+#sm2-test ul.items li div.details {\r
+ display:none; \r
+}\r
+\r
+#sm2-test ul.items li.open div.details,\r
+#sm2-test ul.items li.unknown div.details,\r
+#sm2-test ul.items li.fail div.details {\r
+ display:block;\r
+}\r
+\r
+#sm2-test ul.items li span.yay,\r
+#sm2-test ul.items li span.boo,\r
+#sm2-test ul.items li span.default,\r
+#sm2-test ul.items li span.unknown {\r
+ display:none;\r
+}\r
+\r
+#sm2-test ul.items li span.yay,\r
+#sm2-test ul.items li.pass span.msg {\r
+ color:green;\r
+}\r
+\r
+#sm2-test ul.items li span.boo,\r
+#sm2-test ul.items li.fail span.msg {\r
+ color:red;\r
+}\r
+\r
+#sm2-test ul.items li span.default,\r
+#sm2-test ul.items li.default span.msg {\r
+ color:#ccc;\r
+}\r
+\r
+#sm2-test ul.items li span.unknown,\r
+#sm2-test ul.items li.unknown span.msg {\r
+ color:#666;\r
+}\r
+\r
+#sm2-test ul.items li.default span.msg {\r
+ display:none; /* hide messages in the event a reset occurs */\r
+}\r
+\r
+#sm2-test ul.items li.pass span.yay,\r
+#sm2-test ul.items li.fail span.boo,\r
+#sm2-test ul.items li.default span.default,\r
+#sm2-test ul.items li.unknown span.unknown {\r
+ float:right;\r
+ display:inline;\r
+}\r
+\r
+#sm2-container.flash_debug {\r
+ /* flash movie, when soundManager.debugFlash = true */\r
+ position:relative;\r
+ width:auto;\r
+ height:300px;\r
+ width:100%;\r
+ background:#f6f6f6;\r
+ border:1px solid #ccc;\r
+}\r
+\r
+#sm2-container.flash_debug object,\r
+#sm2-container.flash_debug embed {\r
+ border:1px solid #fff;\r
+}
\ No newline at end of file
--- /dev/null
+// SoundManager 2 start-up troubleshooting tool\r
+\r
+// FlashDetect, by Carl Yestrau\r
+// http://www.featureblend.com/license.txt\r
+var FlashDetect=new function(){var self=this;self.installed=false;self.raw="";self.major=-1;self.minor=-1;self.revision=-1;self.revisionStr="";var activeXDetectRules=[{"name":"ShockwaveFlash.ShockwaveFlash.7","version":function(obj){return getActiveXVersion(obj);}},{"name":"ShockwaveFlash.ShockwaveFlash.6","version":function(obj){var version="6,0,21";try{obj.AllowScriptAccess="always";version=getActiveXVersion(obj);}catch(err){}\r
+return version;}},{"name":"ShockwaveFlash.ShockwaveFlash","version":function(obj){return getActiveXVersion(obj);}}];var getActiveXVersion=function(activeXObj){var version=-1;try{version=activeXObj.GetVariable("$version");}catch(err){}\r
+return version;};var getActiveXObject=function(name){var obj=-1;try{obj=new ActiveXObject(name);}catch(err){}\r
+return obj;};var parseActiveXVersion=function(str){var versionArray=str.split(",");return{"raw":str,"major":parseInt(versionArray[0].split(" ")[1],10),"minor":parseInt(versionArray[1],10),"revision":parseInt(versionArray[2],10),"revisionStr":versionArray[2]};};var parseStandardVersion=function(str){var descParts=str.split(/ +/);var majorMinor=descParts[2].split(/\./);var revisionStr=descParts[3];return{"raw":str,"major":parseInt(majorMinor[0],10),"minor":parseInt(majorMinor[1],10),"revisionStr":revisionStr,"revision":parseRevisionStrToInt(revisionStr)};};var parseRevisionStrToInt=function(str){return parseInt(str.replace(/[a-zA-Z]/g,""),10)||self.revision;};self.majorAtLeast=function(version){return self.major>=version;};self.FlashDetect=function(){if(navigator.plugins&&navigator.plugins.length>0){var type='application/x-shockwave-flash';var mimeTypes=navigator.mimeTypes;if(mimeTypes&&mimeTypes[type]&&mimeTypes[type].enabledPlugin&&mimeTypes[type].enabledPlugin.description){var version=mimeTypes[type].enabledPlugin.description;var versionObj=parseStandardVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revisionStr=versionObj.revisionStr;self.revision=versionObj.revision;self.installed=true;}}else if(navigator.appVersion.indexOf("Mac")==-1&&window.execScript){var version=-1;for(var i=0;i<activeXDetectRules.length&&version==-1;i++){var obj=getActiveXObject(activeXDetectRules[i].name);if(typeof obj=="object"){self.installed=true;version=activeXDetectRules[i].version(obj);if(version!=-1){var versionObj=parseActiveXVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revision=versionObj.revision;self.revisionStr=versionObj.revisionStr;}}}}}();};FlashDetect.release="1.0.3";\r
+\r
+// flash version URL switch (for this demo page)\r
+var winLoc = window.location.toString();\r
+if (winLoc.match(/flash9/i)) {\r
+ soundManager.setup({\r
+ flashVersion: 9,\r
+ preferFlash: true\r
+ });\r
+ if (winLoc.match(/highperformance/i)) {\r
+ soundManager.setup({\r
+ useHighPerformance: true\r
+ });\r
+ }\r
+} else if (winLoc.match(/flash8/i)) {\r
+ soundManager.setup({\r
+ flashVersion: 8,\r
+ preferFlash: true\r
+ });\r
+}\r
+\r
+var sm2Debugger = null;\r
+\r
+function SM2Debugger() {\r
+\r
+ var elementIDs = ['flashtojs','jstoflash','onload','soundtest','swf','hasflash'];\r
+ var elements = {};\r
+ var self = this;\r
+\r
+ this.getXHR = function() {\r
+ var xhr = null;\r
+ if (typeof window.XMLHttpRequest != 'undefined') {\r
+ try {\r
+ xhr = new XMLHttpRequest();\r
+ } catch(e) {\r
+ // d'oh\r
+ }\r
+ }\r
+ if (!xhr) {\r
+ try {\r
+ xhr = new ActiveXObject('Msxml2.XMLHTTP');\r
+ } catch(e) {\r
+ try {\r
+ xhr = new ActiveXObject('Microsoft.XMLHTTP');\r
+ } catch(E) {\r
+ xhr = null;\r
+ }\r
+ }\r
+ }\r
+ return xhr;\r
+ }\r
+\r
+ this.testURL = function(sURL,fOnComplete) {\r
+ var xhr = self.getXHR();\r
+ var msg = '<a href="'+soundManager.url+'" title="This should be a valid .SWF URL, not a 404 etc.">'+soundManager.url+'</a>';\r
+ if (soundManager.getMoviePercent() == 100) {\r
+ // SWF may have already loaded\r
+ fOnComplete(true,msg);\r
+ } else {\r
+ try {\r
+ xhr.open("HEAD",sURL,true);\r
+ xhr.onreadystatechange = function() {\r
+ if (xhr.readyState == 4) {\r
+ if (xhr.status == '200') {\r
+ fOnComplete(true,msg);\r
+ } else if (xhr.status == '404') {\r
+ fOnComplete(false,msg);\r
+ } else {\r
+ // some other response\r
+ fOnComplete('unknown',(xhr.status != '0'?'HTTP response: '+xhr.status+', ':'')+msg); // safari returns 0 when offline\r
+ }\r
+ }\r
+ }\r
+ xhr.send(null);\r
+\r
+ } catch(e) {\r
+ // fail (cross-domain, or no XHR) unless offline\r
+ fOnComplete('unknown',msg);\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+\r
+ this.handleEvent = function(sEventType,bSuccess,sMessage) {\r
+ var o = elements[sEventType];\r
+ if (o) {\r
+ o.className = (bSuccess == true?'pass':(bSuccess != false?bSuccess:'fail')); // true = pass, className as argument, or false == fail\r
+ if (sMessage) {\r
+ var oSpan = o.getElementsByTagName('span')[4];\r
+ if (oSpan) {\r
+ oSpan.innerHTML = (oSpan.innerHTML +' <span class="msg">'+sMessage+'</msg>');\r
+ } else {\r
+ o.title = sMessage;\r
+ }\r
+ }\r
+ // associated events\r
+ if (sEventType == 'onload') {\r
+ if (bSuccess) {\r
+ self.doSoundTest();\r
+ } else {\r
+ self.testURL(soundManager.url,function(bSuccess,sMessage) {\r
+ if (typeof sMessage == 'undefined') {\r
+ sMessage = null;\r
+ }\r
+ self.handleEvent('swf',bSuccess,sMessage);\r
+ });\r
+ }\r
+ } else if (sEventType == 'swf') {\r
+ if (bSuccess == false) {\r
+ // don't show flashtojs at all if SWF failed to load\r
+ self.handleEvent('flashtojs','default'); // reset to N/A status\r
+ }\r
+ } else if (sEventType == 'flashtojs') {\r
+ if (bSuccess != true) {\r
+ // online or offline help messages\r
+ if (soundManager._overHTTP) {\r
+ document.getElementById('d-flashtojs-offline').style.display = 'none';\r
+ } else {\r
+ document.getElementById('d-flashtojs-online').style.display = 'none';\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ soundManager._writeDebug('SM2 debugger warning: Undefined event type "'+sEventType+'"',1);\r
+ }\r
+ }\r
+\r
+ this.doSoundTest = function() {\r
+ var foo = soundManager.createSound({\r
+ id: 'sm2TestSound',\r
+ url: ('http://www.schillmania.com/projects/soundmanager2/demo/_mp3/mouseover.mp3')\r
+ });\r
+ if (!soundManager._disabled) {\r
+ foo.play();\r
+ // looks to be OK..\r
+ if (!soundManager._disabled) {\r
+ // still OK..\r
+ self.handleEvent('soundtest',true);\r
+ } else {\r
+ self.handleEvent('soundtest',false,': Failed after play()'); \r
+ }\r
+ } else {\r
+ self.handleEvent('soundtest',false,': Failed after createSound()');\r
+ }\r
+ }\r
+\r
+ this.init = function() {\r
+ // map event elements to DOM nodes - eg. elements.flashtojs = document.getElementById('d-flashtojs');\r
+ for (var i=elementIDs.length; i--;) {\r
+ elements[elementIDs[i]] = document.getElementById('d-'+elementIDs[i]);\r
+ }\r
+ self.doFlashTest();\r
+ }\r
+\r
+ this.doFlashTest = function() {\r
+ var fd = FlashDetect;\r
+ var hasFlash = fd.installed;\r
+ var fv = soundManager.setupOptions.flashVersion;\r
+ var isSupported = (hasFlash && fd.major >= fv);\r
+ var flashVersion = fd.major+'.'+fd.minor+'.'+fd.revisionStr;\r
+ var flashInfo = ' version '+(!isSupported?'unsupported ('+flashVersion+', SWF version '+fv+')':flashVersion);\r
+ document.getElementById('d-flashversion').innerHTML = 'soundManager.flashVersion = '+fv+';';\r
+ if (hasFlash) {\r
+ self.handleEvent('hasflash',isSupported,hasFlash?flashInfo:null);\r
+ } else {\r
+ self.handleEvent('hasflash','default',hasFlash?flashInfo:null);\r
+ }\r
+ }\r
+\r
+ soundManager.setup({\r
+ debugFlash: true // try to get flash debug output, as well\r
+ });\r
+\r
+ this.init();\r
+\r
+}\r
+\r
+function sm2DebugInit() {\r
+ sm2Debugger = new SM2Debugger();\r
+}
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"\r
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\r
+<head>\r
+<title>SoundManager 2 Start-up Test / Troubleshooting Tool</title>
+<meta name="robots" content="noindex" />\r
+<meta name="description" content="A standalone version of the SoundManager 2 Start-up Troubleshooting Tool." />\r
+<meta name="keywords" content="javascript sound, javascript audio, javascript play mp3, javascript sound control, javascript video, mp3, mp4, mpeg4" />\r
+<meta name="robots" content="all" />\r
+<meta name="author" content="Scott Schiller" />\r
+<meta name="copyright" content="Copyright (C) 1997 onwards Scott Schiller" />\r
+<meta name="language" content="en-us" />\r
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+<link rel="stylesheet" type="text/css" media="screen" href="../demo/index.css" /> <!-- prettier fonts etc., optional -->\r
+<link rel="stylesheet" type="text/css" media="screen" href="debug.css" />\r
+<!-- soundManager.useFlashBlock: related CSS -->\r
+<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />\r
+<style type="text/css">\r
+#sm2-container {\r
+ position:relative;\r
+ width:auto;\r
+ height:auto;\r
+ max-height:200px;\r
+ margin-top:1em;\r
+ border:1px solid #999;\r
+ background:#eee;\r
+ padding:0.5em;\r
+}\r
+</style>\r
+<script type="text/javascript" src="../script/soundmanager2.js"></script>\r
+<script type="text/javascript">\r
+soundManager.setup({\r
+ url: '../swf/'\r
+});\r
+</script>\r
+\r
+<script type="text/javascript" src="debug.js"></script>\r
+</head>\r
+\r
+<body>\r
+\r
+<!-- the following markup, debug.css and debug.js are required. -->\r
+\r
+<div style="position:relative;width:500px;margin:1em">\r
+\r
+<p class="note">Flash options: <a href="#flash8" onclick="window.location.replace(this.href);window.location.reload()">Flash 8</a> (default), <a href="#flash9" onclick="window.location.replace(this.href);window.location.reload()">Flash 9</a> (normal) or <a href="#flash9-highperformance" onclick="window.location.replace(this.href);window.location.reload()">Flash 9 + highPerformance + fastPolling</a> modes.</p>\r
+\r
+<div id="sm2-test">\r
+ <ul class="items">\r
+\r
+ <li id="d-onload" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">FAIL</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>SoundManager 2 start-up</span></h3>\r
+ <div id="sm2-startup" class="details">\r
+ <p>soundManager onready() or ontimeout() events are ultimately called when start-up completes.</p>\r
+ <p>If you're seeing a failure, refer to the below for troubleshooting details for common causes.</p>\r
+ </div>\r
+ </li>\r
+\r
+ <li id="d-hasflash" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>Flash</span></h3>\r
+ <div class="details">\r
+ <p>Flash 8 or 9 may be required for SoundManager 2 to start, depending on HTML5 support. You are currently using <b id="d-flashversion">[unknown]</b>.</p>\r
+ </div>\r
+ </li>\r
+\r
+ <li id="d-swf" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>Flash SWF</span></h3>\r
+ <div class="details">\r
+ <p>SoundManager 2 must load a flash movie before initialisation can proceed. If you have errors here, check that soundManager.url is correctly defined and that the URL being loaded is correct.</p>\r
+ <p>If the Flash movie URL is OK, Flash security or flash blockers are the likely cause. Check the section below.</p>\r
+ </div>\r
+ </li>\r
+\r
+ <li id="d-flashtojs" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>Flash -> JS</span></h3>\r
+ <div class="details">\r
+ <p>Once the flash component of SM2 has loaded, it tries to make a call to Javascript-land. This is a common point of failure, for security reasons:</p>\r
+ <ul>\r
+ <li>\r
+ <p><b>Have a flash blocker?</b> Check that the <a href="#flashdebug">SM2 flash movie</a> (below) is loading and is not being blocked.</p>\r
+ </li>\r
+ <li>\r
+ Is your browser URL at file:// or c:/path/ or otherwise not using HTTP? Flash security "whitelisting" is required to allow Flash + JS to work when offline, placing it in the "LocalTrusted" Flash security sandbox rather than "localWithFile".\r
+ \r
+ <div id="d-flashtojs-offline" style="padding-bottom:1em">\r
+ <h4>Offline viewing: Adding a "trusted location" to the Flash Security Settings Panel</h4>\r
+ <p>The Flash Player Global Security Settings Panel is a web-based control panel which allows you to configure Flash security. You will need to add the path of the SoundManager 2 project in order for it to work "offline" (ie., when viewing via file:// or c:/)</p>\r
+ <p id="ss"><a href="#screenshots" onclick="document.getElementById('ss-box').style.display = 'block';document.getElementById('ss').style.display='none';return false">Show me how</a>: Adding a "trusted location"</p>\r
+ <div id="ss-box" style="display:none">\r
+ <h4>Illustrated guide: Adding a "trusted location" in Flash</h4>\r
+ <p>Below: Adding a location, and selecting "Browse for folder" (or directory), to whitelist the SoundManager 2 project directory for offline viewing.</p>\r
+ <p><img src="fpgss-add-location.png" alt="Adding a location: Browse for the file or directory to whitelist" style="width:100%;_width:auto;min-width:72px;max-width:396px" /></p>\r
+ <p><img src="fpgss-added-location.png" alt="Whitelisted location has now been added, JS + Flash will work under this path" style="width:100%;_width:auto;min-width:72px;max-width:396px" /></p>\r
+ </div>\r
+ <p><a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html" target="_blank" class="feature">Launch the Flash Security Settings Panel</a></p>\r
+ </div>\r
+ \r
+ </li>\r
+ <li style="margin-top:0.5em">Flash blockers (FlashBlock, "click to flash" etc.) preventing flash load and start-up - need whitelisting/"allow this domain" to work smoothly. If you suspect blocking is the issue, try the <a href="../demo/flashblock/">SoundManager 2 Flashblock demo</a>.</li>\r
+ <li style="margin-top:0.5em">Online viewing (HTTP/S): Same-domain security rules apply to HTML + Flash content by default (crossdomain.xml/allowDomain() in .AS source required to override.)</li>\r
+ </ul>\r
+ <p>See <a href="#flashdebug" title="SoundManager 2 flash debug output">Flash debug output</a> for more security error details.</p>\r
+\r
+ <div id="d-flashtojs-online">\r
+ <h4>Online viewing: Cross-domain security restrictions</h4>\r
+ <p>HTML page on domain A loading .SWF from domain B: Flash security prevents JS + Flash when a cross-domain XML permission file is not available on domain B, and/or flash movie was not compiled with allowDomain('domainA') or allowDomain('*') - note that the SWF distributed with SM2 does not use this by default; try using the cross-domain version of the SWF, or compile your own which whitelists your own domain(s).</p>\r
+\r
+ <h4>Flash Blockers</h4>\r
+ <p>Browser extensions/add-ons like "FlashBlock" and "click to flash" can prevent the .SWF from loading, and this will mean SM2 will time-out and fail waiting for a response from Flash. For development, it's best to whitelist the domain(s) or the .SWF for SM2 to allow it to work.</p>\r
+ <p>Have a flash blocker installed? Want to test it? Try the <a href="../../demo/flashblock">SoundManager 2 Flashblock demo</a>.</p>\r
+\r
+ </div>\r
+\r
+ </div>\r
+ </li>\r
+\r
+ <li id="d-jstoflash" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>JS -> Flash</span></h3>\r
+ <div class="details">\r
+ <p>At this point, Javascript attempts to respond to Flash's initial outgoing Flash -> JS call, completing the test for JS/flash communication. If SM2 does not receive a response from flash, it will eventually fail.</p>\r
+ <p>Offline viewing conditions and cross-domain security rules will prevent Flash <-> JS communication. See the details of Flash -> JS for information.</p>\r
+ <p><b>Special Firefox Note</b>: Some versions of Firefox (9.0 and newer?) may break JS/Flash in the file:// or offline case even when the path has been whitelisted in the Flash player security settings panel. IE, Chrome, Safari and Opera do not have this issue.</p>\r
+ </div> \r
+ </li>\r
+\r
+ <li id="d-soundtest" class="default">\r
+ <h3><span class="yay">OK</span><span class="boo">Error</span><span class="default">N/A</span><span class="unknown">Unknown</span><span>Sound test</span></h3>\r
+ <div class="details">\r
+ <p>Here, a simple createSound() call is made to test SM2's actual operation. A sound should load and play provided SM2 was able to start successfully.</p>\r
+ </div>\r
+ </li>\r
+\r
+ </ul>\r
+</div>\r
+\r
+<div class="block" style="margin-top:1em">\r
+ <div id="soundmanager-debug" class="code">\r
+ <!-- live debug goes here -->\r
+ </div>\r
+</div>\r
+\r
+<div id="flashdebug">\r
+ <div id="sm2-container">\r
+ <!-- flash goes here -->\r
+ </div>\r
+</div>\r
+\r
+<script type="text/javascript">\r
+sm2DebugInit();\r
+</script>\r
+\r
+</div>\r
+</body>\r
+</html>
--- /dev/null
+{% extends "layout.html" %}
+{% block title %}Page non existante{% endblock %}
+{% block body %}
+ <p>Cette page est non existante.</p>
+ <p><a href="{{ url_for('index') }}">go somewhere nice</a></p>
+{% endblock %}
--- /dev/null
+{% extends "layout.html" %}
+{% block body %}
+<h2>Analyse d’un nouveau fichier son : {{ filename }}</h2>
+
+<div class="sm2-bar-ui flat">
+ <div class="sm2-bar-ui">
+
+ <div class="bd sm2-main-controls">
+
+ <div class="sm2-inline-texture"></div>
+ <div class="sm2-inline-gradient"></div>
+
+ <div class="sm2-inline-element sm2-button-element">
+ <div class="sm2-button-bd">
+ <a href="#play" class="sm2-inline-button play-pause">Play / pause</a>
+ </div>
+ </div>
+
+ <div class="sm2-inline-element sm2-inline-status">
+
+ <div class="sm2-playlist">
+ <div class="sm2-playlist-target">
+ <!-- playlist <ul> + <li> markup will be injected here -->
+ <!-- if you want default / non-JS content, you can put that here. -->
+ <noscript><p>JavaScript is required.</p></noscript>
+ </div>
+ </div>
+
+ <div class="sm2-progress">
+ <div class="sm2-row">
+ <div class="sm2-inline-time">0:00</div>
+ <div class="sm2-progress-bd">
+ <div class="sm2-progress-track">
+ <div class="sm2-progress-bar"></div>
+ <div class="sm2-progress-ball"><div class="icon-overlay"></div></div>
+ </div>
+ </div>
+ <div class="sm2-inline-duration">0:00</div>
+ </div>
+ </div>
+
+ </div>
+
+ <div class="sm2-inline-element sm2-button-element sm2-volume">
+ <div class="sm2-button-bd">
+ <span class="sm2-inline-button sm2-volume-control volume-shade"></span>
+ <a href="#volume" class="sm2-inline-button sm2-volume-control">volume</a>
+ </div>
+ </div>
+ </div>
+
+ <div class="bd sm2-playlist-drawer sm2-element">
+
+ <div class="sm2-inline-texture">
+ <div class="sm2-box-shadow"></div>
+ </div>
+
+ <!-- playlist content is mirrored here -->
+
+ <div class="sm2-playlist-wrapper">
+
+ <ul class="sm2-playlist-bd">
+ <li>
+ <div class="sm2-row">
+ <div class="sm2-col sm2-wide">
+ <a href="{{ url_for('download', filename=filename) }}"" class="exclude button-exclude inline-exclude"><b>blabla</b> - blublu </a>
+ </div>
+ </div>
+ </li>
+ </ul>
+
+ </div>
+
+ <div class="sm2-extra-controls">
+
+ <div class="bd">
+
+ <div class="sm2-inline-element sm2-button-element">
+ <a href="#prev" title="Previous" class="sm2-inline-button previous">< previous</a>
+ </div>
+
+ <div class="sm2-inline-element sm2-button-element">
+ <a href="#next" title="Next" class="sm2-inline-button next">> next</a>
+ </div>
+ </div>
+
+ </div>
+
+ </div>
+ </div>
+</div>
+
+ <script>
+ swf_url = "{{ url_for('static', filename='soundmanager/swf') }}";
+ mp3_url = "{{ url_for('download', filename=filename) }}";
+
+ soundManager.setup({
+ // where to find flash audio SWFs, as needed
+ url: swf_url,
+ onready: function() {
+ var mySound = soundManager.createSound({
+ url: mp3_url,
+ });
+
+ console.log("Play, "+ mp3_url);
+ // ...and play it
+ //mySound.play();
+ },
+ ontimeout: function() {
+ console.log("Error playing, "+ mp3_url);
+ // Hrmm, SM2 could not start. Missing SWF? Flash blocked? Show an error, etc.?
+ }
+ });
+</script>
+
+{% endblock %}
--- /dev/null
+{% extends "layout.html" %}
+{% block body %}
+<h2>Sommaire (très, oui)</h2>
+
+<ul>
+ <li><a href="{{ url_for('upload_file') }}">Analyser un nouveau fichier</a></li>
+</ul>
+{% endblock %}
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <title>Femtoblackpool</title>
+
+ <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
+ <link rel="stylesheet" href="{{ url_for('static', filename='soundmanager/demo/bar-ui/css/bar-ui.css') }}" />
+
+ <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
+
+ <script src="{{ url_for('static', filename='js/jquery.min.js') }}"></script>
+ <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
+ <script src="{{ url_for('static', filename='soundmanager/script/soundmanager2.js') }}"></script>
+ <script src="{{ url_for('static', filename='soundmanager/demo/bar-ui/script/bar-ui.js') }}"></script>
+ <script src="https://cdn.socket.io/socket.io-1.3.7.js"></script>
+ </head>
+ <body>
+ <div class="container">
+ <h1><a href="{{ url_for('index') }}">Femtoblack. Pull!</a></h1>
+ {% block body %}{% endblock %}
+ </div>
+ </body>
+</html>
--- /dev/null
+{% extends "layout.html" %}
+{% block body %}
+
+ <form id="emit" method="POST" action='#'>
+ <input type="text" name="emit_data" id="emit_data" placeholder="Message">
+ <input type="submit" value="Echo">
+ </form>
+ <form id="broadcast" method="POST" action='#'>
+ <input type="text" name="broadcast_data" id="broadcast_data" placeholder="Message">
+ <input type="submit" value="Broadcast">
+ </form>
+ <form id="join" method="POST" action='#'>
+ <input type="text" name="join_room" id="join_room" placeholder="Room Name">
+ <input type="submit" value="Join Room">
+ </form>
+ <form id="leave" method="POST" action='#'>
+ <input type="text" name="leave_room" id="leave_room" placeholder="Room Name">
+ <input type="submit" value="Leave Room">
+ </form>
+ <form id="send_room" method="POST" action='#'>
+ <input type="text" name="room_name" id="room_name" placeholder="Room Name">
+ <input type="text" name="room_data" id="room_data" placeholder="Message">
+ <input type="submit" value="Send to Room">
+ </form>
+ <form id="close" method="POST" action="#">
+ <input type="text" name="close_room" id="close_room" placeholder="Room Name">
+ <input type="submit" value="Close Room">
+ </form>
+ <form id="disconnect" method="POST" action="#">
+ <input type="submit" value="Disconnect">
+ </form>
+ <h2>Receive:</h2>
+ <div id="log"></div>
+
+
+
+<script>
+
+
+ $(document).ready(function(){
+
+namespace = '/test'; // change to an empty string to use the global namespace
+ // the socket.io documentation recommends sending an explicit package upon connection
+ // this is specially important when using the global namespace
+ var socket = io.connect('//' + document.domain + ':' + location.port + namespace);
+ // event handler for server sent data
+ // the data is displayed in the "Received" section of the page
+ socket.on('my response', function(msg) {
+ $('#log').append('<br>Received #' + msg.count + ': ' + msg.data);
+ });
+ // event handler for new connections
+ socket.on('connect', function() {
+ socket.emit('my event', {data: 'I\'m connected!'});
+ });
+ // handlers for the different forms in the page
+ // these send data to the server in a variety of ways
+ $('form#emit').submit(function(event) {
+ socket.emit('my event', {data: $('#emit_data').val()});
+ return false;
+ });
+ $('form#broadcast').submit(function(event) {
+ socket.emit('my broadcast event', {data: $('#broadcast_data').val()});
+ return false;
+ });
+ $('form#join').submit(function(event) {
+ socket.emit('join', {room: $('#join_room').val()});
+ return false;
+ });
+ $('form#leave').submit(function(event) {
+ socket.emit('leave', {room: $('#leave_room').val()});
+ return false;
+ });
+ $('form#send_room').submit(function(event) {
+ socket.emit('my room event', {room: $('#room_name').val(), data: $('#room_data').val()});
+ return false;
+ });
+ $('form#close').submit(function(event) {
+ socket.emit('close room', {room: $('#close_room').val()});
+ return false;
+ });
+ $('form#disconnect').submit(function(event) {
+ socket.emit('disconnect request');
+ return false;
+ });
+ });
+</script>
+
+{% endblock %}
--- /dev/null
+{% extends "layout.html" %}
+{% block body %}
+<h2>Analyser un nouveau fichier son</h2>
+
+<form id="form1" enctype="multipart/form-data" method="post" action="">
+ <div class="row">
+ <label for="fileToUpload">Select a File to Upload</label><br />
+ <input type="file" name="file" id="fileToUpload" onchange="fileSelected();"/>
+ </div>
+ <div id="fileName"></div>
+ <div id="fileSize"></div>
+ <div id="fileType"></div>
+
+ <div class="row">
+ <input type="button" onclick="uploadFile()" value="Upload" />
+ </div>
+
+ <div id="progressNumber"></div>
+</form>
+
+<script>
+ function fileSelected() {
+ var file = document.getElementById('fileToUpload').files[0];
+ if (file) {
+ var fileSize = 0;
+ if (file.size > 1024 * 1024)
+ fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
+ else
+ fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
+
+ document.getElementById('fileName').innerHTML = 'Name: ' + file.name;
+ document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;
+ document.getElementById('fileType').innerHTML = 'Type: ' + file.type;
+ }
+ }
+
+function uploadFile() {
+ var xhr = new XMLHttpRequest();
+ var fd = new FormData(document.getElementById('form1'));
+
+ /* event listners */
+ xhr.upload.addEventListener("progress", uploadProgress, false);
+ xhr.addEventListener("load", uploadComplete, false);
+ xhr.addEventListener("error", uploadFailed, false);
+ xhr.addEventListener("abort", uploadCanceled, false);
+ /* Be sure to change the url below to the url of your upload server side script */
+
+ xhr.open("POST", "/upload");
+ xhr.send(fd);
+}
+
+
+function uploadProgress(evt) {
+ if (evt.lengthComputable) {
+ var percentComplete = Math.round(evt.loaded * 100 / evt.total);
+ document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
+ }
+ else {
+ document.getElementById('progressNumber').innerHTML = 'unable to compute';
+ }
+}
+
+function uploadComplete(evt) {
+ /* This event is raised when the server send back a response */
+ alert(evt.target.responseText);
+}
+
+function uploadFailed(evt) {
+ alert("There was an error attempting to upload the file.");
+}
+
+function uploadCanceled(evt) {
+ alert("The upload has been canceled by the user or the browser dropped the connection.");
+}
+
+</script>
+
+{% endblock %}
--- /dev/null
+[uwsgi]
+socket=/tmp/femtoblackpool-fcgi.sock
+chmod-socket=666
+abstract-socket=false
+
+master=true
+workers=2
+
+virtualenv=/home/bot/flask/env
+plugins=python3
+module=femtoblackweb
+callable=app
+
+post-buffering=8192
+
+daemonize=/home/bot/flask/logs/uwsgi.log
+logto=/home/bot/flask/logs/femtoblackpool.log