diff --git a/python/bootstrap.py b/python/bootstrap.py new file mode 100644 index 00000000000..5f2cb0835c9 --- /dev/null +++ b/python/bootstrap.py @@ -0,0 +1,260 @@ +############################################################################## +# +# Copyright (c) 2006 Zope Foundation and Contributors. +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# +############################################################################## +"""Bootstrap a buildout-based project + +Simply run this script in a directory containing a buildout.cfg. +The script accepts buildout command-line options, so you can +use the -c option to specify an alternate configuration file. +""" + +import os, shutil, sys, tempfile, textwrap, urllib, urllib2, subprocess +from optparse import OptionParser + +if sys.platform == 'win32': + def quote(c): + if ' ' in c: + return '"%s"' % c # work around spawn lamosity on windows + else: + return c +else: + quote = str + +# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments. +stdout, stderr = subprocess.Popen( + [sys.executable, '-Sc', + 'try:\n' + ' import ConfigParser\n' + 'except ImportError:\n' + ' print 1\n' + 'else:\n' + ' print 0\n'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() +has_broken_dash_S = bool(int(stdout.strip())) + +# In order to be more robust in the face of system Pythons, we want to +# run without site-packages loaded. This is somewhat tricky, in +# particular because Python 2.6's distutils imports site, so starting +# with the -S flag is not sufficient. However, we'll start with that: +if not has_broken_dash_S and 'site' in sys.modules: + # We will restart with python -S. + args = sys.argv[:] + args[0:0] = [sys.executable, '-S'] + args = map(quote, args) + os.execv(sys.executable, args) +# Now we are running with -S. We'll get the clean sys.path, import site +# because distutils will do it later, and then reset the path and clean +# out any namespace packages from site-packages that might have been +# loaded by .pth files. +clean_path = sys.path[:] +import site +sys.path[:] = clean_path +for k, v in sys.modules.items(): + if k in ('setuptools', 'pkg_resources') or ( + hasattr(v, '__path__') and + len(v.__path__)==1 and + not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))): + # This is a namespace package. Remove it. + sys.modules.pop(k) + +is_jython = sys.platform.startswith('java') + +setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py' +distribute_source = 'http://python-distribute.org/distribute_setup.py' + +# parsing arguments +def normalize_to_url(option, opt_str, value, parser): + if value: + if '://' not in value: # It doesn't smell like a URL. + value = 'file://%s' % ( + urllib.pathname2url( + os.path.abspath(os.path.expanduser(value))),) + if opt_str == '--download-base' and not value.endswith('/'): + # Download base needs a trailing slash to make the world happy. + value += '/' + else: + value = None + name = opt_str[2:].replace('-', '_') + setattr(parser.values, name, value) + +usage = '''\ +[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] + +Bootstraps a buildout-based project. + +Simply run this script in a directory containing a buildout.cfg, using the +Python that you want bin/buildout to use. + +Note that by using --setup-source and --download-base to point to +local resources, you can keep this script from going over the network. +''' + +parser = OptionParser(usage=usage) +parser.add_option("-v", "--version", dest="version", + help="use a specific zc.buildout version") +parser.add_option("-d", "--distribute", + action="store_true", dest="use_distribute", default=False, + help="Use Distribute rather than Setuptools.") +parser.add_option("--setup-source", action="callback", dest="setup_source", + callback=normalize_to_url, nargs=1, type="string", + help=("Specify a URL or file location for the setup file. " + "If you use Setuptools, this will default to " + + setuptools_source + "; if you use Distribute, this " + "will default to " + distribute_source +".")) +parser.add_option("--download-base", action="callback", dest="download_base", + callback=normalize_to_url, nargs=1, type="string", + help=("Specify a URL or directory for downloading " + "zc.buildout and either Setuptools or Distribute. " + "Defaults to PyPI.")) +parser.add_option("--eggs", + help=("Specify a directory for storing eggs. Defaults to " + "a temporary directory that is deleted when the " + "bootstrap script completes.")) +parser.add_option("-t", "--accept-buildout-test-releases", + dest='accept_buildout_test_releases', + action="store_true", default=False, + help=("Normally, if you do not specify a --version, the " + "bootstrap script and buildout gets the newest " + "*final* versions of zc.buildout and its recipes and " + "extensions for you. If you use this flag, " + "bootstrap and buildout will get the newest releases " + "even if they are alphas or betas.")) +parser.add_option("-c", None, action="store", dest="config_file", + help=("Specify the path to the buildout configuration " + "file to be used.")) + +options, args = parser.parse_args() + +# if -c was provided, we push it back into args for buildout's main function +if options.config_file is not None: + args += ['-c', options.config_file] + +if options.eggs: + eggs_dir = os.path.abspath(os.path.expanduser(options.eggs)) +else: + eggs_dir = tempfile.mkdtemp() + +if options.setup_source is None: + if options.use_distribute: + options.setup_source = distribute_source + else: + options.setup_source = setuptools_source + +if options.accept_buildout_test_releases: + args.append('buildout:accept-buildout-test-releases=true') +args.append('bootstrap') + +try: + import pkg_resources + import setuptools # A flag. Sometimes pkg_resources is installed alone. + if not hasattr(pkg_resources, '_distribute'): + raise ImportError +except ImportError: + ez_code = urllib2.urlopen( + options.setup_source).read().replace('\r\n', '\n') + ez = {} + exec ez_code in ez + setup_args = dict(to_dir=eggs_dir, download_delay=0) + if options.download_base: + setup_args['download_base'] = options.download_base + if options.use_distribute: + setup_args['no_fake'] = True + ez['use_setuptools'](**setup_args) + if 'pkg_resources' in sys.modules: + reload(sys.modules['pkg_resources']) + import pkg_resources + # This does not (always?) update the default working set. We will + # do it. + for path in sys.path: + if path not in pkg_resources.working_set.entries: + pkg_resources.working_set.add_entry(path) + +cmd = [quote(sys.executable), + '-c', + quote('from setuptools.command.easy_install import main; main()'), + '-mqNxd', + quote(eggs_dir)] + +if not has_broken_dash_S: + cmd.insert(1, '-S') + +find_links = options.download_base +if not find_links: + find_links = os.environ.get('bootstrap-testing-find-links') +if find_links: + cmd.extend(['-f', quote(find_links)]) + +if options.use_distribute: + setup_requirement = 'distribute' +else: + setup_requirement = 'setuptools' +ws = pkg_resources.working_set +setup_requirement_path = ws.find( + pkg_resources.Requirement.parse(setup_requirement)).location +env = dict( + os.environ, + PYTHONPATH=setup_requirement_path) + +requirement = 'zc.buildout' +version = options.version +if version is None and not options.accept_buildout_test_releases: + # Figure out the most recent final version of zc.buildout. + import setuptools.package_index + _final_parts = '*final-', '*final' + def _final_version(parsed_version): + for part in parsed_version: + if (part[:1] == '*') and (part not in _final_parts): + return False + return True + index = setuptools.package_index.PackageIndex( + search_path=[setup_requirement_path]) + if find_links: + index.add_find_links((find_links,)) + req = pkg_resources.Requirement.parse(requirement) + if index.obtain(req) is not None: + best = [] + bestv = None + for dist in index[req.project_name]: + distv = dist.parsed_version + if _final_version(distv): + if bestv is None or distv > bestv: + best = [dist] + bestv = distv + elif distv == bestv: + best.append(dist) + if best: + best.sort() + version = best[-1].version +if version: + requirement = '=='.join((requirement, version)) +cmd.append(requirement) + +if is_jython: + import subprocess + exitcode = subprocess.Popen(cmd, env=env).wait() +else: # Windows prefers this, apparently; otherwise we would prefer subprocess + exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env])) +if exitcode != 0: + sys.stdout.flush() + sys.stderr.flush() + print ("An error occurred when trying to install zc.buildout. " + "Look above this message for any errors that " + "were output by easy_install.") + sys.exit(exitcode) + +ws.add_entry(eggs_dir) +ws.require(requirement) +import zc.buildout.buildout +zc.buildout.buildout.main(args) +if not options.eggs: # clean up temporary egg directory + shutil.rmtree(eggs_dir) diff --git a/python/buildout.cfg b/python/buildout.cfg new file mode 100644 index 00000000000..0e0fdf7fedc --- /dev/null +++ b/python/buildout.cfg @@ -0,0 +1,106 @@ +[buildout] +newest = false + +parts = + dirs + py + paster + supervisor + mongodb + mongodb-client-config + mongodb-master-config + +develop = + src/sailing.db + src/sailing.connector + src/sailing.web + +eggs = + PasteScript + sailing.db + sailing.connector + sailing.web + +[conf] +db_home = ${buildout:directory}/data/ +log_home= ${buildout:directory}/data/logs +mongodb_master = localhost +mongodb_host = localhost +mongodb_port = 10200 +supervisord_host_port = 0.0.0.0:10001 + +[supervisor] +recipe = collective.recipe.supervisor +logfile = ${conf:log_home}/supervisord.log +port = 12456 +user = admin +password = admin +loglevel = info +programs = + 10 mongod ${buildout:bin-directory}/mongod [--config ${buildout:directory}/etc/mongodb-master.cfg] ${buildout:directory} + +[dirs] +recipe = z3c.recipe.mkdir +paths = + +[py] +recipe = zc.recipe.egg +eggs = ${buildout:eggs} +interpreter = py +scripts = + trac_listener + +[paster] +recipe = zc.recipe.egg +eggs = ${buildout:eggs} +interpreter = py +scripts = + paster + +[test] +recipe = zc.recipe.testrunner +defaults = ['-v'] +eggs = + ${buildout:eggs} +script = test + +[mongodb] +recipe = rod.recipe.mongodb +linux2-32bit-url = http://downloads.mongodb.org/linux/mongodb-linux-i686-1.8.1.tgz +linux2-64bit-url = http://downloads.mongodb.org/linux/mongodb-linux-x86_64-1.8.1.tgz + +[mongodb-client-config] +recipe = collective.recipe.template +input = templates/db.ini +output = ${buildout:directory}/etc/db.ini + +[mongodb-master-config] +recipe = collective.recipe.template +input = templates/mongodb-master.cfg +output = ${buildout:directory}/etc/mongodb-master.cfg + +[webserver-dev-config] +recipe = collective.recipe.template +input = templates/webserver-dev.ini +output = ${buildout:directory}/etc/webserver-development.ini + +[webserver-dev-runner] +recipe = collective.recipe.template +input = templates/app_debug.sh +output = ${buildout:directory}/bin/debug.sh + +[webserver-prod-config] +recipe = collective.recipe.template +input = templates/webserver-prod.ini +output = ${buildout:directory}/etc/webserver-production.ini + +[webserver-prod-runner-start] +recipe = collective.recipe.template +input = templates/app_production_start.sh +output = ${buildout:directory}/bin/start.sh + +[webserver-prod-runner-stop] +recipe = collective.recipe.template +input = templates/app_production_stop.sh +output = ${buildout:directory}/bin/stop.sh + diff --git a/python/data/.placeholder b/python/data/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/data/cache/.placeholder b/python/data/cache/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/data/logs/.placeholder b/python/data/logs/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/data/logs/mongodb/.placeholder b/python/data/logs/mongodb/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/data/mongodb/.placeholder b/python/data/mongodb/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/dev.cfg b/python/dev.cfg new file mode 100644 index 00000000000..46b5f3df1fe --- /dev/null +++ b/python/dev.cfg @@ -0,0 +1,7 @@ +[buildout] +extends = buildout.cfg + +parts += + test + webserver-dev-config + webserver-dev-runner diff --git a/python/etc/.placeholder b/python/etc/.placeholder new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/prod.cfg b/python/prod.cfg new file mode 100644 index 00000000000..5f076352645 --- /dev/null +++ b/python/prod.cfg @@ -0,0 +1,10 @@ +[buildout] +extends = buildout.cfg + +eggs += + pastegevent + +parts += + webserver-prod-config + webserver-prod-runner-start + webserver-prod-runner-stop diff --git a/python/src/sailing.connector/README.txt b/python/src/sailing.connector/README.txt new file mode 100644 index 00000000000..329413e04ca --- /dev/null +++ b/python/src/sailing.connector/README.txt @@ -0,0 +1,6 @@ +Introduction +============ + + + +This product may contain traces of nuts. diff --git a/python/src/sailing.connector/docs/HISTORY.txt b/python/src/sailing.connector/docs/HISTORY.txt new file mode 100644 index 00000000000..306a4fd0e50 --- /dev/null +++ b/python/src/sailing.connector/docs/HISTORY.txt @@ -0,0 +1,7 @@ +Changelog +========= + +1.0dev (unreleased) +------------------- + +- Initial release diff --git a/python/src/sailing.connector/sailing/__init__.py b/python/src/sailing.connector/sailing/__init__.py new file mode 100644 index 00000000000..f48ad105287 --- /dev/null +++ b/python/src/sailing.connector/sailing/__init__.py @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/python/src/sailing.connector/sailing/connector/__init__.py b/python/src/sailing.connector/sailing/connector/__init__.py new file mode 100644 index 00000000000..1cb4a8565f4 --- /dev/null +++ b/python/src/sailing.connector/sailing/connector/__init__.py @@ -0,0 +1,84 @@ + +import cjson +import urllib, urllib2 + +from sailing.web.util import get_abspath + +import logging +logging.basicConfig(level=logging.INFO) +log = logging.getLogger(__name__) + +class URIConfigurator(object): + + def __init__(self, host, port): + self.host = host + self.port = port + + def copy(self): + inst = URIConfigurator(self.host, self.port) + inst.__dict__ = self.__dict__.copy() + return inst + + def key(self): + return '%s:%s' % (self.host, self.port) + + def clear(self): + try: + del self.__dict__['parameters'] + del self.__dict__['_parameters'] + except: + pass + + def setContext(self, context): + self.clear() + self.context = context + + def setCommand(self, command): + self.command = command + + def setRace(self, race): + self.race = race + + def setParameters(self, parameters={}): + if hasattr(self, 'command'): + parameters['action'] = self.command + + if hasattr(self, 'race') and self.race: + parameters['eventname'] = self.race.event + parameters['racename'] = self.race.name + + self.parameters = urllib.urlencode(parameters) + self._parameters = parameters + + def hasParameter(self, name): + return self._parameters.has_key(name) + + def URI(self): + if not hasattr(self, 'parameters'): + # ensure that parameters are set correctly + self.setParameters() + + uri = 'http://%s:%s/%s?%s' % (self.host, self.port, self.context, self.parameters) + return uri + + def trigger(self, request=None): + log.info('Triggering URI %s' % self.URI()) + return urllib2.urlopen(self.URI()) + +def jsonByUrl(configurator): + """ Connects to specified REST service and returns parsed data """ + + # small hack to make tests easier + if configurator.port is None: + handle = open(get_abspath('sailing.web:tests/data/%s' % configurator.host), 'r') + data = handle.read() + handle.close() + + else: + data = configurator.trigger().read() + + if data.find('Exception')>0: + raise Exception, 'Java triggered exception: %s' % data[:350] + + return cjson.decode(data.strip()) + diff --git a/python/src/sailing.connector/sailing/connector/provider.py b/python/src/sailing.connector/sailing/connector/provider.py new file mode 100644 index 00000000000..8c92ca6bc60 --- /dev/null +++ b/python/src/sailing.connector/sailing/connector/provider.py @@ -0,0 +1,275 @@ + +import sys, threading, datetime, time + +import cjson +import urllib, urllib2 + +from sailing.db import database +from sailing.db import model +from sailing.connector import jsonByUrl + +from sailing.web import config +from sailing.connector import URIConfigurator + +import logging +logging.basicConfig(level=logging.INFO) +log = logging.getLogger('sailing.connector.run#main') + +class LiveDataReceiver(threading.Thread): + + def __init__(self, host, port, eventname, racename): + self.host = host + self.port = port + self.eventname = eventname + self.racename = racename + + self.last_update = None + self.updatecount = 0 + + self.running = False + self.paused = True + + threading.Thread.__init__(self) + + def run(self): + log.info('START listener for %s:%s (%s, %s)' % (self.host, self.port, self.eventname, self.racename)) + self.running = True + + lock = threading.Lock() + while self.running is True: + + # make it possible to pause listener + if self.paused is True: + time.sleep(1) + continue + + conf = URIConfigurator(self.host, self.port) + conf.setContext(config.MODERATOR) + conf.setCommand(config.LIVE_EVENTS) + conf.setRace(model.RaceImpl.queryOneBy(event=self.eventname, name=self.racename)) + + # blocking call by updatecount setting + conf.setParameters(dict(eventname=self.eventname, racename=self.racename, sinceupdate=self.updatecount)) + + try: + # need to lock because other threads could overwrite information + with lock: + updatecount = liveRaceInformation(conf) + + self.last_update = datetime.datetime.now() + self.updatecount = updatecount + + except Exception, ex: + # print error but do not kill thread as this could be recoverable + log.error('Error in thread for %s %s' % (self.eventname, self.racename), exc_info=True) + + # avoid filling console with errors + time.sleep(2) + + # avoid hammering java server - can occur if call does not block correctly + time.sleep(1) + + log.info('STOP listener for %s:%s (%s, %s)' % (self.host, self.port, self.eventname, self.racename)) + +def computeRank(newvalue, oldvalue): + return newvalue + +def eventConfiguration(configurator): + """ Reads current event configuration from server """ + + # this can block if there are no tracked races available + events = jsonByUrl(configurator) + + for event in events: + dbevent = model.EventImpl.queryOneBy(name=event['name']) + if not dbevent: + dbevent = model.EventImpl() + + # create competitors for the whole event + cpnames = []; cobjects = [] + for cp in event['competitors']: + cpnames.append(cp['name']) + + cfound = model.CompetitorImpl.queryOneBy(name=cp['name'], event=event['name']) + if not cfound: + competitor = model.CompetitorImpl() + competitor.update(dict(name=cp['name'], nationality=cp['nationality'], event=event['name'])) + cobjects.append(competitor) + else: + cobjects.append(cfound) + + # prepare race and mark names + rcnames = []; rcmarks = [] + raceindex = 0; + for rc in event['races']: + rcnames.append( (rc['name'], rc['start']) ) + raceindex += 1 + + dbrace = model.RaceImpl.queryOneBy(event=event['name'], name=rc['name']) + if not dbrace: + dbrace = model.RaceImpl() + dbrace.update(dict(event=event['name'], name=rc['name'])) + + # make sure to include start to enable sorting + if rc.has_key('start'): + dbrace.update(dict(start=rc['start'])) + + marknames = [] + for leg in rc['legs']: + # including all legs where something ends into model + # in this case we get the last mark that equals the + # points for the whole race + marknames.append(leg['end']) + + rcmarks.append(marknames) + + rcnames.sort(lambda x,y: cmp(x[1], y[1])) + + # fill competitors with empty data + for cp in cobjects: + races = [0.0 for r in range(raceindex)] + + marks = cp.marks; values = cp.values + for r in range(raceindex): + if len(races) < r+1: + races.append(0.0) + + if len(marks) < r+1: + marks.append([]) + + if len(values) < r+1: + values.append([]) + + for m in range(len(rcmarks[r])): + if len(marks[r]) < m+1: + marks[r].append(0.0) + + if len(values[r]) < m+1: + values[r].append([]) + + cp.update(dict(races=races, marks=marks)) + + # finally create or update event + dbevent.update(dict(name=event['name'], boatclass=event['boatclass'], competitors=cpnames, races=[rname[0] for rname in rcnames], marks=rcmarks)) + + # return all received events + return events + +def liveRaceInformation(configurator): + """ Reads live race information from provider. Should be called + in a thread because execution can block until new data are available. """ + + data = jsonByUrl(configurator) + + racename = configurator.race.name + eventname = configurator.race.event + + # it is important to know which position the race has + # so we look it up in the Event itself + event = model.EventImpl.queryOneBy(name=eventname) + raceindex = event.races.index(racename) + + # this should help us finding out which legs are still running + # we assume that only one race at time is running so we stick + # to the legs + + lcount = 0; current_legs = {} + for leg in data['legs']: + for competitor in leg['competitors']: + comp = model.CompetitorImpl.queryOneBy(name=competitor['name'], event=eventname) + if not comp: + raise Exception, 'Could not find competitor %s for event %s' % (competitor['name'], eventname) + + c_races = comp.races + c_marks = comp.marks + c_values = comp.values + c_total_rank = comp.total + + # if competitor hasn't yet started we just ignore this leg + if competitor.get('started', False) is False: + continue + + # we take to into account because this is the one we have saved before + mark_name = leg['to'] + + # last mark in race? + is_last_mark = event.marks[raceindex][-1] == mark_name + + # competitor finished this leg? + finished = competitor['finished'] + + # we are now in race[raceindex].legs[legcount] and need to map this + # to competitor structures + + if finished: + # competitor has finished this leg so we need to save rank + # to the next mark (e.g. mark_name is 'Mark 1' and finished + # then competitor.marks[raceindex][lcount] = rank). This works + # because leg[position] equals marks[position] in list + if competitor.has_key('rank'): + c_marks[raceindex][lcount] = computeRank(competitor['rank'], c_marks[raceindex][lcount]) + + # if finished and last mark then update race information + if is_last_mark: + c_races[raceindex] = computeRank(competitor['rank'], c_races[raceindex]) + + # for the last race just update total rank + if raceindex+1 == len(c_races): + c_total_rank = computeRank(competitor['rank'], c_total_rank) + + else: + c_marks[raceindex][lcount] = 0.0 + if is_last_mark: + c_races[raceindex] = 0.0 + + if raceindex+1 == len(c_races): + c_total_rank = 0.0 + + else: + # leg not finished so put this leg into unfinished legs + current_legs[lcount] = 1 + + # now update values for the current position + for key in config.SORTED_LEG_VALUE_NAMES: + + # dynamically extend this one + attr = config.LEG_VALUE_DATA[key] + if len(c_values[raceindex][lcount]) < attr[0]+1: + c_values[raceindex][lcount].append(0.0) + + k = competitor.get(key, None) + if k in [None, 'null', 'Null', '']: + k = 0.0 + + c_values[raceindex][lcount][attr[0]] = k + + # compute total rank for competitor + rank = competitor.get('rank', 0) + if data.has_key('ranks'): + for c in data['ranks']: + if c['competitor'] == competitor['name']: + rank = c['rank'] + break + + comp.update(dict(current_rank=rank,races=c_races, marks=c_marks, values=c_values, total=c_total_rank)) + + # next leg + lcount += 1 + + # update race with current information + dbrace = model.RaceImpl.queryOneBy(event=eventname, name=racename) + mdup = dict(startoftracking=data['startoftracking'], + start=data['start'], finish=data['finish'], + timeofnewestevent=data['timeofnewestevent'], + updatecount=data['updatecount']) + + if data.get('wind'): + mdup['wind_source'] = data['wind']['source'] + mdup['wind_bearing'] = data['wind']['truebearingdeg'] + mdup['wind_speed'] = data['wind']['knowspeed'] + + mdup['current_legs'] = current_legs.keys() + dbrace.update(mdup) + + return data['updatecount'] + diff --git a/python/src/sailing.connector/setup.py b/python/src/sailing.connector/setup.py new file mode 100644 index 00000000000..f85396561db --- /dev/null +++ b/python/src/sailing.connector/setup.py @@ -0,0 +1,34 @@ +from setuptools import setup, find_packages +import os + +version = '1.0' + +setup(name='sailing.connector', + version=version, + description="Connector to TracTrac Application wrapped by Java", + long_description=open("README.txt").read() + "\n" + + open(os.path.join("docs", "HISTORY.txt")).read(), + # Get more strings from + # http://pypi.python.org/pypi?:action=list_classifiers + classifiers=[ + "Programming Language :: Python", + ], + keywords='', + author='', + author_email='', + url='http://svn.plone.org/svn/collective/', + license='GPL', + packages=find_packages(exclude=['ez_setup']), + namespace_packages=['sailing'], + include_package_data=True, + zip_safe=False, + install_requires=[ + 'setuptools', + 'pymongo', + 'mongokit', + 'python-cjson' + ], + entry_points=""" + # -*- Entry points: -*- + """, + ) diff --git a/python/src/sailing.db/README.txt b/python/src/sailing.db/README.txt new file mode 100644 index 00000000000..329413e04ca --- /dev/null +++ b/python/src/sailing.db/README.txt @@ -0,0 +1,6 @@ +Introduction +============ + + + +This product may contain traces of nuts. diff --git a/python/src/sailing.db/docs/HISTORY.txt b/python/src/sailing.db/docs/HISTORY.txt new file mode 100644 index 00000000000..306a4fd0e50 --- /dev/null +++ b/python/src/sailing.db/docs/HISTORY.txt @@ -0,0 +1,7 @@ +Changelog +========= + +1.0dev (unreleased) +------------------- + +- Initial release diff --git a/python/src/sailing.db/sailing/__init__.py b/python/src/sailing.db/sailing/__init__.py new file mode 100644 index 00000000000..f48ad105287 --- /dev/null +++ b/python/src/sailing.db/sailing/__init__.py @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/python/src/sailing.db/sailing/db/__init__.py b/python/src/sailing.db/sailing/db/__init__.py new file mode 100644 index 00000000000..36bdf0afeeb --- /dev/null +++ b/python/src/sailing.db/sailing/db/__init__.py @@ -0,0 +1,45 @@ + +import os, logging +from ConfigParser import ConfigParser + +LOG = logging.getLogger('sailing.db') + +ALL_KEYS = ('host', 'port', 'dbname', 'username', 'password', 'collections', 'master_host') +MANDATORY_KEYS = ('host', 'port', 'dbname', 'collections') + +def readDatabaseConfiguration(db_ini='db.ini'): + """ Read the database configuration """ + + if not os.path.exists(db_ini): + raise ConfigurationError('No database configuration found (%s)' % db_ini) + + CP = ConfigParser() + CP.read(db_ini) + result = dict() + for section in CP.sections(): + d = dict() + for k in ALL_KEYS: + v = None + if CP.has_option(section, k): + if k == 'port': + v = CP.getint(section, k) + elif k == 'collections': + v = [x.strip() for x in CP.get(section, k).split(',') if x.strip()] + else: + v = CP.get(section, k) + + if k in MANDATORY_KEYS and not v: + raise ConfigurationError('Database configuration error: [%s]>%s in "%s" is mandatory' % (section, k, db_ini)) + d[k] = v + result[section] = d + return result + + +# Read the database configuration either from $YSH_DATABASE_CONFIGURATION +# or /etc/db.ini + +filename = os.environ.get('YSH_DATABASE_CONFIGURATION', + os.path.join(os.getcwd(), 'etc', 'db.ini')) +LOG.info('Reading database configuration from %s' % filename) +DB_CONFIG = readDatabaseConfiguration(filename) + diff --git a/python/src/sailing.db/sailing/db/config.py b/python/src/sailing.db/sailing/db/config.py new file mode 100644 index 00000000000..662cb4436f5 --- /dev/null +++ b/python/src/sailing.db/sailing/db/config.py @@ -0,0 +1,11 @@ +# format for dates +# http://docs.python.org/library/datetime.html#strftime-and-strptime-behavior +# DATE_TIME_FORMAT = '%Y/%m/%d %H:%M' +DATE_TIME_FORMAT = '%Y/%m/%d' +DATE_FORMAT_STRING = '%b %d %Y' + +# db backend sort identifier +import pymongo +ASCENDING = pymongo.ASCENDING +DESCENDING = pymongo.DESCENDING + diff --git a/python/src/sailing.db/sailing/db/database.py b/python/src/sailing.db/sailing/db/database.py new file mode 100644 index 00000000000..920627f01fd --- /dev/null +++ b/python/src/sailing.db/sailing/db/database.py @@ -0,0 +1,71 @@ +import logging + +import mongokit +import mongokit.master_slave_connection + +from sailing.db import DB_CONFIG + +logging.basicConfig(level=logging.INFO) +LOG = logging.getLogger('sailing.db') + +__all__ = ('getCollection',) + +def setupDatabases(): + """ Setup MongoDB database connections and collections """ + + global collections, databases, connections, collection2database + + for d in DB_CONFIG.values(): + + dbname = d['dbname'] + slave_configuration = dict(host=d['host'], port=d['port']) + + if d['master_host']: + # master and slaves share the same configuration - except + # the hostname of the master host + master_configuration = slave_configuration.copy() + master_configuration['host'] = d['master_host'] + LOG.info('Setting up database as master-slave (database: %s, master: %s, slave: %s)' % + (dbname, master_configuration, slave_configuration)) + conn = mongokit.master_slave_connection.MasterSlaveConnection(master_configuration, [slave_configuration]) + else: + LOG.info('Setting up database (database:%s , master: %s)' % (dbname, slave_configuration)) + conn = mongokit.Connection(**slave_configuration) + + db = mongokit.Database(conn, dbname) + databases[dbname] = db + connections[dbname] = conn + + for collection in d['collections']: + collections[collection] = mongokit.Collection(db, collection) + collection2connection[collection] = conn + + LOG.info('Attached collections: %s' % ', '.join(collections)) + +def getCollection(collection): + """ Return a MongoDB collection by its name """ + coll = collections.get(collection) + if not coll: + raise ValueError('No collection %s configured' % collection) + return coll + +def getConnection(database): + """ Return connection for a given database """ + conn = connections.get(database) + if not conn: + raise ValueError('No connection for database %s found' % database) + return conn + +def getConnectionByCollectionName(collection): + """ Return connection object for a given collection name """ + db = collection2connection.get(collection) + if not db: + raise ValueError('No database for collection %s found' % collection) + return db + +collection2connection = dict() +connections = dict() +databases = dict() +collections = dict() +setupDatabases() + diff --git a/python/src/sailing.db/sailing/db/model/__init__.py b/python/src/sailing.db/sailing/db/model/__init__.py new file mode 100644 index 00000000000..0c6d2f1a5d2 --- /dev/null +++ b/python/src/sailing.db/sailing/db/model/__init__.py @@ -0,0 +1,58 @@ + +import datetime + +from base import ModelBase +from util import registerClass, queryContent, createContent + +from entities import * + +class EventImpl(ModelBase): + linked_model = Event + +class RaceImpl(ModelBase): + linked_model = Race + + default_values = { + 'running': False, + } + +class CompetitorImpl(ModelBase): + linked_model = Competitor + + default_values = { + 'races': [], + 'marks': [[]] + } + + @classmethod + def sortedBy(cls, eventname, raceindex=None, markindex=None, valueindex=None): + """ Returns competitors sorted by given index. If index + is None no sorting is performed on this index. If all index + params are None sorting is performed by total. """ + + def sorter(x, y): + xval = x.total + yval = y.total + + if valueindex is not None: + try: + xval = x.values[raceindex][markindex][valueindex] + yval = y.values[raceindex][markindex][valueindex] + except IndexError: + xval = 0.0 + yval = 0.0 + + elif markindex is not None: + xval = x.marks[raceindex][markindex] + yval = y.marks[raceindex][markindex] + + elif raceindex is not None: + xval = x.races[raceindex] + yval = y.races[raceindex] + + return cmp(xval, yval) + + competitors = cls.queryBy(event=eventname) + competitors.sort(sorter) + return competitors + diff --git a/python/src/sailing.db/sailing/db/model/base.py b/python/src/sailing.db/sailing/db/model/base.py new file mode 100644 index 00000000000..fec1ffb86bc --- /dev/null +++ b/python/src/sailing.db/sailing/db/model/base.py @@ -0,0 +1,277 @@ + +import datetime + +import mongokit +from pymongo.objectid import ObjectId + +from sailing.db.model.util import queryContent, createContent +from sailing.db import config + +MARKER = object + +class BaseDocument(mongokit.Document): + skip_validation = True + safe_mode = True + + def _updateInternal(self, **kw): + kw['safe'] = self.safe_mode + if not hasattr(self, 'created') or \ + not kw.get('created', None): + self['created'] = datetime.datetime.now() + + if not hasattr(self, 'typename') or \ + not kw.get('typename', None): + self['typename'] = self.__class__.__name__ + + return kw + + def save(self, *args, **kw): + kw = self._updateInternal(**kw) + super(BaseDocument, self).save(*args, **kw) + + def insert(self, *args, **kw): + kw = self._updateInternal(**kw) + super(BaseDocument, self).insert(*args, **kw) + + def update(self, *args, **kw): + kw = self._updateInternal(**kw) + super(BaseDocument, self).update(*args, **kw) + +class ModelBase(object): + + @classmethod + def collectionName(cls): + return cls.linked_model._collection + + @classmethod + def query(cls, uid, wrap=True): + uid = str(uid).strip() + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.get_from_id(ObjectId(uid)) + + if wrap is True: + if backend_instance: + if isinstance(backend_instance, list): + backend_instance = backend_instance[0] + return cls(backend_instance) + else: + return backend_instance + + return None + + @classmethod + def queryRaw(cls, input, limit=0, sortby='created', sortorder=config.DESCENDING): + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find(input).limit(limit).sort(sortby, sortorder) + + if backend_instance: + if backend_instance.count(): + return [cls(ba) for ba in backend_instance] + + return [] + + @classmethod + def queryBy(cls, limit=0, sortby='created', sortorder=config.DESCENDING, **fields): + assert isinstance(limit, int) + + klass = queryContent(cls.linked_model.__name__) + + # update fields with typename + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + # better would be to use fetch here because this includes structure but + # because we have one type per collection this doesn't matter + backend_instance = klass.find(fields).limit(limit).sort(sortby, direction=sortorder) + + if backend_instance: + if backend_instance.count(): + return [cls(ba) for ba in backend_instance] + + return [] + + @classmethod + def queryByCount(cls, limit=0, sortby='created', sortorder=config.DESCENDING, **fields): + assert isinstance(limit, int) + + # update fields with typename + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find(fields).limit(limit).sort(sortby, direction=sortorder) + return backend_instance.count() + + @classmethod + def queryCount(cls, limit=0, sortby='created', sortorder=config.DESCENDING, **fields): + # update fields with typename + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find(fields).limit(limit).sort(sortby, direction=sortorder) + return backend_instance.count() + + @classmethod + def queryRawCount(cls, input, limit=0, sortby='created', sortorder=config.DESCENDING): + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find(input).limit(limit).sort(sortby, direction=sortorder) + return backend_instance.count() + + @classmethod + def queryOneBy(cls, **fields): + # update fields with typename + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + klass = queryContent(cls.linked_model.__name__) + backend_instance = klass.find_one(fields) + + if backend_instance: + return cls(backend_instance) + return None + + @classmethod + def removeAllBy(cls, **fields): + if not fields.get('typename', None): + fields['typename'] = cls.linked_model.__name__ + + fields['atomic'] = True + klass = queryContent(cls.linked_model.__name__) + klass.collection.remove(**fields) + + # assuming that we clean all objects + klass.collection.drop_indexes() + + def __getstate__(self): + # we need to return a state where there is no connection + # to mongodb directly established - we just save the internal + # UID so to be able to rebuild the state later on + + dc = self.__dict__.copy() + inst = dc['_instance'] + + if getattr(inst, '__dict__', None): + # we preserve the instance to avoid reloading it + # on unpickle - just preserving raw values + idc = {}; footprint = inst.structure + + for k in footprint.keys(): + # model changes can yield non-complete instances + if inst.has_key(k): + idc[str(k)] = inst[k] + + idc['_id'] = dc['_instance']['_id'] + + del dc['_instance'] + dc['_instance'] = idc + + return dc + + def __setstate__(self, state): + self.__dict__ = state + + def __init__(self, instance = None, *args, **kw): + self._instance = instance + + def __getattr__(self, key): + # instance attributes are held by backend + value = self.get(key, default=object) + + # make sure to fall back to this class + if value is object: + return getattr(self.__class__, key) + + return value + + def get(self, key, default=None): + if key in self.__class__.linked_model.structure or key in ['_id', ]: + inst = self.__dict__['_instance'] + if inst.has_key(key): + return inst.get(key) + return default + + @property + def uid(self): + uid = getattr(self, '_id', None) + if uid: + return unicode(str(uid)) + return None + + def _backend(self): + return self.__class__.linked_model + + def _instance_(self): + # use this method only for direct operations (crud) + inst = self.__dict__['_instance'] + if inst: + # unpickling returns dict and not real mongokit instance + if not hasattr(inst, '__dict__'): + self.__dict__['_instance'] = self.query(inst['_id'], wrap=False) + return self.__dict__['_instance'] + return inst + + def getURL(self): + raise Exception, 'NotImplementedHere' + + def getTitle(self): + raise Exception, 'NotImplementedHere' + + def creationTime(self, pretty=False): + if pretty is True: + return pretty_date(self.created) + return self.created + + def reload(self): + self._instance = self.query(self.uid, wrap=False) + + def delete(self): + uid = self.uid + if not uid: + return False + + self._instance_().delete() + return True + + def update(self, dictionary=None, dosave=True): + klassname = self._backend().__name__ + + # make sure to make a difference between new and update + # new objects should always have empty uid field + if self.uid is None: + self._instance = createContent(klassname) + iis = self._instance_() + + if hasattr(self, '_before_update'): + self._before_update(dictionary, creation=True) + + # check that defaults are NOT set on backend + if hasattr(iis.__class__, 'default_values'): + if len(iis.__class__.default_values.keys())>0: + raise Exception, 'Implementation error: instance can not have defaults! Set defaults in model! Model: %s' % self._instance.__class__ + + # make sure to activate defaults + if hasattr(self.__class__, 'default_values'): + for dk,dv in self.__class__.default_values.items(): + if dictionary is None \ + or not dk in dictionary: + if callable(dv): + dv = dv() + + iis[dk] = dv + else: + if self._instance_() is None: + self._instance = self.query(self.uid, wrap=False) + + iis = self._instance_() + if hasattr(self, '_before_update'): + self._before_update(dictionary, creation=False) + + if dictionary: + for k,v in dictionary.items(): + iis[k] = v # need explicit set here + + # save also works for update process + if dosave is True: + iis.save() + diff --git a/python/src/sailing.db/sailing/db/model/entities.py b/python/src/sailing.db/sailing/db/model/entities.py new file mode 100644 index 00000000000..94a35355da9 --- /dev/null +++ b/python/src/sailing.db/sailing/db/model/entities.py @@ -0,0 +1,83 @@ + +import datetime + +from base import BaseDocument +from util import registerClass, queryContent, createContent + +class Event(BaseDocument): + _collection = 'events' + skip_validation = True + + structure = { + 'name': unicode, + 'boatclass': unicode, + 'competitors': [unicode, ], + 'races': [unicode, ], + 'marks': [[unicode, ]], + 'typename': unicode, + 'created': datetime.datetime + } + + indexes = [ + { + 'fields' : ['name'], + 'unique': True + }, + ] + +registerClass(Event) + +class Race(BaseDocument): + _collection = 'races' + skip_validation = True + + structure = { + 'name': unicode, + 'event': unicode, + 'current_legs': [int, ], # holds a list of positions of current legs + 'startoftracking': float, + 'start': float, + 'finish' : float, + 'timeofnewestevent': float, + 'updatecount': float, + 'wind_source': unicode, + 'wind_bearing': float, + 'wind_speed': float, + 'typename': unicode, + 'created': datetime.datetime + } + + indexes = [ + { + 'fields' : ['name', 'event'], + 'unique': True + }, + ] + +registerClass(Race) + +class Competitor(BaseDocument): + _collection = 'competitors' + skip_validation = True + + structure = { + 'name': unicode, + 'event': unicode, + 'nationality': unicode, + + 'total': float, + 'current_rank': int, # current rank for given time + 'races' : [float, ], + 'marks' : [[float, ], ], + 'values' : [[[float, ]]] + } + + indexes = [ + { + 'fields' : ['name', 'event'], + 'unique': True + }, + ] + +registerClass(Competitor) + diff --git a/python/src/sailing.db/sailing/db/model/util.py b/python/src/sailing.db/sailing/db/model/util.py new file mode 100644 index 00000000000..800127eaa37 --- /dev/null +++ b/python/src/sailing.db/sailing/db/model/util.py @@ -0,0 +1,32 @@ +from sailing.db.database import getConnection, getCollection, getConnectionByCollectionName + +classes = dict() + +def registerClass(cls): + """ Register class with MongoKit """ + + collection = cls._collection + conn = getConnectionByCollectionName(collection) + conn.register([cls]) + classes[cls.__name__] = cls + +def createContent(cls_name, **kw): + + try: + collection = getCollection(classes[cls_name]._collection) + except KeyError: + raise ValueError('Class "%s" is not registered' % cls_name) + + inst = getattr(collection, cls_name)() + for k,v in kw.items(): + inst[k] = v + return inst + +def queryContent(cls_name): + try: + collection = getCollection(classes[cls_name]._collection) + except KeyError: + raise ValueError('Class "%s" is not registered' % cls_name) + + return getattr(collection, cls_name) + diff --git a/python/src/sailing.db/sailing/db/monitoring.py b/python/src/sailing.db/sailing/db/monitoring.py new file mode 100644 index 00000000000..58af35096bb --- /dev/null +++ b/python/src/sailing.db/sailing/db/monitoring.py @@ -0,0 +1,35 @@ +from database import databases, collections + +def dbStats(): + result = dict() + for dbname in databases: + db = databases[dbname] + stats = db.command('dbstats') + result[dbname] = stats + return result + +def serverStatus(): + db = databases[databases.keys()[0]] + stats = db.command('serverStatus') + return stats + + +def collectionStats(): + result = dict() + for dbname in databases: + db = databases[dbname] + for coll in db.collection_names(): + result[coll] = db.command({'collstats' : coll}) + result[coll]['dbname'] = dbname + return result + +def dropDB(): + """ Drops all database data """ + + from database import databases + for k, db in databases.items(): + for name in db.collection_names(): + if name not in ('system.indexes',): + db[name].drop_indexes() + db.drop_collection(name) + diff --git a/python/src/sailing.db/setup.py b/python/src/sailing.db/setup.py new file mode 100644 index 00000000000..68dc6f4ddc9 --- /dev/null +++ b/python/src/sailing.db/setup.py @@ -0,0 +1,32 @@ +from setuptools import setup, find_packages +import os + +version = '1.0' + +setup(name='sailing.db', + version=version, + description="Connection to database for sailing", + long_description=open("README.txt").read() + "\n" + + open(os.path.join("docs", "HISTORY.txt")).read(), + # Get more strings from + # http://pypi.python.org/pypi?:action=list_classifiers + classifiers=[ + "Programming Language :: Python", + ], + keywords='', + author='', + author_email='', + url='http://svn.plone.org/svn/collective/', + license='GPL', + packages=find_packages(exclude=['ez_setup']), + namespace_packages=['sailing'], + include_package_data=True, + zip_safe=False, + install_requires=[ + 'setuptools', + # -*- Extra requirements: -*- + ], + entry_points=dict(console_scripts=( + 'trac_listener=sailing.connector.run:main', + )), + ) diff --git a/python/src/sailing.web/MANIFEST.in b/python/src/sailing.web/MANIFEST.in new file mode 100644 index 00000000000..68a2d33eeb7 --- /dev/null +++ b/python/src/sailing.web/MANIFEST.in @@ -0,0 +1,3 @@ +include *.ini *.cfg +exclude .installed.cfg +recursive-include src *.html diff --git a/python/src/sailing.web/README.txt b/python/src/sailing.web/README.txt new file mode 100644 index 00000000000..329413e04ca --- /dev/null +++ b/python/src/sailing.web/README.txt @@ -0,0 +1,6 @@ +Introduction +============ + + + +This product may contain traces of nuts. diff --git a/python/src/sailing.web/docs/HISTORY.txt b/python/src/sailing.web/docs/HISTORY.txt new file mode 100644 index 00000000000..306a4fd0e50 --- /dev/null +++ b/python/src/sailing.web/docs/HISTORY.txt @@ -0,0 +1,7 @@ +Changelog +========= + +1.0dev (unreleased) +------------------- + +- Initial release diff --git a/python/src/sailing.web/sailing/__init__.py b/python/src/sailing.web/sailing/__init__.py new file mode 100644 index 00000000000..f48ad105287 --- /dev/null +++ b/python/src/sailing.web/sailing/__init__.py @@ -0,0 +1,6 @@ +# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) diff --git a/python/src/sailing.web/sailing/web/__init__.py b/python/src/sailing.web/sailing/web/__init__.py new file mode 100644 index 00000000000..9e0d65a9bd3 --- /dev/null +++ b/python/src/sailing.web/sailing/web/__init__.py @@ -0,0 +1,29 @@ + +from pyramid.config import Configurator + +from pyramid_beaker import BeakerSessionFactoryConfig,\ + session_factory_from_settings, set_cache_regions_from_settings + +def init_app(request): + return {} + +def app(global_config, **settings): + """ This function returns a pyramid.router.Router object. + It is usually called by the PasteDeploy framework during ``paster serve``. + """ + + # paster app config callback + import sailing.web + + # beaker stuff for session and caching + session_factory = session_factory_from_settings(settings) + set_cache_regions_from_settings(settings) + + from sailing.web.util import reloader_watch_files + reloader_watch_files(global_config, **settings) + + config = Configurator(settings=settings, root_factory=init_app, session_factory=session_factory) + config.include('pyramid_zcml') + config.load_zcml('configure.zcml') + + return config.make_wsgi_app() diff --git a/python/src/sailing.web/sailing/web/adapter/__init__.py b/python/src/sailing.web/sailing/web/adapter/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/src/sailing.web/sailing/web/adapter/configure.zcml b/python/src/sailing.web/sailing/web/adapter/configure.zcml new file mode 100644 index 00000000000..5408ee3cc75 --- /dev/null +++ b/python/src/sailing.web/sailing/web/adapter/configure.zcml @@ -0,0 +1,10 @@ + + + + + + diff --git a/python/src/sailing.web/sailing/web/browser/__init__.py b/python/src/sailing.web/sailing/web/browser/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/src/sailing.web/sailing/web/browser/configure.zcml b/python/src/sailing.web/sailing/web/browser/configure.zcml new file mode 100644 index 00000000000..0e4df24dfc1 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/configure.zcml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + diff --git a/python/src/sailing.web/sailing/web/browser/core.py b/python/src/sailing.web/sailing/web/browser/core.py new file mode 100644 index 00000000000..205282462c5 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/core.py @@ -0,0 +1,185 @@ + +import time, datetime + +import urllib + +from webob.exc import HTTPFound +from pyramid.renderers import get_renderer, render_to_response + +from sailing.connector import provider, URIConfigurator, jsonByUrl +from sailing.db import model +from sailing.db import monitoring + +from sailing.web import config + +import logging +log = logging.getLogger(__name__) +logging.basicConfig() + +current_leaderboard_event = None + +class BaseView(object): + + def __init__(self, context, request): + self.context = context + self.request = request + + # don't forget to call save() if you changed s/th on the session + self.session = request['beaker.session'] + + def __call__(self): + return {'main': self.mainTemplate()} + + def yieldMessage(self, message): + parameters = urllib.urlencode(dict(message=message)) + return HTTPFound(location='/?%s' % parameters) + + def mainTemplate(self): + return get_renderer('templates/maintemplate.pt').implementation() + + def eventUrlHistory(self): + return self.session.get('event.url_history', ['No URLs to TracTrac events gathered until now']) + + def raceUrlHistory(self): + return self.session.get('race.url_history', ['No URLs to TracTrac races gathered until now']) + + def dbDatabaseStats(self): + return monitoring.dbStats() + + def dbCollectionStats(self): + return monitoring.collectionStats() + + def dbServerStatus(self): + return monitoring.serverStatus() + + def millisToDatetime(self, millis, short=False): + if millis is None or millis >= 9023372036854775807: + return None + + try: + tm = time.gmtime(millis/1000) + + if tm.tm_year >= 2000: + dt = datetime.datetime(year=tm.tm_year, month=tm.tm_mon, day=tm.tm_mday, hour=tm.tm_hour, minute=tm.tm_min, second=tm.tm_sec) + return dt + except: + log.error('Error', exc_info=True) + + return None + + def datetimeToMillis(self, dt): + if dt: + dtnew = datetime.datetime(year=dt.year, month=dt.month, day=dt.day, hour=dt.hour+2, minute=dt.minute, second=dt.second) + return time.mktime(dtnew.timetuple())*1000 + return 0 + + def parseDatetime(self, dt, format='%m/%d/%Y %H:%M:%S'): + return datetime.datetime.strptime(dt.strip(), format) + + def listenerStarted(self): + return self.session.get('listener-started', False) + + def listenerConf(self): + if self.listenerStarted(): + return self.session['listener-conf'].copy() + return None + + def currentRace(self): + if not self.session.has_key('current-race'): + raise Exception, 'No current race could be determined' + + return model.RaceImpl.queryOneBy(event=self.session['current-event'], name=self.session['current-race']) + + def currentEvent(self): + return model.EventImpl.queryOneBy(name=self.session['current-event']) + + def currentLeaderboardEvent(self): + cev = model.EventImpl.queryOneBy(name=current_leaderboard_event) + + # XXX remove this + if not cev: + return model.EventImpl.queryBy()[0] + + return cev + + def raceBy(self, event, name): + return model.RaceImpl.queryOneBy(event=event, name=name) + + def currentWind(self): + conf = self.listenerConf() + race = self.currentRace() + + conf.setContext(config.ADMIN) + conf.setCommand(config.SHOW_WIND) + conf.setParameters(dict(eventname=race.event, racename=race.name)) + + return jsonByUrl(conf) + + def allEvents(self): + return model.EventImpl.queryBy() + + def allRacesFor(self, event=None): + if event is None: + allevents = self.allEvents() + + races = [] + for event in allevents: + races += event.races + + return races + + return model.EventImpl.queryOneBy(name=event).races + + def allCompetitorsFor(self, event): + return model.CompetitorImpl.queryBy(event=event) + + def competitorsSortedBy(self, eventname, sortparam): + param = sortparam + if param == 'name': + competitors = model.CompetitorImpl.sortedBy(eventname=eventname) + competitors.sort(lambda x,y: cmp(x.name, y.name)) + + elif param == 'total': + competitors = model.CompetitorImpl.sortedBy(eventname=eventname) + + elif param.find(',')>0: + params = param.strip().split(',') + + if len(params) == 2: + competitors = model.CompetitorImpl.sortedBy(eventname=eventname, raceindex=int(params[0])-1, markindex=int(params[1])-1) + elif len(params) == 3: + competitors = model.CompetitorImpl.sortedBy(eventname=eventname, raceindex=int(params[0])-1, markindex=int(params[1])-1, valueindex=int(params[2])-1) + + else: + param = int(param.strip()) + competitors = model.CompetitorImpl.sortedBy(eventname=eventname, raceindex=param-1) + + return competitors + +def callFunction(context, request): + """ Calls a function dynamically """ + + import functions + return getattr(functions, request.matchdict.get('function'))(context, request) + +def renderTemplate(context, request): + """ Renders a template dynamically """ + + view = BaseView(context, request) + return render_to_response('templates/%s.pt' % request.matchdict.get('template'), + {'context' : context, 'view':view, + 'main' : view.mainTemplate()}, + request=request) + +def renderCSS(context, request): + """ Renders a CSS template dynamically """ + + response = render_to_response('static/css/%s.txt' % request.matchdict.get('template'), + {'context' : context}, + request=request) + + # could be more generic + response.content_type = 'text/css' + return response + + diff --git a/python/src/sailing.web/sailing/web/browser/functions.py b/python/src/sailing.web/sailing/web/browser/functions.py new file mode 100644 index 00000000000..89c00564766 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/functions.py @@ -0,0 +1,481 @@ + +import urllib, urllib2 +import time +import threading + +from webob.exc import HTTPFound +from webob import Response + +from pyramid.exceptions import NotFound +from pyramid.renderers import render_to_response + +from sailing.db import model +from sailing.db.monitoring import dropDB as realDropDB + +from sailing.connector import provider, URIConfigurator, jsonByUrl + +from sailing.web import config +from sailing.web.util import jsonize + +import core + +import logging +log = logging.getLogger(__name__) +logging.basicConfig() + +# map holding association of host:port -> threads +threaded_listener = {} + +def dropDB(context, request): + from sailing.db.monitoring import dropDB + dropDB() + return HTTPFound(location='/') + +def startListenerThreads(conf, eventlist): + # now we should have an event configuration + # read this configuration and for each event and race + # start a listener thread + + lock = threading.Lock() + with lock: + for event in eventlist: + event_impl = model.EventImpl.queryOneBy(name=event['name']) + for racename in event_impl.races: + key = hash('%s-%s-%s-%s' % (conf.host, conf.port, event['name'], racename)) + + # remove dead threads + lstn = threaded_listener.get(key, None) + if lstn and lstn.running is False and lstn.is_alive() is False: + del threaded_listener[key] + + # now there should be only running threads left + if not threaded_listener.has_key(key): + t = provider.LiveDataReceiver(conf.host, conf.port, event['name'], racename) + threaded_listener[key] = t + t.start() + +# addEvent +def configureListener(context, request): + host = request.POST.get('host', 'localhost') + port = request.POST.get('port', '8888') + + lock = threading.Lock() + + view = core.BaseView(context, request) + + conf = URIConfigurator(host, port) + view.session['listener-conf'] = conf + + if request.POST.get('listener-start', None): + conf.setContext(config.ADMIN) + + if request.POST.get('eventJSONURL'): + conf.setCommand(config.ADD_EVENT) + conf.setParameters(dict(eventJSONURL=request.POST.get('eventJSONURL'), + liveURI=request.POST.get('liveURI'), + storedURI=request.POST.get('storedURI'))) + + elif request.POST.get('paramURL'): + conf.setCommand(config.ADD_RACE) + conf.setParameters(dict(paramURL=request.POST.get('paramURL'), + liveURI=request.POST.get('liveURI'), + storedURI=request.POST.get('storedURI'))) + + if not view.session.get('race.url_history'): + view.session['race.url_history'] = [] + + if request.POST.get('paramURL') not in view.session['race.url_history']: + view.session['race.url_history'].append(request.POST.get('paramURL')) + view.session.save() + + else: + return view.yieldMessage('Please specify an event or race URL!') + + try: + result = conf.trigger() + except Exception, ex: + return view.yieldMessage('Error: %s' % str(ex)) + + # can take a while until event data is ready + if request.POST.get('drop_db'): + realDropDB() + + time.sleep(5) + + # load event listing here + with lock: + eventlist = [] + try: + conf.setContext(config.MODERATOR) + conf.setCommand(config.LIST_EVENTS) + eventlist = provider.eventConfiguration(conf) + + # do not accept empty event list + if len(eventlist) == 0: + raise Exception, 'No events configured.' + + except Exception, ex: + return view.yieldMessage('Could not gather any data! Seems that Java listener is not ready yet. Please reconnect. Error: %s' % str(ex)) + + startListenerThreads(conf, eventlist) + + # mark all stuff done and listener running + view.session['listener-started'] = True + view.session.save() + + elif request.POST.get('disconnect-server', None): + # disconnect does not stop listeners but just disconnects the + # session of the user from server + view.session['listener-started'] = False + del view.session['listener-conf'] + view.session.save() + + elif request.POST.get('listener-stop', None): + + eventname = request.POST.get('event', None) + racename = request.POST.get('race', None) + + conf.setContext(config.ADMIN) + + if racename: + conf.setCommand(config.STOP_RACE) + conf.setParameters(dict(eventname=eventname, racename=racename)) + else: + conf.setCommand(config.STOP_EVENT) + conf.setParameters(dict(eventname=eventname)) + + # remove listener started before any error can occur + view.session['listener-started'] = False + del view.session['listener-conf'] + view.session.save() + + key = hash('%s-%s-%s-%s' % (conf.host, conf.port, eventname, racename)) + if threaded_listener.has_key(key): + threaded_listener[key].running = False + + try: + conf.trigger() + except Exception, ex: + return view.yieldMessage('Error: %s' % str(ex)) + + elif request.POST.get('listener-event-refresh', None): + with lock: + conf.setContext(config.MODERATOR) + conf.setCommand(config.LIST_EVENTS) + eventlist = provider.eventConfiguration(conf) + + if model.EventImpl.queryCount() == 0: + return view.yieldMessage('Seems that there are no events that can be shown! Listener not started?') + + # start listener thread if this is not yet active + startListenerThreads(conf, eventlist) + + view.session['listener-started'] = True + view.session['listener-conf'] = conf + view.session.save() + + return view.yieldMessage('Event handler refreshed!') + + elif request.POST.get('leaderboard-default-event', None): + core.current_leaderboard_event = request.POST.get('event') + + return HTTPFound(location='/') + +@jsonize +def configuredListeners(context, request): + + out = [] + for key, listener in threaded_listener.items(): + out.append( {'host': listener.host, 'port': listener.port, + 'eventname': listener.eventname, 'last_update': listener.last_update and listener.last_update.strftime('%d.%m %H:%M:%S') or '-', + 'paused' : listener.paused, 'running': listener.running, 'id' : key, + 'racename': listener.racename} ) + + return out + +@jsonize +def pauseListener(context, request): + tid = int(request.params.get('tid', 0)) + + if request.params.get('all'): + for v in threaded_listener.values(): + v.paused = True + else: + if threaded_listener.has_key(tid): + threaded_listener.get(tid).paused = True + return True + +@jsonize +def unPauseListener(context, request): + tid = int(request.params.get('tid', 0)) + + if request.params.get('all'): + for v in threaded_listener.values(): + v.paused = False + else: + if threaded_listener.has_key(tid): + threaded_listener.get(tid).paused = False + return True + +@jsonize +def stopListener(context, request): + tid = int(request.params.get('tid', 0)) + if threaded_listener.has_key(tid): + threaded_listener.get(tid).running = False + return True + +def saveEventRace(context, request): + eventname = request.params.get('eventname', request.params.get('event')) + racename = request.params.get('racename', request.params.get('race')) + + lock = threading.Lock() + + view = core.BaseView(context, request) + if not racename: + racename = view.currentRace().name + + view.session['current-event'] = eventname + view.session['current-race'] = racename + view.session.save() + + if request.params.get('template'): + return render_to_response('templates/%s.pt' % request.params.get('template'), + {'view': view, 'additional': request.params.get('additional')}, request=request) + +@jsonize +def mapCompetitors(context, request): + # returns competitors with their current rank at the given timepoint + + view = core.BaseView(context, request) + + _at = request.params.get('at') + at_millis = view.datetimeToMillis(view.parseDatetime(_at)) + + conf = view.listenerConf() + conf.setContext(config.MODERATOR) + conf.setCommand(config.LIVE_EVENTS) + + race = view.currentRace() + conf.setRace(race) + conf.setParameters(dict(eventname=race.event, racename=race.name, timeasmillis='%.f' % at_millis)) + + data = jsonByUrl(conf) + + if data.get('ranks'): + data = data['ranks'] + data.sort(lambda x,y: cmp(x['rank'], y['rank'])) + + return data + +@jsonize +def windSettings(context, request): + view = core.BaseView(context, request) + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setRace(view.currentRace()) + + if request.POST.get('setsource'): + conf.setCommand(config.SET_WIND_SOURCE) + conf.setParameters(dict(sourcename=request.POST.get('windsource'))) + conf.trigger() + + elif request.POST.get('setcustom'): + conf.setCommand(config.SET_WIND) + + dc = {} + for k in ['truebearingdegrees', 'knotspeed', 'lngdeg', 'latdeg', 'timeasmillis']: + if request.POST.get(k): + dc[k] = request.POST.get(k) + + conf.setParameters(dc) + conf.trigger() + + return True + +@jsonize +def readWind(context, request): + view = core.BaseView(context, request) + + wind = view.currentWind() + source = wind[wind['currentwindsource']] + + if source and len(source) > 0: + return source[0] + return {} + +@jsonize +def readWaypoints(context, request): + return readWaypointsImpl(context, request) + +def readWaypointsImpl(context, request): + view = core.BaseView(context, request) + + conf = view.listenerConf() + conf.setContext(config.MODERATOR) + conf.setCommand(config.SHOW_WAYPOINTS) + conf.setRace(view.currentRace()) + + data = jsonByUrl(conf) + + # we want to show unique buoys so lets iter thru data + result = {} + for wp in data: + for by in wp['buoys']: + result[by['name']] = by + + return result.values() + +@jsonize +def loadTracks(context, request): + view = core.BaseView(context, request) + + _at = request.POST.get('at') + at_millis = view.datetimeToMillis(view.parseDatetime(_at)) + + # lets take 2 secs before and after given time + from_millis = at_millis - 1000 + to_millis = at_millis + 1000 + + conf = view.listenerConf() + conf.setContext(config.MODERATOR) + conf.setCommand(config.SHOW_BOAT_POSITIONS) + conf.setRace(view.currentRace()) + conf.setParameters(dict(sinceasmillis='%.f' % from_millis, toasmillis='%.f' % to_millis)) + + data = jsonByUrl(conf) + + # filter out the position that is the most current one + results = [] + for c in data['competitors']: + if len(c['track'])>0: + fix = c['track'][-1] or {} + else: fix = {} + results.append(dict(name=c['name'], **fix)) + + return results + +@jsonize +def determineWindDirection(context, request): + """ Returns the wind for all known marks """ + + buoys = readWaypointsImpl(context, request) + + view = core.BaseView(context, request) + + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setCommand(config.ADD_WIND) + conf.setRace(view.currentRace()) + + _at = request.params.get('at') + if _at: + at_millis = view.datetimeToMillis(view.parseDatetime(_at)) + conf.setParameters(dict(timeasmillis='%.f' % at_millis)) + + else: + # take start of race + conf.setParameters(dict(timeasmillis='%.f' % view.currentRace().start)) + + params = [] + for buoy in buoys: + if buoy.has_key('lat'): + params.append('latdeg=%s' % buoy['lat']) + params.append('lngdeg=%s' % buoy['lng']) + + conf.parameters += '&%s' % '&'.join(params) + + try: + data = jsonByUrl(conf) + except Exception, ex: + log.error('Error', exc_info=True) + return str(ex) + + # simply return the list + return data + +@jsonize +def listWindTrackers(context, request): + view = core.BaseView(context, request) + + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setCommand(config.LIST_WIND_TRACKERS) + + data = jsonByUrl(conf) + return data + +@jsonize +def stopReceiver(context, request): + view = core.BaseView(context, request) + + saveEventRace(context, request) + + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setCommand(config.STOP_EXP_WIND) + conf.setRace(view.currentRace()) + conf.trigger() + + return 1 + +@jsonize +def startWindTracker(context, request): + view = core.BaseView(context, request) + + saveEventRace(context, request) + + conf = view.listenerConf() + conf.setContext(config.ADMIN) + conf.setCommand(config.START_EXP_WIND) + conf.setRace(view.currentRace()) + + correct = request.POST.get('declination', False) and 'true' or 'false' + conf.setParameters(dict(port=request.POST.get('port'), correctexpeditionwindbearingbydeclination=correct)) + conf.trigger() + + return 1 + +@jsonize +def adminLiveData(context, request): + # searches for all running races and displays information for all competitors + + view = core.BaseView(context, request) + + race = view.currentRace() + event = model.EventImpl.queryOneBy(name=race.event) + racepos = event.races.index(race.name) + + competitors = model.CompetitorImpl.queryBy(event=event.name) + currentlegs = race.current_legs + + if currentlegs: + if currentlegs[0] != 0: + # always show the last leg + currentlegs.insert(0, currentlegs[0]-1) + + results = '' + for pos in range(len(currentlegs)): + legpos = currentlegs[pos] + + results += '\nLEG: %s RACE-START: %s NEWEST: %s WIND: (%s %s %s)\n' % (legpos+1, view.millisToDatetime(race.start), view.millisToDatetime(race.timeofnewestevent), race.wind_source, race.wind_bearing, race.wind_speed) + results += 'NAME'.ljust(16) + 'TOTAL'.ljust(7) + 'CRANK'.ljust(7) + 'RRANK'.ljust(7) + results += 'MRANK'.ljust(7) + 'LRANK'.ljust(9) + 'SPD'.ljust(9) + 'DST'.ljust(9) + 'VMG'.ljust(9) + 'AVMG'.ljust(9) + 'SGAP'.ljust(9) + 'ETA'.ljust(9) + 'DSTGO'.ljust(9) + results += '\n' + + # sort competitors by rank in current leg + competitors.sort(lambda x,y:cmp(x.values[racepos][legpos] and x.values[racepos][legpos][0] or 6000, y.values[racepos][legpos] and y.values[racepos][legpos][0] or 6000)) + + for c in competitors: + results += '%s %s %s' % (c.name.ljust(15), str(c.total).ljust(6), str(c.current_rank).ljust(6)) + results += '%s %s' % (str(c.races[racepos]).ljust(7), str(c.marks[racepos][legpos]).ljust(7)) + + for v in c.values[racepos][legpos]: + results += str('%.1f' % v).ljust(9) + + results += '\n' + + if not results: + return 'This race seems to be finished!' + + return results + diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/app.js b/python/src/sailing.web/sailing/web/browser/moderator-static/app.js new file mode 100644 index 00000000000..5ec810a351a --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/app.js @@ -0,0 +1,6 @@ +$(document).ready(function() { + var wHeight = $(window).height(); + + $("#rootwrapper").css("height", wHeight); + $("#appinterface").css("height", wHeight-131); +}); diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-bottom.png b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-bottom.png new file mode 100644 index 00000000000..e453bf96a74 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-bottom.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-left.png b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-left.png new file mode 100644 index 00000000000..e65e1d434a2 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-left.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-right.png b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-right.png new file mode 100644 index 00000000000..136606efdff Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-right.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-top.png b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-top.png new file mode 100644 index 00000000000..747709ade57 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/arrow-top.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/border-activity.png b/python/src/sailing.web/sailing/web/browser/moderator-static/border-activity.png new file mode 100644 index 00000000000..705a64004c5 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/border-activity.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/freeze.png b/python/src/sailing.web/sailing/web/browser/moderator-static/freeze.png new file mode 100644 index 00000000000..3931b442c0a Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/freeze.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/index.html b/python/src/sailing.web/sailing/web/browser/moderator-static/index.html new file mode 100644 index 00000000000..44065dee108 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/index.html @@ -0,0 +1,1714 @@ + + + + SAP Sailing Analytics + + + +
+ +
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 1 + + GER10 + + EVANS +
+ 2 + + GBR12 + + ALONSO +
+ 3 + + AUS15 + + ALONSO +
+ 4 + + AUS1 + + BROTHERTHOl +
+ 5 + + IND66 + + ASQUITH +
+ 6 + + SUI 89 + + CZAJKOWSKI +
+ 7 + + NZL878 + + NIELSEN +
+ 8 + + USA23 + + NIELSEN +
+ 9 + + GBR25 + + PIASECKI +
+ 10 + + AUS34 + + FONSECA +
+ 11 + + GER34 + + GRAEL +
+ 12 + + GER2 + + NORREGAARD +
+ 13 + + GBR45 + + LANG +
+ 14 + + AUS26 + + KOSTOV +
+ 15 + + SWE87 + + CUPAC +
+ 16 + + NOR3 + + STORCK +
+ 17 + + GBR9 + + MOORE +
+ 18 + + SUI28 + + DELLE +
+ 19 + + DEN234 + + RESCH +
+ 20 + + GER666 + + DRAPER +
+
    +
  • + +
  • +
  • + +
  • +
+
+ +
+ + +
+ + +
+
    +
  • + 1 +
  • +
  • + 2 +
  • +
  • + 3 +
  • +
  • + 4 +
  • +
  • + 5 +
  • +
  • + 6 +
  • +
  • + 7 +
  • +
  • + 8 +
  • +
  • + 9 +
  • +
  • + 10 +
  • +
  • + 11 +
  • +
  • + 12 +
  • +
  • + 13 +
  • +
  • + 14 +
  • +
  • + 15 +
  • +
  • + 16 +
  • +
  • + 17 +
  • +
  • + 18 +
  • +
  • + 19 +
  • +
  • + 20 +
  • +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ gap + + a. speed + + distance + + g&l mt + + g&l pl +
+ + + + + + + + + +
+ 1 + + 30 + + 20 + + 50 + + 10 +
+ 2 + + 31 + + 21 + + 51 + + 11 +
+ 3 + + 32 + + 22 + + 52 + + 12 +
+ 4 + + 33 + + 23 + + 53 + + 13 +
+ 5 + + 34 + + 24 + + 54 + + 14 +
+ 6 + + 35 + + 25 + + 55 + + 15 +
+ 7 + + 36 + + 26 + + 56 + + 16 +
+ 8 + + 37 + + 27 + + 57 + + 17 +
+ 9 + + 38 + + 28 + + 58 + + 18 +
+ 10 + + 39 + + 29 + + 59 + + 19 +
+ 11 + + 40 + + 30 + + 60 + + 20 +
+ 12 + + 41 + + 31 + + 61 + + 21 +
+ 13 + + 42 + + 32 + + 62 + + 22 +
+ 14 + + 43 + + 33 + + 63 + + 23 +
+ 15 + + 44 + + 34 + + 64 + + 24 +
+ 16 + + 45 + + 35 + + 65 + + 25 +
+ 17 + + 46 + + 36 + + 66 + + 26 +
+ 18 + + 47 + + 37 + + 67 + + 27 +
+ 19 + + 48 + + 38 + + 68 + + 28 +
+ 20 + + 49 + + 39 + + 69 + + 29 +
+
+ + + + + + + + +
+ + + + + +
+ + +
+
+ + + + diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/iphone-splash-screen.png b/python/src/sailing.web/sailing/web/browser/moderator-static/iphone-splash-screen.png new file mode 100644 index 00000000000..56b6ea4e6d8 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/iphone-splash-screen.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/iphone.html b/python/src/sailing.web/sailing/web/browser/moderator-static/iphone.html new file mode 100644 index 00000000000..c4afd153171 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/iphone.html @@ -0,0 +1,120 @@ + + + + SAP Sailing Analytics + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Rank + + Name +
1EVANS
2ALONSO
3ALONSO
4BROTHERTHOl
5ASQUITH
6CZAJKOWSKI
7NIELSEN
8NIELSEN
9PIASECKI
10FONSECA
11GRAEL
12NORREGAARD
13LANG
14KOSTOV
15CUPAC
16STORCK
17MOORE
18DELLE
19RESCH
20DRAPER
+ + + diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/jquery.js b/python/src/sailing.web/sailing/web/browser/moderator-static/jquery.js new file mode 100644 index 00000000000..b2ac1747f3c --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/jquery.js @@ -0,0 +1,18 @@ +/*! + * jQuery JavaScript Library v1.6.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu May 12 15:04:36 2011 -0400 + */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!cj[a]){var b=f("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),c.body.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write("");b=cl.createElement(a),cl.body.appendChild(b),d=f.css(b,"display"),c.body.removeChild(ck)}cj[a]=d}return cj[a]}function cu(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function ct(){cq=b}function cs(){setTimeout(ct,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g=0===c})}function W(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function O(a,b){return(a&&a!=="*"?a+".":"")+b.replace(A,"`").replace(B,"&")}function N(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;ic)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function L(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function F(){return!0}function E(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function H(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(H,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=d.userAgent,x,y,z,A=Object.prototype.toString,B=Object.prototype.hasOwnProperty,C=Array.prototype.push,D=Array.prototype.slice,E=String.prototype.trim,F=Array.prototype.indexOf,G={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.1",length:0,size:function(){return this.length},toArray:function(){return D.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?C.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(D.apply(this,arguments),"slice",D.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:C,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!y){y=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",z,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",z),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&H()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):G[A.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!B.call(a,"constructor")&&!B.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||B.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c
a",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};f=c.createElement("select"),g=f.appendChild(c.createElement("option")),h=a.getElementsByTagName("input")[0],j={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},h.checked=!0,j.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,j.optDisabled=!g.disabled;try{delete a.test}catch(s){j.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function b(){j.noCloneEvent=!1,a.detachEvent("onclick",b)}),a.cloneNode(!0).fireEvent("onclick")),h=c.createElement("input"),h.value="t",h.setAttribute("type","radio"),j.radioValue=h.value==="t",h.setAttribute("checked","checked"),a.appendChild(h),k=c.createDocumentFragment(),k.appendChild(a.firstChild),j.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",l=c.createElement("body"),m={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"};for(q in m)l.style[q]=m[q];l.appendChild(a),b.insertBefore(l,b.firstChild),j.appendChecked=h.checked,j.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,j.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
",j.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
t
",n=a.getElementsByTagName("td"),r=n[0].offsetHeight===0,n[0].style.display="",n[1].style.display="none",j.reliableHiddenOffsets=r&&n[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(i=c.createElement("div"),i.style.width="0",i.style.marginRight="0",a.appendChild(i),j.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(i,null)||{marginRight:0}).marginRight,10)||0)===0),l.innerHTML="",b.removeChild(l);if(a.attachEvent)for(q in{submit:1,change:1,focusin:1})p="on"+q,r=p in a,r||(a.setAttribute(p,"return;"),r=typeof a[p]=="function"),j[q+"Bubbles"]=r;return j}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;return(e.value||"").replace(p,"")}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);c=j&&f.attrFix[c]||c,i=f.attrHooks[c],i||(!t.test(c)||typeof d!="boolean"&&d!==b&&d.toLowerCase()!==c.toLowerCase()?v&&(f.nodeName(a,"form")||u.test(c))&&(i=v):i=w);if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j)return i.get(a,c);h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);c=i&&f.propFix[c]||c,h=f.propHooks[c];return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return a[f.propFix[c]||c]?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=b),a.setAttribute(c,c.toLowerCase()));return c}},f.attrHooks.value={get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return a.value},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=Object.prototype.hasOwnProperty,y=/\.(.*)$/,z=/^(?:textarea|input|select)$/i,A=/\./g,B=/ /g,C=/[^\w\s.|`]/g,D=function(a){return a.replace(C,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=E;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=E);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),D).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem +)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},K=function(c){var d=c.target,e,g;if(!!z.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=J(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:K,beforedeactivate:K,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&K.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&K.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",J(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in I)f.event.add(this,c+".specialChange",I[c]);return z.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return z.test(this.nodeName)}},I=f.event.special.change.filters,I.focus=I.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(h=g;h0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=U.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(W(c[0])||W(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=T.call(arguments);P.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!V[a]?f.unique(e):e,(this.length>1||R.test(d))&&Q.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var Y=/ jQuery\d+="(?:\d+|null)"/g,Z=/^\s+/,$=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,_=/<([\w:]+)/,ba=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Y,""):null;if(typeof a=="string"&&!bc.test(a)&&(f.support.leadingWhitespace||!Z.test(a))&&!bg[(_.exec(a)||["",""])[1].toLowerCase()]){a=a.replace($,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bj(a,d),e=bk(a),g=bk(d);for(h=0;e[h];++h)bj(e[h],g[h])}if(b){bi(a,d);if(c){e=bk(a),g=bk(d);for(h=0;e[h];++h)bi(e[h],g[h])}}return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument|| +b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!bb.test(k))k=b.createTextNode(k);else{k=k.replace($,"<$1>");var l=(_.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=ba.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Z.test(k)&&o.insertBefore(b.createTextNode(Z.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bp.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bo.test(g)?g.replace(bo,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,c){var d,e,g;c=c.replace(br,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bs.test(d)&&bt.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bE=/%20/g,bF=/\[\]$/,bG=/\r?\n/g,bH=/#.*$/,bI=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bJ=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bK=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bL=/^(?:GET|HEAD)$/,bM=/^\/\//,bN=/\?/,bO=/)<[^<]*)*<\/script>/gi,bP=/^(?:select|textarea)/i,bQ=/\s+/,bR=/([?&])_=[^&]*/,bS=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bT=f.fn.load,bU={},bV={},bW,bX;try{bW=e.href}catch(bY){bW=c.createElement("a"),bW.href="",bW=bW.href}bX=bS.exec(bW.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bT)return bT.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bO,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bP.test(this.nodeName)||bJ.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bG,"\r\n")}}):{name:b.name,value:c.replace(bG,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bW,isLocal:bK.test(bX[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bZ(bU),ajaxTransport:bZ(bV),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?ca(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=cb(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bI.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bH,"").replace(bM,bX[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bQ),d.crossDomain==null&&(r=bS.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bX[1]&&r[2]==bX[2]&&(r[3]||(r[1]==="http:"?80:443))==(bX[3]||(bX[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bU,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bL.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bN.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bR,"$1_="+x);d.url=y+(y===d.url?(bN.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bV,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bE,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq,cr=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b
";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){return this[0]?parseFloat(f.css(this[0],d,"padding")):null},f.fn["outer"+c]=function(a){return this[0]?parseFloat(f.css(this[0],d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/mobile.css b/python/src/sailing.web/sailing/web/browser/moderator-static/mobile.css new file mode 100644 index 00000000000..5e1b5a4af1b --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/mobile.css @@ -0,0 +1,112 @@ +.overall-blue { + background: #008fcc !important; } + +.c-race-1-orange { + background: #de8a2e !important; } + +.c-race-2-yellow { + background: #fec631 !important; } + +.c-race-3-lila { + background: #9c277b !important; } + +.c-race-4-green { + background: #95aa31 !important; } + +.c-race-5-red { + background: #d83c3c !important; } + +.c-table-odd { + background: #484848 !important; } + +.c-systeminfo { + background: #e1e1e1 !important; } + +.c-main-dark-bg { + background: #151515 !important; } + +.c-font-white { + background: #ececec !important; } + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; } + +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; } + +body { + line-height: 1; } + +ol, ul { + list-style: none; } + +blockquote, q { + quotes: none; } + +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; + content: none; } + +table { + border-collapse: collapse; + border-spacing: 0; } + +.clear { + clear: both; + font-size: 1px; + height: 0px; + line-height: 0px; + margin: -1px 0 0; + width: 100%; } + +.cover { + left: -1000px; + overflow: hidden; + position: absolute; + top: -1000px; } + +body { + background: #151515; + color: #ececec; + font-family: "Trebuchet MS"; } + body a { + text-decoration: none; + color: #ececec; } + body a:hover { + text-decoration: none; + color: #ececec; } + +.overview li { + padding: 10px; } + .overview li.current-race { + background: #484848; } + +.race-table thead th { + background: #008fcc; + padding: 10px; + text-align: left; + vertical-align: top; } +.race-table tbody tr td { + padding: 10px; } +.race-table tbody tr.odd td { + background: #484848; } diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/overall.html b/python/src/sailing.web/sailing/web/browser/moderator-static/overall.html new file mode 100644 index 00000000000..5574551392d --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/overall.html @@ -0,0 +1,1145 @@ + + + + SAP Sailing Analytics + + + +
+ +
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ 1 + + GER10 + + EVANS +
+ 2 + + GBR12 + + ALONSO +
+ 3 + + AUS15 + + ALONSO +
+ 4 + + AUS1 + + BROTHERTHOl +
+ 5 + + IND66 + + ASQUITH +
+ 6 + + SUI 89 + + CZAJKOWSKI +
+ 7 + + NZL878 + + NIELSEN +
+ 8 + + USA23 + + NIELSEN +
+ 9 + + GBR25 + + PIASECKI +
+ 10 + + AUS34 + + FONSECA +
+ 11 + + GER34 + + GRAEL +
+ 12 + + GER2 + + NORREGAARD +
+ 13 + + GBR45 + + LANG +
+ 14 + + AUS26 + + KOSTOV +
+ 15 + + SWE87 + + CUPAC +
+ 16 + + NOR3 + + STORCK +
+ 17 + + GBR9 + + MOORE +
+ 18 + + SUI28 + + DELLE +
+ 19 + + DEN234 + + RESCH +
+ 20 + + GER666 + + DRAPER +
+
+ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Rank + + Flag + + Skipper + + Crew + + Total Points + + Net Points +
+ + + + + + + + + + + +
+ 1 + + 30 + + 20 + + 50 + + 10 + + 10 +
+ 2 + + 31 + + 21 + + 51 + + 11 + + 11 +
+ 3 + + 32 + + 22 + + 52 + + 12 + + 12 +
+ 4 + + 33 + + 23 + + 53 + + 13 + + 13 +
+ 5 + + 34 + + 24 + + 54 + + 14 + + 14 +
+ 6 + + 35 + + 25 + + 55 + + 15 + + 15 +
+ 7 + + 36 + + 26 + + 56 + + 16 + + 16 +
+ 8 + + 37 + + 27 + + 57 + + 17 + + 17 +
+ 9 + + 38 + + 28 + + 58 + + 18 + + 18 +
+ 10 + + 39 + + 29 + + 59 + + 19 + + 19 +
+ 11 + + 40 + + 30 + + 60 + + 20 + + 20 +
+ 12 + + 41 + + 31 + + 61 + + 21 + + 21 +
+ 13 + + 42 + + 32 + + 62 + + 22 + + 22 +
+ 14 + + 43 + + 33 + + 63 + + 23 + + 23 +
+ 15 + + 44 + + 34 + + 64 + + 24 + + 24 +
+ 16 + + 45 + + 35 + + 65 + + 25 + + 25 +
+ 17 + + 46 + + 36 + + 66 + + 26 + + 26 +
+ 18 + + 47 + + 37 + + 67 + + 27 + + 27 +
+ 19 + + 48 + + 38 + + 68 + + 28 + + 28 +
+ 20 + + 49 + + 39 + + 69 + + 29 + + 29 +
+
+ + +
+
+ + + + diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/refresh-icon.png b/python/src/sailing.web/sailing/web/browser/moderator-static/refresh-icon.png new file mode 100644 index 00000000000..c3b50210487 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/refresh-icon.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/sap-logo.png b/python/src/sailing.web/sailing/web/browser/moderator-static/sap-logo.png new file mode 100644 index 00000000000..32c8a68961c Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/sap-logo.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/sap-sailing-app-icon.png b/python/src/sailing.web/sailing/web/browser/moderator-static/sap-sailing-app-icon.png new file mode 100644 index 00000000000..3ff7dbf1aa0 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/sap-sailing-app-icon.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/screen.css b/python/src/sailing.web/sailing/web/browser/moderator-static/screen.css new file mode 100644 index 00000000000..729ce179ae1 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/moderator-static/screen.css @@ -0,0 +1,452 @@ +.overall-blue { + background: #008fcc !important; } + +.c-race-1-orange { + background: #de8a2e !important; } + +.c-race-2-yellow { + background: #fec631 !important; } + +.c-race-3-lila { + background: #9c277b !important; } + +.c-race-4-green { + background: #95aa31 !important; } + +.c-race-5-red { + background: #d83c3c !important; } + +.c-table-odd { + background: #484848 !important; } + +.c-systeminfo { + background: #e1e1e1 !important; } + +.c-main-dark-bg { + background: #151515 !important; } + +.c-font-white { + background: #ececec !important; } + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; } + +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; } + +body { + line-height: 1; } + +ol, ul { + list-style: none; } + +blockquote, q { + quotes: none; } + +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; + content: none; } + +table { + border-collapse: collapse; + border-spacing: 0; } + +.clear { + clear: both; + font-size: 1px; + height: 0px; + line-height: 0px; + margin: -1px 0 0; + width: 100%; } + +.cover { + left: -1000px; + overflow: hidden; + position: absolute; + top: -1000px; } + +body { + background: #151515; + font-family: "Trebuchet MS"; + color: #ececec; } + body a { + text-decoration: none; + color: #ececec; } + body a:hover { + text-decoration: none; + color: #ececec; } + body td span { + padding: 2px; } + +#rootwrapper { + width: 100%; + height: 100%; + overflow: hidden; } + +#appinterface { + position: relative; } + +#header { + padding: 15px 0 0 0; + height: 115px; + background: url(/moderator-static/sap-logo.png) no-repeat 0 0; + font-size: 14px; + font-style: italic; + font-weight: bold; } + #header ul.systeminfo { + float: right; + color: #e1e1e1; + padding: 0 5px 0 0; + *display: inline-block; } + #header ul.systeminfo li { + padding: 10px 0 10px 30px; + border-top: 1px solid #e1e1e1; } + #header ul.systeminfo li.active { + background: url(/moderator-static/refresh-icon.png) no-repeat left center; } + #header ul.systeminfo li.message-0 { + border: none; } + #header ul.systeminfo:after { + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; } + +span.race-count { + padding: 102px 0 0 0; + display: block; + font-size: 18px; } + span.race-count ul { + text-align: center; + margin: 0 0 10px 0; + font-weight: bold; } + span.race-count ul:last-child { + margin: 0; } + span.race-count ul li { + padding: 5px; } + +#left-systembar { + width: 39px; + background: #484848; + height: 100%; + float: left; + margin: 0 10px 0 1px; + position: relative; + font-size: 18px; } + #left-systembar div { + width: 100%; + position: absolute; } + #left-systembar div.blue-table-btn { + top: 0; + left: 0; } + #left-systembar div.blue-table-btn a { + display: block; + height: 92px; + text-decoration: none; + background: url(/moderator-static/arrow-right.png) left top no-repeat #008fcc; } + #left-systembar div.blue-table-btn a:hover { + text-decoration: none; } + #left-systembar .slide-backward { + background: url(/moderator-static/arrow-left.png) left bottom no-repeat #484848; + display: block; + height: 100%; } + +#right-systembar { + width: 39px; + background: #484848; + height: 100%; + float: right; + margin: 0 0 0 10px; + position: relative; + font-size: 18px; } + #right-systembar .function-btn-wrapper { + font-size: 24px; + color: #ececec; + text-transform: uppercase; + text-align: center; + position: absolute; + top: 0; + left: 0; + width: 100%; } + #right-systembar .function-btn-wrapper ul.function-btn { + padding: 1px; + *display: inline-block; } + #right-systembar .function-btn-wrapper ul.function-btn:after { + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; } + #right-systembar .function-btn-wrapper ul.function-btn li { + background: #151515; + padding: 5px 0; } + #right-systembar .function-btn-wrapper ul.function-btn li:first-child { + margin: 0 0 1px 0; } + #right-systembar .slide-forward { + background: url(/moderator-static/arrow-right.png) left bottom no-repeat #484848; + display: block; + height: 100%; } + +#main-interface { + float: left; + height: 100%; } + #main-interface .sort-asc { + background: url(/moderator-static/sort-arrow-top.png) 0 0 no-repeat #151515; } + #main-interface .sort-desc { + background: url(/moderator-static/sort-arrow-bottom.png) 0 0 no-repeat #151515; } + #main-interface .blue-table { + padding: 0 10px 0 0; + font-size: 14px; + float: left; } + #main-interface .blue-table .refresh-btn { + display: block; + height: 39px; + background: url(/moderator-static/refresh-icon.png) right center no-repeat #484848; } + #main-interface .blue-table .sort-rank { + display: block; + height: 39px; } + #main-interface .blue-table #table-scrolling li { + float: left; + width: 94px; + margin: 20px 0 0 0; } + #main-interface .blue-table #table-scrolling li a { + display: block; + height: 24px; } + #main-interface .blue-table #table-scrolling li a.table-scrolldown { + background: url(/moderator-static/arrow-bottom.png) no-repeat left center #484848; } + #main-interface .blue-table #table-scrolling li a.table-scrollup { + background: url(/moderator-static/arrow-top.png) no-repeat right center #484848; } + #main-interface #overall-clipping { + border-collapse: collapse; + width: 170px; + text-align: left; + vertical-align: middle; + margin: 14px 0 0 0; } + #main-interface #overall-clipping td { + padding: 5px; } + #main-interface #overall-clipping tr.odd td { + background: #484848; } + #main-interface .race { + height: 100%; + float: left; + margin: 0 8px 0 0; + font-size: 14px; } + #main-interface .race div { + color: #151515; + font-size: 24px; + font-weight: bold; + height: 100%; + display: block; + float: left; + margin: 0 2px 0 0; + position: relative; } + #main-interface .race div a { + color: #151515; } + #main-interface .race div a.main-box-sort { + position: absolute; + top: 0; + left: 0; + display: block; + height: 92px; + width: 100%; } + #main-interface .race div a.leg-box-sort { + position: absolute; + top: 0; + left: 0; + display: block; + height: 92px; + width: 100%; } + #main-interface .race div.main-box { + width: 39px; } + #main-interface .race div.main-box span { + padding: 6px 0 0 6px; + display: block; + position: absolute; + top: 0; + left: 0; } + #main-interface .race div.main-box .sort-asc { + background: url(/moderator-static/sort-arrow-top.png) center 40px no-repeat; } + #main-interface .race div.main-box .sort-desc { + background: url(/moderator-static/sort-arrow-bottom.png) center 40px no-repeat; } + #main-interface .race div.leg-box { + font-size: 14px; + width: 39px; } + #main-interface .race div.leg-box span { + padding: 14px 0 0 10px; + display: block; + position: absolute; + top: 0; + left: 0; } + #main-interface .race div.leg-box .sort-asc { + background: url(/moderator-static/sort-arrow-top.png) center 40px no-repeat; } + #main-interface .race div.leg-box .sort-desc { + background: url(/moderator-static/sort-arrow-bottom.png) center 40px no-repeat; } + #main-interface .race div.table-box { + width: 39px; + margin: 0; } + #main-interface .race div.table-box .table-box-sort { + display: block; + position: absolute; + top: 0; + left: 0; + height: 92px; + width: 100%; } + #main-interface .race div.table-box .sort-asc { + background: url(/moderator-static/sort-arrow-top.png) center 40px no-repeat; } + #main-interface .race div.table-box .sort-desc { + background: url(/moderator-static/sort-arrow-bottom.png) center 40px no-repeat; } + #main-interface .race div ul { + font-size: 14px; + margin: 92px 0 0 0; + text-align: center; } + #main-interface .race div ul li { + padding: 5px; } + #main-interface .race div.leg-wrap { + background: none; + margin: 0; } + #main-interface .race table.race-table { + border-collapse: collapse; + text-align: left; + vertical-align: middle; + float: left; + margin: 0 2px 0 0; + font-size: 14px; + color: #ececec; + *display: inline-block; } + #main-interface .race table.race-table:after { + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; } + #main-interface .race table.race-table th { + padding: 13px 10px; + color: #151515; + text-transform: uppercase; + font-weight: bold; } + #main-interface .race table.race-table th.firstelement { + width: 39px; + padding: 0; } + #main-interface .race table.race-table th:first-child { + padding-left: 20px; } + #main-interface .race table.race-table th:last-child { + padding-right: 20px; } + #main-interface .race table.race-table tr td { + padding: 5px; } + #main-interface .race table.race-table tr td span { + padding: 2px 0; } + #main-interface .race table.race-table tr td:first-child { + padding-left: 20px; } + #main-interface .race table.race-table tr td:last-child { + padding-right: 20px; } + #main-interface .race table.race-table tr td.table-sorting { + padding-top: 0; + padding-bottom: 0; } + #main-interface .race table.race-table tr td.table-sorting a { + height: 51px; + display: block; } + #main-interface .race table.race-table tr.odd td { + background: #484848; } + #main-interface .race table.race-table tr.odd td span { + background: #484848; } + +#overall-wrap { + background: #151515; + height: 100%; + position: absolute; + left: 50px; } + #overall-wrap #overall { + border-collapse: collapse; + text-align: left; + vertical-align: middle; + background: #151515; } + #overall-wrap #overall th { + padding: 11px; + background: #008fcc; + text-transform: uppercase; + font-weight: bold; } + #overall-wrap #overall th:first-child { + padding-left: 20px; } + #overall-wrap #overall th:last-child { + padding-right: 20px; } + #overall-wrap #overall td { + padding: 5px; } + #overall-wrap #overall td:first-child { + padding-left: 20px; } + #overall-wrap #overall td:last-child { + padding-right: 20px; } + #overall-wrap #overall tr.odd td { + background: #484848; } + +#race-1 div { + background: #de8a2e; } + +#race-2 div { + background: #fec631; } + +#race-3 div { + background: #9c277b; } + +#race-4 div { + background: #95aa31; } + +#race-5 div { + background: #d83c3c; } + +body.race-1 #race-1 table th { + background: #de8a2e; } +body.race-1 #right-systembar ul.function-btn { + background: #de8a2e; } +body.race-1 #right-systembar ul.function-btn-active li { + background: #de8a2e; } + +body.race-2 #race-2 table th { + background: #fec631; } +body.race-2 #right-systembar ul.function-btn { + background: #fec631; } +body.race-2 #right-systembar ul.function-btn-active li { + background: #fec631; } + +body.race-3 #race-3 table th { + background: #9c277b; } +body.race-3 #right-systembar ul.function-btn { + background: #9c277b; } +body.race-3 #right-systembar ul.function-btn-active li { + background: #9c277b; } + +body.race-4 #race-4 table th { + background: #95aa31; } +body.race-4 #right-systembar ul.function-btn { + background: #95aa31; } +body.race-4 #right-systembar ul.function-btn-active li { + background: #95aa31; } + +body.race-5 #race-5 table th { + background: #d83c3c; } +body.race-5 #right-systembar ul.function-btn { + background: #d83c3c; } +body.race-5 #right-systembar ul.function-btn-active li { + background: #d83c3c; } + +.border-activity { + background: url(/moderator-static/border-activity.png) 0 0 no-repeat; } diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-bottom.png b/python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-bottom.png new file mode 100644 index 00000000000..1cd0b84fe66 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-bottom.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-top.png b/python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-top.png new file mode 100644 index 00000000000..f6ca9414247 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/moderator-static/sort-arrow-top.png differ diff --git a/python/src/sailing.web/sailing/web/browser/moderator-static/style.css b/python/src/sailing.web/sailing/web/browser/moderator-static/style.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/python/src/sailing.web/sailing/web/browser/static/core.js b/python/src/sailing.web/sailing/web/browser/static/core.js new file mode 100644 index 00000000000..fab675a5dda --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/core.js @@ -0,0 +1,49 @@ + +var map; + +function random() { + return Math.floor(Math.random()*484887498739872) +} + +/** + * General functionality + **/ +var loader_whitebg = '
'; + +/** + * format("i can speak {language} since i was {age}",{language:'javascript',age:10}); + */ +var format = function (str, col) { + col = typeof col === 'object' ? col : Array.prototype.slice.call(arguments, 1); + + return str.replace(/\{([^}]+)\}/gm, function () { + return col[arguments[1]]; + }); +}; + +/** + * Renders the given template and invokes the callback with response + */ +function template(templatename, parameters, callback) { + $.get(_base_url() + '@@/' + templatename, parameters, function(data) { + callback(data); + }); +} + +/** + * Calls the given function. Must return JSON + */ +function GET(name, parameters, callback) { + $.get(_base_url() + '++/' + name, parameters, function(data) { + if (callback) + callback(data); + }) +} + +function displayLoader(element_desc) { + $(element_desc).html(loader_whitebg); +} + +$(document).ready(function() { + $.ajaxSetup({cache:false}); +}); diff --git a/python/src/sailing.web/sailing/web/browser/static/css/jquery-ui-1.8.11.custom.css.txt b/python/src/sailing.web/sailing/web/browser/static/css/jquery-ui-1.8.11.custom.css.txt new file mode 100644 index 00000000000..5e5a4144698 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/css/jquery-ui-1.8.11.custom.css.txt @@ -0,0 +1,502 @@ +/* + * jQuery UI CSS Framework 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } + + +/* + * jQuery UI CSS Framework 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Theming/API + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(${request.application_url}/images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } +.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(${request.application_url}/images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(${request.application_url}/images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; } +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(${request.application_url}/images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(${request.application_url}/images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(${request.application_url}/images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(${request.application_url}/images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(${request.application_url}/images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(${request.application_url}/images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(${request.application_url}/images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(${request.application_url}/images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(${request.application_url}/images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(${request.application_url}/images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(${request.application_url}/images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(${request.application_url}/images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } +.ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } +.ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; } +.ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(${request.application_url}/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(${request.application_url}/images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* + * jQuery UI Resizable 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* + * jQuery UI Selectable 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Selectable#theming + */ +.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } +/* + * jQuery UI Accordion 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Accordion#theming + */ +/* IE/Win - Fix animation bug - #4615 */ +.ui-accordion { width: 100%; } +.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } +.ui-accordion .ui-accordion-li-fix { display: inline; } +.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } +.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } +.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } +.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } +.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } +.ui-accordion .ui-accordion-content-active { display: block; } +/* + * jQuery UI Autocomplete 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Autocomplete#theming + */ +.ui-autocomplete { position: absolute; cursor: default; } + +/* workarounds */ +* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ + +/* + * jQuery UI Menu 1.8.11 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ +.ui-menu { + list-style:none; + padding: 2px; + margin: 0; + display:block; + float: left; +} +.ui-menu .ui-menu { + margin-top: -3px; +} +.ui-menu .ui-menu-item { + margin:0; + padding: 0; + zoom: 1; + float: left; + clear: left; + width: 100%; +} +.ui-menu .ui-menu-item a { + text-decoration:none; + display:block; + padding:.2em .4em; + line-height:1.5; + zoom:1; +} +.ui-menu .ui-menu-item a.ui-state-hover, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} +/* + * jQuery UI Dialog 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } +/* + * jQuery UI Tabs 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Tabs#theming + */ +.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } +.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } +.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } +/* + * jQuery UI Datepicker 1.8.11 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Datepicker#theming + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +} diff --git a/python/src/sailing.web/sailing/web/browser/static/css/jquery.timeslider.css.txt b/python/src/sailing.web/sailing/web/browser/static/css/jquery.timeslider.css.txt new file mode 100644 index 00000000000..d90bf038034 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/css/jquery.timeslider.css.txt @@ -0,0 +1,117 @@ +.timeslider-container, div.timeslider-arrow, +a.timeslider-slider, div.timeslider-slider-line, +div.timeslider-labels, div.timeslider-label +{ + margin: 0; + padding: 0; + -moz-user-select: none; + -webkit-user-select: none; + user-select: none; +} + +.timeslider-container +{ + position: relative; + width: 146px; + min-height: 40px; +} + +div.timeslider-container +{ + display: -moz-inline-box; + display: inline-block; +} + +div.timeslider-arrow +{ + width: 18px; + height: 18px; + cursor: pointer; + position: absolute; +} + +div.timeslider-down-arrow +{ + left: 0; + background: url("/static/images/pt_controls.png") -18px 0px; +} + +div.timeslider-up-arrow +{ + left: 126px; + background: url("/static/images/pt_controls.png") 0px 0px; +} + +div.timeslider-down-arrow.timeslider-disabled, div.timeslider-disabled div.timeslider-down-arrow +{ + background: url("/static/images/pt_controls.png") -18px -20px; + cursor: inherit; +} + +div.timeslider-up-arrow.timeslider-disabled, div.timeslider-disabled div.timeslider-up-arrow +{ + background: url("/static/images/pt_controls.png") 0px -20px; + cursor: inherit; +} + +div.timeslider-slider-line +{ + position: absolute; + left: 18px; + width: 108px; + height: 18px; + background: url("/static/images/pt_controls.png") -52px 0px; +} + +div.timeslider-disabled div.timeslider-slider-line +{ + background: url("/static/images/pt_controls.png") -52px -20px; +} + +div.timeslider-slider-line-clickable +{ + cursor: pointer; +} + +a.timeslider-slider +{ + display: none; + position: absolute; + left: 0; + width: 16px; + height: 20px; + background: url("/static/images/pt_controls.png") -36px 0px; + cursor: pointer; + text-decoration: none; +} + +a.timeslider-slider:hover +{ + text-decoration: none; +} + +div.timeslider-disabled a.timeslider-slider +{ + background: url("/static/images/pt_controls.png") -36px -20px; + cursor: default; +} + +div.timeslider-labels +{ + position: absolute; + top: 20px; + left: 18px; +} + +div.timeslider-label +{ + position: absolute; + font-size: 85%; +} + +div.timeslider-disabled div.timeslider-labels +{ + visibility: hidden; +} + + diff --git a/python/src/sailing.web/sailing/web/browser/static/css/styles.css.txt b/python/src/sailing.web/sailing/web/browser/static/css/styles.css.txt new file mode 100644 index 00000000000..8167596f7b4 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/css/styles.css.txt @@ -0,0 +1,174 @@ + +body { + font-family: Verdana, Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.4; + padding: 0px; + margin: 0px; + color: #5A554E; + } + +h1, h2, h3 { + margin: 0; + padding: 0; + font-weight: normal; +} + +h1 { + font-size: 2em; +} + +h2 { + font-size: 2.4em; + margin: 3px; +} + +h3 { + font-size: 1.6em; +} + +p, ul, ol { + margin-top: 0; + line-height: 200%; +} + +ul, ol { + margin: 0px; + padding: 0px; + list-style: none; +} + +img { + border: 0; +} + +a { + text-decoration: underline; + color: #516C00; +} + +a:hover { + text-decoration: none; +} + +h2 a { + text-decoration: none; +} + +table { + border-width: 1px; + border-spacing: 0px; + border-color: #ececec; + border-style: solid; +} + +table td { + border-width: 1px; + padding: 2px; + border-style: solid; + border-color: #ececec; +} + +.clear { + clear: both; + font-size: 1px; + line-height: 1px; + } + +div.help { + margin: 2px 1px 6px 1px; + padding: 10px; + border: 1px solid #ececec; +} + +div.field { + padding: 3px 0px 4px 2px; + margin: 5px 3px 2px 2px; +} + +div.field span { + font-weight: bold; +} + + +div.field input { + border: 1px solid #8F8F8F; + width: 234px; + padding: 5px; +} + +div.field input.large { + width: 687px; +} + +form input[type=submit] { + padding: 5px 35px; + margin: 5px 2px 2px 2px; + border: 1px solid #c8c8c8; + background-color: white; + color: black; +} + +select { + border: 1px solid #c8c8c8; + padding: 3px 2px 3px 9px; + background-color: white; +} + +.loader { + text-align: center; + vertical-align: middle; + padding: 5px; + margin: 7px 0px 7px 0px; +} + +div.message { + color: #a0522d; + background-color: #ffffe0; + margin: 10px; + padding: 5px; +} + +#tabs { + margin: 3px !important; +} + +div.info { + margin: 10px 2px 2px 2px; + padding: 7px; + border: 1px solid #ececec; +} + +.maplabel { + color: red; + background-color: white; + font-family: "Lucida Grande", "Arial", sans-serif; + font-size: 9px; + font-weight: bold; + text-align: center; + width: 50px; + border: 2px solid black; + white-space: nowrap; +} + + +.ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; } +.ui-timepicker-div dl{ text-align: left; } +.ui-timepicker-div dl dt{ height: 25px; } +.ui-timepicker-div dl dd{ margin: -25px 10px 10px 65px; } +.ui-timepicker-div td { font-size: 90%; } + +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; }/* + diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-small.gif b/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-small.gif new file mode 100644 index 00000000000..09d621ede9d Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-small.gif differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-whitebg.gif b/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-whitebg.gif new file mode 100644 index 00000000000..3c2f7c05883 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader-whitebg.gif differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader.gif b/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader.gif new file mode 100644 index 00000000000..99517feb4db Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ajax-loader.gif differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/boat.png b/python/src/sailing.web/sailing/web/browser/static/images/boat.png new file mode 100644 index 00000000000..cc57b86a0f1 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/boat.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/boat16.png b/python/src/sailing.web/sailing/web/browser/static/images/boat16.png new file mode 100644 index 00000000000..be876ac4958 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/boat16.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/boat32.png b/python/src/sailing.web/sailing/web/browser/static/images/boat32.png new file mode 100644 index 00000000000..43181c8a4b8 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/boat32.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/button_minus_green.png b/python/src/sailing.web/sailing/web/browser/static/images/button_minus_green.png new file mode 100644 index 00000000000..94dc29e5662 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/button_minus_green.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/button_sort_down.gif b/python/src/sailing.web/sailing/web/browser/static/images/button_sort_down.gif new file mode 100644 index 00000000000..3282a248159 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/button_sort_down.gif differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/button_sort_none.gif b/python/src/sailing.web/sailing/web/browser/static/images/button_sort_none.gif new file mode 100644 index 00000000000..285f041ad84 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/button_sort_none.gif differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/button_sort_up.gif b/python/src/sailing.web/sailing/web/browser/static/images/button_sort_up.gif new file mode 100644 index 00000000000..d820987b6a7 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/button_sort_up.gif differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/favicon.ico b/python/src/sailing.web/sailing/web/browser/static/images/favicon.ico new file mode 100644 index 00000000000..5975b8922e1 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/favicon.ico differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/plus-icon.png b/python/src/sailing.web/sailing/web/browser/static/images/plus-icon.png new file mode 100644 index 00000000000..3e8d9466d97 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/plus-icon.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/pt_controls.png b/python/src/sailing.web/sailing/web/browser/static/images/pt_controls.png new file mode 100644 index 00000000000..c86484f31d4 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/pt_controls.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_asc.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_asc.png new file mode 100644 index 00000000000..a56d0e21902 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/sort_asc.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_asc_disabled.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_asc_disabled.png new file mode 100644 index 00000000000..b7e621ef1c6 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/sort_asc_disabled.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_both.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_both.png new file mode 100644 index 00000000000..839ac4bb5b0 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/sort_both.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_desc.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_desc.png new file mode 100644 index 00000000000..90b295159df Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/sort_desc.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/sort_desc_disabled.png b/python/src/sailing.web/sailing/web/browser/static/images/sort_desc_disabled.png new file mode 100644 index 00000000000..2409653dc94 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/sort_desc_disabled.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_0_aaaaaa_40x100.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 00000000000..5b5dab2ab7b Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_0_aaaaaa_40x100.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_75_ffffff_40x100.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 00000000000..ac8b229af95 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_flat_75_ffffff_40x100.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_55_fbf9ee_1x400.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 00000000000..ad3d6346e00 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_55_fbf9ee_1x400.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_65_ffffff_1x400.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 00000000000..42ccba269b6 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_65_ffffff_1x400.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_dadada_1x400.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 00000000000..5a46b47cb16 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_dadada_1x400.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_e6e6e6_1x400.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_e6e6e6_1x400.png new file mode 100644 index 00000000000..86c2baa655e Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_75_e6e6e6_1x400.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_95_fef1ec_1x400.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_95_fef1ec_1x400.png new file mode 100644 index 00000000000..4443fdc1a15 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_glass_95_fef1ec_1x400.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 00000000000..7c9fa6c6edc Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_222222_256x240.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_222222_256x240.png new file mode 100644 index 00000000000..b273ff111d2 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_222222_256x240.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_2e83ff_256x240.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 00000000000..09d1cdc856c Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_2e83ff_256x240.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_454545_256x240.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_454545_256x240.png new file mode 100644 index 00000000000..59bd45b907c Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_454545_256x240.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_888888_256x240.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_888888_256x240.png new file mode 100644 index 00000000000..6d02426c114 Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_888888_256x240.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_cd0a0a_256x240.png b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_cd0a0a_256x240.png new file mode 100644 index 00000000000..2ab019b73ec Binary files /dev/null and b/python/src/sailing.web/sailing/web/browser/static/images/ui-icons_cd0a0a_256x240.png differ diff --git a/python/src/sailing.web/sailing/web/browser/static/js/jquery-1.4.4.min.js b/python/src/sailing.web/sailing/web/browser/static/js/jquery-1.4.4.min.js new file mode 100644 index 00000000000..8f3ca2e2daf --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/js/jquery-1.4.4.min.js @@ -0,0 +1,167 @@ +/*! + * jQuery JavaScript Library v1.4.4 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Nov 11 19:04:53 2010 -0500 + */ +(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h= +h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;kd)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La, +"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this, +e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a, +"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+ +a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/, +C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j, +s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this, +j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length}, +toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j=== +-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false; +if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload", +b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&& +!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&& +l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H
a";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"), +k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false, +scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent= +false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom= +1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="
";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="
t
";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display= +"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h= +c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando); +else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one"; +if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true}, +attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&& +b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0}; +c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem, +arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid= +d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+ +c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== +8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k=== +"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+ +d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired= +B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type=== +"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]=== +0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); +(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3]; +break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr, +q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h= +l;g.sort(w);if(h)for(var i=1;i0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n, +m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled=== +true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"=== +g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return in[3]-0},nth:function(g,i,n){return n[3]- +0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()=== +i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]]; +if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m, +g);else if(typeof g.length==="number")for(var p=g.length;n";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g); +n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&& +function(){var g=k,i=t.createElement("div");i.innerHTML="

";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F|| +p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g= +t.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition? +function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n0)for(var h=d;h0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h= +h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context): +c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a, +2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a, +b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&& +e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/\s]+\/)>/g,P={option:[1, +""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null; +else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append", +prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument|| +b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]===""&&!x?r.childNodes:[];for(o=k.length- +1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script")))); +d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i, +jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true, +zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b), +h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b); +if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f= +d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left; +e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/)<[^<]*)*<\/script>/gi, +ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b=== +"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("
").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&& +!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})}, +getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html", +script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data|| +!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache= +false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset; +A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type", +b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&& +c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d|| +c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]= +encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess", +[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"), +e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}}); +if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show", +3),a,b,d);else{d=0;for(var e=this.length;d=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b, +d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a* +Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)} +var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true; +this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|| +this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a= +c.timers,b=0;b-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a, +e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&& +c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase(); +c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+ +b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window); diff --git a/python/src/sailing.web/sailing/web/browser/static/js/jquery-ui-timepicker-addon.js b/python/src/sailing.web/sailing/web/browser/static/js/jquery-ui-timepicker-addon.js new file mode 100644 index 00000000000..14b7b683048 --- /dev/null +++ b/python/src/sailing.web/sailing/web/browser/static/js/jquery-ui-timepicker-addon.js @@ -0,0 +1,985 @@ +/* +* jQuery timepicker addon +* By: Trent Richardson [http://trentrichardson.com] +* Version 0.9.5 +* Last Modified: 05/25/2011 +* +* Copyright 2011 Trent Richardson +* Dual licensed under the MIT and GPL licenses. +* http://trentrichardson.com/Impromptu/GPL-LICENSE.txt +* http://trentrichardson.com/Impromptu/MIT-LICENSE.txt +* +* HERES THE CSS: +* .ui-timepicker-div .ui-widget-header{ margin-bottom: 8px; } +* .ui-timepicker-div dl{ text-align: left; } +* .ui-timepicker-div dl dt{ height: 25px; } +* .ui-timepicker-div dl dd{ margin: -25px 10px 10px 65px; } +* .ui-timepicker-div td { font-size: 90%; } +*/ + +(function($) { + +$.extend($.ui, { timepicker: { version: "0.9.5" } }); + +/* Time picker manager. + Use the singleton instance of this class, $.timepicker, to interact with the time picker. + Settings for (groups of) time pickers are maintained in an instance object, + allowing multiple different settings on the same page. */ + +function Timepicker() { + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + currentText: 'Now', + closeText: 'Done', + ampm: false, + timeFormat: 'hh:mm:ss tt', + timeOnlyTitle: 'Choose Time', + timeText: 'Time', + hourText: 'Hour', + minuteText: 'Minute', + secondText: 'Second', + timezoneText: 'Time Zone' + }; + this._defaults = { // Global defaults for all the datetime picker instances + showButtonPanel: true, + timeOnly: false, + showHour: true, + showMinute: true, + showSecond: true, + showTimezone: false, + showTime: true, + stepHour: 0.05, + stepMinute: 0.05, + stepSecond: 0.05, + hour: 0, + minute: 0, + second: 0, + timezone: '+0000', + hourMin: 0, + minuteMin: 0, + secondMin: 0, + hourMax: 23, + minuteMax: 59, + secondMax: 59, + minDateTime: null, + maxDateTime: null, + hourGrid: 0, + minuteGrid: 0, + secondGrid: 0, + alwaysSetTime: true, + separator: ' ', + altFieldTimeOnly: true, + showTimepicker: true, + timezoneList: ["-1100", "-1000", "-0900", "-0800", "-0700", "-0600", + "-0500", "-0400", "-0300", "-0200", "-0100", "+0000", + "+0100", "+0200", "+0300", "+0400", "+0500", "+0600", + "+0700", "+0800", "+0900", "+1000", "+1100", "+1200"] + }; + $.extend(this._defaults, this.regional['']); +} + +$.extend(Timepicker.prototype, { + $input: null, + $altInput: null, + $timeObj: null, + inst: null, + hour_slider: null, + minute_slider: null, + second_slider: null, + timezone_select: null, + hour: 0, + minute: 0, + second: 0, + timezone: '+0000', + hourMinOriginal: null, + minuteMinOriginal: null, + secondMinOriginal: null, + hourMaxOriginal: null, + minuteMaxOriginal: null, + secondMaxOriginal: null, + ampm: '', + formattedDate: '', + formattedTime: '', + formattedDateTime: '', + timezoneList: ["-1100", "-1000", "-0900", "-0800", "-0700", "-0600", + "-0500", "-0400", "-0300", "-0200", "-0100", "+0000", + "+0100", "+0200", "+0300", "+0400", "+0500", "+0600", + "+0700", "+0800", "+0900", "+1000", "+1100", "+1200"], + + /* Override the default settings for all instances of the time picker. + @param settings object - the new settings to use as defaults (anonymous object) + @return the manager object */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + //######################################################################## + // Create a new Timepicker instance + //######################################################################## + _newInst: function($input, o) { + var tp_inst = new Timepicker(), + inlineSettings = {}; + + for (var attrName in this._defaults) { + var attrValue = $input.attr('time:' + attrName); + if (attrValue) { + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, { + beforeShow: function(input, dp_inst) { + if ($.isFunction(o.beforeShow)) + o.beforeShow(input, dp_inst, tp_inst); + }, + onChangeMonthYear: function(year, month, dp_inst) { + // Update the time as well : this prevents the time from disappearing from the $input field. + tp_inst._updateDateTime(dp_inst); + if ($.isFunction(o.onChangeMonthYear)) + o.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst); + }, + onClose: function(dateText, dp_inst) { + if (tp_inst.timeDefined === true && $input.val() != '') + tp_inst._updateDateTime(dp_inst); + if ($.isFunction(o.onClose)) + o.onClose.call($input[0], dateText, dp_inst, tp_inst); + }, + timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker'); + }); + + tp_inst.hour = tp_inst._defaults.hour; + tp_inst.minute = tp_inst._defaults.minute; + tp_inst.second = tp_inst._defaults.second; + tp_inst.ampm = ''; + tp_inst.$input = $input; + + if (o.altField) + tp_inst.$altInput = $(o.altField) + .css({ cursor: 'pointer' }) + .focus(function(){ $input.trigger("focus"); }); + + // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime.. + if(tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) + tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime()); + if(tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) + tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime()); + if(tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) + tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime()); + if(tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) + tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime()); + + return tp_inst; + }, + + //######################################################################## + // add our sliders to the calendar + //######################################################################## + _addTimePicker: function(dp_inst) { + var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? + this.$input.val() + ' ' + this.$altInput.val() : + this.$input.val(); + + this.timeDefined = this._parseTime(currDT); + this._limitMinMaxDateTime(dp_inst, false); + this._injectTimePicker(); + }, + + //######################################################################## + // parse the time string from input value or _setTime + //######################################################################## + _parseTime: function(timeString, withDate) { + var regstr = this._defaults.timeFormat.toString() + .replace(/h{1,2}/ig, '(\\d?\\d)') + .replace(/m{1,2}/ig, '(\\d?\\d)') + .replace(/s{1,2}/ig, '(\\d?\\d)') + .replace(/t{1,2}/ig, '(am|pm|a|p)?') + .replace(/z{1}/ig, '((\\+|-)\\d\\d\\d\\d)?') + .replace(/\s/g, '\\s?') + '$', + order = this._getFormatPositions(), + treg; + + if (!this.inst) this.inst = $.datepicker._getInst(this.$input[0]); + + if (withDate || !this._defaults.timeOnly) { + // the time should come after x number of characters and a space. + // x = at least the length of text specified by the date format + var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat'); + // escape special regex characters in the seperator + var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); + regstr = '.{' + dp_dateFormat.length + ',}' + this._defaults.separator.replace(specials, "\\$&") + regstr; + } + + treg = timeString.match(new RegExp(regstr, 'i')); + + if (treg) { + if (order.t !== -1) + this.ampm = ((treg[order.t] === undefined || treg[order.t].length === 0) ? + '' : + (treg[order.t].charAt(0).toUpperCase() == 'A') ? 'AM' : 'PM').toUpperCase(); + + if (order.h !== -1) { + if (this.ampm == 'AM' && treg[order.h] == '12') + this.hour = 0; // 12am = 0 hour + else if (this.ampm == 'PM' && treg[order.h] != '12') + this.hour = (parseFloat(treg[order.h]) + 12).toFixed(0); // 12pm = 12 hour, any other pm = hour + 12 + else this.hour = Number(treg[order.h]); + } + + if (order.m !== -1) this.minute = Number(treg[order.m]); + if (order.s !== -1) this.second = Number(treg[order.s]); + if (order.z !== -1) this.timezone = treg[order.z]; + + return true; + + } + return false; + }, + + //######################################################################## + // figure out position of time elements.. cause js cant do named captures + //######################################################################## + _getFormatPositions: function() { + var finds = this._defaults.timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|t{1,2}|z)/g), + orders = { h: -1, m: -1, s: -1, t: -1, z: -1 }; + + if (finds) + for (var i = 0; i < finds.length; i++) + if (orders[finds[i].toString().charAt(0)] == -1) + orders[finds[i].toString().charAt(0)] = i + 1; + + return orders; + }, + + //######################################################################## + // generate and inject html for timepicker into ui datepicker + //######################################################################## + _injectTimePicker: function() { + var $dp = this.inst.dpDiv, + o = this._defaults, + tp_inst = this, + // Added by Peter Medeiros: + // - Figure out what the hour/minute/second max should be based on the step values. + // - Example: if stepMinute is 15, then minMax is 45. + hourMax = (o.hourMax - (o.hourMax % o.stepHour)).toFixed(0), + minMax = (o.minuteMax - (o.minuteMax % o.stepMinute)).toFixed(0), + secMax = (o.secondMax - (o.secondMax % o.stepSecond)).toFixed(0), + dp_id = this.inst.id.toString().replace(/([^A-Za-z0-9_])/g, ''); + + // Prevent displaying twice + //if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0) { + if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0 && o.showTimepicker) { + var noDisplay = ' style="display:none;"', + html = '
' + + '
' + o.timeText + '
' + + '
' + + '
' + o.hourText + '
', + hourGridSize = 0, + minuteGridSize = 0, + secondGridSize = 0, + size; + + if (o.showHour && o.hourGrid > 0) { + html += '
' + + '
' + + '
'; + + for (var h = o.hourMin; h < hourMax; h += o.hourGrid) { + hourGridSize++; + var tmph = (o.ampm && h > 12) ? h-12 : h; + if (tmph < 10) tmph = '0' + tmph; + if (o.ampm) { + if (h == 0) tmph = 12 +'a'; + else if (h < 12) tmph += 'a'; + else tmph += 'p'; + } + html += ''; + } + + html += '
' + tmph + '
' + + ''; + } else html += '
'; + + html += '
' + o.minuteText + '
'; + + if (o.showMinute && o.minuteGrid > 0) { + html += '
' + + '
' + + '
'; + + for (var m = o.minuteMin; m < minMax; m += o.minuteGrid) { + minuteGridSize++; + html += ''; + } + + html += '
' + ((m < 10) ? '0' : '') + m + '
' + + '
'; + } else html += '
'; + + html += '
' + o.secondText + '
'; + + if (o.showSecond && o.secondGrid > 0) { + html += '
' + + '
' + + '
'; + + for (var s = o.secondMin; s < secMax; s += o.secondGrid) { + secondGridSize++; + html += ''; + } + + html += '
' + ((s < 10) ? '0' : '') + s + '
' + + '
'; + } else html += '
'; + + html += '
' + o.timezoneText + '
'; + html += '
'; + + html += ''; + $tp = $(html); + + // if we only want time picker... + if (o.timeOnly === true) { + $tp.prepend( + '
' + + '
' + o.timeOnlyTitle + '
' + + '
'); + $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide(); + } + + this.hour_slider = $tp.find('#ui_tpicker_hour_'+ dp_id).slider({ + orientation: "horizontal", + value: this.hour, + min: o.hourMin, + max: hourMax, + step: o.stepHour, + slide: function(event, ui) { + tp_inst.hour_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + // Updated by Peter Medeiros: + // - Pass in Event and UI instance into slide function + this.minute_slider = $tp.find('#ui_tpicker_minute_'+ dp_id).slider({ + orientation: "horizontal", + value: this.minute, + min: o.minuteMin, + max: minMax, + step: o.stepMinute, + slide: function(event, ui) { + // update the global minute slider instance value with the current slider value + tp_inst.minute_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + this.second_slider = $tp.find('#ui_tpicker_second_'+ dp_id).slider({ + orientation: "horizontal", + value: this.second, + min: o.secondMin, + max: secMax, + step: o.stepSecond, + slide: function(event, ui) { + tp_inst.second_slider.slider( "option", "value", ui.value); + tp_inst._onTimeChange(); + } + }); + + + this.timezone_select = $tp.find('#ui_tpicker_timezone_'+ dp_id).append('').find("select"); + $.fn.append.apply(this.timezone_select, + $.map(o.timezoneList, function(val, idx) { + return $("