Beginnings of ETA calc based on actual data
Beginnings of ETA calc based on actual data

file:b/.gitignore (new)
 
  /labs/tiles/12
  /labs/tiles/13
  /labs/tiles/14
  /labs/tiles/15
  /labs/tiles/16
  /labs/tiles/17
  /labs/tiles/19
  /nbproject/private/
file:b/.gitmodules (new)
  [submodule "js/flotr2"]
  path = js/flotr2
  url = https://github.com/HumbleSoftware/Flotr2.git
  [submodule "js/FlashCanvas"]
  path = js/FlashCanvas
  url = https://github.com/timcameronryan/FlashCanvas
  [submodule "lib/amon-php"]
  path = lib/amon-php
  url = https://github.com/martinrusev/amon-php.git
  [submodule "js/yepnope"]
  path = js/yepnope
  url = https://github.com/SlexAxton/yepnope.js.git
  [submodule "javascripts/tesseract"]
  path = javascripts/tesseract
  url = https://github.com/square/tesseract.git
  [submodule "javascripts/d3"]
  path = javascripts/d3
  url = https://github.com/mbostock/d3.git
file:b/Boxfile (new)
  web1:
  php_extensions:
  - pgsql
  - pdo
  - pdo_pgsql
  - curl
 
file:a/about.php -> file:b/about.php
<?php <?php
  /*
  * Copyright 2010,2011 Alexander Sadleir
   
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
   
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
include ('include/common.inc.php'); include ('include/common.inc.php');
include_header("About", "about") include_header("About", "about")
?> ?>
<p> <p>
Busness Time - An ACT bus timetable webapp<br /> Busness Time - An ACT bus timetable webapp<br />
Based on the maxious-canberra-transit-feed (<a Based on the maxious-canberra-transit-feed (<a
href="http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip">download</a>, href="http://busresources.lambdacomplex.org/cbrfeed.zip">download</a>,
last updated <?php last updated <?php echo date("F d Y.", @filemtime('../busresources/cbrfeed.zip')); ?>)<br />
echo date("F d Y.", @filemtime('cbrfeed.zip')); ?>)<br /> Source code for the <a
Source code for the <a href="https://github.com/maxious/ACTBus-data">transit
href="https://github.com/maxious/ACTBus-data">transit feed</a> and <a href="https://github.com/maxious/ACTBus-ui">this
feed</a> and <a href="https://github.com/maxious/ACTBus-ui">this site</a> available from github.<br />
site</a> available from github.<br /> Uses jQuery Mobile, PHP, PostgreSQL, OpenTripPlanner, OpenLayers, OpenStreetMap, Cloudmade Geocoder and Tile Service<br />
Uses jQuery Mobile, PHP, PostgreSQL, OpenTripPlanner, OpenLayers, OpenStreetMap, Cloudmade Geocoder and Tile Service<br /> Suburb Geocoding Based on <A href="http://www.abs.gov.au/AUSSTATS/abs@.nsf/Lookup/1270.0.55.003Main+Features1July%202011?OpenDocument">Australian Bureau of Statistics data.</a><br />
<br /> Street geocoding based on work by OpenStreetMap contributors<br>
Feedback encouraged; contact maxious@lambdacomplex.org<br />  
<br /> <br />
Some icons by Joseph Wain / glyphish.com<br /> Feedback encouraged; contact maxious@lambdacomplex.org<br />
<br /> <br />
<small>Disclaimer: The content of this website is of a general and informative nature. Please check with printed timetables or those available on http://action.act.gov.au before your trip. Some icons by Joseph Wain / glyphish.com<br />
Whilst every effort has been made to ensure the high quality and accuracy of the Site, the Author makes no warranty, Native clients also available for iPhone(<a href="http://itunes.apple.com/au/app/cbrtimetable/id444287349?mt=8">cbrTimetable by Sandor Kolotenko</a>
express or implied concerning the topicality, correctness, completeness or quality of the information, which is provided , <a href="http://itunes.apple.com/au/app/act-buses/id376634797?mt=8">ACT Buses by David Sullivan</a>, <a href="http://itunes.apple.com/app/bus-trips-act/id489146525?mt=8">Bus Trips ACT by Molson Chengalath</a>)
"as is". The Author expressly disclaims all warranties, including but not limited to warranties of fitness for a particular purpose and warranties of merchantability. , Android (<a href="https://market.android.com/details?id=com.action">MyBus 2.0 by Imagine Team</a>, <A href="https://market.android.com/details?id=GetMe2CanberraFree.source">GetMe2 Canberra by
All offers are not binding and without obligation. The Author expressly reserves the right, in his discretion, to suspend, Colin Thompson </a>, <a href="https://market.android.com/details?id=au.com.transittimes.android">TransitTimes+ by Zervaas Enterprises</a>)
change, modify, add or remove portions of the Site and to restrict or terminate the use and accessibility of the Site and Windows Phone 7 (<a href="http://www.windowsphone.com/en-AU/apps/d840375e-429c-4aa4-a358-80eec6ea9e66">TransHub Canberra by Soul Solutions</a>) Other web clients include <a href="http://canberra.itranzit.com/option.html">iTranzit</a>.
without prior notice. </small> <br />
<?php GTFS-realtime API:
include_footer(); Alerts and Trip Updates (but only Cancelled or Stop Skipped)
?> Default format binary Protocol Buffer but can get JSON by adding ?ascii=yes
  <br />
  <br />
  <small>Disclaimer: The content of this website is of a general and informative nature. Please check with printed timetables or those available on http://action.act.gov.au before your trip.
  Whilst every effort has been made to ensure the high quality and accuracy of the Site, the Author makes no warranty,
  express or implied concerning the topicality, correctness, completeness or quality of the information, which is provided
  "as is". The Author expressly disclaims all warranties, including but not limited to warranties of fitness for a particular purpose and warranties of merchantability.
  All offers are not binding and without obligation. The Author expressly reserves the right, in his discretion, to suspend,
  change, modify, add or remove portions of the Site and to restrict or terminate the use and accessibility of the Site
  without prior notice. </small>
  <?php
  include_footer();
  ?>
   
file:a/aws/awsStartup.sh (deleted)
#!/bin/bash  
#this script should be run from a fresh git checkout from github  
#ami base must have yum install lighttpd-fastcgi, git, tomcat6  
#php-cli php-gd tomcat6-webapps tomcat6-admin-webapps svn maven2  
#postgres postgres-server php-pg  
#http://www.how2forge.org/installing-lighttpd-with-php5-and-mysql-support-on-fedora-12  
 
cp /root/aws.php /tmp/  
mkdir /var/www/lib/staticmaplite/cache  
chcon -h system_u:object_r:httpd_sys_content_t /var/www  
chcon -R -h root:object_r:httpd_sys_content_t /var/www/*  
chcon -R -t httpd_sys_content_rw_t /var/www/lib/staticmaplite/cache  
chmod -R 777 /var/www/lib/staticmaplite/cache  
chcon -R -t httpd_sys_content_rw_t /var/www/labs/tiles  
chmod -R 777 /var/www/labs/tiles  
wget http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip \  
-O /var/www/cbrfeed.zip  
 
createdb transitdata  
createlang -d transitdata plpgsql  
psql -d transitdata -f /var/www/lib/postgis.sql  
# curl https://github.com/maxious/ACTBus-ui/raw/master/transitdata.cbrfeed.sql.gz -o transitdata.cbrfeed.sql.gz  
#made with pg_dump transitdata | gzip -c > transitdata.cbrfeed.sql.gz  
gunzip /var/www/transitdata.cbrfeed.sql.gz  
psql -d transitdata -f /var/www/transitdata.cbrfeed.sql  
#createuser transitdata -SDRP  
#password transitdata  
#psql -d transitdata -c \"GRANT SELECT ON TABLE agency,calendar,calendar_dates,routes,stop_times,stops,trips TO transitdata;\"  
php /var/www/updatedb.php  
 
wget http://s3-ap-southeast-1.amazonaws.com/busresources/Graph.obj \  
-O /tmp/Graph.obj  
rm -rfv /usr/share/tomcat6/webapps/opentripplanner*  
wget http://s3-ap-southeast-1.amazonaws.com/busresources/opentripplanner-webapp.war \  
-O /usr/share/tomcat6/webapps/opentripplanner-webapp.war  
wget http://s3-ap-southeast-1.amazonaws.com/busresources/opentripplanner-api-webapp.war \  
-O /usr/share/tomcat6/webapps/opentripplanner-api-webapp.war  
/etc/init.d/tomcat6 restart  
 
file:a/aws/compress.conf (deleted)
#######################################################################  
##  
## Output Compression  
## --------------------  
##  
## see http://www.lighttpd.net/documentation/compress.html  
##  
server.modules += ( "mod_compress" )  
 
##  
## where should the compressed files be cached?  
## see the base config for the declaration of the variable.  
##  
## This directory should be changed per vhost otherwise you can  
## run into trouble with overlapping filenames  
##  
compress.cache-dir = cache_dir + "/compress"  
 
##  
## FileTypes to compress.  
##  
#compress.filetype = ("text/plain", "text/html")  
compress.filetype = ("text/plain", "text/html", "text/javascript", "text/css", "text/xml")  
 
##  
## Maximum filesize that will be compressed.  
## Default is 0, which means unlimited file size.  
##  
#compress.max-filesize = 0  
 
##  
#######################################################################  
 
file:a/aws/expire.conf (deleted)
#######################################################################  
##  
## Expire Module  
## ---------------  
##  
## See http://www.lighttpd.net/documentation/expire.html  
##  
server.modules += ( "mod_expire" )  
 
##  
## assignes a expiration to all files below the specified path. The  
## specification of the time is made up of:  
##  
## <access|modification> <number> <years|months|days|hours|minutes|seconds>  
##  
#expire.url = (  
# "/buggy/" => "access 2 hours",  
# "/images/" => "access plus 1 seconds 2 minutes"  
#)  
etag.use-mtime = "enable"  
etag.use-inode = "disable"  
static-file.etags = "enable"  
$HTTP["url"] =~ "\.(css|js|png|jpg|ico|gif)$" {  
expire.url = ( "" => "access 7 days" )  
}  
 
##  
#######################################################################  
 
file:a/aws/fastcgi.conf (deleted)
#######################################################################  
##  
## FastCGI Module  
## ---------------  
##  
## http://www.lighttpd.net/documentation/fastcgi.html  
##  
server.modules += ( "mod_fastcgi" )  
fastcgi.server = ( ".php" =>  
( "localhost" =>  
(  
"socket" =>  
"/var/run/lighttpd/php-fastcgi.socket",  
"bin-path" => "/usr/bin/php-cgi"  
)  
)  
)  
##  
## PHP Example  
## For PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini.  
##  
## The number of php processes you will get can be easily calculated:  
##  
## num-procs = max-procs * ( 1 + PHP_FCGI_CHILDREN )  
##  
## for the php-num-procs example it means you will get 17*5 = 85 php  
## processes. you always should need this high number for your very  
## busy sites. And if you have a lot of RAM. :)  
##  
#fastcgi.server = ( ".php" =>  
# ( "php-local" =>  
# (  
# "socket" => socket_dir + "/php-fastcgi-1.socket",  
# "bin-path" => server_root + "/php-cgi",  
# "max-procs" => 1,  
# "broken-scriptfilename" => "enable",  
# )  
# ),  
# ( "php-tcp" =>  
# (  
# "host" => "127.0.0.1",  
# "port" => 9999,  
# "check-local" => "disable",  
# "broken-scriptfilename" => "enable",  
# )  
# ),  
#  
# ( "php-num-procs" =>  
# (  
# "socket" => socket_dir + "/php-fastcgi-2.socket",  
# "bin-path" => server_root + "/php-cgi",  
# "bin-environment" => (  
# "PHP_FCGI_CHILDREN" => "16",  
# "PHP_FCGI_MAX_REQUESTS" => "10000",  
# ),  
# "max-procs" => 5,  
# "broken-scriptfilename" => "enable",  
# )  
# ),  
# )  
 
##  
## Ruby on Rails Example  
##  
## Normally you only run one Rails application on one vhost.  
##  
#$HTTP["host"] == "rails1.example.com" {  
# server.document-root = server_root + "/rails/someapp/public"  
# server.error-handler-404 = "/dispatch.fcgi"  
# fastcgi.server = ( ".fcgi" =>  
# ("someapp" =>  
# ( "socket" => socket_dir + "/someapp-fcgi.socket",  
# "bin-path" => server_root + "/rails/someapp/public/dispatch.fcgi",  
# "bin-environment" => (  
# "RAILS_ENV" => "production",  
# "TMP" => home_dir + "/rails/someapp",  
# ),  
# )  
# )  
# )  
#}  
 
##  
## Another example with multiple rails applications on one vhost.  
##  
## http://blog.lighttpd.net/articles/2005/11/23/lighttpd-1-4-8-and-multiple-rails-apps  
##  
#$HTTP["host"] == "rails2.example.com" {  
# $HTTP["url"] =~ "^/someapp1" {  
# server.document-root = server_root + "/rails/someapp1/public"  
# server.error-handler-404 = "/dispatch.fcgi"  
# fastcgi.server = ( ".fcgi" =>  
# ("someapp1" =>  
# ( "socket" => socket_dir + "/someapp1-fcgi.socket",  
# "bin-path" => server_root + "/rails/someapp1/public/dispatch.fcgi",  
# "bin-environment" => (  
# "RAILS_ENV" => "production",  
# "TMP" => home_dir + "/rails/someapp1",  
# ),  
# "strip-request-uri" => "/someapp1/"  
# )  
# )  
# )  
# }  
#  
# $HTTP["url"] =~ "^/someapp2" {  
# server.document-root = server_root + "/rails/someapp2/public"  
# server.error-handler-404 = "/dispatch.fcgi"  
# fastcgi.server = ( ".fcgi" =>  
# ("someapp2" =>  
# ( "socket" => socket_dir + "/someapp2-fcgi.socket",  
# "bin-path" => server_root + "/rails/someapp2/public/dispatch.fcgi",  
# "bin-environment" => (  
# "RAILS_ENV" => "production",  
# "TMP" => home_dir + "/rails/someapp2",  
# ),  
# "strip-request-uri" => "/someapp2/"  
# )  
# )  
# )  
# }  
#}  
 
## chrooted webserver + external PHP  
##  
## $ spawn-fcgi -f /usr/bin/php-cgi -p 2000 -a 127.0.0.1 -C 8  
##  
## webserver chrooted to /srv/www/  
## php running outside the chroot  
#  
#fastcgi.server = (  
# ".php" => ((  
# "host" => "127.0.0.1",  
# "port" => "2000",  
# "docroot" => "/srv/www/servers/www.example.org/htdocs/"  
# )))  
#  
#server.chroot = "/srv/www"  
#server.document-root = "/servers/wwww.example.org/htdocs/"  
#  
 
##  
#######################################################################  
 
file:a/aws/modules.conf (deleted)
#######################################################################  
##  
## Modules to load  
## -----------------  
##  
## at least mod_access and mod_accesslog should be loaded  
## all other module should only be loaded if really neccesary  
##  
## - saves some time  
## - saves memory  
##  
## the default module set contains:  
##  
## "mod_indexfile", "mod_dirlisting", "mod_staticfile"  
##  
## you dont have to include those modules in your list  
##  
## Modules, which are pulled in via conf.d/*.conf  
##  
## NOTE: the order of modules is important.  
##  
## - mod_accesslog -> conf.d/access_log.conf  
## - mod_compress -> conf.d/compress.conf  
## - mod_status -> conf.d/status.conf  
## - mod_webdav -> conf.d/webdav.conf  
## - mod_cml -> conf.d/cml.conf  
## - mod_evhost -> conf.d/evhost.conf  
## - mod_simple_vhost -> conf.d/simple_vhost.conf  
## - mod_mysql_vhost -> conf.d/mysql_vhost.conf  
## - mod_trigger_b4_dl -> conf.d/trigger_b4_dl.conf  
## - mod_userdir -> conf.d/userdir.conf  
## - mod_rrdtool -> conf.d/rrdtool.conf  
## - mod_ssi -> conf.d/ssi.conf  
## - mod_cgi -> conf.d/cgi.conf  
## - mod_scgi -> conf.d/scgi.conf  
## - mod_fastcgi -> conf.d/fastcgi.conf  
## - mod_proxy -> conf.d/proxy.conf  
## - mod_secdownload -> conf.d/secdownload.conf  
## - mod_expire -> conf.d/expire.conf  
##  
 
server.modules = (  
"mod_access",  
# "mod_alias",  
# "mod_auth",  
# "mod_evasive",  
# "mod_redirect",  
# "mod_rewrite",  
# "mod_setenv",  
# "mod_usertrack",  
)  
 
##  
#######################################################################  
 
#######################################################################  
##  
## Config for various Modules  
##  
 
##  
## mod_ssi  
##  
#include "conf.d/ssi.conf"  
 
##  
## mod_status  
##  
#include "conf.d/status.conf"  
 
##  
## mod_webdav  
##  
#include "conf.d/webdav.conf"  
 
##  
## mod_compress  
##  
include "conf.d/compress.conf"  
 
##  
## mod_userdir  
##  
#include "conf.d/userdir.conf"  
 
##  
## mod_magnet  
##  
#include "conf.d/magnet.conf"  
 
##  
## mod_cml  
##  
#include "conf.d/cml.conf"  
 
##  
## mod_rrdtool  
##  
#include "conf.d/rrdtool.conf"  
 
##  
## mod_proxy  
##  
#include "conf.d/proxy.conf"  
 
##  
## mod_expire  
##  
include "conf.d/expire.conf"  
 
##  
## mod_secdownload  
##  
#include "conf.d/secdownload.conf"  
 
##  
#######################################################################  
 
#######################################################################  
##  
## CGI modules  
##  
 
##  
## SCGI (mod_scgi)  
##  
#include "conf.d/scgi.conf"  
 
##  
## FastCGI (mod_fastcgi)  
##  
include "conf.d/fastcgi.conf"  
 
##  
## plain old CGI (mod_cgi)  
##  
#include "conf.d/cgi.conf"  
 
##  
#######################################################################  
 
#######################################################################  
##  
## VHost Modules  
##  
## Only load ONE of them!  
## ========================  
##  
 
##  
## You can use conditionals for vhosts aswell.  
##  
## see http://www.lighttpd.net/documentation/configuration.html  
##  
 
##  
## mod_evhost  
##  
#include "conf.d/evhost.conf"  
 
##  
## mod_simple_vhost  
##  
#include "conf.d/simple_vhost.conf"  
 
##  
## mod_mysql_vhost  
##  
#include "conf.d/mysql_vhost.conf"  
 
##  
#######################################################################  
 
file:a/aws/pg_hba.conf (deleted)
# PostgreSQL Client Authentication Configuration File  
# ===================================================  
#  
# Refer to the "Client Authentication" section in the  
# PostgreSQL documentation for a complete description  
# of this file. A short synopsis follows.  
#  
# This file controls: which hosts are allowed to connect, how clients  
# are authenticated, which PostgreSQL user names they can use, which  
# databases they can access. Records take one of these forms:  
#  
# local DATABASE USER METHOD [OPTIONS]  
# host DATABASE USER CIDR-ADDRESS METHOD [OPTIONS]  
# hostssl DATABASE USER CIDR-ADDRESS METHOD [OPTIONS]  
# hostnossl DATABASE USER CIDR-ADDRESS METHOD [OPTIONS]  
#  
# (The uppercase items must be replaced by actual values.)  
#  
# The first field is the connection type: "local" is a Unix-domain socket,  
# "host" is either a plain or SSL-encrypted TCP/IP socket, "hostssl" is an  
# SSL-encrypted TCP/IP socket, and "hostnossl" is a plain TCP/IP socket.  
#  
# DATABASE can be "all", "sameuser", "samerole", a database name, or  
# a comma-separated list thereof.  
#  
# USER can be "all", a user name, a group name prefixed with "+", or  
# a comma-separated list thereof. In both the DATABASE and USER fields  
# you can also write a file name prefixed with "@" to include names from  
# a separate file.  
#  
# CIDR-ADDRESS specifies the set of hosts the record matches.  
# It is made up of an IP address and a CIDR mask that is an integer  
# (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that specifies  
# the number of significant bits in the mask. Alternatively, you can write  
# an IP address and netmask in separate columns to specify the set of hosts.  
#  
# METHOD can be "trust", "reject", "md5", "password", "gss", "sspi", "krb5",  
# "ident", "pam", "ldap" or "cert". Note that "password" sends passwords  
# in clear text; "md5" is preferred since it sends encrypted passwords.  
#  
# OPTIONS are a set of options for the authentication in the format  
# NAME=VALUE. The available options depend on the different authentication  
# methods - refer to the "Client Authentication" section in the documentation  
# for a list of which options are available for which authentication methods.  
#  
# Database and user names containing spaces, commas, quotes and other special  
# characters must be quoted. Quoting one of the keywords "all", "sameuser" or  
# "samerole" makes the name lose its special character, and just match a  
# database or username with that name.  
#  
# This file is read on server startup and when the postmaster receives  
# a SIGHUP signal. If you edit the file on a running system, you have  
# to SIGHUP the postmaster for the changes to take effect. You can use  
# "pg_ctl reload" to do that.  
 
# Put your actual configuration here  
# ----------------------------------  
#  
# If you want to allow non-local connections, you need to add more  
# "host" records. In that case you will also need to make PostgreSQL listen  
# on a non-local interface via the listen_addresses configuration parameter,  
# or via the -i or -h command line switches.  
#  
 
 
 
# TYPE DATABASE USER CIDR-ADDRESS METHOD  
 
# "local" is for Unix domain socket connections only  
local all all trust  
# IPv4 local connections:  
host all all 127.0.0.1/32 trust  
# IPv6 local connections:  
host all all ::1/128 trust  
#Allow any IP to connect, with a password:  
host all all 0.0.0.0 0.0.0.0 md5  
 
file:a/aws/php.ini (deleted)
[PHP]  
 
date.timezone = "Australia/Sydney"  
 
;;;;;;;;;;;;;;;;;;;  
; About php.ini ;  
;;;;;;;;;;;;;;;;;;;  
; PHP's initialization file, generally called php.ini, is responsible for  
; configuring many of the aspects of PHP's behavior.  
 
; PHP attempts to find and load this configuration from a number of locations.  
; The following is a summary of its search order:  
; 1. SAPI module specific location.  
; 2. The PHPRC environment variable. (As of PHP 5.2.0)  
; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0)  
; 4. Current working directory (except CLI)  
; 5. The web server's directory (for SAPI modules), or directory of PHP  
; (otherwise in Windows)  
; 6. The directory from the --with-config-file-path compile time option, or the  
; Windows directory (C:\windows or C:\winnt)  
; See the PHP docs for more specific information.  
; http://www.php.net/manual/en/configuration.file.php  
 
; The syntax of the file is extremely simple. Whitespace and Lines  
; beginning with a semicolon are silently ignored (as you probably guessed).  
; Section headers (e.g. [Foo]) are also silently ignored, even though  
; they might mean something in the future.  
 
; Directives following the section heading [PATH=/www/mysite] only  
; apply to PHP files in the /www/mysite directory. Directives  
; following the section heading [HOST=www.example.com] only apply to  
; PHP files served from www.example.com. Directives set in these  
; special sections cannot be overridden by user-defined INI files or  
; at runtime. Currently, [PATH=] and [HOST=] sections only work under  
; CGI/FastCGI.  
; http://www.php.net/manual/en/ini.sections.php  
 
; Directives are specified using the following syntax:  
; directive = value  
; Directive names are *case sensitive* - foo=bar is different from FOO=bar.  
; Directives are variables used to configure PHP or PHP extensions.  
; There is no name validation. If PHP can't find an expected  
; directive because it is not set or is mistyped, a default value will be used.  
 
; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one  
; of the INI constants (On, Off, True, False, Yes, No and None) or an expression  
; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a  
; previously set variable or directive (e.g. ${foo})  
 
; Expressions in the INI file are limited to bitwise operators and parentheses:  
; | bitwise OR  
; ^ bitwise XOR  
; & bitwise AND  
; ~ bitwise NOT  
; ! boolean NOT  
 
; Boolean flags can be turned on using the values 1, On, True or Yes.  
; They can be turned off using the values 0, Off, False or No.  
 
; An empty string can be denoted by simply not writing anything after the equal  
; sign, or by using the None keyword:  
 
; foo = ; sets foo to an empty string  
; foo = None ; sets foo to an empty string  
; foo = "None" ; sets foo to the string 'None'  
 
; If you use constants in your value, and these constants belong to a  
; dynamically loaded extension (either a PHP extension or a Zend extension),  
; you may only use these constants *after* the line that loads the extension.  
 
;;;;;;;;;;;;;;;;;;;  
; About this file ;  
;;;;;;;;;;;;;;;;;;;  
; PHP comes packaged with two INI files. One that is recommended to be used  
; in production environments and one that is recommended to be used in  
; development environments.  
 
; php.ini-production contains settings which hold security, performance and  
; best practices at its core. But please be aware, these settings may break  
; compatibility with older or less security conscience applications. We  
; recommending using the production ini in production and testing environments.  
 
; php.ini-development is very similar to its production variant, except it's  
; much more verbose when it comes to errors. We recommending using the  
; development version only in development environments as errors shown to  
; application users can inadvertently leak otherwise secure information.  
 
; This 2 files are provided, by RPM, in /usr/share/doc/php-common-*/  
; File used by RPM (the /etc/php.ini) is mainly the php.ini-production  
 
;;;;;;;;;;;;;;;;;;;  
; Quick Reference ;  
;;;;;;;;;;;;;;;;;;;  
; The following are all the settings which are different in either the production  
; or development versions of the INIs with respect to PHP's default behavior.  
; Please see the actual settings later in the document for more details as to why  
; we recommend these changes in PHP's behavior.  
 
; allow_call_time_pass_reference  
; Default Value: On  
; Development Value: Off  
; Production Value: Off  
 
; display_errors  
; Default Value: On  
; Development Value: On  
; Production Value: Off  
 
; display_startup_errors  
; Default Value: Off  
; Development Value: On  
; Production Value: Off  
 
; error_reporting  
; Default Value: E_ALL & ~E_NOTICE  
; Development Value: E_ALL | E_STRICT  
; Production Value: E_ALL & ~E_DEPRECATED  
 
; html_errors  
; Default Value: On  
; Development Value: On  
; Production value: Off  
 
; log_errors  
; Default Value: Off  
; Development Value: On  
; Production Value: On  
 
; magic_quotes_gpc  
; Default Value: On  
; Development Value: Off  
; Production Value: Off  
 
; max_input_time  
; Default Value: -1 (Unlimited)  
; Development Value: 60 (60 seconds)  
; Production Value: 60 (60 seconds)  
 
; output_buffering  
; Default Value: Off  
; Development Value: 4096  
; Production Value: 4096  
 
; register_argc_argv  
; Default Value: On  
; Development Value: Off  
; Production Value: Off  
 
; register_long_arrays  
; Default Value: On  
; Development Value: Off  
; Production Value: Off  
 
; request_order  
; Default Value: None  
; Development Value: "GP"  
; Production Value: "GP"  
 
; session.bug_compat_42  
; Default Value: On  
; Development Value: On  
; Production Value: Off  
 
; session.bug_compat_warn  
; Default Value: On  
; Development Value: On  
; Production Value: Off  
 
; session.gc_divisor  
; Default Value: 100  
; Development Value: 1000  
; Production Value: 1000  
 
; session.hash_bits_per_character  
; Default Value: 4  
; Development Value: 5  
; Production Value: 5  
 
; short_open_tag  
; Default Value: On  
; Development Value: Off  
; Production Value: Off  
 
; track_errors  
; Default Value: Off  
; Development Value: On  
; Production Value: Off  
 
; url_rewriter.tags  
; Default Value: "a=href,area=href,frame=src,form=,fieldset="  
; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry"  
; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry"  
 
; variables_order  
; Default Value: "EGPCS"  
; Development Value: "GPCS"  
; Production Value: "GPCS"  
 
;;;;;;;;;;;;;;;;;;;;  
; php.ini Options ;  
;;;;;;;;;;;;;;;;;;;;  
; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini"  
;user_ini.filename = ".user.ini"  
 
; To disable this feature set this option to empty value  
;user_ini.filename =  
 
; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes)  
;user_ini.cache_ttl = 300  
 
;;;;;;;;;;;;;;;;;;;;  
; Language Options ;  
;;;;;;;;;;;;;;;;;;;;  
 
; Enable the PHP scripting language engine under Apache.  
; http://www.php.net/manual/en/apache.configuration.php#ini.engine  
engine = On  
 
; This directive determines whether or not PHP will recognize code between  
; <? and ?> tags as PHP source which should be processed as such. It's been  
; recommended for several years that you not use the short tag "short cut" and  
; instead to use the full <?php and ?> tag combination. With the wide spread use  
; of XML and use of these tags by other languages, the server can become easily  
; confused and end up parsing the wrong code in the wrong context. But because  
; this short cut has been a feature for such a long time, it's currently still  
; supported for backwards compatibility, but we recommend you don't use them.  
; Default Value: On  
; Development Value: Off  
; Production Value: Off  
; http://www.php.net/manual/en/ini.core.php#ini.short-open-tag  
short_open_tag = Off  
 
; Allow ASP-style <% %> tags.  
; http://www.php.net/manual/en/ini.core.php#ini.asp-tags  
asp_tags = Off  
 
; The number of significant digits displayed in floating point numbers.  
; http://www.php.net/manual/en/ini.core.php#ini.precision  
precision = 14  
 
; Enforce year 2000 compliance (will cause problems with non-compliant browsers)  
; http://www.php.net/manual/en/ini.core.php#ini.y2k-compliance  
y2k_compliance = On  
 
; Output buffering is a mechanism for controlling how much output data  
; (excluding headers and cookies) PHP should keep internally before pushing that  
; data to the client. If your application's output exceeds this setting, PHP  
; will send that data in chunks of roughly the size you specify.  
; Turning on this setting and managing its maximum buffer size can yield some  
; interesting side-effects depending on your application and web server.  
; You may be able to send headers and cookies after you've already sent output  
; through print or echo. You also may see performance benefits if your server is  
; emitting less packets due to buffered output versus PHP streaming the output  
; as it gets it. On production servers, 4096 bytes is a good setting for performance  
; reasons.  
; Note: Output buffering can also be controlled via Output Buffering Control  
; functions.  
; Possible Values:  
; On = Enabled and buffer is unlimited. (Use with caution)  
; Off = Disabled  
; Integer = Enables the buffer and sets its maximum size in bytes.  
; Default Value: Off  
; Development Value: 4096  
; Production Value: 4096  
; http://www.php.net/manual/en/outcontrol.configuration.php#ini.output-buffering  
output_buffering = 4096  
 
; You can redirect all of the output of your scripts to a function. For  
; example, if you set output_handler to "mb_output_handler", character  
; encoding will be transparently converted to the specified encoding.  
; Setting any output handler automatically turns on output buffering.  
; Note: People who wrote portable scripts should not depend on this ini  
; directive. Instead, explicitly set the output handler using ob_start().  
; Using this ini directive may cause problems unless you know what script  
; is doing.  
; Note: You cannot use both "mb_output_handler" with "ob_iconv_handler"  
; and you cannot use both "ob_gzhandler" and "zlib.output_compression".  
; Note: output_handler must be empty if this is set 'On' !!!!  
; Instead you must use zlib.output_handler.  
; http://www.php.net/manual/en/outcontrol.configuration.php#ini.output-handler  
;output_handler =  
 
; Transparent output compression using the zlib library  
; Valid values for this option are 'off', 'on', or a specific buffer size  
; to be used for compression (default is 4KB)  
; Note: Resulting chunk size may vary due to nature of compression. PHP  
; outputs chunks that are few hundreds bytes each as a result of  
; compression. If you prefer a larger chunk size for better  
; performance, enable output_buffering in addition.  
; Note: You need to use zlib.output_handler instead of the standard  
; output_handler, or otherwise the output will be corrupted.  
; http://www.php.net/manual/en/zlib.configuration.php#ini.zlib.output-compression  
zlib.output_compression = on  
 
; http://www.php.net/manual/en/zlib.configuration.php#ini.zlib.output-compression-level  
;zlib.output_compression_level = -1  
 
; You cannot specify additional output handlers if zlib.output_compression  
; is activated here. This setting does the same as output_handler but in  
; a different order.  
; http://www.php.net/manual/en/zlib.configuration.php#ini.zlib.output-handler  
;zlib.output_handler =  
 
; Implicit flush tells PHP to tell the output layer to flush itself  
; automatically after every output block. This is equivalent to calling the  
; PHP function flush() after each and every call to print() or echo() and each  
; and every HTML block. Turning this option on has serious performance  
; implications and is generally recommended for debugging purposes only.  
; http://www.php.net/manual/en/outcontrol.configuration.php#ini.implicit-flush  
implicit_flush = Off  
 
; The unserialize callback function will be called (with the undefined class'  
; name as parameter), if the unserializer finds an undefined class  
; which should be instantiated. A warning appears if the specified function is  
; not defined, or if the function doesn't include/implement the missing class.  
; So only set this entry, if you really want to implement such a  
; callback-function.  
unserialize_callback_func =  
 
; When floats & doubles are serialized store serialize_precision significant  
; digits after the floating point. The default value ensures that when floats  
; are decoded with unserialize, the data will remain the same.  
serialize_precision = 100  
 
; This directive allows you to enable and disable warnings which PHP will issue  
; if you pass a value by reference at function call time. Passing values by  
; reference at function call time is a deprecated feature which will be removed  
; from PHP at some point in the near future. The acceptable method for passing a  
; value by reference to a function is by declaring the reference in the functions  
; definition, not at call time. This directive does not disable this feature, it  
; only determines whether PHP will warn you about it or not. These warnings  
; should enabled in development environments only.  
; Default Value: On (Suppress warnings)  
; Development Value: Off (Issue warnings)  
; Production Value: Off (Issue warnings)  
; http://www.php.net/manual/en/ini.core.php#ini.allow-call-time-pass-reference  
allow_call_time_pass_reference = Off  
 
; Safe Mode  
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.safe-mode  
safe_mode = Off  
 
; By default, Safe Mode does a UID compare check when  
; opening files. If you want to relax this to a GID compare,  
; then turn on safe_mode_gid.  
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.safe-mode-gid  
safe_mode_gid = Off  
 
; When safe_mode is on, UID/GID checks are bypassed when  
; including files from this directory and its subdirectories.  
; (directory must also be in include_path or full path must  
; be used when including)  
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.safe-mode-include-dir  
safe_mode_include_dir =  
 
; When safe_mode is on, only executables located in the safe_mode_exec_dir  
; will be allowed to be executed via the exec family of functions.  
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.safe-mode-exec-dir  
safe_mode_exec_dir =  
 
; Setting certain environment variables may be a potential security breach.  
; This directive contains a comma-delimited list of prefixes. In Safe Mode,  
; the user may only alter environment variables whose names begin with the  
; prefixes supplied here. By default, users will only be able to set  
; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR).  
; Note: If this directive is empty, PHP will let the user modify ANY  
; environment variable!  
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.safe-mode-allowed-env-vars  
safe_mode_allowed_env_vars = PHP_  
 
; This directive contains a comma-delimited list of environment variables that  
; the end user won't be able to change using putenv(). These variables will be  
; protected even if safe_mode_allowed_env_vars is set to allow to change them.  
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.safe-mode-protected-env-vars  
safe_mode_protected_env_vars = LD_LIBRARY_PATH  
 
; open_basedir, if set, limits all file operations to the defined directory  
; and below. This directive makes most sense if used in a per-directory  
; or per-virtualhost web server configuration file. This directive is  
; *NOT* affected by whether Safe Mode is turned On or Off.  
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.open-basedir  
;open_basedir =  
 
; This directive allows you to disable certain functions for security reasons.  
; It receives a comma-delimited list of function names. This directive is  
; *NOT* affected by whether Safe Mode is turned On or Off.  
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.disable-functions  
disable_functions =  
 
; This directive allows you to disable certain classes for security reasons.  
; It receives a comma-delimited list of class names. This directive is  
; *NOT* affected by whether Safe Mode is turned On or Off.  
; http://www.php.net/manual/en/ini.sect.safe-mode.php#ini.disable-classes  
disable_classes =  
 
; Colors for Syntax Highlighting mode. Anything that's acceptable in  
; <span style="color: ???????"> would work.  
; http://www.php.net/manual/en/misc.configuration.php#ini.syntax-highlighting  
;highlight.string = #DD0000  
;highlight.comment = #FF9900  
;highlight.keyword = #007700  
;highlight.bg = #FFFFFF  
;highlight.default = #0000BB  
;highlight.html = #000000  
 
; If enabled, the request will be allowed to complete even if the user aborts  
; the request. Consider enabling it if executing long requests, which may end up  
; being interrupted by the user or a browser timing out. PHP's default behavior  
; is to disable this feature.  
; http://www.php.net/manual/en/misc.configuration.php#ini.ignore-user-abort  
;ignore_user_abort = On  
 
; Determines the size of the realpath cache to be used by PHP. This value should  
; be increased on systems where PHP opens many files to reflect the quantity of  
; the file operations performed.  
; http://www.php.net/manual/en/ini.core.php#ini.realpath-cache-size  
;realpath_cache_size = 16k  
 
; Duration of time, in seconds for which to cache realpath information for a given  
; file or directory. For systems with rarely changing files, consider increasing this  
; value.  
; http://www.php.net/manual/en/ini.core.php#ini.realpath-cache-ttl  
;realpath_cache_ttl = 120  
 
;;;;;;;;;;;;;;;;;  
; Miscellaneous ;  
;;;;;;;;;;;;;;;;;  
 
; Decides whether PHP may expose the fact that it is installed on the server  
; (e.g. by adding its signature to the Web server header). It is no security  
; threat in any way, but it makes it possible to determine whether you use PHP  
; on your server or not.  
; http://www.php.net/manual/en/ini.core.php#ini.expose-php  
expose_php = On  
 
;;;;;;;;;;;;;;;;;;;  
; Resource Limits ;  
;;;;;;;;;;;;;;;;;;;  
 
; Maximum execution time of each script, in seconds  
; http://www.php.net/manual/en/info.configuration.php#ini.max-execution-time  
max_execution_time = 30  
 
; Maximum amount of time each script may spend parsing request data. It's a good  
; idea to limit this time on productions servers in order to eliminate unexpectedly  
; long running scripts.  
; Default Value: -1 (Unlimited)  
; Development Value: 60 (60 seconds)  
; Production Value: 60 (60 seconds)  
; http://www.php.net/manual/en/info.configuration.php#ini.max-input-time  
max_input_time = 60  
 
; Maximum input variable nesting level  
; http://www.php.net/manual/en/info.configuration.php#ini.max-input-nesting-level  
;max_input_nesting_level = 64  
 
; Maximum amount of memory a script may consume (128MB)  
; http://www.php.net/manual/en/ini.core.php#ini.memory-limit  
memory_limit = 128M  
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
; Error handling and logging ;  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;  
 
; This directive informs PHP of which errors, warnings and notices you would like  
; it to take action for. The recommended way of setting values for this  
; directive is through the use of the error level constants and bitwise  
; operators. The error level constants are below here for convenience as well as  
; some common settings and their meanings.  
; By default, PHP is set to take action on all errors, notices and warnings EXCEPT  
; those related to E_NOTICE and E_STRICT, which together cover best practices and  
; recommended coding standards in PHP. For performance reasons, this is the  
; recommend error reporting setting. Your production server shouldn't be wasting  
; resources complaining about best practices and coding standards. That's what  
; development servers and development settings are for.  
; Note: The php.ini-development file has this setting as E_ALL | E_STRICT. This  
; means it pretty much reports everything which is exactly what you want during  
; development and early testing.  
;  
; Error Level Constants:  
; E_ALL - All errors and warnings (includes E_STRICT as of PHP 6.0.0)  
; E_ERROR - fatal run-time errors  
; E_RECOVERABLE_ERROR - almost fatal run-time errors  
; E_WARNING - run-time warnings (non-fatal errors)  
; E_PARSE - compile-time parse errors  
; E_NOTICE - run-time notices (these are warnings which often result  
; from a bug in your code, but it's possible that it was  
; intentional (e.g., using an uninitialized variable and  
; relying on the fact it's automatically initialized to an  
; empty string)  
; E_STRICT - run-time notices, enable to have PHP suggest changes  
; to your code which will ensure the best interoperability  
; and forward compatibility of your code  
; E_CORE_ERROR - fatal errors that occur during PHP's initial startup  
; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's  
; initial startup  
; E_COMPILE_ERROR - fatal compile-time errors  
; E_COMPILE_WARNING - compile-time warnings (non-fatal errors)  
; E_USER_ERROR - user-generated error message  
; E_USER_WARNING - user-generated warning message  
; E_USER_NOTICE - user-generated notice message  
; E_DEPRECATED - warn about code that will not work in future versions  
; of PHP  
; E_USER_DEPRECATED - user-generated deprecation warnings  
;  
; Common Values:  
; E_ALL & ~E_NOTICE (Show all errors, except for notices and coding standards warnings.)  
; E_ALL & ~E_NOTICE | E_STRICT (Show all errors, except for notices)  
; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors)  
; E_ALL | E_STRICT (Show all errors, warnings and notices including coding standards.)  
; Default Value: E_ALL & ~E_NOTICE  
; Development Value: E_ALL | E_STRICT  
; Production Value: E_ALL & ~E_DEPRECATED  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.error-reporting  
error_reporting = E_ALL & ~E_DEPRECATED  
 
; This directive controls whether or not and where PHP will output errors,  
; notices and warnings too. Error output is very useful during development, but  
; it could be very dangerous in production environments. Depending on the code  
; which is triggering the error, sensitive information could potentially leak  
; out of your application such as database usernames and passwords or worse.  
; It's recommended that errors be logged on production servers rather than  
; having the errors sent to STDOUT.  
; Possible Values:  
; Off = Do not display any errors  
; stderr = Display errors to STDERR (affects only CGI/CLI binaries!)  
; On or stdout = Display errors to STDOUT  
; Default Value: On  
; Development Value: On  
; Production Value: Off  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors  
display_errors = Off  
 
; The display of errors which occur during PHP's startup sequence are handled  
; separately from display_errors. PHP's default behavior is to suppress those  
; errors from clients. Turning the display of startup errors on can be useful in  
; debugging configuration problems. But, it's strongly recommended that you  
; leave this setting off on production servers.  
; Default Value: Off  
; Development Value: On  
; Production Value: Off  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.display-startup-errors  
display_startup_errors = Off  
 
; Besides displaying errors, PHP can also log errors to locations such as a  
; server-specific log, STDERR, or a location specified by the error_log  
; directive found below. While errors should not be displayed on productions  
; servers they should still be monitored and logging is a great way to do that.  
; Default Value: Off  
; Development Value: On  
; Production Value: On  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.log-errors  
log_errors = On  
 
; Set maximum length of log_errors. In error_log information about the source is  
; added. The default is 1024 and 0 allows to not apply any maximum length at all.  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.log-errors-max-len  
log_errors_max_len = 1024  
 
; Do not log repeated messages. Repeated errors must occur in same file on same  
; line unless ignore_repeated_source is set true.  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.ignore-repeated-errors  
ignore_repeated_errors = Off  
 
; Ignore source of message when ignoring repeated messages. When this setting  
; is On you will not log errors with repeated messages from different files or  
; source lines.  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.ignore-repeated-source  
ignore_repeated_source = Off  
 
; If this parameter is set to Off, then memory leaks will not be shown (on  
; stdout or in the log). This has only effect in a debug compile, and if  
; error reporting includes E_WARNING in the allowed list  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.report-memleaks  
report_memleaks = On  
 
; This setting is on by default.  
;report_zend_debug = 0  
 
; Store the last error/warning message in $php_errormsg (boolean). Setting this value  
; to On can assist in debugging and is appropriate for development servers. It should  
; however be disabled on production servers.  
; Default Value: Off  
; Development Value: On  
; Production Value: Off  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.track-errors  
track_errors = Off  
 
; Turn off normal error reporting and emit XML-RPC error XML  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.xmlrpc-errors  
;xmlrpc_errors = 0  
 
; An XML-RPC faultCode  
;xmlrpc_error_number = 0  
 
; When PHP displays or logs an error, it has the capability of inserting html  
; links to documentation related to that error. This directive controls whether  
; those HTML links appear in error messages or not. For performance and security  
; reasons, it's recommended you disable this on production servers.  
; Default Value: On  
; Development Value: On  
; Production value: Off  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.html-errors  
html_errors = Off  
 
; If html_errors is set On PHP produces clickable error messages that direct  
; to a page describing the error or function causing the error in detail.  
; You can download a copy of the PHP manual from http://www.php.net/docs.php  
; and change docref_root to the base URL of your local copy including the  
; leading '/'. You must also specify the file extension being used including  
; the dot. PHP's default behavior is to leave these settings empty.  
; Note: Never use this feature for production boxes.  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.docref-root  
; Examples  
;docref_root = "/phpmanual/"  
 
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.docref-ext  
;docref_ext = .html  
 
; String to output before an error message. PHP's default behavior is to leave  
; this setting blank.  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.error-prepend-string  
; Example:  
;error_prepend_string = "<font color=#ff0000>"  
 
; String to output after an error message. PHP's default behavior is to leave  
; this setting blank.  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.error-append-string  
; Example:  
;error_append_string = "</font>"  
 
; Log errors to specified file. PHP's default behavior is to leave this value  
; empty.  
; http://www.php.net/manual/en/errorfunc.configuration.php#ini.error-log  
; Example:  
;error_log = php_errors.log  
; Log errors to syslog (Event Log on NT, not valid in Windows 95).  
;error_log = syslog  
 
;;;;;;;;;;;;;;;;;  
; Data Handling ;  
;;;;;;;;;;;;;;;;;  
 
; Note - track_vars is ALWAYS enabled as of PHP 4.0.3  
 
; The separator used in PHP generated URLs to separate arguments.  
; PHP's default setting is "&".  
; http://www.php.net/manual/en/ini.core.php#ini.arg-separator.output  
; Example:  
;arg_separator.output = "&amp;"  
 
; List of separator(s) used by PHP to parse input URLs into variables.  
; PHP's default setting is "&".  
; NOTE: Every character in this directive is considered as separator!  
; http://www.php.net/manual/en/ini.core.php#ini.arg-separator.input  
; Example:  
;arg_separator.input = ";&"  
 
; This directive determines which super global arrays are registered when PHP  
; starts up. If the register_globals directive is enabled, it also determines  
; what order variables are populated into the global space. G,P,C,E & S are  
; abbreviations for the following respective super globals: GET, POST, COOKIE,  
; ENV and SERVER. There is a performance penalty paid for the registration of  
; these arrays and because ENV is not as commonly used as the others, ENV is  
; is not recommended on productions servers. You can still get access to  
; the environment variables through getenv() should you need to.  
; Default Value: "EGPCS"  
; Development Value: "GPCS"  
; Production Value: "GPCS";  
; http://www.php.net/manual/en/ini.core.php#ini.variables-order  
variables_order = "GPCS"  
 
; This directive determines which super global data (G,P,C,E & S) should  
; be registered into the super global array REQUEST. If so, it also determines  
; the order in which that data is registered. The values for this directive are  
; specified in the same manner as the variables_order directive, EXCEPT one.  
; Leaving this value empty will cause PHP to use the value set in the  
; variables_order directive. It does not mean it will leave the super globals  
; array REQUEST empty.  
; Default Value: None  
; Development Value: "GP"  
; Production Value: "GP"  
; http://www.php.net/manual/en/ini.core.php#ini.request-order  
request_order = "GP"  
 
; Whether or not to register the EGPCS variables as global variables. You may  
; want to turn this off if you don't want to clutter your scripts' global scope  
; with user data. This makes most sense when coupled with track_vars - in which  
; case you can access all of the GPC variables through the $HTTP_*_VARS[],  
; variables.  
; You should do your best to write your scripts so that they do not require  
; register_globals to be on; Using form variables as globals can easily lead  
; to possible security problems, if the code is not very well thought of.  
; http://www.php.net/manual/en/ini.core.php#ini.register-globals  
register_globals = Off  
 
; Determines whether the deprecated long $HTTP_*_VARS type predefined variables  
; are registered by PHP or not. As they are deprecated, we obviously don't  
; recommend you use them. They are on by default for compatibility reasons but  
; they are not recommended on production servers.  
; Default Value: On  
; Development Value: Off  
; Production Value: Off  
; http://www.php.net/manual/en/ini.core.php#ini.register-long-arrays  
register_long_arrays = Off  
 
; This directive determines whether PHP registers $argv & $argc each time it  
; runs. $argv contains an array of all the arguments passed to PHP when a script  
; is invoked. $argc contains an integer representing the number of arguments  
; that were passed when the script was invoked. These arrays are extremely  
; useful when running scripts from the command line. When this directive is  
; enabled, registering these variables consumes CPU cycles and memory each time  
; a script is executed. For performance reasons, this feature should be disabled  
; on production servers.  
; Default Value: On  
; Development Value: Off  
; Production Value: Off  
; http://www.php.net/manual/en/ini.core.php#ini.register-argc-argv  
register_argc_argv = Off  
 
; When enabled, the SERVER and ENV variables are created when they're first  
; used (Just In Time) instead of when the script starts. If these variables  
; are not used within a script, having this directive on will result in a  
; performance gain. The PHP directives register_globals, register_long_arrays,  
; and register_argc_argv must be disabled for this directive to have any affect.  
; http://www.php.net/manual/en/ini.core.php#ini.auto-globals-jit  
auto_globals_jit = On  
 
; Maximum size of POST data that PHP will accept.  
; http://www.php.net/manual/en/ini.core.php#ini.post-max-size  
post_max_size = 8M  
 
; Magic quotes are a preprocessing feature of PHP where PHP will attempt to  
; escape any character sequences in GET, POST, COOKIE and ENV data which might  
; otherwise corrupt data being placed in resources such as databases before  
; making that data available to you. Because of character encoding issues and  
; non-standard SQL implementations across many databases, it's not currently  
; possible for this feature to be 100% accurate. PHP's default behavior is to  
; enable the feature. We strongly recommend you use the escaping mechanisms  
; designed specifically for the database your using instead of relying on this  
; feature. Also note, this feature has been deprecated as of PHP 5.3.0 and is  
; scheduled for removal in PHP 6.  
; Default Value: On  
; Development Value: Off  
; Production Value: Off  
; http://www.php.net/manual/en/info.configuration.php#ini.magic-quotes-gpc  
magic_quotes_gpc = Off  
 
; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.  
; http://www.php.net/manual/en/info.configuration.php#ini.magic-quotes-runtime  
magic_quotes_runtime = Off  
 
; Use Sybase-style magic quotes (escape ' with '' instead of \').  
; http://www.php.net/manual/en/sybase.configuration.php#ini.magic-quotes-sybase  
magic_quotes_sybase = Off  
 
; Automatically add files before PHP document.  
; http://www.php.net/manual/en/ini.core.php#ini.auto-prepend-file  
auto_prepend_file =  
 
; Automatically add files after PHP document.  
; http://www.php.net/manual/en/ini.core.php#ini.auto-append-file  
auto_append_file =  
 
; As of 4.0b4, PHP always outputs a character encoding by default in  
; the Content-type: header. To disable sending of the charset, simply  
; set it to be empty.  
;  
; PHP's built-in default is text/html  
; http://www.php.net/manual/en/ini.core.php#ini.default-mimetype  
default_mimetype = "text/html"  
 
; PHP's default character set is set to empty.  
; http://www.php.net/manual/en/ini.core.php#ini.default-charset  
;default_charset = "iso-8859-1"  
 
; Always populate the $HTTP_RAW_POST_DATA variable. PHP's default behavior is  
; to disable this feature.  
; http://www.php.net/manual/en/ini.core.php#ini.always-populate-raw-post-data  
;always_populate_raw_post_data = On  
 
;;;;;;;;;;;;;;;;;;;;;;;;;  
; Paths and Directories ;  
;;;;;;;;;;;;;;;;;;;;;;;;;  
 
; UNIX: "/path1:/path2"  
;include_path = ".:/php/includes"  
;  
; Windows: "\path1;\path2"  
;include_path = ".;c:\php\includes"  
;  
; PHP's default setting for include_path is ".;/path/to/php/pear"  
; http://www.php.net/manual/en/ini.core.php#ini.include-path  
 
; The root of the PHP pages, used only if nonempty.  
; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root  
; if you are running php as a CGI under any web server (other than IIS)  
; see documentation for security issues. The alternate is to use the  
; cgi.force_redirect configuration below  
; http://www.php.net/manual/en/ini.core.php#ini.doc-root  
doc_root =  
 
; The directory under which PHP opens the script using /~username used only  
; if nonempty.  
; http://www.php.net/manual/en/ini.core.php#ini.user-dir  
user_dir =  
 
; Directory in which the loadable extensions (modules) reside.  
; http://www.php.net/manual/en/ini.core.php#ini.extension-dir  
; extension_dir = "./"  
 
; Whether or not to enable the dl() function. The dl() function does NOT work  
; properly in multithreaded servers, such as IIS or Zeus, and is automatically  
; disabled on them.  
; http://www.php.net/manual/en/info.configuration.php#ini.enable-dl  
enable_dl = Off  
 
; cgi.force_redirect is necessary to provide security running PHP as a CGI under  
; most web servers. Left undefined, PHP turns this on by default. You can  
; turn it off here AT YOUR OWN RISK  
; **You CAN safely turn this off for IIS, in fact, you MUST.**  
; http://www.php.net/manual/en/ini.core.php#ini.cgi.force-redirect  
;cgi.force_redirect = 1  
 
; if cgi.nph is enabled it will force cgi to always sent Status: 200 with  
; every request. PHP's default behavior is to disable this feature.  
;cgi.nph = 1  
 
; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape  
; (iPlanet) web servers, you MAY need to set an environment variable name that PHP  
; will look for to know it is OK to continue execution. Setting this variable MAY  
; cause security issues, KNOW WHAT YOU ARE DOING FIRST.  
; http://www.php.net/manual/en/ini.core.php#ini.cgi.redirect-status-env  
;cgi.redirect_status_env = ;  
 
; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's  
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok  
; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting  
; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting  
; of zero causes PHP to behave as before. Default is 1. You should fix your scripts  
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.  
; http://www.php.net/manual/en/ini.core.php#ini.cgi.fix-pathinfo  
cgi.fix_pathinfo=1  
 
; FastCGI under IIS (on WINNT based OS) supports the ability to impersonate  
; security tokens of the calling client. This allows IIS to define the  
; security context that the request runs under. mod_fastcgi under Apache  
; does not currently support this feature (03/17/2002)  
; Set to 1 if running under IIS. Default is zero.  
; http://www.php.net/manual/en/ini.core.php#ini.fastcgi.impersonate  
;fastcgi.impersonate = 1;  
 
; Disable logging through FastCGI connection. PHP's default behavior is to enable  
; this feature.  
;fastcgi.logging = 0  
 
; cgi.rfc2616_headers configuration option tells PHP what type of headers to  
; use when sending HTTP response code. If it's set 0 PHP sends Status: header that  
; is supported by Apache. When this option is set to 1 PHP will send  
; RFC2616 compliant header.  
; Default is zero.  
; http://www.php.net/manual/en/ini.core.php#ini.cgi.rfc2616-headers  
;cgi.rfc2616_headers = 0  
 
;;;;;;;;;;;;;;;;  
; File Uploads ;  
;;;;;;;;;;;;;;;;  
 
; Whether to allow HTTP file uploads.  
; http://www.php.net/manual/en/ini.core.php#ini.file-uploads  
file_uploads = On  
 
; Temporary directory for HTTP uploaded files (will use system default if not  
; specified).  
; http://www.php.net/manual/en/ini.core.php#ini.upload-tmp-dir  
;upload_tmp_dir =  
 
; Maximum allowed size for uploaded files.  
; http://www.php.net/manual/en/ini.core.php#ini.upload-max-filesize  
upload_max_filesize = 2M  
 
;;;;;;;;;;;;;;;;;;  
; Fopen wrappers ;  
;;;;;;;;;;;;;;;;;;  
 
; Whether to allow the treatment of URLs (like http:// or ftp://) as files.  
; http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen  
allow_url_fopen = On  
 
; Whether to allow include/require to open URLs (like http:// or ftp://) as files.  
; http://www.php.net/manual/en/filesystem.configuration.php#ini.allow-url-include  
allow_url_include = Off  
 
; Define the anonymous ftp password (your email address). PHP's default setting  
; for this is empty.  
; http://www.php.net/manual/en/filesystem.configuration.php#ini.from  
;from="john@doe.com"  
 
; Define the User-Agent string. PHP's default setting for this is empty.  
; http://www.php.net/manual/en/filesystem.configuration.php#ini.user-agent  
;user_agent="PHP"  
 
; Default timeout for socket based streams (seconds)  
; http://www.php.net/manual/en/filesystem.configuration.php#ini.default-socket-timeout  
default_socket_timeout = 60  
 
; If your scripts have to deal with files from Macintosh systems,  
; or you are running on a Mac and need to deal with files from  
; unix or win32 systems, setting this flag will cause PHP to  
; automatically detect the EOL character in those files so that  
; fgets() and file() will work regardless of the source of the file.  
; http://www.php.net/manual/en/filesystem.configuration.php#ini.auto-detect-line-endings  
;auto_detect_line_endings = Off  
 
;;;;;;;;;;;;;;;;;;;;;;  
; Dynamic Extensions ;  
;;;;;;;;;;;;;;;;;;;;;;  
 
; If you wish to have an extension loaded automatically, use the following  
; syntax:  
;  
; extension=modulename.extension  
;  
; For example  
;  
; extension=msql.so  
;  
; ... or with a path:  
;  
; extension=/path/to/extension/msql.so  
;  
; If you only provide the name of the extension, PHP will look for it in its  
; default extension directory.  
 
;;;;  
; Note: packaged extension modules are now loaded via the .ini files  
; found in the directory /etc/php.d; these are loaded by default.  
;;;;  
 
 
;;;;;;;;;;;;;;;;;;;  
; Module Settings ;  
;;;;;;;;;;;;;;;;;;;  
 
[Date]  
; Defines the default timezone used by the date functions  
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.timezone  
;date.timezone =  
 
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.default-latitude  
;date.default_latitude = 31.7667  
 
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.default-longitude  
;date.default_longitude = 35.2333  
 
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.sunrise-zenith  
;date.sunrise_zenith = 90.583333  
 
; http://www.php.net/manual/en/datetime.configuration.php#ini.date.sunset-zenith  
;date.sunset_zenith = 90.583333  
 
[filter]  
; http://www.php.net/manual/en/filter.configuration.php#ini.filter.default  
;filter.default = unsafe_raw  
 
; http://www.php.net/manual/en/filter.configuration.php#ini.filter.default-flags  
;filter.default_flags =  
 
[iconv]  
;iconv.input_encoding = ISO-8859-1  
;iconv.internal_encoding = ISO-8859-1  
;iconv.output_encoding = ISO-8859-1  
 
[intl]  
;intl.default_locale =  
 
[sqlite]  
; http://www.php.net/manual/en/sqlite.configuration.php#ini.sqlite.assoc-case  
;sqlite.assoc_case = 0  
 
[sqlite3]  
;sqlite3.extension_dir =  
 
[Pcre]  
;PCRE library backtracking limit.  
; http://www.php.net/manual/en/pcre.configuration.php#ini.pcre.backtrack-limit  
;pcre.backtrack_limit=100000  
 
;PCRE library recursion limit.  
;Please note that if you set this value to a high number you may consume all  
;the available process stack and eventually crash PHP (due to reaching the  
;stack size limit imposed by the Operating System).  
; http://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit  
;pcre.recursion_limit=100000  
 
[Pdo]  
; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off"  
; http://www.php.net/manual/en/ref.pdo-odbc.php#ini.pdo-odbc.connection-pooling  
;pdo_odbc.connection_pooling=strict  
 
[Phar]  
; http://www.php.net/manual/en/phar.configuration.php#ini.phar.readonly  
;phar.readonly = On  
 
; http://www.php.net/manual/en/phar.configuration.php#ini.phar.require-hash  
;phar.require_hash = On  
 
;phar.cache_list =  
 
[Syslog]  
; Whether or not to define the various syslog variables (e.g. $LOG_PID,  
; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In  
; runtime, you can define these variables by calling define_syslog_variables().  
; http://www.php.net/manual/en/network.configuration.php#ini.define-syslog-variables  
define_syslog_variables = Off  
 
[mail function]  
; For Win32 only.  
; http://www.php.net/manual/en/mail.configuration.php#ini.smtp  
SMTP = localhost  
; http://www.php.net/manual/en/mail.configuration.php#ini.smtp-port  
smtp_port = 25  
 
; For Win32 only.  
; http://www.php.net/manual/en/mail.configuration.php#ini.sendmail-from  
;sendmail_from = me@example.com  
 
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").  
; http://www.php.net/manual/en/mail.configuration.php#ini.sendmail-path  
sendmail_path = /usr/sbin/sendmail -t -i  
 
; Force the addition of the specified parameters to be passed as extra parameters  
; to the sendmail binary. These parameters will always replace the value of  
; the 5th parameter to mail(), even in safe mode.  
;mail.force_extra_parameters =  
 
; Add X-PHP-Originaiting-Script: that will include uid of the script followed by the filename  
mail.add_x_header = On  
 
; Log all mail() calls including the full path of the script, line #, to address and headers  
;mail.log =  
 
[SQL]  
; http://www.php.net/manual/en/ini.core.php#ini.sql.safe-mode  
sql.safe_mode = Off  
 
[ODBC]  
; http://www.php.net/manual/en/odbc.configuration.php#ini.uodbc.default-db  
;odbc.default_db = Not yet implemented  
 
; http://www.php.net/manual/en/odbc.configuration.php#ini.uodbc.default-user  
;odbc.default_user = Not yet implemented  
 
; http://www.php.net/manual/en/odbc.configuration.php#ini.uodbc.default-pw  
;odbc.default_pw = Not yet implemented  
 
; Allow or prevent persistent links.  
; http://www.php.net/manual/en/odbc.configuration.php#ini.uodbc.allow-persistent  
odbc.allow_persistent = On  
 
; Check that a connection is still valid before reuse.  
; http://www.php.net/manual/en/odbc.configuration.php#ini.uodbc.check-persistent  
odbc.check_persistent = On  
 
; Maximum number of persistent links. -1 means no limit.  
; http://www.php.net/manual/en/odbc.configuration.php#ini.uodbc.max-persistent  
odbc.max_persistent = -1  
 
; Maximum number of links (persistent + non-persistent). -1 means no limit.  
; http://www.php.net/manual/en/odbc.configuration.php#ini.uodbc.max-links  
odbc.max_links = -1  
 
; Handling of LONG fields. Returns number of bytes to variables. 0 means  
; passthru.  
; http://www.php.net/manual/en/odbc.configuration.php#ini.uodbc.defaultlrl  
odbc.defaultlrl = 4096  
 
; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char.  
; See the documentation on odbc_binmode and odbc_longreadlen for an explanation  
; of uodbc.defaultlrl and uodbc.defaultbinmode  
; http://www.php.net/manual/en/odbc.configuration.php#ini.uodbc.defaultbinmode  
odbc.defaultbinmode = 1  
 
;birdstep.max_links = -1  
 
[MySQL]  
; Allow or prevent persistent links.  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.allow-persistent  
mysql.allow_persistent = On  
 
; Maximum number of persistent links. -1 means no limit.  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.max-persistent  
mysql.max_persistent = -1  
 
; Maximum number of links (persistent + non-persistent). -1 means no limit.  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.max-links  
mysql.max_links = -1  
 
; Default port number for mysql_connect(). If unset, mysql_connect() will use  
; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the  
; compile-time value defined MYSQL_PORT (in that order). Win32 will only look  
; at MYSQL_PORT.  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.default-port  
mysql.default_port =  
 
; Default socket name for local MySQL connects. If empty, uses the built-in  
; MySQL defaults.  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.default-socket  
mysql.default_socket =  
 
; Default host for mysql_connect() (doesn't apply in safe mode).  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.default-host  
mysql.default_host =  
 
; Default user for mysql_connect() (doesn't apply in safe mode).  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.default-user  
mysql.default_user =  
 
; Default password for mysql_connect() (doesn't apply in safe mode).  
; Note that this is generally a *bad* idea to store passwords in this file.  
; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password")  
; and reveal this password! And of course, any users with read access to this  
; file will be able to reveal the password as well.  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.default-password  
mysql.default_password =  
 
; Maximum time (in seconds) for connect timeout. -1 means no limit  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.connect-timeout  
mysql.connect_timeout = 60  
 
; Trace mode. When trace_mode is active (=On), warnings for table/index scans and  
; SQL-Errors will be displayed.  
; http://www.php.net/manual/en/mysql.configuration.php#ini.mysql.trace-mode  
mysql.trace_mode = Off  
 
[MySQLi]  
 
; Maximum number of links. -1 means no limit.  
; http://www.php.net/manual/en/mysqli.configuration.php#ini.mysqli.max-links  
mysqli.max_links = -1  
 
; Default port number for mysqli_connect(). If unset, mysqli_connect() will use  
; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the  
; compile-time value defined MYSQL_PORT (in that order). Win32 will only look  
; at MYSQL_PORT.  
; http://www.php.net/manual/en/mysqli.configuration.php#ini.mysqli.default-port  
mysqli.default_port = 3306  
 
; Default socket name for local MySQL connects. If empty, uses the built-in  
; MySQL defaults.  
; http://www.php.net/manual/en/mysqli.configuration.php#ini.mysqli.default-socket  
mysqli.default_socket =  
 
; Default host for mysql_connect() (doesn't apply in safe mode).  
; http://www.php.net/manual/en/mysqli.configuration.php#ini.mysqli.default-host  
mysqli.default_host =  
 
; Default user for mysql_connect() (doesn't apply in safe mode).  
; http://www.php.net/manual/en/mysqli.configuration.php#ini.mysqli.default-user  
mysqli.default_user =  
 
; Default password for mysqli_connect() (doesn't apply in safe mode).  
; Note that this is generally a *bad* idea to store passwords in this file.  
; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw")  
; and reveal this password! And of course, any users with read access to this  
; file will be able to reveal the password as well.  
; http://www.php.net/manual/en/mysqli.configuration.php#ini.mysqli.default-pw  
mysqli.default_pw =  
 
; Allow or prevent reconnect  
mysqli.reconnect = Off  
 
[PostgresSQL]  
; Allow or prevent persistent links.  
; http://www.php.net/manual/en/pgsql.configuration.php#ini.pgsql.allow-persistent  
pgsql.allow_persistent = On  
 
; Detect broken persistent links always with pg_pconnect().  
; Auto reset feature requires a little overheads.  
; http://www.php.net/manual/en/pgsql.configuration.php#ini.pgsql.auto-reset-persistent  
pgsql.auto_reset_persistent = Off  
 
; Maximum number of persistent links. -1 means no limit.  
; http://www.php.net/manual/en/pgsql.configuration.php#ini.pgsql.max-persistent  
pgsql.max_persistent = -1  
 
; Maximum number of links (persistent+non persistent). -1 means no limit.  
; http://www.php.net/manual/en/pgsql.configuration.php#ini.pgsql.max-links  
pgsql.max_links = -1  
 
; Ignore PostgreSQL backends Notice message or not.  
; Notice message logging require a little overheads.  
; http://www.php.net/manual/en/pgsql.configuration.php#ini.pgsql.ignore-notice  
pgsql.ignore_notice = 0  
 
; Log PostgreSQL backends Noitce message or not.  
; Unless pgsql.ignore_notice=0, module cannot log notice message.  
; http://www.php.net/manual/en/pgsql.configuration.php#ini.pgsql.log-notice  
pgsql.log_notice = 0  
 
[Sybase-CT]  
; Allow or prevent persistent links.  
; http://www.php.net/manual/en/sybase.configuration.php#ini.sybct.allow-persistent  
sybct.allow_persistent = On  
 
; Maximum number of persistent links. -1 means no limit.  
; http://www.php.net/manual/en/sybase.configuration.php#ini.sybct.max-persistent  
sybct.max_persistent = -1  
 
; Maximum number of links (persistent + non-persistent). -1 means no limit.  
; http://www.php.net/manual/en/sybase.configuration.php#ini.sybct.max-links  
sybct.max_links = -1  
 
; Minimum server message severity to display.  
; http://www.php.net/manual/en/sybase.configuration.php#ini.sybct.min-server-severity  
sybct.min_server_severity = 10  
 
; Minimum client message severity to display.  
; http://www.php.net/manual/en/sybase.configuration.php#ini.sybct.min-client-severity  
sybct.min_client_severity = 10  
 
; Set per-context timeout  
; http://www.php.net/manual/en/sybase.configuration.php#ini.sybct.timeout  
;sybct.timeout=  
 
;sybct.packet_size  
 
[bcmath]  
; Number of decimal digits for all bcmath functions.  
; http://www.php.net/manual/en/bc.configuration.php#ini.bcmath.scale  
bcmath.scale = 0  
 
[browscap]  
; http://www.php.net/manual/en/misc.configuration.php#ini.browscap  
;browscap = extra/browscap.ini  
 
[Session]  
; Handler used to store/retrieve data.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.save-handler  
session.save_handler = files  
 
; Argument passed to save_handler. In the case of files, this is the path  
; where data files are stored. Note: Windows users have to change this  
; variable in order to use PHP's session functions.  
;  
; As of PHP 4.0.1, you can define the path as:  
;  
; session.save_path = "N;/path"  
;  
; where N is an integer. Instead of storing all the session files in  
; /path, what this will do is use subdirectories N-levels deep, and  
; store the session data in those directories. This is useful if you  
; or your OS have problems with lots of files in one directory, and is  
; a more efficient layout for servers that handle lots of sessions.  
;  
; NOTE 1: PHP will not create this directory structure automatically.  
; You can use the script in the ext/session dir for that purpose.  
; NOTE 2: See the section on garbage collection below if you choose to  
; use subdirectories for session storage  
;  
; The file storage module creates files using mode 600 by default.  
; You can change that by using  
;  
; session.save_path = "N;MODE;/path"  
;  
; where MODE is the octal representation of the mode. Note that this  
; does not overwrite the process's umask.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.save-path  
session.save_path = "/tmp"  
 
; Whether to use cookies.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.use-cookies  
session.use_cookies = 1  
 
; http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-secure  
;session.cookie_secure =  
 
; This option forces PHP to fetch and use a cookie for storing and maintaining  
; the session id. We encourage this operation as it's very helpful in combatting  
; session hijacking when not specifying and managing your own session id. It is  
; not the end all be all of session hijacking defense, but it's a good start.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.use-only-cookies  
session.use_only_cookies = 1  
 
; Name of the session (used as cookie name).  
; http://www.php.net/manual/en/session.configuration.php#ini.session.name  
session.name = PHPSESSID  
 
; Initialize session on request startup.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.auto-start  
session.auto_start = 0  
 
; Lifetime in seconds of cookie or, if 0, until browser is restarted.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime  
session.cookie_lifetime = 0  
 
; The path for which the cookie is valid.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-path  
session.cookie_path = /  
 
; The domain for which the cookie is valid.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-domain  
session.cookie_domain =  
 
; Whether or not to add the httpOnly flag to the cookie, which makes it inaccessible to browser scripting languages such as JavaScript.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-httponly  
session.cookie_httponly =  
 
; Handler used to serialize data. php is the standard serializer of PHP.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.serialize-handler  
session.serialize_handler = php  
 
; Defines the probability that the 'garbage collection' process is started  
; on every session initialization. The probability is calculated by using  
; gc_probability/gc_divisor. Where session.gc_probability is the numerator  
; and gc_divisor is the denominator in the equation. Setting this value to 1  
; when the session.gc_divisor value is 100 will give you approximately a 1% chance  
; the gc will run on any give request.  
; Default Value: 1  
; Development Value: 1  
; Production Value: 1  
; http://www.php.net/manual/en/session.configuration.php#ini.session.gc-probability  
session.gc_probability = 1  
 
; Defines the probability that the 'garbage collection' process is started on every  
; session initialization. The probability is calculated by using the following equation:  
; gc_probability/gc_divisor. Where session.gc_probability is the numerator and  
; session.gc_divisor is the denominator in the equation. Setting this value to 1  
; when the session.gc_divisor value is 100 will give you approximately a 1% chance  
; the gc will run on any give request. Increasing this value to 1000 will give you  
; a 0.1% chance the gc will run on any give request. For high volume production servers,  
; this is a more efficient approach.  
; Default Value: 100  
; Development Value: 1000  
; Production Value: 1000  
; http://www.php.net/manual/en/session.configuration.php#ini.session.gc-divisor  
session.gc_divisor = 1000  
 
; After this number of seconds, stored data will be seen as 'garbage' and  
; cleaned up by the garbage collection process.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime  
session.gc_maxlifetime = 1440  
 
; NOTE: If you are using the subdirectory option for storing session files  
; (see session.save_path above), then garbage collection does *not*  
; happen automatically. You will need to do your own garbage  
; collection through a shell script, cron entry, or some other method.  
; For example, the following script would is the equivalent of  
; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes):  
; cd /path/to/sessions; find -cmin +24 | xargs rm  
 
; PHP 4.2 and less have an undocumented feature/bug that allows you to  
; to initialize a session variable in the global scope, even when register_globals  
; is disabled. PHP 4.3 and later will warn you, if this feature is used.  
; You can disable the feature and the warning separately. At this time,  
; the warning is only displayed, if bug_compat_42 is enabled. This feature  
; introduces some serious security problems if not handled correctly. It's  
; recommended that you do not use this feature on production servers. But you  
; should enable this on development servers and enable the warning as well. If you  
; do not enable the feature on development servers, you won't be warned when it's  
; used and debugging errors caused by this can be difficult to track down.  
; Default Value: On  
; Development Value: On  
; Production Value: Off  
; http://www.php.net/manual/en/session.configuration.php#ini.session.bug-compat-42  
session.bug_compat_42 = Off  
 
; This setting controls whether or not you are warned by PHP when initializing a  
; session value into the global space. session.bug_compat_42 must be enabled before  
; these warnings can be issued by PHP. See the directive above for more information.  
; Default Value: On  
; Development Value: On  
; Production Value: Off  
; http://www.php.net/manual/en/session.configuration.php#ini.session.bug-compat-warn  
session.bug_compat_warn = Off  
 
; Check HTTP Referer to invalidate externally stored URLs containing ids.  
; HTTP_REFERER has to contain this substring for the session to be  
; considered as valid.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.referer-check  
session.referer_check =  
 
; How many bytes to read from the file.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.entropy-length  
session.entropy_length = 0  
 
; Specified here to create the session id.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.entropy-file  
;session.entropy_file = /dev/urandom  
session.entropy_file =  
 
; http://www.php.net/manual/en/session.configuration.php#ini.session.entropy-length  
;session.entropy_length = 16  
 
; Set to {nocache,private,public,} to determine HTTP caching aspects  
; or leave this empty to avoid sending anti-caching headers.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.cache-limiter  
session.cache_limiter = nocache  
 
; Document expires after n minutes.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.cache-expire  
session.cache_expire = 180  
 
; trans sid support is disabled by default.  
; Use of trans sid may risk your users security.  
; Use this option with caution.  
; - User may send URL contains active session ID  
; to other person via. email/irc/etc.  
; - URL that contains active session ID may be stored  
; in publically accessible computer.  
; - User may access your site with the same session ID  
; always using URL stored in browser's history or bookmarks.  
; http://www.php.net/manual/en/session.configuration.php#ini.session.use-trans-sid  
session.use_trans_sid = 0  
 
; Select a hash function for use in generating session ids.  
; Possible Values  
; 0 (MD5 128 bits)  
; 1 (SHA-1 160 bits)  
; http://www.php.net/manual/en/session.configuration.php#ini.session.hash-function  
session.hash_function = 0  
 
; Define how many bits are stored in each character when converting  
; the binary hash data to something readable.  
; Possible values:  
; 4 (4 bits: 0-9, a-f)  
; 5 (5 bits: 0-9, a-v)  
; 6 (6 bits: 0-9, a-z, A-Z, "-", ",")  
; Default Value: 4  
; Development Value: 5  
; Production Value: 5  
; http://www.php.net/manual/en/session.configuration.php#ini.session.hash-bits-per-character  
session.hash_bits_per_character = 5  
 
; The URL rewriter will look for URLs in a defined set of HTML tags.  
; form/fieldset are special; if you include them here, the rewriter will  
; add a hidden <input> field with the info which is otherwise appended  
; to URLs. If you want XHTML conformity, remove the form entry.  
; Note that all valid entries require a "=", even if no value follows.  
; Default Value: "a=href,area=href,frame=src,form=,fieldset="  
; Development Value: "a=href,area=href,frame=src,input=src,form=fakeentry"  
; Production Value: "a=href,area=href,frame=src,input=src,form=fakeentry"  
; http://www.php.net/manual/en/session.configuration.php#ini.url-rewriter.tags  
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"  
 
[MSSQL]  
; Allow or prevent persistent links.  
mssql.allow_persistent = On  
 
; Maximum number of persistent links. -1 means no limit.  
mssql.max_persistent = -1  
 
; Maximum number of links (persistent+non persistent). -1 means no limit.  
mssql.max_links = -1  
 
; Minimum error severity to display.  
mssql.min_error_severity = 10  
 
; Minimum message severity to display.  
mssql.min_message_severity = 10  
 
; Compatibility mode with old versions of PHP 3.0.  
mssql.compatability_mode = Off  
 
; Connect timeout  
;mssql.connect_timeout = 5  
 
; Query timeout  
;mssql.timeout = 60  
 
; Valid range 0 - 2147483647. Default = 4096.  
;mssql.textlimit = 4096  
 
; Valid range 0 - 2147483647. Default = 4096.  
;mssql.textsize = 4096  
 
; Limits the number of records in each batch. 0 = all records in one batch.  
;mssql.batchsize = 0  
 
; Specify how datetime and datetim4 columns are returned  
; On => Returns data converted to SQL server settings  
; Off => Returns values as YYYY-MM-DD hh:mm:ss  
;mssql.datetimeconvert = On  
 
; Use NT authentication when connecting to the server  
mssql.secure_connection = Off  
 
; Specify max number of processes. -1 = library default  
; msdlib defaults to 25  
; FreeTDS defaults to 4096  
;mssql.max_procs = -1  
 
; Specify client character set.  
; If empty or not set the client charset from freetds.comf is used  
; This is only used when compiled with FreeTDS  
;mssql.charset = "ISO-8859-1"  
 
[Assertion]  
; Assert(expr); active by default.  
; http://www.php.net/manual/en/info.configuration.php#ini.assert.active  
;assert.active = On  
 
; Issue a PHP warning for each failed assertion.  
; http://www.php.net/manual/en/info.configuration.php#ini.assert.warning  
;assert.warning = On  
 
; Don't bail out by default.  
; http://www.php.net/manual/en/info.configuration.php#ini.assert.bail  
;assert.bail = Off  
 
; User-function to be called if an assertion fails.  
; http://www.php.net/manual/en/info.configuration.php#ini.assert.callback  
;assert.callback = 0  
 
; Eval the expression with current error_reporting(). Set to true if you want  
; error_reporting(0) around the eval().  
; http://www.php.net/manual/en/info.configuration.php#ini.assert.quiet-eval  
;assert.quiet_eval = 0  
 
[COM]  
; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs  
; http://www.php.net/manual/en/com.configuration.php#ini.com.typelib-file  
;com.typelib_file =  
 
; allow Distributed-COM calls  
; http://www.php.net/manual/en/com.configuration.php#ini.com.allow-dcom  
;com.allow_dcom = true  
 
; autoregister constants of a components typlib on com_load()  
; http://www.php.net/manual/en/com.configuration.php#ini.com.autoregister-typelib  
;com.autoregister_typelib = true  
 
; register constants casesensitive  
; http://www.php.net/manual/en/com.configuration.php#ini.com.autoregister-casesensitive  
;com.autoregister_casesensitive = false  
 
; show warnings on duplicate constant registrations  
; http://www.php.net/manual/en/com.configuration.php#ini.com.autoregister-verbose  
;com.autoregister_verbose = true  
 
[mbstring]  
; language for internal character representation.  
; http://www.php.net/manual/en/mbstring.configuration.php#ini.mbstring.language  
;mbstring.language = Japanese  
 
; internal/script encoding.  
; Some encoding cannot work as internal encoding.  
; (e.g. SJIS, BIG5, ISO-2022-*)  
; http://www.php.net/manual/en/mbstring.configuration.php#ini.mbstring.internal-encoding  
;mbstring.internal_encoding = EUC-JP  
 
; http input encoding.  
; http://www.php.net/manual/en/mbstring.configuration.php#ini.mbstring.http-input  
;mbstring.http_input = auto  
 
; http output encoding. mb_output_handler must be  
; registered as output buffer to function  
; http://www.php.net/manual/en/mbstring.configuration.php#ini.mbstring.http-output  
;mbstring.http_output = SJIS  
 
; enable automatic encoding translation according to  
; mbstring.internal_encoding setting. Input chars are  
; converted to internal encoding by setting this to On.  
; Note: Do _not_ use automatic encoding translation for  
; portable libs/applications.  
; http://www.php.net/manual/en/mbstring.configuration.php#ini.mbstring.encoding-translation  
;mbstring.encoding_translation = Off  
 
; automatic encoding detection order.  
; auto means  
; http://www.php.net/manual/en/mbstring.configuration.php#ini.mbstring.detect-order  
;mbstring.detect_order = auto  
 
; substitute_character used when character cannot be converted  
; one from another  
; http://www.php.net/manual/en/mbstring.configuration.php#ini.mbstring.substitute-character  
;mbstring.substitute_character = none;  
 
; overload(replace) single byte functions by mbstring functions.  
; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(),  
; etc. Possible values are 0,1,2,4 or combination of them.  
; For example, 7 for overload everything.  
; 0: No overload  
; 1: Overload mail() function  
; 2: Overload str*() functions  
; 4: Overload ereg*() functions  
; http://www.php.net/manual/en/mbstring.configuration.php#ini.mbstring.func-overload  
;mbstring.func_overload = 0  
 
; enable strict encoding detection.  
;mbstring.strict_detection = Off  
 
; This directive specifies the regex pattern of content types for which mb_output_handler()  
; is activated.  
; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml)  
;mbstring.http_output_conv_mimetype=  
 
[gd]  
; Tell the jpeg decode to ignore warnings and try to create  
; a gd image. The warning will then be displayed as notices  
; disabled by default  
; http://www.php.net/manual/en/image.configuration.php#ini.image.jpeg-ignore-warning  
;gd.jpeg_ignore_warning = 0  
 
[exif]  
; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS.  
; With mbstring support this will automatically be converted into the encoding  
; given by corresponding encode setting. When empty mbstring.internal_encoding  
; is used. For the decode settings you can distinguish between motorola and  
; intel byte order. A decode setting cannot be empty.  
; http://www.php.net/manual/en/exif.configuration.php#ini.exif.encode-unicode  
;exif.encode_unicode = ISO-8859-15  
 
; http://www.php.net/manual/en/exif.configuration.php#ini.exif.decode-unicode-motorola  
;exif.decode_unicode_motorola = UCS-2BE  
 
; http://www.php.net/manual/en/exif.configuration.php#ini.exif.decode-unicode-intel  
;exif.decode_unicode_intel = UCS-2LE  
 
; http://www.php.net/manual/en/exif.configuration.php#ini.exif.encode-jis  
;exif.encode_jis =  
 
; http://www.php.net/manual/en/exif.configuration.php#ini.exif.decode-jis-motorola  
;exif.decode_jis_motorola = JIS  
 
; http://www.php.net/manual/en/exif.configuration.php#ini.exif.decode-jis-intel  
;exif.decode_jis_intel = JIS  
 
[Tidy]  
; The path to a default tidy configuration file to use when using tidy  
; http://www.php.net/manual/en/tidy.configuration.php#ini.tidy.default-config  
;tidy.default_config = /usr/local/lib/php/default.tcfg  
 
; Should tidy clean and repair output automatically?  
; WARNING: Do not use this option if you are generating non-html content  
; such as dynamic images  
; http://www.php.net/manual/en/tidy.configuration.php#ini.tidy.clean-output  
tidy.clean_output = Off  
 
[soap]  
; Enables or disables WSDL caching feature.  
; http://www.php.net/manual/en/soap.configuration.php#ini.soap.wsdl-cache-enabled  
soap.wsdl_cache_enabled=1  
 
; Sets the directory name where SOAP extension will put cache files.  
; http://www.php.net/manual/en/soap.configuration.php#ini.soap.wsdl-cache-dir  
soap.wsdl_cache_dir="/tmp"  
 
; (time to live) Sets the number of second while cached file will be used  
; instead of original one.  
; http://www.php.net/manual/en/soap.configuration.php#ini.soap.wsdl-cache-ttl  
soap.wsdl_cache_ttl=86400  
 
[sysvshm]  
; A default size of the shared memory segment  
;sysvshm.init_mem = 10000  
 
 
; Local Variables:  
; tab-width: 4  
; End:  
 
file:a/aws/postgresql.conf (deleted)
# -----------------------------  
# PostgreSQL configuration file  
# -----------------------------  
#  
# This file consists of lines of the form:  
#  
# name = value  
#  
# (The "=" is optional.) Whitespace may be used. Comments are introduced with  
# "#" anywhere on a line. The complete list of parameter names and allowed  
# values can be found in the PostgreSQL documentation.  
#  
# The commented-out settings shown in this file represent the default values.  
# Re-commenting a setting is NOT sufficient to revert it to the default value;  
# you need to reload the server.  
#  
# This file is read on server startup and when the server receives a SIGHUP  
# signal. If you edit the file on a running system, you have to SIGHUP the  
# server for the changes to take effect, or use "pg_ctl reload". Some  
# parameters, which are marked below, require a server shutdown and restart to  
# take effect.  
#  
# Any parameter can also be given as a command-line option to the server, e.g.,  
# "postgres -c log_connections=on". Some parameters can be changed at run time  
# with the "SET" SQL command.  
#  
# Memory units: kB = kilobytes Time units: ms = milliseconds  
# MB = megabytes s = seconds  
# GB = gigabytes min = minutes  
# h = hours  
# d = days  
 
 
#------------------------------------------------------------------------------  
# FILE LOCATIONS  
#------------------------------------------------------------------------------  
 
# The default values of these variables are driven from the -D command-line  
# option or PGDATA environment variable, represented here as ConfigDir.  
 
#data_directory = 'ConfigDir' # use data in another directory  
# (change requires restart)  
#hba_file = 'ConfigDir/pg_hba.conf' # host-based authentication file  
# (change requires restart)  
#ident_file = 'ConfigDir/pg_ident.conf' # ident configuration file  
# (change requires restart)  
 
# If external_pid_file is not explicitly set, no extra PID file is written.  
#external_pid_file = '(none)' # write an extra PID file  
# (change requires restart)  
 
 
#------------------------------------------------------------------------------  
# CONNECTIONS AND AUTHENTICATION  
#------------------------------------------------------------------------------  
 
# - Connection Settings -  
 
listen_addresses = '*' # what IP address(es) to listen on;  
# comma-separated list of addresses;  
# defaults to 'localhost', '*' = all  
# (change requires restart)  
#port = 5432 # (change requires restart)  
max_connections = 100 # (change requires restart)  
# Note: Increasing max_connections costs ~400 bytes of shared memory per  
# connection slot, plus lock space (see max_locks_per_transaction).  
#superuser_reserved_connections = 3 # (change requires restart)  
#unix_socket_directory = '' # (change requires restart)  
#unix_socket_group = '' # (change requires restart)  
#unix_socket_permissions = 0777 # begin with 0 to use octal notation  
# (change requires restart)  
#bonjour_name = '' # defaults to the computer name  
# (change requires restart)  
 
# - Security and Authentication -  
 
#authentication_timeout = 1min # 1s-600s  
#ssl = off # (change requires restart)  
#ssl_ciphers = 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH' # allowed SSL ciphers  
# (change requires restart)  
#ssl_renegotiation_limit = 512MB # amount of data between renegotiations  
#password_encryption = on  
#db_user_namespace = off  
 
# Kerberos and GSSAPI  
#krb_server_keyfile = ''  
#krb_srvname = 'postgres' # (Kerberos only)  
#krb_caseins_users = off  
 
# - TCP Keepalives -  
# see "man 7 tcp" for details  
 
#tcp_keepalives_idle = 0 # TCP_KEEPIDLE, in seconds;  
# 0 selects the system default  
#tcp_keepalives_interval = 0 # TCP_KEEPINTVL, in seconds;  
# 0 selects the system default  
#tcp_keepalives_count = 0 # TCP_KEEPCNT;  
# 0 selects the system default  
 
 
#------------------------------------------------------------------------------  
# RESOURCE USAGE (except WAL)  
#------------------------------------------------------------------------------  
 
# - Memory -  
 
shared_buffers = 32MB # min 128kB  
# (change requires restart)  
#temp_buffers = 8MB # min 800kB  
#max_prepared_transactions = 0 # zero disables the feature  
# (change requires restart)  
# Note: Increasing max_prepared_transactions costs ~600 bytes of shared memory  
# per transaction slot, plus lock space (see max_locks_per_transaction).  
# It is not advisable to set max_prepared_transactions nonzero unless you  
# actively intend to use prepared transactions.  
#work_mem = 1MB # min 64kB  
#maintenance_work_mem = 16MB # min 1MB  
#max_stack_depth = 2MB # min 100kB  
 
# - Kernel Resource Usage -  
 
#max_files_per_process = 1000 # min 25  
# (change requires restart)  
#shared_preload_libraries = '' # (change requires restart)  
 
# - Cost-Based Vacuum Delay -  
 
#vacuum_cost_delay = 0ms # 0-100 milliseconds  
#vacuum_cost_page_hit = 1 # 0-10000 credits  
#vacuum_cost_page_miss = 10 # 0-10000 credits  
#vacuum_cost_page_dirty = 20 # 0-10000 credits  
#vacuum_cost_limit = 200 # 1-10000 credits  
 
# - Background Writer -  
 
#bgwriter_delay = 200ms # 10-10000ms between rounds  
#bgwriter_lru_maxpages = 100 # 0-1000 max buffers written/round  
#bgwriter_lru_multiplier = 2.0 # 0-10.0 multipler on buffers scanned/round  
 
# - Asynchronous Behavior -  
 
#effective_io_concurrency = 1 # 1-1000. 0 disables prefetching  
 
 
#------------------------------------------------------------------------------  
# WRITE AHEAD LOG  
#------------------------------------------------------------------------------  
 
# - Settings -  
 
#fsync = on # turns forced synchronization on or off  
#synchronous_commit = on # immediate fsync at commit  
#wal_sync_method = fsync # the default is the first option  
# supported by the operating system:  
# open_datasync  
# fdatasync  
# fsync  
# fsync_writethrough  
# open_sync  
#full_page_writes = on # recover from partial page writes  
#wal_buffers = 64kB # min 32kB  
# (change requires restart)  
#wal_writer_delay = 200ms # 1-10000 milliseconds  
 
#commit_delay = 0 # range 0-100000, in microseconds  
#commit_siblings = 5 # range 1-1000  
 
# - Checkpoints -  
 
#checkpoint_segments = 3 # in logfile segments, min 1, 16MB each  
#checkpoint_timeout = 5min # range 30s-1h  
#checkpoint_completion_target = 0.5 # checkpoint target duration, 0.0 - 1.0  
#checkpoint_warning = 30s # 0 disables  
 
# - Archiving -  
 
#archive_mode = off # allows archiving to be done  
# (change requires restart)  
#archive_command = '' # command to use to archive a logfile segment  
#archive_timeout = 0 # force a logfile segment switch after this  
# number of seconds; 0 disables  
 
 
#------------------------------------------------------------------------------  
# QUERY TUNING  
#------------------------------------------------------------------------------  
 
# - Planner Method Configuration -  
 
#enable_bitmapscan = on  
#enable_hashagg = on  
#enable_hashjoin = on  
#enable_indexscan = on  
#enable_mergejoin = on  
#enable_nestloop = on  
#enable_seqscan = on  
#enable_sort = on  
#enable_tidscan = on  
 
# - Planner Cost Constants -  
 
#seq_page_cost = 1.0 # measured on an arbitrary scale  
#random_page_cost = 4.0 # same scale as above  
#cpu_tuple_cost = 0.01 # same scale as above  
#cpu_index_tuple_cost = 0.005 # same scale as above  
#cpu_operator_cost = 0.0025 # same scale as above  
#effective_cache_size = 128MB  
 
# - Genetic Query Optimizer -  
 
#geqo = on  
#geqo_threshold = 12  
#geqo_effort = 5 # range 1-10  
#geqo_pool_size = 0 # selects default based on effort  
#geqo_generations = 0 # selects default based on effort  
#geqo_selection_bias = 2.0 # range 1.5-2.0  
 
# - Other Planner Options -  
 
#default_statistics_target = 100 # range 1-10000  
#constraint_exclusion = partition # on, off, or partition  
#cursor_tuple_fraction = 0.1 # range 0.0-1.0  
#from_collapse_limit = 8  
#join_collapse_limit = 8 # 1 disables collapsing of explicit  
# JOIN clauses  
 
 
#------------------------------------------------------------------------------  
# ERROR REPORTING AND LOGGING  
#------------------------------------------------------------------------------  
 
# - Where to Log -  
 
#log_destination = 'stderr' # Valid values are combinations of  
# stderr, csvlog, syslog and eventlog,  
# depending on platform. csvlog  
# requires logging_collector to be on.  
 
# This is used when logging to stderr:  
logging_collector = on # Enable capturing of stderr and csvlog  
# into log files. Required to be on for  
# csvlogs.  
# (change requires restart)  
 
# These are only used if logging_collector is on:  
log_directory = 'pg_log' # directory where log files are written,  
# can be absolute or relative to PGDATA  
log_filename = 'postgresql-%a.log' # log file name pattern,  
# can include strftime() escapes  
log_truncate_on_rotation = on # If on, an existing log file of the  
# same name as the new log file will be  
# truncated rather than appended to.  
# But such truncation only occurs on  
# time-driven rotation, not on restarts  
# or size-driven rotation. Default is  
# off, meaning append to existing files  
# in all cases.  
log_rotation_age = 1d # Automatic rotation of logfiles will  
# happen after that time. 0 disables.  
log_rotation_size = 0 # Automatic rotation of logfiles will  
# happen after that much log output.  
# 0 disables.  
 
# These are relevant when logging to syslog:  
#syslog_facility = 'LOCAL0'  
#syslog_ident = 'postgres'  
 
#silent_mode = off # Run server silently.  
# DO NOT USE without syslog or  
# logging_collector  
# (change requires restart)  
 
 
# - When to Log -  
 
#client_min_messages = notice # values in order of decreasing detail:  
# debug5  
# debug4  
# debug3  
# debug2  
# debug1  
# log  
# notice  
# warning  
# error  
 
#log_min_messages = warning # values in order of decreasing detail:  
# debug5  
# debug4  
# debug3  
# debug2  
# debug1  
# info  
# notice  
# warning  
# error  
# log  
# fatal  
# panic  
 
#log_error_verbosity = default # terse, default, or verbose messages  
 
#log_min_error_statement = error # values in order of decreasing detail:  
# debug5  
# debug4  
# debug3  
# debug2  
# debug1  
# info  
# notice  
# warning  
# error  
# log  
# fatal  
# panic (effectively off)  
 
#log_min_duration_statement = -1 # -1 is disabled, 0 logs all statements  
# and their durations, > 0 logs only  
# statements running at least this number  
# of milliseconds  
 
 
# - What to Log -  
 
#debug_print_parse = off  
#debug_print_rewritten = off  
#debug_print_plan = off  
#debug_pretty_print = on  
#log_checkpoints = off  
#log_connections = off  
#log_disconnections = off  
#log_duration = off  
#log_hostname = off  
#log_line_prefix = '' # special values:  
# %u = user name  
# %d = database name  
# %r = remote host and port  
# %h = remote host  
# %p = process ID  
# %t = timestamp without milliseconds  
# %m = timestamp with milliseconds  
# %i = command tag  
# %c = session ID  
# %l = session line number  
# %s = session start timestamp  
# %v = virtual transaction ID  
# %x = transaction ID (0 if none)  
# %q = stop here in non-session  
# processes  
# %% = '%'  
# e.g. '<%u%%%d> '  
#log_lock_waits = off # log lock waits >= deadlock_timeout  
#log_statement = 'none' # none, ddl, mod, all  
#log_temp_files = -1 # log temporary files equal or larger  
# than the specified size in kilobytes;  
# -1 disables, 0 logs all temp files  
#log_timezone = unknown # actually, defaults to TZ environment  
# setting  
 
 
#------------------------------------------------------------------------------  
# RUNTIME STATISTICS  
#------------------------------------------------------------------------------  
 
# - Query/Index Statistics Collector -  
 
#track_activities = on  
#track_counts = on  
#track_functions = none # none, pl, all  
#track_activity_query_size = 1024  
#update_process_title = on  
#stats_temp_directory = 'pg_stat_tmp'  
 
 
# - Statistics Monitoring -  
 
#log_parser_stats = off  
#log_planner_stats = off  
#log_executor_stats = off  
#log_statement_stats = off  
 
 
#------------------------------------------------------------------------------  
# AUTOVACUUM PARAMETERS  
#------------------------------------------------------------------------------  
 
#autovacuum = on # Enable autovacuum subprocess? 'on'  
# requires track_counts to also be on.  
#log_autovacuum_min_duration = -1 # -1 disables, 0 logs all actions and  
# their durations, > 0 logs only  
# actions running at least this number  
# of milliseconds.  
#autovacuum_max_workers = 3 # max number of autovacuum subprocesses  
#autovacuum_naptime = 1min # time between autovacuum runs  
#autovacuum_vacuum_threshold = 50 # min number of row updates before  
# vacuum  
#autovacuum_analyze_threshold = 50 # min number of row updates before  
# analyze  
#autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum  
#autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze  
#autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum  
# (change requires restart)  
#autovacuum_vacuum_cost_delay = 20ms # default vacuum cost delay for  
# autovacuum, in milliseconds;  
# -1 means use vacuum_cost_delay  
#autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for  
# autovacuum, -1 means use  
# vacuum_cost_limit  
 
 
#------------------------------------------------------------------------------  
# CLIENT CONNECTION DEFAULTS  
#------------------------------------------------------------------------------  
 
# - Statement Behavior -  
 
#search_path = '"$user",public' # schema names  
#default_tablespace = '' # a tablespace name, '' uses the default  
#temp_tablespaces = '' # a list of tablespace names, '' uses  
# only default tablespace  
#check_function_bodies = on  
#default_transaction_isolation = 'read committed'  
#default_transaction_read_only = off  
#session_replication_role = 'origin'  
#statement_timeout = 0 # in milliseconds, 0 is disabled  
#vacuum_freeze_min_age = 50000000  
#vacuum_freeze_table_age = 150000000  
#xmlbinary = 'base64'  
#xmloption = 'content'  
 
# - Locale and Formatting -  
 
datestyle = 'iso, mdy'  
#intervalstyle = 'postgres'  
#timezone = unknown # actually, defaults to TZ environment  
# setting  
#timezone_abbreviations = 'Default' # Select the set of available time zone  
# abbreviations. Currently, there are  
# Default  
# Australia  
# India  
# You can create your own file in  
# share/timezonesets/.  
#extra_float_digits = 0 # min -15, max 2  
#client_encoding = sql_ascii # actually, defaults to database  
# encoding  
 
# These settings are initialized by initdb, but they can be changed.  
lc_messages = 'en_US.UTF-8' # locale for system error message  
# strings  
lc_monetary = 'en_US.UTF-8' # locale for monetary formatting  
lc_numeric = 'en_US.UTF-8' # locale for number formatting  
lc_time = 'en_US.UTF-8' # locale for time formatting  
 
# default configuration for text search  
default_text_search_config = 'pg_catalog.english'  
 
# - Other Defaults -  
 
#dynamic_library_path = '$libdir'  
#local_preload_libraries = ''  
 
 
#------------------------------------------------------------------------------  
# LOCK MANAGEMENT  
#------------------------------------------------------------------------------  
 
#deadlock_timeout = 1s  
#max_locks_per_transaction = 64 # min 10  
# (change requires restart)  
# Note: Each lock table slot uses ~270 bytes of shared memory, and there are  
# max_locks_per_transaction * (max_connections + max_prepared_transactions)  
# lock table slots.  
 
 
#------------------------------------------------------------------------------  
# VERSION/PLATFORM COMPATIBILITY  
#------------------------------------------------------------------------------  
 
# - Previous PostgreSQL Versions -  
 
#add_missing_from = off  
#array_nulls = on  
#backslash_quote = safe_encoding # on, off, or safe_encoding  
#default_with_oids = off  
#escape_string_warning = on  
#regex_flavor = advanced # advanced, extended, or basic  
#sql_inheritance = on  
#standard_conforming_strings = off  
#synchronize_seqscans = on  
 
# - Other Platforms and Clients -  
 
#transform_null_equals = off  
 
 
#------------------------------------------------------------------------------  
# CUSTOMIZED OPTIONS  
#------------------------------------------------------------------------------  
 
#custom_variable_classes = '' # list of custom variable class names  
 
file:a/aws/rc.local (deleted)
#!/bin/sh  
#  
# This script will be executed *after* all the other init scripts.  
# You can put your own initialization stuff in here if you don't  
# want to do the full Sys V style init stuff.  
 
touch /var/lock/subsys/local  
cd /tmp  
rm -rfv busui  
git clone http://maxious.lambdacomplex.org/busui/git  
sh busui/aws/awsStartup.sh  
 
 
 
/* /*
* jQuery UI CSS Framework 1.8.12 * jQuery UI CSS Framework 1.8.12
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Theming/API * http://docs.jquery.com/UI/Theming/API
*/ */
   
/* Layout helpers /* Layout helpers
----------------------------------*/ ----------------------------------*/
.ui-helper-hidden { display: none; } .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-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-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:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; } .ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/ /* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; } * html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; } .ui-helper-clearfix { display:block; }
/* end clearfix */ /* end clearfix */
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
   
   
/* Interaction Cues /* Interaction Cues
----------------------------------*/ ----------------------------------*/
.ui-state-disabled { cursor: default !important; } .ui-state-disabled { cursor: default !important; }
   
   
/* Icons /* Icons
----------------------------------*/ ----------------------------------*/
   
/* states and images */ /* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } .jqui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
   
   
/* Misc visuals /* Misc visuals
----------------------------------*/ ----------------------------------*/
   
/* Overlays */ /* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
   
   
/* /*
* jQuery UI CSS Framework 1.8.12 * jQuery UI CSS Framework 1.8.12
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Theming/API * http://docs.jquery.com/UI/Theming/API
* *
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS,%20Tahoma,%20Verdana,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=03_highlight_soft.png&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=08_diagonals_thick.png&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=08_diagonals_thick.png&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
*/ */
   
   
/* Component containers /* Component containers
----------------------------------*/ ----------------------------------*/
.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; } .ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; } .ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; } .ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
.ui-widget-content a { color: #333333; } .ui-widget-content a { color: #333333; }
.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } .ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
.ui-widget-header a { color: #ffffff; } .ui-widget-header a { color: #ffffff; }
   
/* Interaction states /* Interaction states
----------------------------------*/ ----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; } .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; } .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; 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 #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; } .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 #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; }
.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; } .ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; } .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; } .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; }
.ui-widget :active { outline: none; } .ui-widget :active { outline: none; }
   
/* Interaction Cues /* Interaction Cues
----------------------------------*/ ----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; } .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top 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-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: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; } .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; } .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; } .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } .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-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; } .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 /* Icons
----------------------------------*/ ----------------------------------*/
   
/* states and images */ /* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } .jqui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); } .ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); } .ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); } .ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); } .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); } .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
   
/* positioning */ /* positioning */
.ui-icon-carat-1-n { background-position: 0 0; } .ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; } .ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; } .ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; } .ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; } .ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; } .ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; } .ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; } .ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; } .ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; } .ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; } .ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; } .ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; } .ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; } .ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; } .ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; } .ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; } .ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; } .ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; } .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; } .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; } .ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; } .ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; } .ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; } .ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; } .ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; } .ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; } .ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; } .ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -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-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; } .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; } .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; } .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; } .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; } .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; } .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; } .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; } .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; } .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; } .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -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-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; } .ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; } .ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; } .ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; } .ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; } .ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; } .ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; } .ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; } .ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; } .ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; } .ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; } .ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; } .ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; } .ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; } .ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; } .ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; } .ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; } .ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; } .ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; } .ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; } .ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; } .ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; } .ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; } .ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; } .ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; } .ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; } .ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; } .ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; } .ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; } .ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; } .ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; } .ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; } .ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; } .ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; } .ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; } .ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; } .ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; } .ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; } .ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; } .ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; } .ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; } .ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; } .ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; } .ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; } .ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; } .ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; } .ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; } .ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; } .ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; } .ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; } .ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; } .ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; } .ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; } .ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; } .ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; } .ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; } .ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; } .ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; } .ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; } .ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; } .ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; } .ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; } .ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; } .ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; } .ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; } .ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; } .ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; } .ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; } .ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; } .ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; } .ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; } .ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -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 is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; } .ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; } .ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; } .ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; } .ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; } .ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; } .ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; } .ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; } .ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; } .ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; } .ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; } .ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; } .ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; } .ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; } .ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; } .ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; } .ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; } .ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; } .ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; } .ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; } .ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; } .ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; } .ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; } .ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; } .ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; } .ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; } .ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; } .ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; } .ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; } .ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; } .ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; } .ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; } .ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; } .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; } .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
   
   
/* Misc visuals /* Misc visuals
----------------------------------*/ ----------------------------------*/
   
/* Corner radius */ /* Corner radius */
.ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; } .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-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-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-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-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-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-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-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; } .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
   
/* Overlays */ /* Overlays */
.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); } .ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/* .ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/*
* jQuery UI Autocomplete 1.8.12 * jQuery UI Autocomplete 1.8.12
* *
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Autocomplete#theming * http://docs.jquery.com/UI/Autocomplete#theming
*/ */
.ui-autocomplete { position: absolute; cursor: default; } .ui-autocomplete { position: absolute; cursor: default; }
   
/* workarounds */ /* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ * html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
   
/* /*
* jQuery UI Menu 1.8.12 * jQuery UI Menu 1.8.12
* *
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses. * Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license * http://jquery.org/license
* *
* http://docs.jquery.com/UI/Menu#theming * http://docs.jquery.com/UI/Menu#theming
*/ */
.ui-menu { .ui-menu {
list-style:none; list-style:none;
padding: 2px; padding: 2px;
margin: 0; margin: 0;
display:block; display:block;
float: left; float: left;
} }
.ui-menu .ui-menu { .ui-menu .ui-menu {
margin-top: -3px; margin-top: -3px;
} }
.ui-menu .ui-menu-item { .ui-menu .ui-menu-item {
margin:0; margin:0;
padding: 0; padding: 0;
zoom: 1; zoom: 1;
float: left; float: left;
clear: left; clear: left;
width: 100%; width: 100%;
} }
.ui-menu .ui-menu-item a { .ui-menu .ui-menu-item a {
text-decoration:none; text-decoration:none;
display:block; display:block;
padding:.2em .4em; padding:.2em .4em;
line-height:1.5; line-height:1.5;
zoom:1; zoom:1;
} }
.ui-menu .ui-menu-item a.ui-state-hover, .ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active { .ui-menu .ui-menu-item a.ui-state-active {
font-weight: normal; font-weight: normal;
margin: -1px; margin: -1px;
} }
   
/*!  
* jQuery Mobile v1.0b1  
* http://jquerymobile.com/  
*  
* Copyright 2010, jQuery Project  
* Dual licensed under the MIT or GPL Version 2 licenses.  
* http://jquery.org/license  
*/  
/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.  
* Note: Code is in draft form and is subject to change  
*/  
 
 
/* A  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-bar-a {  
border: 1px solid #2A2A2A;  
background: #111111;  
color: #ffffff;  
font-weight: bold;  
text-shadow: 0 -1px 1px #000000;  
background-image: -moz-linear-gradient(top,  
#3c3c3c,  
#111111);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #3c3c3c),  
color-stop(1, #111111));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#3c3c3c', EndColorStr='#111111')";  
}  
.ui-bar-a,  
.ui-bar-a input,  
.ui-bar-a select,  
.ui-bar-a textarea,  
.ui-bar-a button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-bar-a .ui-link-inherit {  
color: #fff;  
}  
.ui-bar-a .ui-link {  
color: #7cc4e7;  
font-weight: bold;  
}  
.ui-body-a {  
border: 1px solid #2A2A2A;  
background: #222222;  
color: #fff;  
text-shadow: 0 1px 0 #000;  
font-weight: normal;  
background-image: -moz-linear-gradient(top,  
#666666,  
#222222);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #666666),  
color-stop(1, #222222));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#666666', EndColorStr='#222222)')";  
}  
.ui-body-a,  
.ui-body-a input,  
.ui-body-a select,  
.ui-body-a textarea,  
.ui-body-a button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-body-a .ui-link-inherit {  
color: #fff;  
}  
.ui-body-a .ui-link {  
color: #2489CE;  
font-weight: bold;  
}  
.ui-br {  
border-bottom: rgb(130,130,130);  
border-bottom: rgba(130,130,130,.3);  
border-bottom-width: 1px;  
border-bottom-style: solid;  
}  
.ui-btn-up-a {  
border: 1px solid #222;  
background: #333333;  
font-weight: bold;  
color: #fff;  
text-shadow: 0 -1px 1px #000;  
background-image: -moz-linear-gradient(top,  
#555555,  
#333333);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #555555),  
color-stop(1, #333333));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#555555', EndColorStr='#333333')";  
}  
.ui-btn-up-a a.ui-link-inherit {  
color: #fff;  
}  
.ui-btn-hover-a {  
border: 1px solid #000;  
background: #444444;  
font-weight: bold;  
color: #fff;  
text-shadow: 0 -1px 1px #000;  
background-image: -moz-linear-gradient(top,  
#666666,  
#444444);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #666666),  
color-stop(1, #444444));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#666666', EndColorStr='#444444')";  
}  
.ui-btn-hover-a a.ui-link-inherit {  
color: #fff;  
}  
.ui-btn-down-a {  
border: 1px solid #000;  
background: #3d3d3d;  
font-weight: bold;  
color: #fff;  
text-shadow: 0 -1px 1px #000;  
background-image: -moz-linear-gradient(top,  
#333333,  
#5a5a5a);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #333333),  
color-stop(1, #5a5a5a));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#333333', EndColorStr='#5a5a5a')";  
}  
.ui-btn-down-a a.ui-link-inherit {  
color: #fff;  
}  
.ui-btn-up-a,  
.ui-btn-hover-a,  
.ui-btn-down-a {  
font-family: Helvetica, Arial, sans-serif;  
text-decoration: none;  
}  
 
 
/* B  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-bar-b {  
border: 1px solid #456f9a;  
background: #5e87b0;  
color: #fff;  
font-weight: bold;  
text-shadow: 0 -1px 1px #254f7a;  
background-image: -moz-linear-gradient(top,  
#81a8ce,  
#5e87b0);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #81a8ce),  
color-stop(1, #5e87b0));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#81a8ce', EndColorStr='#5e87b0')";  
}  
.ui-bar-b,  
.ui-bar-b input,  
.ui-bar-b select,  
.ui-bar-b textarea,  
.ui-bar-b button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-bar-b .ui-link-inherit {  
color: #fff;  
}  
.ui-bar-b .ui-link {  
color: #7cc4e7;  
font-weight: bold;  
}  
 
.ui-body-b {  
border: 1px solid #C6C6C6;  
background: #cccccc;  
color: #333333;  
text-shadow: 0 1px 0 #fff;  
font-weight: normal;  
background-image: -moz-linear-gradient(top,  
#e6e6e6,  
#cccccc);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #e6e6e6),  
color-stop(1, #cccccc));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#e6e6e6', EndColorStr='#cccccc')";  
}  
.ui-body-b,  
.ui-body-b input,  
.ui-body-b select,  
.ui-body-b textarea,  
.ui-body-b button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-body-b .ui-link-inherit {  
color: #333333;  
}  
.ui-body-b .ui-link {  
color: #2489CE;  
font-weight: bold;  
}  
.ui-btn-up-b {  
border: 1px solid #145072;  
background: #2567ab;  
font-weight: bold;  
color: #fff;  
text-shadow: 0 -1px 1px #145072;  
background-image: -moz-linear-gradient(top,  
#4e89c5,  
#2567ab);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #5f9cc5),  
color-stop(1, #396b9e));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#4e89c5', EndColorStr='#2567ab')";  
}  
.ui-btn-up-b a.ui-link-inherit {  
color: #fff;  
}  
.ui-btn-hover-b {  
border: 1px solid #00516e;  
background: #4b88b6;  
font-weight: bold;  
color: #fff;  
text-shadow: 0 -1px 1px #014D68;  
background-image: -moz-linear-gradient(top,  
#72b0d4,  
#4b88b6);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #72b0d4),  
color-stop(1, #4b88b6));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#72b0d4', EndColorStr='#4b88b6')";  
}  
.ui-btn-hover-b a.ui-link-inherit {  
color: #fff;  
}  
.ui-btn-down-b {  
border: 1px solid #225377;  
background: #4e89c5;  
font-weight: bold;  
color: #fff;  
text-shadow: 0 -1px 1px #225377;  
background-image: -moz-linear-gradient(top,  
#396b9e,  
#4e89c5);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #396b9e),  
color-stop(1, #4e89c5));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#396b9e', EndColorStr='#4e89c5')";  
}  
.ui-btn-down-b a.ui-link-inherit {  
color: #fff;  
}  
.ui-btn-up-b,  
.ui-btn-hover-b,  
.ui-btn-down-b {  
font-family: Helvetica, Arial, sans-serif;  
text-decoration: none;  
}  
 
 
/* C  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-bar-c {  
border: 1px solid #B3B3B3;  
background: #e9eaeb;  
color: #3E3E3E;  
font-weight: bold;  
text-shadow: 0 1px 1px #fff;  
background-image: -moz-linear-gradient(top,  
#f0f0f0,  
#e9eaeb);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #f0f0f0),  
color-stop(1, #e9eaeb));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#f0f0f0', EndColorStr='#e9eaeb')";  
}  
.ui-bar-c,  
.ui-bar-c input,  
.ui-bar-c select,  
.ui-bar-c textarea,  
.ui-bar-c button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-body-c {  
border: 1px solid #B3B3B3;  
color: #333333;  
text-shadow: 0 1px 0 #fff;  
background: #f0f0f0;  
background-image: -moz-linear-gradient(top,  
#eeeeee,  
#dddddd);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #eeeeee),  
color-stop(1, #dddddd));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#dddddd')";  
}  
.ui-body-c,  
.ui-body-c input,  
.ui-body-c select,  
.ui-body-c textarea,  
.ui-body-c button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-body-c .ui-link-inherit {  
color: #333333;  
}  
.ui-body-c .ui-link {  
color: #2489CE;  
font-weight: bold;  
}  
 
.ui-btn-up-c {  
border: 1px solid #ccc;  
background: #eee;  
font-weight: bold;  
color: #444;  
text-shadow: 0 1px 1px #f6f6f6;  
background-image: -moz-linear-gradient(top,  
#fefefe,  
#eeeeee);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #fdfdfd),  
color-stop(1, #eeeeee));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fdfdfd', EndColorStr='#eeeeee')";  
}  
.ui-btn-up-c a.ui-link-inherit {  
color: #2F3E46;  
}  
 
.ui-btn-hover-c {  
border: 1px solid #bbb;  
background: #dadada;  
font-weight: bold;  
color: #101010;  
text-shadow: 0 1px 1px #fff;  
background-image: -moz-linear-gradient(top,  
#ededed,  
#dadada);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #ededed),  
color-stop(1, #dadada));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ededed', EndColorStr='#dadada')";  
}  
.ui-btn-hover-c a.ui-link-inherit {  
color: #2F3E46;  
}  
.ui-btn-down-c {  
border: 1px solid #808080;  
background: #fdfdfd;  
font-weight: bold;  
color: #111111;  
text-shadow: 0 1px 1px #ffffff;  
background-image: -moz-linear-gradient(top,  
#eeeeee,  
#fdfdfd);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #eeeeee),  
color-stop(1, #fdfdfd));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#fdfdfd')";  
}  
.ui-btn-down-c a.ui-link-inherit {  
color: #2F3E46;  
}  
.ui-btn-up-c,  
.ui-btn-hover-c,  
.ui-btn-down-c {  
font-family: Helvetica, Arial, sans-serif;  
text-decoration: none;  
}  
 
 
/* D  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-bar-d {  
border: 1px solid #ccc;  
background: #bbb;  
color: #333;  
text-shadow: 0 1px 0 #eee;  
background-image: -moz-linear-gradient(top,  
#ddd,  
#bbb);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #ddd),  
color-stop(1, #bbb));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#dddddd', EndColorStr='#bbbbbb')";  
}  
.ui-bar-d,  
.ui-bar-d input,  
.ui-bar-d select,  
.ui-bar-d textarea,  
.ui-bar-d button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-bar-d .ui-link-inherit {  
color: #333;  
}  
.ui-bar-d .ui-link {  
color: #2489CE;  
font-weight: bold;  
}  
.ui-body-d {  
border: 1px solid #ccc;  
color: #333333;  
text-shadow: 0 1px 0 #fff;  
background: #ffffff;  
}  
.ui-body-d,  
.ui-body-d input,  
.ui-body-d select,  
.ui-body-d textarea,  
.ui-body-d button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-body-d .ui-link-inherit {  
color: #333333;  
}  
.ui-body-d .ui-link {  
color: #2489CE;  
font-weight: bold;  
}  
.ui-btn-up-d {  
border: 1px solid #ccc;  
background: #fff;  
font-weight: bold;  
color: #444;  
text-shadow: 0 1px 1px #fff;  
}  
.ui-btn-up-d a.ui-link-inherit {  
color: #333;  
}  
.ui-btn-hover-d {  
border: 1px solid #aaa;  
background: #eeeeee;  
font-weight: bold;  
color: #222;  
cursor: pointer;  
text-shadow: 0 1px 1px #fff;  
background-image: -moz-linear-gradient(top,  
#fdfdfd,  
#eeeeee);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #fdfdfd),  
color-stop(1, #eeeeee));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fdfdfd', EndColorStr='#eeeeee')";  
}  
.ui-btn-hover-d a.ui-link-inherit {  
color: #222;  
}  
.ui-btn-down-d {  
border: 1px solid #aaaaaa;  
background: #ffffff;  
font-weight: bold;  
color: #111;  
text-shadow: 0 1px 1px #ffffff;  
background-image: -moz-linear-gradient(top,  
#eeeeee,  
#ffffff);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #eeeeee),  
color-stop(1, #ffffff));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#eeeeee', EndColorStr='#ffffff')";  
}  
.ui-btn-down-d a.ui-link-inherit {  
color: #111;  
}  
.ui-btn-up-d,  
.ui-btn-hover-d,  
.ui-btn-down-d {  
font-family: Helvetica, Arial, sans-serif;  
text-decoration: none;  
}  
 
 
/* E  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-bar-e {  
border: 1px solid #F7C942;  
background: #fadb4e;  
color: #333;  
text-shadow: 0 1px 0 #fff;  
background-image: -moz-linear-gradient(top,  
#fceda7,  
#fadb4e);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #fceda7),  
color-stop(1, #fadb4e));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fceda7', EndColorStr='#fadb4e')";  
}  
.ui-bar-e,  
.ui-bar-e input,  
.ui-bar-e select,  
.ui-bar-e textarea,  
.ui-bar-d button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-bar-e .ui-link-inherit {  
color: #333;  
}  
.ui-bar-e .ui-link {  
color: #2489CE;  
font-weight: bold;  
}  
.ui-body-e {  
border: 1px solid #F7C942;  
color: #333333;  
text-shadow: 0 1px 0 #fff;  
background: #faeb9e;  
background-image: -moz-linear-gradient(top,  
#fff,  
#faeb9e);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #fff),  
color-stop(1, #faeb9e));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#faeb9e')";  
}  
.ui-body-e,  
.ui-body-e input,  
.ui-body-e select,  
.ui-body-e textarea,  
.ui-body-e button {  
font-family: Helvetica, Arial, sans-serif;  
}  
.ui-body-e .ui-link-inherit {  
color: #333333;  
}  
.ui-body-e .ui-link {  
color: #2489CE;  
font-weight: bold;  
}  
.ui-btn-up-e {  
border: 1px solid #F7C942;  
background: #fadb4e;  
font-weight: bold;  
color: #333;  
text-shadow: 0 1px 0 #fff;  
background-image: -moz-linear-gradient(top,  
#fceda7,  
#fadb4e);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #fceda7),  
color-stop(1, #fadb4e));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fceda7', EndColorStr='#fadb4e')";  
}  
.ui-btn-up-e a.ui-link-inherit {  
color: #333;  
}  
.ui-btn-hover-e {  
border: 1px solid #e79952;  
background: #fbe26f;  
font-weight: bold;  
color: #111;  
text-shadow: 0 1px 1px #fff;  
background-image: -moz-linear-gradient(top,  
#fcf0b5,  
#fbe26f);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #fcf0b5),  
color-stop(1, #fbe26f));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fcf0b5', EndColorStr='#fbe26f')";  
}  
 
.ui-btn-hover-e a.ui-link-inherit {  
color: #333;  
}  
.ui-btn-down-e {  
border: 1px solid #F7C942;  
background: #fceda7;  
font-weight: bold;  
color: #111;  
text-shadow: 0 1px 1px #ffffff;  
background-image: -moz-linear-gradient(top,  
#fadb4e,  
#fceda7);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #fadb4e),  
color-stop(1, #fceda7));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#fadb4e', EndColorStr='#fceda7')";  
}  
.ui-btn-down-e a.ui-link-inherit {  
color: #333;  
}  
.ui-btn-up-e,  
.ui-btn-hover-e,  
.ui-btn-down-e {  
font-family: Helvetica, Arial, sans-serif;  
text-decoration: none;  
}  
 
 
/* links within "buttons"  
-----------------------------------------------------------------------------------------------------------*/  
 
a.ui-link-inherit {  
text-decoration: none !important;  
}  
 
 
/* Active class used as the "on" state across all themes  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-btn-active {  
border: 1px solid #155678;  
background: #4596ce;  
font-weight: bold;  
color: #fff;  
cursor: pointer;  
text-shadow: 0 -1px 1px #145072;  
text-decoration: none;  
background-image: -moz-linear-gradient(top,  
#85bae4,  
#5393c5);  
background-image: -webkit-gradient(linear,left top,left bottom,  
color-stop(0, #85bae4),  
color-stop(1, #5393c5));  
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#85bae4', EndColorStr='#5393c5')";  
outline: none;  
}  
.ui-btn-active a.ui-link-inherit {  
color: #fff;  
}  
 
 
/* button inner top highlight  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-btn-inner {  
border-top: 1px solid #fff;  
border-color: rgba(255,255,255,.3);  
}  
 
 
/* corner rounding classes  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-corner-tl {  
-moz-border-radius-topleft: .6em;  
-webkit-border-top-left-radius: .6em;  
border-top-left-radius: .6em;  
}  
.ui-corner-tr {  
-moz-border-radius-topright: .6em;  
-webkit-border-top-right-radius: .6em;  
border-top-right-radius: .6em;  
}  
.ui-corner-bl {  
-moz-border-radius-bottomleft: .6em;  
-webkit-border-bottom-left-radius: .6em;  
border-bottom-left-radius: .6em;  
}  
.ui-corner-br {  
-moz-border-radius-bottomright: .6em;  
-webkit-border-bottom-right-radius: .6em;  
border-bottom-right-radius: .6em;  
}  
.ui-corner-top {  
-moz-border-radius-topleft: .6em;  
-webkit-border-top-left-radius: .6em;  
border-top-left-radius: .6em;  
-moz-border-radius-topright: .6em;  
-webkit-border-top-right-radius: .6em;  
border-top-right-radius: .6em;  
}  
.ui-corner-bottom {  
-moz-border-radius-bottomleft: .6em;  
-webkit-border-bottom-left-radius: .6em;  
border-bottom-left-radius: .6em;  
-moz-border-radius-bottomright: .6em;  
-webkit-border-bottom-right-radius: .6em;  
border-bottom-right-radius: .6em;  
}  
.ui-corner-right {  
-moz-border-radius-topright: .6em;  
-webkit-border-top-right-radius: .6em;  
border-top-right-radius: .6em;  
-moz-border-radius-bottomright: .6em;  
-webkit-border-bottom-right-radius: .6em;  
border-bottom-right-radius: .6em;  
}  
.ui-corner-left {  
-moz-border-radius-topleft: .6em;  
-webkit-border-top-left-radius: .6em;  
border-top-left-radius: .6em;  
-moz-border-radius-bottomleft: .6em;  
-webkit-border-bottom-left-radius: .6em;  
border-bottom-left-radius: .6em;  
}  
.ui-corner-all {  
-moz-border-radius: .6em;  
-webkit-border-radius: .6em;  
border-radius: .6em;  
}  
 
 
 
/* Interaction cues  
-----------------------------------------------------------------------------------------------------------*/  
.ui-disabled {  
opacity: .3;  
}  
.ui-disabled,  
.ui-disabled a {  
cursor: default;  
}  
 
/* Icons  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-icon {  
background: #666;  
background: rgba(0,0,0,.4);  
background-image: url(images/icons-18-white.png);  
background-repeat: no-repeat;  
-moz-border-radius: 9px;  
-webkit-border-radius: 9px;  
border-radius: 9px;  
}  
 
 
/* Alt icon color  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-icon-alt {  
background: #fff;  
background: rgba(255,255,255,.3);  
background-image: url(images/icons-18-black.png);  
background-repeat: no-repeat;  
}  
 
/* HD/"retina" sprite  
-----------------------------------------------------------------------------------------------------------*/  
 
@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  
only screen and (min--moz-device-pixel-ratio: 1.5),  
only screen and (min-resolution: 240dpi) {  
 
.ui-icon-plus, .ui-icon-minus, .ui-icon-delete, .ui-icon-arrow-r,  
.ui-icon-arrow-l, .ui-icon-arrow-u, .ui-icon-arrow-d, .ui-icon-check,  
.ui-icon-gear, .ui-icon-refresh, .ui-icon-forward, .ui-icon-back,  
.ui-icon-grid, .ui-icon-star, .ui-icon-alert, .ui-icon-info, .ui-icon-home, .ui-icon-search,  
.ui-icon-checkbox-off, .ui-icon-checkbox-on, .ui-icon-radio-off, .ui-icon-radio-on {  
background-image: url(images/icons-36-white.png);  
-moz-background-size: 776px 18px;  
-o-background-size: 776px 18px;  
-webkit-background-size: 776px 18px;  
background-size: 776px 18px;  
}  
.ui-icon-alt {  
background-image: url(images/icons-36-black.png);  
}  
}  
 
/* plus minus */  
.ui-icon-plus {  
background-position: -0 50%;  
}  
.ui-icon-minus {  
background-position: -36px 50%;  
}  
 
/* delete/close */  
.ui-icon-delete {  
background-position: -72px 50%;  
}  
 
/* arrows */  
.ui-icon-arrow-r {  
background-position: -108px 50%;  
}  
.ui-icon-arrow-l {  
background-position: -144px 50%;  
}  
.ui-icon-arrow-u {  
background-position: -180px 50%;  
}  
.ui-icon-arrow-d {  
background-position: -216px 50%;  
}  
 
/* misc */  
.ui-icon-check {  
background-position: -252px 50%;  
}  
.ui-icon-gear {  
background-position: -288px 50%;  
}  
.ui-icon-refresh {  
background-position: -324px 50%;  
}  
.ui-icon-forward {  
background-position: -360px 50%;  
}  
.ui-icon-back {  
background-position: -396px 50%;  
}  
.ui-icon-grid {  
background-position: -432px 50%;  
}  
.ui-icon-star {  
background-position: -468px 50%;  
}  
.ui-icon-alert {  
background-position: -504px 50%;  
}  
.ui-icon-info {  
background-position: -540px 50%;  
}  
.ui-icon-home {  
background-position: -576px 50%;  
}  
.ui-icon-search {  
background-position: -612px 50%;  
}  
.ui-icon-checkbox-off {  
background-position: -684px 50%;  
}  
.ui-icon-checkbox-on {  
background-position: -648px 50%;  
}  
.ui-icon-radio-off {  
background-position: -756px 50%;  
}  
.ui-icon-radio-on {  
background-position: -720px 50%;  
}  
 
 
/* checks,radios */  
.ui-icon-checkbox-off,  
.ui-icon-checkbox-on,  
.ui-icon-radio-off,  
.ui-icon-radio-on {  
background-color: transparent;  
-moz-border-radius: 0;  
-webkit-border-radius: 0;  
border-radius: 0;  
}  
.ui-icon-searchfield {  
background-image: url(images/icon-search-black.png);  
background-size: 16px 16px;  
}  
 
/* loading icon */  
.ui-icon-loading {  
background-image: url(images/ajax-loader.png);  
width: 40px;  
height: 40px;  
-moz-border-radius: 20px;  
-webkit-border-radius: 20px;  
border-radius: 20px;  
background-size: 35px 35px;  
}  
 
 
/* Button corner classes  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-btn-corner-tl {  
-moz-border-radius-topleft: 1em;  
-webkit-border-top-left-radius: 1em;  
border-top-left-radius: 1em;  
}  
.ui-btn-corner-tr {  
-moz-border-radius-topright: 1em;  
-webkit-border-top-right-radius: 1em;  
border-top-right-radius: 1em;  
}  
.ui-btn-corner-bl {  
-moz-border-radius-bottomleft: 1em;  
-webkit-border-bottom-left-radius: 1em;  
border-bottom-left-radius: 1em;  
}  
.ui-btn-corner-br {  
-moz-border-radius-bottomright: 1em;  
-webkit-border-bottom-right-radius: 1em;  
border-bottom-right-radius: 1em;  
}  
.ui-btn-corner-top {  
-moz-border-radius-topleft: 1em;  
-webkit-border-top-left-radius: 1em;  
border-top-left-radius: 1em;  
-moz-border-radius-topright: 1em;  
-webkit-border-top-right-radius: 1em;  
border-top-right-radius: 1em;  
}  
.ui-btn-corner-bottom {  
-moz-border-radius-bottomleft: 1em;  
-webkit-border-bottom-left-radius: 1em;  
border-bottom-left-radius: 1em;  
-moz-border-radius-bottomright: 1em;  
-webkit-border-bottom-right-radius: 1em;  
border-bottom-right-radius: 1em;  
}  
.ui-btn-corner-right {  
-moz-border-radius-topright: 1em;  
-webkit-border-top-right-radius: 1em;  
border-top-right-radius: 1em;  
-moz-border-radius-bottomright: 1em;  
-webkit-border-bottom-right-radius: 1em;  
border-bottom-right-radius: 1em;  
}  
.ui-btn-corner-left {  
-moz-border-radius-topleft: 1em;  
-webkit-border-top-left-radius: 1em;  
border-top-left-radius: 1em;  
-moz-border-radius-bottomleft: 1em;  
-webkit-border-bottom-left-radius: 1em;  
border-bottom-left-radius: 1em;  
}  
.ui-btn-corner-all {  
-moz-border-radius: 1em;  
-webkit-border-radius: 1em;  
border-radius: 1em;  
}  
 
/* radius clip workaround for cleaning up corner trapping */  
.ui-corner-tl,  
.ui-corner-tr,  
.ui-corner-bl,  
.ui-corner-br,  
.ui-corner-top,  
.ui-corner-bottom,  
.ui-corner-right,  
.ui-corner-left,  
.ui-corner-all,  
.ui-btn-corner-tl,  
.ui-btn-corner-tr,  
.ui-btn-corner-bl,  
.ui-btn-corner-br,  
.ui-btn-corner-top,  
.ui-btn-corner-bottom,  
.ui-btn-corner-right,  
.ui-btn-corner-left,  
.ui-btn-corner-all {  
-webkit-background-clip: padding-box;  
-moz-background-clip: padding-box;  
background-clip: padding-box;  
}  
 
/* Overlay / modal  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-overlay {  
background: #666;  
opacity: .5;  
filter: Alpha(Opacity=50);  
position: absolute;  
width: 100%;  
height: 100%;  
}  
.ui-overlay-shadow {  
-moz-box-shadow: 0px 0px 12px rgba(0,0,0,.6);  
-webkit-box-shadow: 0px 0px 12px rgba(0,0,0,.6);  
box-shadow: 0px 0px 12px rgba(0,0,0,.6);  
}  
.ui-shadow {  
-moz-box-shadow: 0px 1px 4px rgba(0,0,0,.3);  
-webkit-box-shadow: 0px 1px 4px rgba(0,0,0,.3);  
box-shadow: 0px 1px 4px rgba(0,0,0,.3);  
}  
.ui-bar-a .ui-shadow,  
.ui-bar-b .ui-shadow ,  
.ui-bar-c .ui-shadow {  
-moz-box-shadow: 0px 1px 0 rgba(255,255,255,.3);  
-webkit-box-shadow: 0px 1px 0 rgba(255,255,255,.3);  
box-shadow: 0px 1px 0 rgba(255,255,255,.3);  
}  
.ui-shadow-inset {  
-moz-box-shadow: inset 0px 1px 4px rgba(0,0,0,.2);  
-webkit-box-shadow: inset 0px 1px 4px rgba(0,0,0,.2);  
box-shadow: inset 0px 1px 4px rgba(0,0,0,.2);  
}  
.ui-icon-shadow {  
-moz-box-shadow: 0px 1px 0 rgba(255,255,255,.4);  
-webkit-box-shadow: 0px 1px 0 rgba(255,255,255,.4);  
box-shadow: 0px 1px 0 rgba(255,255,255,.4);  
}  
 
 
/* Focus state - set here for specificity  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-focus {  
-moz-box-shadow: 0px 0px 12px #387bbe;  
-webkit-box-shadow: 0px 0px 12px #387bbe;  
box-shadow: 0px 0px 12px #387bbe;  
}  
 
/* unset box shadow in browsers that don't do it right  
-----------------------------------------------------------------------------------------------------------*/  
 
.ui-mobile-nosupport-boxshadow * {  
-moz-box-shadow: none !important;  
-webkit-box-shadow: none !important;  
box-shadow: none !important;  
}  
 
/* ...and bring back focus */  
.ui-mobile-nosupport-boxshadow .ui-focus {  
outline-width: 2px;  
}/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.  
* Note: Code is in draft form and is subject to change  
*/  
 
/* some unsets - more probably needed */  
.ui-mobile, .ui-mobile body { height: 100%; }  
.ui-mobile fieldset, .ui-page { padding: 0; margin: 0; }  
.ui-mobile a img, .ui-mobile fieldset { border: 0; }  
 
/* responsive page widths */  
.ui-mobile-viewport { margin: 0; overflow-x: hidden; -webkit-text-size-adjust: none; -ms-text-size-adjust:none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }  
 
/* "page" containers - full-screen views, one should always be in view post-pageload */  
.ui-mobile [data-role=page], .ui-mobile [data-role=dialog], .ui-page { top: 0; left: 0; width: 100%; min-height: 100%; position: absolute; display: none; border: 0; }  
.ui-mobile .ui-page-active { display: block; overflow: visible; }  
 
/*orientations from js are available */  
.portrait,  
.portrait .ui-page { min-height: 420px; }  
.landscape,  
.landscape .ui-page { min-height: 300px; }  
 
/* loading screen */  
.ui-loading .ui-mobile-viewport { overflow: hidden !important; }  
.ui-loading .ui-loader { display: block; }  
.ui-loading .ui-page { overflow: hidden; }  
.ui-loader { display: none; position: absolute; opacity: .85; z-index: 100; left: 50%; width: 200px; margin-left: -130px; margin-top: -35px; padding: 10px 30px; }  
.ui-loader h1 { font-size: 15px; text-align: center; }  
.ui-loader .ui-icon { position: static; display: block; opacity: .9; margin: 0 auto; width: 35px; height: 35px; background-color: transparent; }  
 
/*fouc*/  
.ui-mobile-rendering > * { visibility: hidden; }  
 
/*headers, content panels*/  
.ui-bar, .ui-body { position: relative; padding: .4em 15px; overflow: hidden; display: block; clear:both; }  
.ui-bar { font-size: 16px; margin: 0; }  
.ui-bar h1, .ui-bar h2, .ui-bar h3, .ui-bar h4, .ui-bar h5, .ui-bar h6 { margin: 0; padding: 0; font-size: 16px; display: inline-block; }  
 
.ui-header, .ui-footer { display: block; }  
.ui-page .ui-header, .ui-page .ui-footer { position: relative; }  
.ui-header .ui-btn-left { position: absolute; left: 10px; top: .4em; }  
.ui-header .ui-btn-right { position: absolute; right: 10px; top: .4em; }  
.ui-header .ui-title, .ui-footer .ui-title { min-height: 1.1em; text-align: center; font-size: 16px; display: block; margin: .6em 90px .8em; padding: 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; outline: 0 !important; }  
 
/*content area*/  
.ui-content { border-width: 0; overflow: visible; overflow-x: hidden; padding: 15px; }  
.ui-page-fullscreen .ui-content { padding:0; }  
 
/* icons sizing */  
.ui-icon { width: 18px; height: 18px; }  
 
/* fullscreen class on ui-content div */  
.ui-fullscreen { }  
.ui-fullscreen img { max-width: 100%; }  
 
/* non-js content hiding */  
.ui-nojs { position: absolute; left: -9999px; }  
/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.spin {  
-webkit-transform: rotate(360deg);  
-webkit-animation-name: spin;  
-webkit-animation-duration: 1s;  
-webkit-animation-iteration-count: infinite;  
}  
@-webkit-keyframes spin {  
from {-webkit-transform: rotate(0deg);}  
to {-webkit-transform: rotate(360deg);}  
}  
 
/* Transitions from jQtouch (with small modifications): http://www.jqtouch.com/  
Built by David Kaneda and maintained by Jonathan Stark.  
*/  
.in, .out {  
-webkit-animation-timing-function: ease-in-out;  
-webkit-animation-duration: 350ms;  
}  
 
.slide.in {  
-webkit-transform: translateX(0);  
-webkit-animation-name: slideinfromright;  
}  
 
.slide.out {  
-webkit-transform: translateX(-100%);  
-webkit-animation-name: slideouttoleft;  
}  
 
.slide.in.reverse {  
-webkit-transform: translateX(0);  
-webkit-animation-name: slideinfromleft;  
}  
 
.slide.out.reverse {  
-webkit-transform: translateX(100%);  
-webkit-animation-name: slideouttoright;  
}  
 
.slideup.in {  
-webkit-transform: translateY(0);  
-webkit-animation-name: slideinfrombottom;  
z-index: 10;  
}  
 
.slideup.out {  
-webkit-animation-name: dontmove;  
z-index: 0;  
}  
 
.slideup.out.reverse {  
-webkit-transform: translateY(100%);  
z-index: 10;  
-webkit-animation-name: slideouttobottom;  
}  
 
.slideup.in.reverse {  
z-index: 0;  
-webkit-animation-name: dontmove;  
}  
.slidedown.in {  
-webkit-transform: translateY(0);  
-webkit-animation-name: slideinfromtop;  
z-index: 10;  
}  
 
.slidedown.out {  
-webkit-animation-name: dontmove;  
z-index: 0;  
}  
 
.slidedown.out.reverse {  
-webkit-transform: translateY(-100%);  
z-index: 10;  
-webkit-animation-name: slideouttotop;  
}  
 
.slidedown.in.reverse {  
z-index: 0;  
-webkit-animation-name: dontmove;  
}  
 
@-webkit-keyframes slideinfromright {  
from { -webkit-transform: translateX(100%); }  
to { -webkit-transform: translateX(0); }  
}  
 
@-webkit-keyframes slideinfromleft {  
from { -webkit-transform: translateX(-100%); }  
to { -webkit-transform: translateX(0); }  
}  
 
@-webkit-keyframes slideouttoleft {  
from { -webkit-transform: translateX(0); }  
to { -webkit-transform: translateX(-100%); }  
}  
 
@-webkit-keyframes slideouttoright {  
from { -webkit-transform: translateX(0); }  
to { -webkit-transform: translateX(100%); }  
}  
 
 
@-webkit-keyframes slideinfromtop {  
from { -webkit-transform: translateY(-100%); }  
to { -webkit-transform: translateY(0); }  
}  
 
@-webkit-keyframes slideinfrombottom {  
from { -webkit-transform: translateY(100%); }  
to { -webkit-transform: translateY(0); }  
}  
 
@-webkit-keyframes slideouttobottom {  
from { -webkit-transform: translateY(0); }  
to { -webkit-transform: translateY(100%); }  
}  
 
@-webkit-keyframes slideouttotop {  
from { -webkit-transform: translateY(0); }  
to { -webkit-transform: translateY(-100%); }  
}  
@-webkit-keyframes fadein {  
from { opacity: 0; }  
to { opacity: 1; }  
}  
 
@-webkit-keyframes fadeout {  
from { opacity: 1; }  
to { opacity: 0; }  
}  
 
.fade.in {  
opacity: 1;  
z-index: 10;  
-webkit-animation-name: fadein;  
}  
.fade.out {  
z-index: 0;  
-webkit-animation-name: fadeout;  
}  
 
/* The properties in this rule are only necessary for the 'flip' transition.  
* We need specify the perspective to create a projection matrix. This will add  
* some depth as the element flips. The depth number represents the distance of  
* the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate  
* value.  
*/  
.viewport-flip {  
-webkit-perspective: 1000;  
position: absolute;  
}  
 
.ui-mobile-viewport-transitioning,  
.ui-mobile-viewport-transitioning .ui-page {  
width: 100%;  
height: 100%;  
overflow: hidden;  
}  
 
.flip {  
-webkit-animation-duration: .65s;  
-webkit-backface-visibility:hidden;  
-webkit-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */  
}  
 
.flip.in {  
-webkit-transform: rotateY(0) scale(1);  
-webkit-animation-name: flipinfromleft;  
}  
 
.flip.out {  
-webkit-transform: rotateY(-180deg) scale(.8);  
-webkit-animation-name: flipouttoleft;  
}  
 
/* Shake it all about */  
 
.flip.in.reverse {  
-webkit-transform: rotateY(0) scale(1);  
-webkit-animation-name: flipinfromright;  
}  
 
.flip.out.reverse {  
-webkit-transform: rotateY(180deg) scale(.8);  
-webkit-animation-name: flipouttoright;  
}  
 
@-webkit-keyframes flipinfromright {  
from { -webkit-transform: rotateY(-180deg) scale(.8); }  
to { -webkit-transform: rotateY(0) scale(1); }  
}  
 
@-webkit-keyframes flipinfromleft {  
from { -webkit-transform: rotateY(180deg) scale(.8); }  
to { -webkit-transform: rotateY(0) scale(1); }  
}  
 
@-webkit-keyframes flipouttoleft {  
from { -webkit-transform: rotateY(0) scale(1); }  
to { -webkit-transform: rotateY(-180deg) scale(.8); }  
}  
 
@-webkit-keyframes flipouttoright {  
from { -webkit-transform: rotateY(0) scale(1); }  
to { -webkit-transform: rotateY(180deg) scale(.8); }  
}  
 
 
/* Hackish, but reliable. */  
 
@-webkit-keyframes dontmove {  
from { opacity: 1; }  
to { opacity: 1; }  
}  
 
.pop {  
-webkit-transform-origin: 50% 50%;  
}  
 
.pop.in {  
-webkit-transform: scale(1);  
opacity: 1;  
-webkit-animation-name: popin;  
z-index: 10;  
}  
 
.pop.out.reverse {  
-webkit-transform: scale(.2);  
opacity: 0;  
-webkit-animation-name: popout;  
z-index: 10;  
}  
 
.pop.in.reverse {  
z-index: 0;  
-webkit-animation-name: dontmove;  
}  
 
@-webkit-keyframes popin {  
from {  
-webkit-transform: scale(.2);  
opacity: 0;  
}  
to {  
-webkit-transform: scale(1);  
opacity: 1;  
}  
}  
 
@-webkit-keyframes popout {  
from {  
-webkit-transform: scale(1);  
opacity: 1;  
}  
to {  
-webkit-transform: scale(.2);  
opacity: 0;  
}  
}/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
 
/* content configurations. */  
.ui-grid-a, .ui-grid-b, .ui-grid-c, .ui-grid-d { overflow: hidden; }  
.ui-block-a, .ui-block-b, .ui-block-c, .ui-block-d, .ui-block-e { margin: 0; padding: 0; border: 0; float: left; min-height:1px;}  
 
/* grid solo: 100 - single item fallback */  
.ui-grid-solo .ui-block-a { width: 100%; float: none; }  
 
/* grid a: 50/50 */  
.ui-grid-a .ui-block-a, .ui-grid-a .ui-block-b { width: 50%; }  
.ui-grid-a .ui-block-a { clear: left; }  
 
/* grid b: 33/33/33 */  
.ui-grid-b .ui-block-a, .ui-grid-b .ui-block-b, .ui-grid-b .ui-block-c { width: 33.333%; }  
.ui-grid-b .ui-block-a { clear: left; }  
 
/* grid c: 25/25/25/25 */  
.ui-grid-c .ui-block-a, .ui-grid-c .ui-block-b, .ui-grid-c .ui-block-c, .ui-grid-c .ui-block-d { width: 25%; }  
.ui-grid-c .ui-block-a { clear: left; }  
 
/* grid d: 20/20/20/20/20 */  
.ui-grid-d .ui-block-a, .ui-grid-d .ui-block-b, .ui-grid-d .ui-block-c, .ui-grid-d .ui-block-d, .ui-grid-d .ui-block-e { width: 20%; }  
.ui-grid-d .ui-block-a { clear: left; }  
/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
/* fixed page header & footer configuration */  
.ui-header, .ui-footer, .ui-page-fullscreen .ui-header, .ui-page-fullscreen .ui-footer { position: absolute; overflow: hidden; width: 100%; border-left-width: 0; border-right-width: 0; }  
.ui-header-fixed, .ui-footer-fixed {  
z-index: 1000;  
-webkit-transform: translateZ(0); /* Force header/footer rendering to go through the same rendering pipeline as native page scrolling. */  
}  
.ui-footer-duplicate, .ui-page-fullscreen .ui-fixed-inline { display: none; }  
.ui-page-fullscreen .ui-header, .ui-page-fullscreen .ui-footer { opacity: .9; }  
/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.ui-navbar { overflow: hidden; }  
.ui-navbar ul, .ui-navbar-expanded ul { list-style:none; padding: 0; margin: 0; position: relative; display: block; border: 0;}  
.ui-navbar-collapsed ul { float: left; width: 75%; margin-right: -2px; }  
.ui-navbar-collapsed .ui-navbar-toggle { float: left; width: 25%; }  
.ui-navbar li.ui-navbar-truncate { position: absolute; left: -9999px; top: -9999px; }  
.ui-navbar li .ui-btn, .ui-navbar .ui-navbar-toggle .ui-btn { display: block; font-size: 12px; text-align: center; margin: 0; border-right-width: 0; }  
.ui-navbar li .ui-btn { margin-right: -1px; }  
.ui-navbar li .ui-btn:last-child { margin-right: 0; }  
.ui-header .ui-navbar li .ui-btn, .ui-header .ui-navbar .ui-navbar-toggle .ui-btn,  
.ui-footer .ui-navbar li .ui-btn, .ui-footer .ui-navbar .ui-navbar-toggle .ui-btn { border-top-width: 0; border-bottom-width: 0; }  
.ui-navbar .ui-btn-inner { padding-left: 2px; padding-right: 2px; }  
.ui-navbar-noicons li .ui-btn .ui-btn-inner, .ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner { padding-top: .8em; padding-bottom: .9em; }  
/*expanded page styles*/  
.ui-navbar-expanded .ui-btn { margin: 0; font-size: 14px; }  
.ui-navbar-expanded .ui-btn-inner { padding-left: 5px; padding-right: 5px; }  
.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner { padding: 45px 5px 15px; text-align: center; }  
.ui-navbar-expanded .ui-btn-icon-top .ui-icon { top: 15px; }  
.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner { padding: 15px 5px 45px; text-align: center; }  
.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon { bottom: 15px; }  
.ui-navbar-expanded li .ui-btn .ui-btn-inner { min-height: 2.5em; }  
.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner { padding-top: 1.8em; padding-bottom: 1.9em; }  
/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.ui-btn { display: block; text-align: center; cursor:pointer; position: relative; margin: .5em 5px; padding: 0; }  
.ui-btn:focus, .ui-btn:active { outline: none; }  
.ui-header .ui-btn, .ui-footer .ui-btn, .ui-bar .ui-btn { display: inline-block; font-size: 13px; margin: 0; }  
.ui-btn-inline { display: inline-block; }  
.ui-btn-inner { padding: .6em 25px; display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; position: relative; }  
.ui-header .ui-btn-inner, .ui-footer .ui-btn-inner, .ui-bar .ui-btn-inner { padding: .4em 8px .5em; }  
.ui-btn-icon-notext { display: inline-block; width: 20px; height: 20px; padding: 2px 1px 2px 3px; text-indent: -9999px; }  
.ui-btn-icon-notext .ui-btn-inner { padding: 0; }  
.ui-btn-icon-notext .ui-btn-text { position: absolute; left: -999px; }  
.ui-btn-icon-left .ui-btn-inner { padding-left: 33px; }  
.ui-header .ui-btn-icon-left .ui-btn-inner,  
.ui-footer .ui-btn-icon-left .ui-btn-inner,  
.ui-bar .ui-btn-icon-left .ui-btn-inner { padding-left: 27px; }  
.ui-btn-icon-right .ui-btn-inner { padding-right: 33px; }  
.ui-header .ui-btn-icon-right .ui-btn-inner,  
.ui-footer .ui-btn-icon-right .ui-btn-inner,  
.ui-bar .ui-btn-icon-right .ui-btn-inner { padding-right: 27px; }  
.ui-btn-icon-top .ui-btn-inner { padding-top: 33px; }  
.ui-header .ui-btn-icon-top .ui-btn-inner,  
.ui-footer .ui-btn-icon-top .ui-btn-inner,  
.ui-bar .ui-btn-icon-top .ui-btn-inner { padding-top: 27px; }  
.ui-btn-icon-bottom .ui-btn-inner { padding-bottom: 33px; }  
.ui-header .ui-btn-icon-bottom .ui-btn-inner,  
.ui-footer .ui-btn-icon-bottom .ui-btn-inner,  
.ui-bar .ui-btn-icon-bottom .ui-btn-inner { padding-bottom: 27px; }  
 
/*btn icon positioning*/  
.ui-btn-icon-notext .ui-icon { display: block; }  
.ui-btn-icon-left .ui-icon, .ui-btn-icon-right .ui-icon { position: absolute; top: 50%; margin-top: -9px; }  
.ui-btn-icon-top .ui-icon, .ui-btn-icon-bottom .ui-icon { position: absolute; left: 50%; margin-left: -9px; }  
.ui-btn-icon-left .ui-icon { left: 10px; }  
.ui-btn-icon-right .ui-icon {right: 10px; }  
.ui-header .ui-btn-icon-left .ui-icon,  
.ui-footer .ui-btn-icon-left .ui-icon,  
.ui-bar .ui-btn-icon-left .ui-icon { left: 4px; }  
.ui-header .ui-btn-icon-right .ui-icon,  
.ui-footer .ui-btn-icon-right .ui-icon,  
.ui-bar .ui-btn-icon-right .ui-icon { right: 4px; }  
.ui-header .ui-btn-icon-top .ui-icon,  
.ui-footer .ui-btn-icon-top .ui-icon,  
.ui-bar .ui-btn-icon-top .ui-icon { top: 4px; }  
.ui-header .ui-btn-icon-bottom .ui-icon,  
.ui-footer .ui-btn-icon-bottom .ui-icon,  
.ui-bar .ui-btn-icon-bottom .ui-icon { bottom: 4px; }  
.ui-btn-icon-top .ui-icon { top: 5px; }  
.ui-btn-icon-bottom .ui-icon { bottom: 5px; }  
/*hiding native button,inputs */  
.ui-btn-hidden { position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-appearance: button; opacity: 0; cursor: pointer; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter: alpha(opacity=0); background: transparent; }  
/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.ui-collapsible-contain { margin: .5em 0; }  
.ui-collapsible-heading { font-size: 16px; display: block; margin: 0 -8px; padding: 0; border-width: 0 0 1px 0; position: relative; }  
.ui-collapsible-heading a { text-align: left; margin: 0; }  
.ui-collapsible-heading a .ui-btn-inner { padding-left: 40px; }  
.ui-collapsible-heading a span.ui-btn { position: absolute; left: 6px; top: 50%; margin: -12px 0 0 0; width: 20px; height: 20px; padding: 1px 0px 1px 2px; text-indent: -9999px; }  
.ui-collapsible-heading a span.ui-btn .ui-btn-inner { padding: 10px 0; }  
.ui-collapsible-heading a span.ui-btn .ui-icon { left: 0; margin-top: -10px; }  
.ui-collapsible-heading-status { position:absolute; left:-9999px; }  
.ui-collapsible-content { display: block; padding: 10px 0 10px 8px; }  
.ui-collapsible-content-collapsed { display: none; }  
 
.ui-collapsible-set { margin: .5em 0; }  
.ui-collapsible-set .ui-collapsible-contain { margin: -1px 0 0; }  
/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.ui-controlgroup, fieldset.ui-controlgroup { padding: 0; margin: .5em 0 1em; }  
.ui-bar .ui-controlgroup { margin: 0 .3em; }  
.ui-controlgroup-label { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .3em; }  
.ui-controlgroup-controls { display: block; width: 95%;}  
.ui-controlgroup li { list-style: none; }  
.ui-controlgroup-vertical .ui-btn,  
.ui-controlgroup-vertical .ui-checkbox, .ui-controlgroup-vertical .ui-radio { margin: 0; border-bottom-width: 0; }  
.ui-controlgroup-vertical .ui-controlgroup-last { border-bottom-width: 1px; }  
.ui-controlgroup-horizontal { padding: 0; }  
.ui-controlgroup-horizontal .ui-btn,  
.ui-controlgroup-horizontal .ui-checkbox, .ui-controlgroup-horizontal .ui-radio { display: inline-block; margin: 0 -5px 0 0; }  
.ui-controlgroup-horizontal .ui-checkbox, .ui-controlgroup-horizontal .ui-radio { display: inline; }  
.ui-controlgroup-horizontal .ui-checkbox .ui-btn, .ui-controlgroup-horizontal .ui-radio .ui-btn,  
.ui-controlgroup-horizontal .ui-checkbox:last-child, .ui-controlgroup-horizontal .ui-radio:last-child { margin-right: 0; }  
.ui-controlgroup-horizontal .ui-controlgroup-last { margin-right: 0; }  
.ui-controlgroup .ui-checkbox label, .ui-controlgroup .ui-radio label { font-size: 16px; }  
/* conflicts with listview..  
.ui-controlgroup .ui-btn-icon-notext { width: 30px; height: 30px; text-indent: -9999px; }  
.ui-controlgroup .ui-btn-icon-notext .ui-btn-inner { padding: 5px 6px 5px 5px; }  
*/  
 
@media all and (min-width: 450px){  
.ui-controlgroup-label { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; }  
.ui-controlgroup-controls { width: 60%; display: inline-block; }  
} /*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.ui-dialog { min-height: 480px; }  
.ui-dialog .ui-header, .ui-dialog .ui-content, .ui-dialog .ui-footer { margin: 15px; position: relative; }  
.ui-dialog .ui-header, .ui-dialog .ui-footer { z-index: 10; width: auto; }  
.ui-dialog .ui-content, .ui-dialog .ui-footer { margin-top: -15px; }/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.ui-checkbox, .ui-radio { position:relative; margin: .2em 0 .5em; z-index: 1; }  
.ui-checkbox .ui-btn, .ui-radio .ui-btn { margin: 0; text-align: left; z-index: 2; }  
.ui-checkbox .ui-btn-inner, .ui-radio .ui-btn-inner { white-space: normal; }  
.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner { padding-left: 45px; }  
.ui-checkbox .ui-btn-icon-right .ui-btn-inner, .ui-radio .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; }  
.ui-checkbox .ui-icon, .ui-radio .ui-icon { top: 1.1em; }  
.ui-checkbox .ui-btn-icon-left .ui-icon, .ui-radio .ui-btn-icon-left .ui-icon {left: 15px; }  
.ui-checkbox .ui-btn-icon-right .ui-icon, .ui-radio .ui-btn-icon-right .ui-icon {right: 15px; }  
/* input, label positioning */  
.ui-checkbox input,.ui-radio input { position:absolute; left:20px; top:50%; width: 10px; height: 10px; margin:-5px 0 0 0; outline: 0 !important; z-index: 1; }/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.ui-field-contain { background: none; padding: 1.5em 0; margin: 0; border-bottom-width: 1px; overflow: visible; }  
.ui-field-contain:first-child { border-top-width: 0; }  
@media all and (min-width: 450px){  
.ui-field-contain { border-width: 0; padding: 0; margin: 1em 0; }  
} /*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.ui-select { display: block; position: relative; }  
.ui-select select { position: absolute; left: -9999px; top: -9999px; }  
.ui-select .ui-btn { overflow: hidden; }  
.ui-select .ui-btn select { cursor: pointer; -webkit-appearance: button; left: 0; top:0; width: 100%; height: 100%; opacity: 0; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter: alpha(opacity=0); }  
@-moz-document url-prefix() {.ui-select .ui-btn select { opacity: 0.0001; }}  
.ui-select .ui-btn select.ui-select-nativeonly { opacity: 1; text-indent: 0; }  
 
.ui-select .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; }  
.ui-select .ui-btn-icon-right .ui-icon { right: 15px; }  
 
/* labels */  
label.ui-select { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .3em; display: block; }  
 
/*listbox*/  
.ui-select .ui-btn-text, .ui-selectmenu .ui-btn-text { display: inline-block; min-height: 1em; }  
.ui-select .ui-btn-text { text-overflow: ellipsis; overflow: hidden; display: block;}  
 
.ui-selectmenu { position: absolute; padding: 0; z-index: 100 !important; width: 80%; max-width: 350px; padding: 6px; }  
.ui-selectmenu .ui-listview { margin: 0; }  
.ui-selectmenu .ui-btn.ui-li-divider { cursor: default; }  
.ui-selectmenu-hidden { top: -9999px; left: -9999px; }  
.ui-selectmenu-screen { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 99; }  
.ui-screen-hidden, .ui-selectmenu-list .ui-li .ui-icon { display: none; }  
.ui-selectmenu-list .ui-li .ui-icon { display: block; }  
.ui-li.ui-selectmenu-placeholder { display: none; }  
.ui-selectmenu .ui-header .ui-title { margin: 0.6em 46px 0.8em; }  
 
@media all and (min-width: 450px){  
label.ui-select { display: inline-block; width: 20%; margin: 0 2% 0 0; }  
.ui-select { width: 60%; display: inline-block; }  
}  
 
/* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button. this shim's content in there */  
.ui-selectmenu .ui-header h1:after { content: '.'; visibility: hidden; }/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
label.ui-input-text { font-size: 16px; line-height: 1.4; display: block; font-weight: normal; margin: 0 0 .3em; }  
input.ui-input-text, textarea.ui-input-text { background-image: none; padding: .4em; line-height: 1.4; font-size: 16px; display: block; width: 95%; }  
input.ui-input-text { -webkit-appearance: none; }  
textarea.ui-input-text { height: 50px; -webkit-transition: height 200ms linear; -moz-transition: height 200ms linear; -o-transition: height 200ms linear; transition: height 200ms linear; }  
.ui-input-search { padding: 0 30px; width: 77%; background-position: 8px 50%; background-repeat: no-repeat; position: relative; }  
.ui-input-search input.ui-input-text { border: none; width: 98%; padding: .4em 0; margin: 0; display: block; background: transparent none; outline: 0 !important; }  
.ui-input-search .ui-input-clear { position: absolute; right: 0; top: 50%; margin-top: -14px; }  
.ui-input-search .ui-input-clear-hidden { display: none; }  
 
/* orientation adjustments - incomplete!*/  
@media all and (min-width: 450px){  
label.ui-input-text { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0 }  
input.ui-input-text,  
textarea.ui-input-text,  
.ui-input-search { width: 60%; display: inline-block; }  
.ui-input-search { width: 50%; }  
.ui-input-search input.ui-input-text { width: 98%; /*echos rule from above*/ }  
}/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
.ui-listview { margin: 0; counter-reset: listnumbering; }  
.ui-content .ui-listview { margin: -15px; }  
.ui-content .ui-listview-inset { margin: 1em 0; }  
.ui-listview, .ui-li { list-style:none; padding:0; }  
.ui-li, .ui-li.ui-field-contain { display: block; margin:0; position: relative; overflow: visible; text-align: left; border-width: 0; border-top-width: 1px; }  
.ui-li .ui-btn-text a.ui-link-inherit { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }  
.ui-li-divider, .ui-li-static { padding: .5em 15px; font-size: 14px; font-weight: bold; }  
.ui-li-divider { counter-reset: listnumbering; }  
ol.ui-listview .ui-link-inherit:before, ol.ui-listview .ui-li-static:before, .ui-li-dec { font-size: .8em; display: inline-block; padding-right: .3em; font-weight: normal;counter-increment: listnumbering; content: counter(listnumbering) ". "; }  
ol.ui-listview .ui-li-jsnumbering:before { content: "" !important; } /* to avoid chance of duplication */  
.ui-listview-inset .ui-li { border-right-width: 1px; border-left-width: 1px; }  
.ui-li:last-child, .ui-li.ui-field-contain:last-child { border-bottom-width: 1px; }  
.ui-li>.ui-btn-inner { display: block; position: relative; padding: 0; }  
.ui-li .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li { padding: .7em 75px .7em 15px; display: block; }  
.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-thumb { min-height: 60px; padding-left: 100px; }  
.ui-li-has-icon .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-icon { min-height: 20px; padding-left: 40px; }  
.ui-li-heading { font-size: 16px; font-weight: bold; display: block; margin: .6em 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }  
.ui-li-desc { font-size: 12px; font-weight: normal; display: block; margin: -.5em 0 .6em; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; }  
.ui-li-thumb, .ui-li-icon { position: absolute; left: 1px; top: 0; max-height: 80px; max-width: 80px; }  
.ui-li-icon { max-height: 40px; max-width: 40px; left: 10px; top: .9em; }  
.ui-li-thumb, .ui-li-icon, .ui-li-content { float: left; margin-right: 10px; }  
 
.ui-li-aside { float: right; width: 50%; text-align: right; margin: .3em 0; }  
@media all and (min-width: 480px){  
.ui-li-aside { width: 45%; }  
}  
.ui-li-divider { cursor: default; }  
.ui-li-has-alt .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-alt { padding-right: 95px; }  
.ui-li-count { position: absolute; font-size: 11px; font-weight: bold; padding: .2em .5em; top: 50%; margin-top: -.9em; right: 38px; }  
.ui-li-divider .ui-li-count, .ui-li-static .ui-li-count { right: 10px; }  
.ui-li-has-alt .ui-li-count { right: 55px; }  
.ui-li-link-alt { position: absolute; width: 40px; height: 100%; border-width: 0; border-left-width: 1px; top: 0; right: 0; margin: 0; padding: 0; }  
.ui-li-link-alt .ui-btn { overflow: hidden; position: absolute; right: 8px; top: 50%; margin: -11px 0 0 0; border-bottom-width: 1px; }  
.ui-li-link-alt .ui-btn-inner { padding: 0; position: static; }  
.ui-li-link-alt .ui-btn .ui-icon { right: 50%; margin-right: -9px; }  
 
.ui-listview-filter { border-width: 0; overflow: hidden; margin: -15px -15px 15px -15px }  
.ui-listview-filter .ui-input-search { margin: 5px; width: auto; display: block; }  
 
.ui-listview-filter-inset { margin: -15px -5px -15px -5px; background: transparent; }  
.ui-li.ui-screen-hidden{display:none;}  
/* Odd iPad positioning issue. */  
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {  
.ui-li .ui-btn-text { overflow: visible; }  
}/*  
* jQuery Mobile Framework  
* Copyright (c) jQuery Project  
* Dual licensed under the MIT (MIT-LICENSE.txt) or GPL (GPL-LICENSE.txt) licenses.  
*/  
label.ui-slider { display: block; }  
input.ui-slider-input { display: inline-block; width: 50px; }  
select.ui-slider-switch { display: none; }  
div.ui-slider { position: relative; display: inline-block; overflow: visible; height: 15px; padding: 0; margin: 0 2% 0 20px; top: 4px; width: 66%; }  
a.ui-slider-handle { position: absolute; z-index: 10; top: 50%; width: 28px; height: 28px; margin-top: -15px; margin-left: -15px; }  
a.ui-slider-handle .ui-btn-inner { padding-left: 0; padding-right: 0; }  
@media all and (min-width: 480px){  
label.ui-slider { display: inline-block; width: 20%; margin: 0 2% 0 0; }  
div.ui-slider { width: 45%; }  
}  
 
div.ui-slider-switch { height: 32px; overflow: hidden; margin-left: 0; }  
div.ui-slider-inneroffset { margin-left: 50%; position: absolute; top: 1px; height: 100%; width: 50%; }  
div.ui-slider-handle-snapping { -webkit-transition: left 100ms linear; }  
div.ui-slider-labelbg { position: absolute; top:0; margin: 0; border-width: 0; }  
div.ui-slider-switch div.ui-slider-labelbg-a { width: 60%; height: 100%; left: 0; }  
div.ui-slider-switch div.ui-slider-labelbg-b { width: 60%; height: 100%; right: 0; }  
.ui-slider-switch-a div.ui-slider-labelbg-a, .ui-slider-switch-b div.ui-slider-labelbg-b { z-index: -1; }  
.ui-slider-switch-a div.ui-slider-labelbg-b, .ui-slider-switch-b div.ui-slider-labelbg-a { z-index: 0; }  
 
div.ui-slider-switch a.ui-slider-handle { z-index: 20; width: 101%; height: 32px; margin-top: -18px; margin-left: -101%; }  
span.ui-slider-label { width: 100%; position: absolute;height: 32px; font-size: 16px; text-align: center; line-height: 2; background: none; border-color: transparent; }  
span.ui-slider-label-a { left: -100%; margin-right: -1px }  
span.ui-slider-label-b { right: -100%; margin-left: -1px }  
 
file:b/css/local.css.php (new)
  <?php
 
  header('Content-type: text/css');
  ob_start("compress");
 
  function compress($buffer) {
  /* remove comments */
  $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
  /* remove tabs, spaces, newlines, etc. */
  $buffer = str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $buffer);
  return $buffer;
  }
 
  echo '
  .ui-li-thumb, .ui-li-icon { position: relative; }
 
  .ui-navbar {
  width: 100%;
  }
  .ui-btn-inner {
  white-space: normal !important;
  }
  .ui-li-heading {
  white-space: normal !important;
  }
  .ui-listview-filter {
  margin: 0 !important;
  }
  .ui-icon-navigation {
  background-image: url(images/113-navigation.png);
  background-position: 1px 0;
  }
  .ui-icon-beaker {
  background-image: url(images/91-beaker-2.png);
  background-position: 1px 0;
  }
  #footer {
  text-size: 0.75em;
  text-align: center;
  }
  body {
  background-color: #F0F0F0;
  }
  #jqm-homeheader {
  text-align: center;
  }
  .viaPoints {
  display: none;
  text-size: 0.2em;
  }
  .min-width-480px .viaPoints {
  display: inline;
  }
  #extrainfo {
  visibility: hidden;
  display: none;
  }
  .servicewarning {
  padding: 1em;
  margin-bottom: 0.5em;
  text-size: 0.2em;
  background-color: #FF9;
  -moz-border-radius: 15px;
  border-radius: 15px;
  }
 
 
  #footer {
  clear:both;
  text-align:center;
  }
  // source http://webaim.org/techniques/skipnav/
  #skip a, #skip a:hover, #skip a:visited
  {
  position:absolute;
  left:0px;
  top:-500px;
  width:1px;
  height:1px;
  overflow:hidden;
  }
 
  #skip a:active, #skip a:focus
  {
  position:static;
  width:auto;
  height:auto;
  }';
 
  //if (false)
  echo '
  // adaptive layout from jQuery Mobile docs site
  .type-interior .content-secondary {
  border-right: 0;
  border-left: 0;
  margin: 10px -15px 0;
  background: #fff;
  border-top: 1px solid #ccc;
  }
  .type-home .ui-content {
  margin-top: 5px;
  }
  .type-interior .ui-content {
  padding-bottom: 0;
  }
  .content-secondary .ui-collapsible-contain {
  padding: 10px 15px;
 
  }
  .content-secondary .ui-collapsible-heading {
  margin: 0 0 30px;
  }
  .content-secondary .ui-collapsible-heading-collapsed,
  .content-secondary .ui-collapsible-content {
  padding:0;
  margin: 0;
  }
  /* hires ahoy */
  @media all and (min-width: 650px){
 
  .content-secondary {
  text-align: left;
  float: left;
  width: 45%;
  background: none;
  border-top: 0;
  }
  .content-secondary,
  .type-interior .content-secondary {
  margin: 30px 0 20px 2%;
  padding: 20px 4% 0 0;
  background: none;
  }
  .type-index .content-secondary {
  padding: 0;
  }
  .type-index .content-secondary .ui-listview {
  margin: 0;
  }
  .content-primary {
  width: 45%;
  float: right;
  margin-top: 30px;
  margin-right: 1%;
  padding-right: 1%;
  }
  .content-primary ul:first-child {
  margin-top: 0;
  }
 
  .type-interior .content-primary {
  padding: 1.5em 6% 3em 0;
  margin: 0;
  }
  /* fix up the collapsibles - expanded on desktop */
  .content-secondary .ui-collapsible-heading {
  display: none;
  }
  .content-secondary .ui-collapsible-contain {
  margin:0;
  }
  .content-secondary .ui-collapsible-content {
  display: block;
  margin: 0;
  padding: 0;
  }
  .type-interior .content-secondary .ui-li-divider {
  padding-top: 1em;
  padding-bottom: 1em;
  }
  .type-interior .content-secondary {
  margin: 0;
  padding: 0;
  }
  }
  @media all and (min-width: 750px){
  .type-home .ui-content,
  .type-interior .ui-content {
  background-position: 39%;
  }
  .content-secondary {
  width: 34%;
  }
  .content-primary {
  width: 56%;
  padding-right: 1%;
  }
  .type-interior .ui-content {
  background-position: 34%;
  }
  }
 
  @media all and (min-width: 1200px){
  .type-home .ui-content{
  background-position: 38.5%;
  }
  .type-interior .ui-content {
  background-position: 30%;
  }
  .content-secondary {
  width: 30%;
  padding-right:6%;
  margin: 30px 0 20px 5%;
  }
  .type-interior .content-secondary {
  margin: 0;
  padding: 0;
  }
  .content-primary {
  width: 50%;
  margin-right: 5%;
  padding-right: 3%;
  }
  .type-interior .content-primary {
  width: 60%;
  }
  }
  ';
  ob_end_flush();
  ?>
 
#!/bin/bash #!/bin/bash
#dotcloud postinstall #dotcloud postinstall
   
curl http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip \ curl http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip \
-o /home/dotcloud/current/cbrfeed.zip -o /home/dotcloud/current/cbrfeed.zip
wget http://s3-ap-southeast-1.amazonaws.com/busresources/Graph.obj \ curl http://s3-ap-southeast-1.amazonaws.com/busresources/Graph.obj \
-O /tmp/Graph.obj -o /tmp/Graph.obj
   
#db setup #db setup
#curl https://github.com/maxious/ACTBus-ui/raw/master/transitdata.cbrfeed.sql.gz -o transitdata.cbrfeed.sql.gz #curl https://github.com/maxious/ACTBus-ui/raw/master/transitdata.cbrfeed.sql.gz -o transitdata.cbrfeed.sql.gz
#curl https://github.com/maxious/ACTBus-ui/raw/master/lib/postgis.sql -o postgis.sql #curl https://github.com/maxious/ACTBus-ui/raw/master/lib/postgis.sql -o postgis.sql
#createlang -d transitdata plpgsql #createlang -d transitdata plpgsql
#psql -d transitdata -f postgis.sql #psql -d transitdata -f postgis.sql
#gunzip /var/www/transitdata.cbrfeed.sql.gz #gunzip /var/www/transitdata.cbrfeed.sql.gz
#psql -d transitdata -f transitdata.cbrfeed.sql #psql -d transitdata -f transitdata.cbrfeed.sql
#createuser transitdata -SDRP #createuser transitdata -SDRP
#password transitdata #password transitdata
#psql -c \"GRANT SELECT ON TABLE agency,calendar,calendar_dates,routes,stop_times,stops,trips TO transitdata;\" #psql -c \"GRANT SELECT ON TABLE agency,calendar,calendar_dates,routes,stop_times,stops,trips TO transitdata;\"
   
<?php <?php
include ("include/common.inc.php"); include ("include/common.inc.php");
  $GTFSREnabled = false;
include_header("Feedback", "feedback"); include_header("Feedback", "feedback");
function sendEmail($topic, $message) function sendEmail($topic, $message)
{ {
$address = "maxious@lambdacomplex.org"; $address = "maxious@lambdacomplex.org";
if (file_exists("/tmp/aws.php")) {  
include_once ("lib/ses.php");  
include_once ("/tmp/aws.php");  
$con = new SimpleEmailService($accessKey, $secretKey);  
//$con->verifyEmailAddress($address);  
//$con->listVerifiedEmailAddresses();  
$m = new SimpleEmailServiceMessage();  
$m->addTo($address);  
$m->setFrom($address);  
$m->setSubject($topic);  
$m->setMessageFromString($message);  
$con->sendEmail($m);  
}  
else {  
// In case any of our lines are larger than 70 characters, we should use wordwrap() // In case any of our lines are larger than 70 characters, we should use wordwrap()
$message = wordwrap($message, 70); $message = wordwrap($message, 70);
// Send // Send
mail($address, $topic, $message); mail($address, $topic, $message);
}  
} }
if (isset($_REQUEST['feedback']) || isset($_REQUEST['newlocation'])){ if (isset($_REQUEST['feedback']) || isset($_REQUEST['newlocation'])){
sendEmail("bus.lambda feedback",print_r($_REQUEST,true)); sendEmail("bus.lambda feedback",print_r($_REQUEST,true));
echo "<h2 style='text-align: center;'>Thank you for your feedback!</h2>"; echo "<h2 style='text-align: center;'>Thank you for your feedback!</h2>";
} else { } else {
$stopid = ""; $stopid = "";
$stopcode = ""; $stopcode = "";
$urlparts = explode("?",$_SERVER["HTTP_REFERER"]); if (isset($_SERVER["HTTP_REFERER"])) $urlparts = explode("?",$_SERVER["HTTP_REFERER"]);
if (isset($urlparts[1])) { if (isset($urlparts[1])) {
$getparams = explode("&",$urlparts[1]); $getparams = explode("&",$urlparts[1]);
foreach ($getparams as $param) { foreach ($getparams as $param) {
$paramparts=explode("=",$param); $paramparts=explode("=",$param);
if ($paramparts[0] == "stopid") $stopid = $paramparts[1]; if ($paramparts[0] == "stopid") $stopid = $paramparts[1];
if ($paramparts[0] == "stopcode") $stopcode = $paramparts[1]; if ($paramparts[0] == "stopcode") $stopcode = $paramparts[1];
} }
} }
   
?> ?>
<h3>Add/Move/Delete a Bus Stop Location</h3> <h3>Add/Move/Delete a Bus Stop Location</h3>
<form action="feedback.php" method="post"> <form action="feedback.php" method="post">
StopID: <input type="text" name="stopid" value="<?php echo $stopid ?>"/><br> StopID: <input type="text" name="stopid" value="<?php echo $stopid ?>"/><br>
or StopCode: <input type="text" name="stopcode" value="<?php echo $stopcode ?>"/><br> or StopCode: <input type="text" name="stopcode" value="<?php echo $stopcode ?>"/><br>
<small> if you click on feedback from a stop page, these will get filled in automatically. else describe the location/street of the stop in one of these boxes </small><br> <small> if you click on feedback from a stop page, these will get filled in automatically. else describe the location/street of the stop in one of these boxes </small><br>
   
Suggested Stop Location (lat/long or words): <input type="text" name="newlocation"/><br> Suggested Stop Location (lat/long or words): <input type="text" name="newlocation"/><br>
<!--<small> if your device supports javascript, you can pick a location from the map above</small><br>--> <!--<small> if your device supports javascript, you can pick a location from the map above</small><br>-->
   
<input type="submit" value="Submit!"/> <input type="submit" value="Submit!"/>
</form> </form>
<h3>Bug Report/Feedback</h3> <h3>Bug Report/Feedback</h3>
Please leave feedback about bugs/errors or general suggestions about improvements that could be made to the way the data is presented! Please leave feedback about bugs/errors or general suggestions about improvements that could be made to the way the data is presented!
<form action="feedback.php" method="post"> <form action="feedback.php" method="post">
<textarea name="feedback"> <textarea name="feedback">
</textarea> </textarea>
<textarea name="extrainfo" id="extrainfo"> <textarea name="extrainfo" id="extrainfo">
<?php <?php
echo "Referrer URL: ".$_SERVER["HTTP_REFERER"]; echo "Referrer URL: ".($_SERVER["HTTP_REFERER"] ? $_SERVER["HTTP_REFERER"] : "");
echo "\nCurrent page URL: ".curPageURL(); echo "\nCurrent page URL: ".curPageURL();
echo "\nUser Agent: ".$_SERVER["HTTP_USER_AGENT"]; echo "\nUser Agent: ".$_SERVER["HTTP_USER_AGENT"];
echo "\nUser host/IP: ".$_SERVER["HTTP_X_FORWARDED_FOR"]." ".$_SERVER["REMOTE_ADDR"]; echo "\nUser host/IP: ".$_SERVER["HTTP_X_FORWARDED_FOR"]." ".$_SERVER["REMOTE_ADDR"];
echo "\nServer host/IP: ".php_uname("n"); echo "\nServer host/IP: ".php_uname("n");
echo "\nCurrent date/time: ". date("c"); echo "\nCurrent date/time: ". date("c");
echo "\nCurrent code revision: ".exec("git rev-parse --short HEAD"); echo "\nCurrent code revision: ".exec("git rev-parse --short HEAD");
echo "\nCurrent timetables version: ".date("c",@filemtime('cbrfeed.zip')); echo "\nCurrent timetables version: ".date("c",@filemtime('../busresources/cbrfeed.zip'));
echo "\nDump of session: ".print_r($_SESSION,true); echo "\nDump of session: ".print_r($_SESSION,true);
?> ?>
</textarea> </textarea>
   
<input type="submit" value="Submit!"/> <input type="submit" value="Submit!"/>
</form> </form>
<?php <?php
} }
include_footer(); include_footer();
?> ?>
   
   
<?php <?php
header('Content-Type: application/vnd.google-earth.kml+xml'); header('Content-Type: application/vnd.google-earth.kml+xml');
include ('../include/common.inc.php'); include ('../include/common.inc.php');
  header('Content-Disposition: attachment; filename="route.' . urlencode($routeid) . '.kml"');
  $debugOkay = Array(); // disable debugging output even on dev server
echo '<?xml version="1.0" encoding="UTF-8"?> echo '<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"><Document>'; <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"><Document>';
echo ' echo '
<Style id="yellowLineGreenPoly"> <Style id="ylw-pushpin">
  <IconStyle>
  <Icon>
  <href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
   
  </Icon>
  </IconStyle>
   
  </Style>
  <Style id="blue-pushpin">
  <IconStyle>
  <Icon>
  <href>http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png</href>
   
  </Icon>
  </IconStyle>
   
  </Style>
  <Style id="grn-pushpin">
  <IconStyle>
  <Icon>
  <href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href>
   
  </Icon>
  </IconStyle>
  </Style>
  <Style id="yellowLineYellowPoly">
<LineStyle> <LineStyle>
<color>7f00ff00</color> <color>7f00ebff</color>
<width>4</width> <width>4</width>
</LineStyle> </LineStyle>
<PolyStyle> <PolyStyle>
<color>7f00ffff</color> <color>7f00ebff</color>
</PolyStyle> </PolyStyle>
</Style>'; </Style>
  <Style id="blueLineBluePoly">
  <LineStyle>
  <color>7fff0000</color>
  <width>4</width>
  </LineStyle>
  <PolyStyle>
  <color>7fff0000</color>
  </PolyStyle>
  </Style>
  ';
$route = getRoute($routeid); $route = getRoute($routeid);
echo "\n<Placemark>\n"; echo "\n<Placemark>\n";
$link = curPageURL()."/../trip.php?routeid=".htmlspecialchars ($route["route_id"]); $_REQUEST['time'] = "12:00";
echo "<name>".$route['route_short_name']."</name>"; $trip = getRouteNextTrip($routeid, 0);
echo '<atom:link href="'.$link.'"/>'; $link = curPageURL() . "/../trip.php?routeid=" . htmlspecialchars($route["route_id"]. "&directionid=0&tripid=".$trip['trip_id']) ;
echo '<description><![CDATA[ <a href="'.$link.'">'.$route['route_short_name']." ".$route['route_long_name']."</a>]]> </description>"; echo "<name>" . $route['route_short_name'] . " Direction 0 </name>";
echo "<styleUrl>#yellowLineGreenPoly</styleUrl>"; echo '<atom:link rel="related" href="' . $link . '"/>';
  echo '<description><![CDATA[ <a href="' . $link . '">' . $route['route_short_name'] . " Direction 0</a>]]> </description>";
  echo "<styleUrl>#yellowLineYellowPoly</styleUrl>";
   
$trips = getRouteTrips($routeid); echo getTripShape($trip['trip_id']);
echo getTripShape($trips[0]['trip_id']); echo "</Placemark>\n";
  $stops = Array();
  foreach (getTripStops($trip['trip_id']) as $stop) {
  $stop['style'] = "#ylw-pushpin";
  $stops[$stop['stop_id']] = $stop;
  }
   
echo "</Placemark>\n</Document></kml>\n";  
  echo "\n<Placemark>\n";
  $trip = getRouteNextTrip($routeid, 1);
  $link = curPageURL() . "/../trip.php?routeid=" . htmlspecialchars($route["route_id"]. "&directionid=1&tripid=".$trip['trip_id']) ;
  echo "<name>" . $route['route_short_name'] . " Direction 1 </name>";
  echo '<atom:link rel="related" href="' . $link . '"/>';
  echo '<description><![CDATA[ <a href="' . $link . '">' . $route['route_short_name'] . " Direction 1</a>]]> </description>";
  echo "<styleUrl>#blueLineBluePoly</styleUrl>";
   
  echo getTripShape($trip['trip_id']);
  echo "</Placemark>\n";
  foreach (getTripStops($trip['trip_id']) as $stop) {
  if (isset($stops[$stop['stop_id']])) {
  $stop['style'] = "#grn-pushpin";
  } else {
  $stop['style'] = "#blue-pushpin";
  }
  $stops[$stop['stop_id']] = $stop;
  }
  foreach ($stops as $stop) {
  echo "\n<Placemark>\n";
  $link = curPageURL() . '/../stop.php?stopid=' . htmlspecialchars($stop['stop_id']);
  echo "<name>" . htmlspecialchars($stop['stop_name']) . "</name>";
  echo '<atom:link rel="related" href="' . $link . '"/>';
  echo '<description><![CDATA[ <a href="' . $link . '">' . htmlspecialchars($stop['stop_name']) . "</a>]]> </description>";
  echo "<styleUrl>" . $stop['style'] . "</styleUrl>";
  echo $stop['positionkml'];
  echo "</Placemark>\n";
  }
   
  echo "</Document></kml>\n";
?> ?>
   
   
<?php <?php
header('Content-type: application/vnd.google-earth.kml+xml'); header('Content-type: application/vnd.google-earth.kml+xml');
  include ('../include/common.inc.php');
  header('Content-Disposition: attachment; filename="stops.kml"');
  $debugOkay = Array(); // disable debugging output even on dev server
//http://wiki.openstreetmap.org/wiki/OpenLayers_Dynamic_KML //http://wiki.openstreetmap.org/wiki/OpenLayers_Dynamic_KML
// Creates the KML/XML Document. // Creates the KML/XML Document.
$dom = new DOMDocument('1.0', 'UTF-8'); $dom = new DOMDocument('1.0', 'UTF-8');
// Creates the root KML element and appends it to the root document. // Creates the root KML element and appends it to the root document.
$node = $dom->createElementNS('http://earth.google.com/kml/2.1', 'kml'); $node = $dom->createElementNS('http://www.opengis.net/kml/2.2', 'kml');
$parNode = $dom->appendChild($node); $parNode = $dom->appendChild($node);
// Creates a KML Document element and append it to the KML element. // Creates a KML Document element and append it to the KML element.
$dnode = $dom->createElement('Document'); $dnode = $dom->createElement('Document');
$docNode = $parNode->appendChild($dnode); $docNode = $parNode->appendChild($dnode);
if ($suburb != "") $result_stops = getStopsBySuburb($suburb); if ($suburb != "") $result_stops = getStopsBySuburb($suburb);
else $result_stops = getStops(); else $result_stops = getStops();
foreach ($result_stops as $stop) { foreach ($result_stops as $stop) {
$description = 'http://bus.lambdacomplex.org/' . 'stop.php?stopid=' . $stop['stop_id'] . " <br>"; $description = '<a href="'.curPageURL() . '/../stop.php?stopid=' . $stop['stop_id'] . '">View stop page</a><br>';
// Creates a Placemark and append it to the Document. // Creates a Placemark and append it to the Document.
$node = $dom->createElement('Placemark'); $node = $dom->createElement('Placemark');
$placeNode = $docNode->appendChild($node); $placeNode = $docNode->appendChild($node);
// Creates an id attribute and assign it the value of id column. // Creates an id attribute and assign it the value of id column.
$placeNode->setAttribute('id', 'placemark' . $stop['stop_id']); $placeNode->setAttribute('id', 'placemark' . $stop['stop_id']);
// Create name, and description elements and assigns them the values of the name and address columns from the results. // Create name, and description elements and assigns them the values of the name and address columns from the results.
$nameNode = $dom->createElement('name', htmlentities($stop['stop_name'])); $nameNode = $dom->createElement('name', htmlentities($stop['stop_name']));
$descriptionNode = $dom->createElement('description', $description); $descriptionNode = $dom->createElement('description', $description);
$placeNode->appendChild($nameNode); $placeNode->appendChild($nameNode);
$placeNode->appendChild($descriptionNode); $placeNode->appendChild($descriptionNode);
// Creates a Point element. // Creates a Point element.
$pointNode = $dom->createElement('Point'); $pointNode = $dom->createElement('Point');
$placeNode->appendChild($pointNode); $placeNode->appendChild($pointNode);
// Creates a coordinates element and gives it the value of the lng and lat columns from the results. // Creates a coordinates element and gives it the value of the lng and lat columns from the results.
$coorStr = $stop['stop_lon'] . ',' . $stop['stop_lat']; $coorStr = $stop['stop_lon'] . ',' . $stop['stop_lat'];
$coorNode = $dom->createElement('coordinates', $coorStr); $coorNode = $dom->createElement('coordinates', $coorStr);
$pointNode->appendChild($coorNode); $pointNode->appendChild($coorNode);
} }
$kmlOutput = $dom->saveXML(); $kmlOutput = $dom->saveXML();
echo $kmlOutput; echo $kmlOutput;
?> ?>
   
file:b/geo/trip.kml.php (new)
  <?php
  header('Content-Type: application/vnd.google-earth.kml+xml');
  include ('../include/common.inc.php');
  header('Content-Disposition: attachment; filename="trip.' . urlencode($tripid) . '.kml"');
  $debugOkay = Array(); // disable debugging output even on dev server
  echo '<?xml version="1.0" encoding="UTF-8"?>
  <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom"><Document>';
  echo '
  <Style id="ylw-pushpin">
  <IconStyle>
  <Icon>
  <href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
 
  </Icon>
  </IconStyle>
 
  </Style>
  <Style id="blue-pushpin">
  <IconStyle>
  <Icon>
  <href>http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png</href>
 
  </Icon>
  </IconStyle>
 
  </Style>
  <Style id="grn-pushpin">
  <IconStyle>
  <Icon>
  <href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href>
 
  </Icon>
  </IconStyle>
  </Style>
  <Style id="yellowLineGreenPoly">
  <LineStyle>
  <color>7f00ff00</color>
  <width>4</width>
  </LineStyle>
  <PolyStyle>
  <color>7f00ffff</color>
  </PolyStyle>
  </Style>';
  $trip = getTrip($tripid);
  echo "\n<Placemark>\n";
  $link = curPageURL() . "/../trip.php?tripid=" . htmlspecialchars($$tripid);
  echo "<name>" . $tripid . "</name>";
  echo '<atom:link rel="related" href="' . $link . '"/>';
  echo '<description><![CDATA[ <a href="' . $link . '">' . $tripid . "</a>]]> </description>";
  echo "<styleUrl>#yellowLineGreenPoly</styleUrl>";
 
 
  echo getTripShape($tripid);
 
  echo "</Placemark>\n";
  foreach (getTripStopTimes($tripid) as $stop) {
  echo "\n<Placemark>\n";
  $link = curPageURL() . '/../trip.php?tripid=' . htmlspecialchars($tripid);
  echo "<name>" . $stop['arrival_time'] . " @ " . htmlspecialchars($stop['stop_name']) . "</name>";
  echo '<atom:link rel="related" href="' . $link . '"/>';
  echo '<description><![CDATA[ <a href="' . $link . '">' . htmlspecialchars($stop['stop_name']) . "</a>]]> </description>";
  echo "<styleUrl>#blue-pushpin</styleUrl>";
  echo "<Point><coordinates>" . $stop['stop_lon'] . "," . $stop['stop_lat'] . "</coordinates></Point>";
 
  echo "</Placemark>\n";
  }
  echo "</Document></kml>\n";
  ?>
 
 
  <?php
  require $basePath.'lib/openid.php';
  $openid = new LightOpenID($_SERVER['HTTP_HOST']);
 
  function login()
  {
  global $openid;
  if(!$openid->mode) {
  $openid->required = array('contact/email');
  $openid->identity = 'https://www.google.com/accounts/o8/id';
  header('Location: ' . $openid->authUrl());
  }
  }
 
 
  function auth()
 
  {
  if ($_SESSION['authed'] == true) return true;
  global $openid;
 
  if($openid->mode) {
  $attr = $openid->getAttributes();
  if ($attr["contact/email"] != "maxious@gmail.com") {
  die("Access Denied");
  } else {
  $_SESSION['authed'] = true;
  }
  } else {
  login();
  }
  }
 
<?php <?php
if (php_uname('n') == "actbus-www") {  
$conn = new PDO("pgsql:dbname=transitdata;user=transitdata;password=transitdata;host=bus-main.lambdacomplex.org"); /*
} * Copyright 2010,2011 Alexander Sadleir
else if (isDebugServer()) {  
$conn = new PDO("pgsql:dbname=transitdata;user=postgres;password=snmc;host=localhost"); Licensed under the Apache License, Version 2.0 (the "License");
} you may not use this file except in compliance with the License.
else { You may obtain a copy of the License at
$conn = new PDO("pgsql:dbname=transitdata;user=transitdata;password=transitdata;host=localhost");  
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
  if (strstr(php_uname('n'),"actbus")) {
  $conn = new PDO("pgsql:dbname=transitdata;user=transitdata;password=transitdata;host=bus-main.lambdacomplex.org");
  } else if (isDebugServer()) {
  $conn = new PDO("pgsql:dbname=transitdata;user=postgres;password=snmc;host=localhost");
  } else {
  $conn = new PDO("pgsql:dbname=transitdata;user=transitdata;password=transitdata;host=localhost");
} }
if (!$conn) { if (!$conn) {
die("A database error occurred.\n"); die("A database error occurred.\n");
} }
if (isDebug()) {  
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); function databaseError($errMsg) {
  if ($errMsg[1] != "") {
  die(print_r($errMsg,true));
  }
} }
function databaseError($errMsg)  
{  
die($errMsg);  
}  
include ('db/route-dao.inc.php'); include ('db/route-dao.inc.php');
include ('db/trip-dao.inc.php'); include ('db/trip-dao.inc.php');
include ('db/stop-dao.inc.php'); include ('db/stop-dao.inc.php');
include ('db/servicealert-dao.inc.php'); include ('db/servicealert-dao.inc.php');
?>  
   
<?php <?php
   
  /*
  * Copyright 2010,2011 Alexander Sadleir
   
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
   
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
// SELECT array_to_string(array(SELECT REPLACE(name_2006, ',', '\,') as name FROM suburbs order by name), ',') // SELECT array_to_string(array(SELECT REPLACE(name_2006, ',', '\,') as name FROM suburbs order by name), ',')
$suburbs = explode(",", "Acton,Ainslie,Amaroo,Aranda,Banks,Barton,Belconnen,Bonner,Bonython,Braddon,Bruce,Calwell,Campbell,Chapman,Charnwood,Chifley,Chisholm,City,Conder,Cook,Curtin,Deakin,Dickson,Downer,Duffy,Dunlop,Evatt,Fadden,Farrer,Fisher,Florey,Flynn,Forrest,Franklin,Fraser,Fyshwick,Garran,Gilmore,Giralang,Gordon,Gowrie,Greenway,Griffith,Gungahlin,Hackett,Hall,Harrison,Hawker,Higgins,Holder,Holt,Hughes,Hume,Isaacs,Isabella Plains,Kaleen,Kambah,Kingston,Latham,Lawson,Lyneham,Lyons,Macarthur,Macgregor,Macquarie,Mawson,McKellar,Melba,Mitchell,Monash,Narrabundah,Ngunnawal,Nicholls,Oaks Estate,O'Connor,O'Malley,Oxley,Page,Palmerston,Parkes,Pearce,Phillip,Pialligo,Red Hill,Reid,Richardson,Rivett,Russell,Scullin,Spence,Stirling,Symonston,Tharwa,Theodore,Torrens,Turner,Wanniassa,Waramanga,Watson,Weetangera,Weston,Yarralumla"); $suburbs = explode(",", "Acton,Ainslie,Amaroo,Aranda,Banks,Barton,Belconnen,Bonner,Bonython,Braddon,Bruce,Calwell,Campbell,Chapman,Charnwood,Chifley,Chisholm,City,Conder,Cook,Curtin,Deakin,Dickson,Downer,Duffy,Dunlop,Evatt,Fadden,Farrer,Fisher,Florey,Flynn,Forrest,Franklin,Fraser,Fyshwick,Garran,Gilmore,Giralang,Gordon,Gowrie,Greenway,Griffith,Gungahlin,Hackett,Hall,Harrison,Hawker,Higgins,Holder,Holt,Hughes,Hume,Isaacs,Isabella Plains,Kaleen,Kambah,Kingston,Latham,Lawson,Lyneham,Lyons,Macarthur,Macgregor,Macquarie,Mawson,McKellar,Melba,Mitchell,Monash,Narrabundah,Ngunnawal,Nicholls,Oaks Estate,O'Connor,O'Malley,Oxley,Page,Palmerston,Parkes,Pearce,Phillip,Pialligo,Red Hill,Reid,Richardson,Rivett,Russell,Scullin,Spence,Stirling,Symonston,Tharwa,Theodore,Torrens,Turner,Wanniassa,Waramanga,Watson,Weetangera,Weston,Yarralumla");
function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb", $collapsible = true)  
{ function staticmap($mapPoints, $collapsible = true, $twotone = false, $path = false, $numbered = false) {
global $labsPath;  
$width = 300; $markers = "";
$height = 300; $height = 300;
$metersperpixel[9] = 305.492 * $width; $width = $height;
$metersperpixel[10] = 152.746 * $width; $index = 0;
$metersperpixel[11] = 76.373 * $width; if (sizeof($mapPoints) < 1)
$metersperpixel[12] = 38.187 * $width; return "map error";
$metersperpixel[13] = 19.093 * $width; if (sizeof($mapPoints) === 1) {
$metersperpixel[14] = 9.547 * $width; $markers = "markers={$mapPoints[0][0]},{$mapPoints[0][1]}";
$metersperpixel[15] = 4.773 * $width; } else {
$metersperpixel[16] = 2.387 * $width; if (!$numbered) {
// $metersperpixel[17]=1.193*$width; $markers = "markers=";
$center = ""; }
$markers = ""; if ($path) {
$minlat = 999; $markers.= "markers={$mapPoints[0][0]},{$mapPoints[0][1]}&amp;path=";
$minlon = 999; }
$maxlat = 0; foreach ($mapPoints as $index => $mapPoint) {
$maxlon = 0; if ($twotone && $index == 0) {
if (sizeof($mapPoints) < 1) return "map error"; $markers = "markerd=color:red|".$mapPoint[0] . "," . $mapPoint[1]."&amp;markers=";
if (sizeof($mapPoints) === 1) { } else {
if ($zoom == 0) $zoom = 14; if ($numbered) {
$markers.= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage"; $label = ($index > 9 ? 9 : $index);
$center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; $markers.= "markers=label:$label|" . $mapPoint[0] . "," . $mapPoint[1];
} if ($index + 1 != sizeof($mapPoints)) {
else { $markers.= "&amp;";
foreach ($mapPoints as $index => $mapPoint) { }
$markers.= $mapPoint[0] . "," . $mapPoint[1] . "," . $markerImage . ($index + 1); } else {
if ($index + 1 != sizeof($mapPoints)) $markers.= "|"; $markers.= $mapPoint[0] . "," . $mapPoint[1];
if ($mapPoint[0] < $minlat) $minlat = $mapPoint[0]; if ($index + 1 != sizeof($mapPoints)) {
if ($mapPoint[0] > $maxlat) $maxlat = $mapPoint[0]; $markers.= "|";
if ($mapPoint[1] < $minlon) $minlon = $mapPoint[1]; }
if ($mapPoint[1] > $maxlon) $maxlon = $mapPoint[1]; }
$totalLat+= $mapPoint[0]; $index++;
$totalLon+= $mapPoint[1]; }
} }
if ($zoom == 0) { }
$mapwidthinmeters = distance($minlat, $minlon, $minlat, $maxlon); $output = "";
foreach (array_reverse($metersperpixel, true) as $zoomLevel => $maxdistance) { if ($collapsible)
if ($zoom == 0 && $mapwidthinmeters < ($maxdistance + 50)) $zoom = $zoomLevel; $output.= '<div class="map" data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
} if (isIOSDevice()) $output.= '<img class="hiresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=2&amp;sensor=true" width=' . $width . ' height=' . $height . ' alt="map of stop location">';
} else $output.= '<img class="lowresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=1&amp;format=jpg&amp;sensor=true" width=' . $width . ' height=' . $height . ' alt="map of stop location">';
$center = $totalLat / sizeof($mapPoints) . "," . $totalLon / sizeof($mapPoints);  
} if ($collapsible)
$output = ""; $output.= '</div>';
if ($collapsible) $output.= '<div class="map" data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>'; return $output;
$output.= '<img class="map" src="' . curPageURL() . '/'. $labsPath. '/lib/staticmaplite/staticmap.php?center=' . $center . '&amp;zoom=' . $zoom . '&amp;size=' . $width . 'x' . $height . '&amp;markers=' .  
$markers . '" width=' . $width . ' height=' . $height . '>';  
if ($collapsible) $output.= '</div>';  
return $output;  
}  
function distance($lat1, $lng1, $lat2, $lng2, $roundLargeValues = false)  
{  
$pi80 = M_PI / 180;  
$lat1*= $pi80;  
$lng1*= $pi80;  
$lat2*= $pi80;  
$lng2*= $pi80;  
$r = 6372.797; // mean radius of Earth in km  
$dlat = $lat2 - $lat1;  
$dlng = $lng2 - $lng1;  
$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);  
$c = 2 * atan2(sqrt($a) , sqrt(1 - $a));  
$km = $r * $c;  
if ($roundLargeValues) {  
if ($km < 1) return floor($km * 1000);  
else return round($km,2)."k";  
} else return floor($km * 1000);  
} }
   
function decodePolylineToArray($encoded) function distance($lat1, $lng1, $lat2, $lng2, $roundLargeValues = false) {
{ $pi80 = M_PI / 180;
// source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5 $lat1*= $pi80;
$length = strlen($encoded); $lng1*= $pi80;
$index = 0; $lat2*= $pi80;
$points = array(); $lng2*= $pi80;
$lat = 0; $r = 6372.797; // mean radius of Earth in km
$lng = 0; $dlat = $lat2 - $lat1;
while ($index < $length) { $dlng = $lng2 - $lng1;
// Temporary variable to hold each ASCII byte. $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);
$b = 0; $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
// The encoded polyline consists of a latitude value followed by a $km = $r * $c;
// longitude value. They should always come in pairs. Read the if ($roundLargeValues) {
// latitude value first. if ($km < 1)
$shift = 0; return floor($km * 1000);
$result = 0; else
do { return round($km, 2) . "k";
// The `ord(substr($encoded, $index++))` statement returns the ASCII }
// code for the character at $index. Subtract 63 to get the original else
// value. (63 was added to ensure proper ASCII characters are displayed return floor($km * 1000);
// in the encoded polyline string, which is `human` readable)  
$b = ord(substr($encoded, $index++)) - 63;  
// AND the bits of the byte with 0x1f to get the original 5-bit `chunk.  
// Then left shift the bits by the required amount, which increases  
// by 5 bits each time.  
// OR the value into $results, which sums up the individual 5-bit chunks  
// into the original value. Since the 5-bit chunks were reversed in  
// order during encoding, reading them in this way ensures proper  
// summation.  
$result|= ($b & 0x1f) << $shift;  
$shift+= 5;  
}  
// Continue while the read byte is >= 0x20 since the last `chunk`  
// was not OR'd with 0x20 during the conversion process. (Signals the end)  
while ($b >= 0x20);  
// Check if negative, and convert. (All negative values have the last bit  
// set)  
$dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1));  
// Compute actual latitude since value is offset from previous value.  
$lat+= $dlat;  
// The next values will correspond to the longitude for this point.  
$shift = 0;  
$result = 0;  
do {  
$b = ord(substr($encoded, $index++)) - 63;  
$result|= ($b & 0x1f) << $shift;  
$shift+= 5;  
} while ($b >= 0x20);  
$dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1));  
$lng+= $dlng;  
// The actual latitude and longitude values were multiplied by  
// 1e5 before encoding so that they could be converted to a 32-bit  
// integer representation. (With a decimal accuracy of 5 places)  
// Convert back to original values.  
$points[] = array(  
$lat * 1e-5,  
$lng * 1e-5  
);  
}  
return $points;  
} }
function geocode($query, $giveOptions)  
{ function decodePolylineToArray($encoded) {
global $cloudmadeAPIkey; // source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5
$url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?query=" . urlencode($query) . "&bbox=-35.5,149.00,-35.15,149.1930&return_location=true&bbox_only=true"; $length = strlen($encoded);
$contents = json_decode(getPage($url)); $index = 0;
if ($giveOptions) return $contents->features; $points = array();
elseif (isset($contents->features[0]->centroid)) return $contents->features[0]->centroid->coordinates[0] . "," . $contents->features[0]->centroid->coordinates[1]; $lat = 0;
else return ""; $lng = 0;
  while ($index < $length) {
  // Temporary variable to hold each ASCII byte.
  $b = 0;
  // The encoded polyline consists of a latitude value followed by a
  // longitude value. They should always come in pairs. Read the
  // latitude value first.
  $shift = 0;
  $result = 0;
  do {
  // The `ord(substr($encoded, $index++))` statement returns the ASCII
  // code for the character at $index. Subtract 63 to get the original
  // value. (63 was added to ensure proper ASCII characters are displayed
  // in the encoded polyline string, which is `human` readable)
  $b = ord(substr($encoded, $index++)) - 63;
  // AND the bits of the byte with 0x1f to get the original 5-bit `chunk.
  // Then left shift the bits by the required amount, which increases
  // by 5 bits each time.
  // OR the value into $results, which sums up the individual 5-bit chunks
  // into the original value. Since the 5-bit chunks were reversed in
  // order during encoding, reading them in this way ensures proper
  // summation.
  $result|= ($b & 0x1f) << $shift;
  $shift+= 5;
  }
  // Continue while the read byte is >= 0x20 since the last `chunk`
  // was not OR'd with 0x20 during the conversion process. (Signals the end)
  while ($b >= 0x20);
  // Check if negative, and convert. (All negative values have the last bit
  // set)
  $dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1));
  // Compute actual latitude since value is offset from previous value.
  $lat+= $dlat;
  // The next values will correspond to the longitude for this point.
  $shift = 0;
  $result = 0;
  do {
  $b = ord(substr($encoded, $index++)) - 63;
  $result|= ($b & 0x1f) << $shift;
  $shift+= 5;
  } while ($b >= 0x20);
  $dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1));
  $lng+= $dlng;
  // The actual latitude and longitude values were multiplied by
  // 1e5 before encoding so that they could be converted to a 32-bit
  // integer representation. (With a decimal accuracy of 5 places)
  // Convert back to original values.
  $points[] = array(
  $lat * 1e-5,
  $lng * 1e-5
  );
  }
  return $points;
} }
function reverseGeocode($lat, $lng)  
{ function geocode($query, $giveOptions) {
global $cloudmadeAPIkey; global $cloudmadeAPIkey;
$url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?around=" . $lat . "," . $lng . "&distance=closest&object_type=road"; $url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?query=" . urlencode($query) . "&bbox=-35.5,149.00,-35.15,149.1930&return_location=true&bbox_only=true";
$contents = json_decode(getPage($url)); $contents = json_decode(getPage($url));
return $contents->features[0]->properties->name; if ($giveOptions)
  return $contents->features;
  elseif (isset($contents->features[0]->centroid))
  return $contents->features[0]->centroid->coordinates[0] . "," . $contents->features[0]->centroid->coordinates[1];
  else
  return "";
} }
?>  
   
  function reverseGeocode($lat, $lng) {
  global $cloudmadeAPIkey;
  $url = "http://geocoding.cloudmade.com/$cloudmadeAPIkey/geocoding/v2/find.js?around=" . $lat . "," . $lng . "&distance=closest&object_type=road";
  $contents = json_decode(getPage($url));
  return $contents->features[0]->properties->name;
  }
   
<?php <?php
function getPage($url)  
{ /*
debug($url, "json"); * Copyright 2010,2011 Alexander Sadleir
$ch = curl_init($url);  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); Licensed under the Apache License, Version 2.0 (the "License");
curl_setopt($ch, CURLOPT_HEADER, 0); you may not use this file except in compliance with the License.
curl_setopt($ch, CURLOPT_TIMEOUT, 45); You may obtain a copy of the License at
$page = curl_exec($ch);  
if (curl_errno($ch)) { http://www.apache.org/licenses/LICENSE-2.0
echo "<font color=red> Database temporarily unavailable: ";  
echo curl_errno($ch) . " " . curl_error($ch); Unless required by applicable law or agreed to in writing, software
if (isDebug()) { distributed under the License is distributed on an "AS IS" BASIS,
echo $url; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
} See the License for the specific language governing permissions and
echo "</font><br>"; limitations under the License.
} */
curl_close($ch);  
debug(print_r($page,true),"json"); function getPage($url) {
return $page; debug($url, "json");
  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_TIMEOUT, 45);
  $page = curl_exec($ch);
  if (curl_errno($ch)) {
  echo "<font color=red> Database temporarily unavailable: ";
  echo curl_errno($ch) . " " . curl_error($ch);
  if (isDebug()) {
  echo $url;
  }
  echo "</font><br>";
  }
  curl_close($ch);
  debug(print_r($page, true), "json");
  return $page;
} }
function curPageURL() function curPageURL() {
{ $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on");
$isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"); $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443")));
$port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443"))); $port = ($port) ? ':' . $_SERVER["SERVER_PORT"] : '';
$port = ($port) ? ':' . $_SERVER["SERVER_PORT"] : ''; $url = ($isHTTPS ? 'https://' : 'http://') . $_SERVER["SERVER_NAME"] . $port . htmlentities(dirname($_SERVER['PHP_SELF']), ENT_QUOTES);
$url = ($isHTTPS ? 'https://' : 'http://') . $_SERVER["SERVER_NAME"] . $port . htmlentities(dirname($_SERVER['PHP_SELF']) , ENT_QUOTES); return $url;
return $url;  
} }
?>  
   
   
<?php <?php
   
  /*
  * Copyright 2010,2011 Alexander Sadleir
   
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
   
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
if (isset($_REQUEST['firstLetter'])) { if (isset($_REQUEST['firstLetter'])) {
$firstLetter = filter_var($_REQUEST['firstLetter'], FILTER_SANITIZE_STRING); $firstLetter = filter_var($_REQUEST['firstLetter'], FILTER_SANITIZE_STRING);
} }
if (isset($_REQUEST['bysuburbs'])) { if (isset($_REQUEST['bysuburbs'])) {
$bysuburbs = true; $bysuburbs = true;
} }
if (isset($_REQUEST['bynumber'])) { if (isset($_REQUEST['bynumber'])) {
$bynumber = true; $bynumber = true;
} }
if (isset($_REQUEST['allstops'])) { if (isset($_REQUEST['allstops'])) {
$allstops = true; $allstops = true;
} }
if (isset($_REQUEST['nearby'])) { if (isset($_REQUEST['nearby'])) {
$nearby = true; $nearby = true;
  }
  if (isset($_REQUEST['labs'])) {
  $labs = true;
} }
if (isset($_REQUEST['suburb'])) { if (isset($_REQUEST['suburb'])) {
$suburb = filter_var($_REQUEST['suburb'], FILTER_SANITIZE_STRING); $suburb = $_REQUEST['suburb'];
} }
$pageKey = filter_var($_REQUEST['pageKey'], FILTER_SANITIZE_NUMBER_INT); if (isset($_REQUEST['pageKey'])) {
$lat = filter_var($_REQUEST['lat'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); $pageKey = filter_var($_REQUEST['pageKey'], FILTER_SANITIZE_NUMBER_INT);
$lon = filter_var($_REQUEST['lon'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); }
$max_distance = filter_var($_REQUEST['radius'], FILTER_SANITIZE_NUMBER_INT); if (isset($_REQUEST['lat'])) {
  $lat = filter_var($_REQUEST['lat'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
  }
  if (isset($_REQUEST['lon'])) {
  $lon = filter_var($_REQUEST['lon'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
  }
  if (isset($_REQUEST['radius'])) {
  $max_distance = filter_var($_REQUEST['radius'], FILTER_SANITIZE_NUMBER_INT);
  }
if (isset($_REQUEST['numberSeries'])) { if (isset($_REQUEST['numberSeries'])) {
$numberSeries = filter_var($_REQUEST['numberSeries'], FILTER_SANITIZE_NUMBER_INT); $numberSeries = filter_var($_REQUEST['numberSeries'], FILTER_SANITIZE_NUMBER_INT);
} }
if (isset($_REQUEST['routeDestination'])) { if (isset($_REQUEST['routeDestination'])) {
$routeDestination = urldecode(filter_var($_REQUEST['routeDestination'], FILTER_SANITIZE_ENCODED)); $routeDestination = urldecode(filter_var($_REQUEST['routeDestination'], FILTER_SANITIZE_ENCODED));
  }
  if (isset($_REQUEST['routename'])) {
  $routename = urldecode(filter_var($_REQUEST['routename'], FILTER_SANITIZE_ENCODED));
} }
if (isset($_REQUEST['stopcode'])) { if (isset($_REQUEST['stopcode'])) {
$stopcode = filter_var($_REQUEST['stopcode'], FILTER_SANITIZE_STRING); $stopcode = filter_var($_REQUEST['stopcode'], FILTER_SANITIZE_STRING);
} }
if (isset($_REQUEST['stopids'])) { if (isset($_REQUEST['stopids'])) {
$stopids = explode(",", filter_var($_REQUEST['stopids'], FILTER_SANITIZE_STRING)); $stopids = explode(",", filter_var($_REQUEST['stopids'], FILTER_SANITIZE_STRING));
  }
  if (isset($_REQUEST['filterIncludeRoutes'])) {
  $filterIncludeRoutes = explode(",", filter_var($_REQUEST['filterIncludeRoutes'], FILTER_SANITIZE_STRING));
  }
  if (isset($_REQUEST['filterHasStop'])) {
  $filterHasStop = filter_var($_REQUEST['filterHasStop'], FILTER_SANITIZE_STRING);
} }
if (isset($_REQUEST['tripid'])) { if (isset($_REQUEST['tripid'])) {
$tripid = filter_var($_REQUEST['tripid'], FILTER_SANITIZE_NUMBER_INT); $tripid = filter_var($_REQUEST['tripid'], FILTER_SANITIZE_STRING);
  }
  if (isset($_REQUEST['routeid'])) {
  $routeid = filter_var($_REQUEST['routeid'], FILTER_SANITIZE_STRING);
  }
  if (isset($_REQUEST['directionid'])) {
  $directionid = filter_var($_REQUEST['directionid'], FILTER_SANITIZE_STRING);
} }
if (isset($_REQUEST['stopid'])) { if (isset($_REQUEST['stopid'])) {
$stopid = filter_var($_REQUEST['stopid'], FILTER_SANITIZE_NUMBER_INT); $stopid = filter_var($_REQUEST['stopid'], FILTER_SANITIZE_NUMBER_INT);
}  
if (isset($_REQUEST['routeid'])) {  
$routeid = filter_var($_REQUEST['routeid'], FILTER_SANITIZE_NUMBER_INT);  
} }
if (isset($_REQUEST['geolocate'])) { if (isset($_REQUEST['geolocate'])) {
$geolocate = filter_var($_REQUEST['geolocate'], FILTER_SANITIZE_URL); $geolocate = filter_var($_REQUEST['geolocate'], FILTER_SANITIZE_URL);
} }
?>  
<?php <?php
   
  /*
  * Copyright 2010,2011 Alexander Sadleir
   
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
   
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
// you have to open the session to be able to modify or remove it // you have to open the session to be able to modify or remove it
session_start(); session_start();
if (isset($_REQUEST['service_period'])) { if (isset($_REQUEST['geolocate']) && $_REQUEST['geolocate'] != "Enter co-ordinates or address here") {
$_SESSION['service_period'] = filter_var($_REQUEST['service_period'], FILTER_SANITIZE_STRING); $geocoded = false;
sessionUpdated(); if (isset($_REQUEST['lat']) && isset($_REQUEST['lon'])) {
  $_SESSION['lat'] = trim(filter_var($_REQUEST['lat'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
  $_SESSION['lon'] = trim(filter_var($_REQUEST['lon'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
  } else {
  if (startsWith($geolocate, "-")) {
  $locateparts = explode(",", $geolocate);
  $_SESSION['lat'] = $locateparts[0];
  $_SESSION['lon'] = $locateparts[1];
  } else if (strpos($geolocate, "(") !== false) {
  $geoParts = explode("(", $geolocate);
  $locateparts = explode(",", str_replace(")", "", $geoParts[1]));
  $_SESSION['lat'] = $locateparts[0];
  $_SESSION['lon'] = $locateparts[1];
  } else {
  $contents = geocode($geolocate, true);
  print_r($contents);
  if (isset($contents[0]->centroid)) {
  $geocoded = true;
  $_SESSION['lat'] = $contents[0]->centroid->coordinates[0];
  $_SESSION['lon'] = $contents[0]->centroid->coordinates[1];
  } else {
  $_SESSION['lat'] = "";
  $_SESSION['lon'] = "";
  }
  }
  }
  sessionUpdated();
} }
if (isset($_REQUEST['time'])) {  
$_SESSION['time'] = filter_var($_REQUEST['time'], FILTER_SANITIZE_STRING); function sessionUpdated() {
sessionUpdated(); $_SESSION['lastUpdated'] = time();
} }
if (isset($_REQUEST['geolocate']) && $_REQUEST['geolocate'] != "Enter co-ordinates or address here") {  
$geocoded = false;  
if (isset($_REQUEST['lat']) && isset($_REQUEST['lon'])) {  
$_SESSION['lat'] = trim(filter_var($_REQUEST['lat'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));  
$_SESSION['lon'] = trim(filter_var($_REQUEST['lon'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));  
}  
else {  
if (startsWith($geolocate, "-")) {  
$locateparts = explode(",", $geolocate);  
$_SESSION['lat'] = $locateparts[0];  
$_SESSION['lon'] = $locateparts[1];  
}  
else if (strpos($geolocate, "(") !== false) {  
$geoParts = explode("(", $geolocate);  
$locateparts = explode(",", str_replace(")", "",$geoParts[1]));  
$_SESSION['lat'] = $locateparts[0];  
$_SESSION['lon'] = $locateparts[1];  
}  
else {  
$contents = geocode($geolocate, true);  
print_r($contents);  
if (isset($contents[0]->centroid)) {  
$geocoded = true;  
$_SESSION['lat'] = $contents[0]->centroid->coordinates[0];  
$_SESSION['lon'] = $contents[0]->centroid->coordinates[1];  
}  
else {  
$_SESSION['lat'] = "";  
$_SESSION['lon'] = "";  
}  
}  
}  
sessionUpdated();  
}  
function sessionUpdated()  
{  
$_SESSION['lastUpdated'] = time();  
}  
// timeoutSession // timeoutSession
$TIMEOUT_LIMIT = 60 * 5; // 5 minutes $TIMEOUT_LIMIT = 60 * 5; // 5 minutes
if (isset($_SESSION['lastUpdated']) && $_SESSION['lastUpdated'] + $TIMEOUT_LIMIT < time()) { if (isset($_SESSION['lastUpdated']) && $_SESSION['lastUpdated'] + $TIMEOUT_LIMIT < time()) {
debug("Session timeout " . ($_SESSION['lastUpdated'] + $TIMEOUT_LIMIT) . ">" . time() , "session"); debug("Session timeout " . ($_SESSION['lastUpdated'] + $TIMEOUT_LIMIT) . ">" . time(), "session");
session_destroy(); session_destroy();
session_start(); session_start();
} }
   
//debug(print_r($_SESSION, true) , "session"); //debug(print_r($_SESSION, true) , "session");
function current_time() function current_time($time = "") {
{ if (isset($_REQUEST['time'])) return $_REQUEST['time'];
return ($_SESSION['time'] ? $_SESSION['time'] : date("H:i:s")); else if ($time != "") date("H:i:s",$time);
  else return date("H:i:s");
} }
?>  
   
   
<?php <?php
   
  /*
  * Copyright 2010,2011 Alexander Sadleir
   
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
   
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
   
// Copyright 2009 Google Inc. All Rights Reserved. // Copyright 2009 Google Inc. All Rights Reserved.
$GA_ACCOUNT = "MO-22173039-1"; $GA_ACCOUNT = "MO-22173039-1";
$GA_PIXEL = "/lib/ga.php"; $GA_PIXEL = "/lib/ga.php";
function googleAnalyticsGetImageUrl()  
{ function googleAnalyticsGetImageUrl() {
global $GA_ACCOUNT, $GA_PIXEL; global $GA_ACCOUNT, $GA_PIXEL;
//if (stristr($_SERVER['HTTP_USER_AGENT'], 'Googlebot') return ""; //if (stristr($_SERVER['HTTP_USER_AGENT'], 'Googlebot') return "";
$url = ""; $url = "";
$url.= $GA_PIXEL . "?"; $url.= $GA_PIXEL . "?";
$url.= "utmac=" . $GA_ACCOUNT; $url.= "utmac=" . $GA_ACCOUNT;
$url.= "&utmn=" . rand(0, 0x7fffffff); $url.= "&utmn=" . rand(0, 0x7fffffff);
$referer = $_SERVER["HTTP_REFERER"]; $referer = (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : "");
$query = $_SERVER["QUERY_STRING"]; $query = $_SERVER["QUERY_STRING"];
$path = $_SERVER["REQUEST_URI"]; $path = $_SERVER["REQUEST_URI"];
if (empty($referer)) { if (empty($referer)) {
$referer = "-"; $referer = "-";
} }
$url.= "&utmr=" . urlencode($referer); $url.= "&utmr=" . urlencode($referer);
if (!empty($path)) { if (!empty($path)) {
$url.= "&utmp=" . urlencode($path); $url.= "&utmp=" . urlencode($path);
} }
$url.= "&guid=ON"; $url.= "&guid=ON";
return str_replace("&", "&amp;", $url); return str_replace("&", "&amp;", $url);
} }
   
function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false) function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false) {
{ global $basePath, $GTFSREnabled, $stopid, $routeid;
global $labsPath; echo '
echo '  
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>' . $pageTitle . '</title> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="google-site-verification" <title>' . $pageTitle . ' - Canberra Bus Timetable</title>
content="-53T5Qn4TB_de1NyfR_ZZkEVdUNcNFSaYKSFkWKx-sY" /> <meta name="google-site-verification" content="-53T5Qn4TB_de1NyfR_ZZkEVdUNcNFSaYKSFkWKx-sY" />
<link rel="stylesheet" href="'.$labsPath.'css/jquery-ui-1.8.12.custom.css" />'; <link rel="dns-prefetch" href="//code.jquery.com">
if (isDebugServer()) { <link rel="dns-prefetch" href="//ajax.googleapis.com">';
echo '<link rel="stylesheet" href="'.$labsPath.'css/jquery.mobile-1.0b1.css" /> $jqmVersion = "1.0.1";
  echo '
<script type="text/javascript" src="'.$labsPath.'js/jquery-1.6.1.min.js"></script> <script src="'.$basePath.'js/yepnope/yepnope.1.5.3-min.js"></script>
<script>$(document).bind("mobileinit", function(){ <script>
  yepnope([{
  load: "//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js",
  complete: function () {
   
  $(document).bind("mobileinit", function(){
$.mobile.ajaxEnabled = false; $.mobile.ajaxEnabled = false;
}); }); }
</script>  
<script type="text/javascript" src="'.$labsPath.'js/jquery.mobile-1.0b1.js"></script>'; }, {
} load: ["//code.jquery.com/mobile/' . $jqmVersion . '/jquery.mobile-' . $jqmVersion . '.min.css","//code.jquery.com/mobile/' . $jqmVersion . '/jquery.mobile-' . $jqmVersion . '.min.js"]
else { }, {
echo '<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.css" /> load: ["' . $basePath . 'css/jquery-ui-1.8.12.custom.css","' . $basePath . 'js/jquery.ui.core.min.js","' . $basePath . 'js/jquery.ui.position.min.js","' . $basePath . 'js/jquery.ui.widget.min.js","' . $basePath . 'js/jquery.ui.autocomplete.min.js"],
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script> complete: function() {
<script>$(document).bind("mobileinit", function(){  
$.mobile.ajaxEnabled = false;  
});  
</script>  
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0b1/jquery.mobile-1.0b1.min.js"></script>';  
}  
echo '  
<script src="'.$labsPath.'js/jquery.ui.autocomplete.min.js"></script>  
<script src="'.$labsPath.'js/jquery.ui.core.min.js"></script>  
<script src="'.$labsPath.'js/jquery.ui.position.min.js"></script>  
<script src="'.$labsPath.'js/jquery.ui.widget.min.js"></script>  
<script>  
$(function() {  
$( "#geolocate" ).autocomplete({ $( "#geolocate" ).autocomplete({
source: "lib/autocomplete.php", source: "lib/autocomplete.php",
minLength: 2 minLength: 2
}); });
$( "#from" ).autocomplete({ $( "#from" ).autocomplete({
source: "lib/autocomplete.php", source: "lib/autocomplete.php",
minLength: 2 minLength: 2
}); });
$( "#to" ).autocomplete({ $( "#to" ).autocomplete({
source: "lib/autocomplete.php", source: "lib/autocomplete.php",
minLength: 2 minLength: 2
}); });
}); }
</script>  
   
  }]);
   
  </script>
'; ';
echo '<style type="text/css"> echo '<style type="text/css">';
.ui-li-thumb, .ui-li-icon { position: relative; }'; if (strstr($_SERVER['HTTP_USER_AGENT'], 'Android'))
  echo '.ui-shadow,.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a,.ui-body-b,.ui-btn-up-b,.ui-btn-hover-b,
if (strstr($_SERVER['HTTP_USER_AGENT'], 'Android')) echo '.ui-shadow,.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a,.ui-body-b,.ui-btn-up-b,.ui-btn-hover-b,  
.ui-btn-down-b,.ui-bar-c,.ui-body-c,.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c,.ui-bar-c,.ui-body-d, .ui-btn-down-b,.ui-bar-c,.ui-body-c,.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c,.ui-bar-c,.ui-body-d,
.ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d,.ui-bar-d,.ui-body-e,.ui-btn-up-e,.ui-btn-hover-e, .ui-btn-up-d,.ui-btn-hover-d,.ui-btn-down-d,.ui-bar-d,.ui-body-e,.ui-btn-up-e,.ui-btn-hover-e,
.ui-btn-down-e,.ui-bar-e,.ui-overlay-shadow,.ui-shadow,.ui-btn-active,.ui-body-a,.ui-bar-a { .ui-btn-down-e,.ui-bar-e,.ui-overlay-shadow,.ui-shadow,.ui-btn-active,.ui-body-a,.ui-bar-a {
text-shadow: none; text-shadow: none;
box-shadow: none; box-shadow: none;
-webkit-box-shadow: none; -webkit-box-shadow: none;
}'; }';
echo ' echo '</style>';
.ui-navbar { echo '<link rel="stylesheet" href="' . $basePath . 'css/local.css.php" />';
width: 100%; if (isIOSDevice()) {
} echo '<meta name="apple-mobile-web-app-capable" content="yes" />
.ui-btn-inner {  
white-space: normal !important;  
}  
.ui-li-heading {  
white-space: normal !important;  
}  
.ui-listview-filter {  
margin: 0 !important;  
}  
.ui-icon-navigation {  
background-image: url('.$labsPath.'css/images/113-navigation.png);  
background-position: 1px 0;  
}  
.ui-icon-beaker {  
background-image: url('.$labsPath.'css/images/91-beaker-2.png);  
background-position: 1px 0;  
}  
#footer {  
text-size: 0.75em;  
text-align: center;  
}  
body {  
background-color: #F0F0F0;  
}  
#jqm-homeheader {  
text-align: center;  
}  
.viaPoints {  
display: none;  
text-size: 0.2em;  
}  
.min-width-480px .viaPoints {  
display: inline;  
}  
#extrainfo {  
visibility: hidden;  
display: none;  
}  
#servicewarning {  
padding: 1em;  
margin-bottom: 0.5em;  
text-size: 0.2em;  
background-color: #FF9;  
-moz-border-radius: 15px;  
border-radius: 15px;  
}  
   
/*#leftcolumn {  
float: none;  
}  
.min-width-768px #leftcolumn {  
float: left;  
width: 30%;  
}  
#rightcolumn {  
float: none;  
}  
.min-width-768px #rightcolumn {  
float: right;  
width: 68%;  
}*/  
   
#footer {  
clear:both;  
text-align:center;  
}  
// source http://webaim.org/techniques/skipnav/  
#skip a, #skip a:hover, #skip a:visited  
{  
position:absolute;  
left:0px;  
top:-500px;  
width:1px;  
height:1px;  
overflow:hidden;  
}  
   
#skip a:active, #skip a:focus  
{  
position:static;  
width:auto;  
height:auto;  
}  
</style>';  
if (strstr($_SERVER['HTTP_USER_AGENT'], 'iPhone') || strstr($_SERVER['HTTP_USER_AGENT'], 'iPod') || strstr($_SERVER['HTTP_USER_AGENT'], 'iPad')) {  
echo '<meta name="apple-mobile-web-app-capable" content="yes" />  
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="apple-touch-startup-image" href="startup.png" /> <link rel="apple-touch-startup-image" href="startup.png" />
<link rel="apple-touch-icon" href="apple-touch-icon.png" />'; <link rel="apple-touch-icon" href="apple-touch-icon.png" />';
} }
if ($geolocate) { if ($geolocate) {
echo "<script> echo "<script>
   
function success(position) { function success(position) {
$('#error').val('Location now detected. Please wait for data to load.'); $('#error').val('Location now detected. Please wait for data to load.');
$('#geolocate').val(position.coords.latitude+','+position.coords.longitude); $('#geolocate').val(position.coords.latitude+','+position.coords.longitude);
$.ajax({ url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude }); $.ajax({ async: false,
location.reload(true); success: function(){
  location.reload(true);
  },
  url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude });
} }
function error(msg) { function error(msg) {
$('#error').val('Error: '+msg); $('#error').val('Error: '+msg);
} }
   
function geolocate() { function geolocate() {
if (navigator.geolocation) { if (navigator.geolocation) {
var options = { var options = {
enableHighAccuracy: true, enableHighAccuracy: true,
timeout: 60000, timeout: 60000,
maximumAge: 10000 maximumAge: 10000
} }
navigator.geolocation.getCurrentPosition(success, error, options); navigator.geolocation.getCurrentPosition(success, error, options);
} }
} }
$(document).ready(function() { $(document).ready(function() {
$('#here').click(function(event) { $('#geolocate').val(geolocate()); return false;}); $('#here').click(function(event) { $('#geolocate').val(geolocate()); return false;});
$('#here').show(); $('#here').show();
/*if ($.mobile.media('screen and (min-width: 768px)')) {  
$('map a:first').click();  
$('#settings a:first').click();  
}*/  
}); });
"; ";
if (!isset($_SESSION['lat']) || $_SESSION['lat'] == "") echo "geolocate();"; if (!isset($_SESSION['lat']) || $_SESSION['lat'] == "")
echo "</script> "; echo "geolocate();";
} echo "</script> ";
if (isAnalyticsOn()) echo ' }
  if (isAnalyticsOn())
  echo '
<script type="text/javascript">' . " <script type="text/javascript">' . "
   
var _gaq = _gaq || []; var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-22173039-1']); _gaq.push(['_setAccount', 'UA-22173039-1']);
_gaq.push(['_trackPageview']); _gaq.push(['_trackPageview']);
_gaq.push(['_trackPageLoadTime']); _gaq.push(['_trackPageLoadTime']);
</script>"; </script>";
echo '</head> echo '</head>
<body> <body>
<div id="skip"> <div id="skip">
<a href="#maincontent">Skip to content</a> <a href="#maincontent">Skip to content</a>
</div> </div>
'; ';
if ($opendiv) { if ($opendiv) {
echo '<div data-role="page"> echo '<div data-role="page">
<div data-role="header" data-position="inline"> <div data-role="header" data-position="inline">
<a href="' . (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : "javascript:history.go(-1)") . '" data-icon="arrow-l" data-rel="back" class="ui-btn-left">Back</a> <a href="' . (isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : "javascript:history.go(-1)") . '" data-icon="arrow-l" data-rel="back" class="ui-btn-left">Back</a>
<h1>' . $pageTitle . '</h1> <h1>' . $pageTitle . '</h1>
<a href="'.$labsPath.'/index.php" data-icon="home" class="ui-btn-right">Home</a> <a href="' . $basePath . '/index.php" data-icon="home" class="ui-btn-right">Home</a>
</div><!-- /header --> </div><!-- /header -->
<a name="maincontent" id="maincontent"></a> <a name="maincontent" id="maincontent"></a>
<div data-role="content"> '; <div data-role="content"> ';
$overrides = getServiceOverride(); if ($GTFSREnabled) {
if ($overrides['service_id']) { $overrides = getServiceOverride();
if ($overrides['service_id'] == "noservice") { if (isset($overrides['service_id'])) {
echo '<div id="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a if ($overrides['service_id'] == "noservice") {
  echo '<div class="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a
href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>'; href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>';
} } else {
else { echo '<div class="servicewarning">Buses are running on an altered timetable today due to industrial action/public holiday. See <a href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>';
echo '<div id="servicewarning">Buses are running on an altered timetable today due to industrial action/public holiday. See <a href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>'; }
} }
} $serviceAlerts = Array();
} $globalAlerts = getServiceAlertsAsArray("agency", "0");
  if ($globalAlerts != null) {
} // echo "getting alerts due to network wide";
function include_footer() $serviceAlerts = array_merge($serviceAlerts, $globalAlerts);
{ }
  if (isset($stopid)) {
global $labsPath; $stopAlerts = getServiceAlertsAsArray("stop", $stopid);
echo '<div id="footer"><a href="'.$labsPath.'about.php">About/Contact Us</a>&nbsp;<a href="'.$labsPath.'feedback.php">Feedback/Bug Report</a>&nbsp;<a href="'.$labsPath.'privacy.php">Privacy Policy</a>'; if ($stopAlerts != null) {
echo '</div>'; // echo "getting alerts due to stop $stopid";
if (isAnalyticsOn()) { $serviceAlerts = array_merge($serviceAlerts, $stopAlerts);
echo "<script> (function() { }
  }
  if (isset($routeid)) {
  $routeAlerts = getServiceAlertsAsArray("route", $routeid);
  if ($routeAlerts != null) {
  // echo "getting alerts due to route $routeid";
  $serviceAlerts = array_merge($serviceAlerts, $routeAlerts);
  }
  }
  if (isset($serviceAlerts['entity']) && sizeof($serviceAlerts['entity']) > 0) {
  foreach ($serviceAlerts['entity'] as $entity) {
  echo "<div class='servicewarning'><b>{$entity['alert']['header_text']['translation'][0]['text']}</b>&nbsp;<small>"
  . date("F jS Y, g:i a", $entity['alert']['active_period'][0]['start']) . " to "
  . date("F jS Y, g:i a", $entity['alert']['active_period'][0]['end']) . "</small>
  <br>Warning: {$entity['alert']['description_text']['translation'][0]['text']}
  <br><a href='{$entity['alert']['url']['translation'][0]['text']}'>Source</a> </div>";
  }
  }
  }
  }
  }
   
  function include_footer() {
  global $basePath;
  echo '<div id="footer"><a href="' . $basePath . 'about.php">About/Contact Us</a>&nbsp;<a href="' . $basePath . 'feedback.php">Feedback/Bug Report</a>&nbsp;<a href="' . $basePath . 'privacy.php">Privacy Policy</a>';
  echo '</div>';
  if (isAnalyticsOn()) {
  echo "<script> (function() {
var ga = document.createElement('script'); ga.type = var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true; 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? ga.src = ('https:' == document.location.protocol ?
'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s); s.parentNode.insertBefore(ga, s);
})();</script>"; })();</script>";
$googleAnalyticsImageUrl = googleAnalyticsGetImageUrl(); $googleAnalyticsImageUrl = googleAnalyticsGetImageUrl();
echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" /></noscript>'; echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" alt=""/></noscript>';
  }
} echo "\n</div></div></body></html>";
echo "\n</div></div></body></html>"; }
}  
function timePlaceSettings($geolocate = false) function timeSettings() {
{ global $service_periods;
global $service_periods; echo '<div id="settings" data-role="collapsible" data-collapsed="true">
$geoerror = false; <h3>Change Time (' . (isset($_REQUEST['time']) ? $_REQUEST['time'] : "Current Time,") . ' ' . ucwords(service_period()) . ')...</h3>
if ($geolocate == true) { <form action="' . basename($_SERVER['PHP_SELF']) . '" method="GET">
$geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == ""; <input type="hidden" name="suburb" id="suburb" value="' . (isset($_REQUEST['suburb']) ? $_REQUEST['suburb'] : "") . '"/>
}  
echo '<div id="error">'; <input type="hidden" name="stopid" id="stopid" value="' . (isset($_REQUEST['stopid']) ? $_REQUEST['stopid'] : "") . '"/>
if ($geoerror) { <input type="hidden" name="stopcode" id="stopcode" value="' . (isset($_REQUEST['stopcode']) ? $_REQUEST['stopcode'] : "") . '"/>
echo 'Sorry, but your location could not currently be detected. <div class="ui-body">
  <div data-role="fieldcontain">
  <label for="time"> Time: </label>
  <input type="time" name="time" id="time" value="' . (isset($_REQUEST['time']) ? $_REQUEST['time'] : date("H:i")) . '"/>
  <a href="#" name="currentTime" id="currentTime" onClick="var d = new Date();' . "$('#time').val(d.getHours() +':'+ (d.getMinutes().toString().length == 1 ? '0'+ d.getMinutes(): d.getMinutes()));" . '">Current Time?</a>
  </div>
  <div data-role="fieldcontain">
  <label for="service_period"> Service Period: </label>
  <select name="service_period" id="service_period">';
  foreach ($service_periods as $service_period) {
  echo "<option value=\"$service_period\"" . (service_period() === $service_period ? " SELECTED" : "") . '>' . ucwords($service_period) . '</option>';
  }
  echo '</select>
  <a href="#" style="display:none" name="currentPeriod" id="currentPeriod">Current Period?</a>
  </div>
   
  <input type="submit" value="Update"/>
  </div></form>
  </div>';
  }
   
  function placeSettings() {
   
  $geoerror = false;
  $geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == "";
   
  echo '<div id="error">';
  if ($geoerror) {
  echo 'Sorry, but your location could not currently be detected.
Please allow location permission, wait for your location to be detected, Please allow location permission, wait for your location to be detected,
or enter an address/co-ordinates in the box below.'; or enter an address/co-ordinates in the box below.';
} }
echo '</div>'; echo '</div>';
echo '<div id="settings" data-role="collapsible" data-collapsed="' . !$geoerror . '"> echo '<div id="settings" data-role="collapsible" data-collapsed="' . !$geoerror . '">
<h3>Change Time/Place (' . (isset($_SESSION['time']) ? $_SESSION['time'] : "Current Time,") . ' ' . ucwords(service_period()) . ')...</h3> <h3>Change Location...</h3>
<form action="' . basename($_SERVER['PHP_SELF']) . "?" . $_SERVER['QUERY_STRING'] . '" method="post"> <form action="' . basename($_SERVER['PHP_SELF']) . "?" . $_SERVER['QUERY_STRING'] . '" method="post">
<div class="ui-body"> <div class="ui-body">
<div data-role="fieldcontain"> <div data-role="fieldcontain">
<label for="geolocate"> Current Location: </label> <label for="geolocate"> Current Location: </label>
<input type="text" id="geolocate" name="geolocate" value="' . (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] . "," . $_SESSION['lon'] : "Enter co-ordinates or address here") . '"/> <a href="#" style="display:none" name="here" id="here">Here?</a> <input type="text" id="geolocate" name="geolocate" value="' . (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] . "," . $_SESSION['lon'] : "Enter co-ordinates or address here") . '"/> <a href="#" style="display:none" name="here" id="here">Here?</a>
</div> </div>
<div data-role="fieldcontain">  
<label for="time"> Time: </label>  
<input type="time" name="time" id="time" value="' . (isset($_SESSION['time']) ? $_SESSION['time'] : date("H:i")) . '"/>  
<a href="#" name="currentTime" id="currentTime" onClick="var d = new Date();' . "$('#time').val(d.getHours() +':'+ (d.getMinutes().toString().length == 1 ? '0'+ d.getMinutes(): d.getMinutes()));" . '">Current Time?</a>  
</div>  
<div data-role="fieldcontain">  
<label for="service_period"> Service Period: </label>  
<select name="service_period" id="service_period">';  
foreach ($service_periods as $service_period) {  
echo "<option value=\"$service_period\"" . (service_period() === $service_period ? " SELECTED" : "") . '>' . ucwords($service_period) . '</option>';  
}  
echo '</select>  
<a href="#" style="display:none" name="currentPeriod" id="currentPeriod">Current Period?</a>  
</div>  
<input type="submit" value="Update"/> <input type="submit" value="Update"/>
</div></form> </div></form>
</div>'; </div>';
} }
function trackEvent($category, $action, $label = "", $value = - 1)  
{ function trackEvent($category, $action, $label = "", $value = - 1) {
if (isAnalyticsOn()) { if (isAnalyticsOn()) {
echo "\n<script> _gaq.push(['_trackEvent', '$category', '$action'" . ($label != "" ? ", '$label'" : "") . ($value != - 1 ? ", $value" : "") . "]);</script>"; echo "\n<script> _gaq.push(['_trackEvent', '$category', '$action'" . ($label != "" ? ", '$label'" : "") . ($value != - 1 ? ", $value" : "") . "]);</script>";
} }
} }
?>  
  //stop list collapsing
  function stopCompare($stopName) {
  return substr(trim(preg_replace("/\(Platform.*/", "", $stopName)), 0, 9);
  }
   
  function stopGroupTitle($stopName, $stopdesc) {
  if (preg_match("/Dr |Cct |Cir |Av |St |Cr |Parade |Way |Bank /", $stopName)) {
  $descParts = explode("<br>", $stopdesc);
  return trim(str_replace("Street: ", "", $descParts[0]));
  } else {
  return trim(preg_replace("/\(Platform.*/", "", $stopName));
  }
  }
   
  function viaPointNames($tripid, $stop_sequence = "") {
  $viaPointNames = Array();
  foreach (viaPoints($tripid, $stop_sequence) as $point) {
  if (strstr($point['stop_name'], "Station")
  || strstr($point['stop_name'], "Shops")
  || strstr($point['stop_name'], "CIT")
  || strstr($point['stop_name'], "School")
  || strstr($point['stop_name'], "University")
  ) {
  $viaPointNames[] = $point['stop_name'];
  }
  }
  if (sizeof($viaPointNames) > 0) {
  return r_implode(", ", $viaPointNames);
  } else {
  return "";
  }
  }
   
<?php <?php
   
  /*
  * Copyright 2010,2011 Alexander Sadleir
   
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
   
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
$service_periods = Array( $service_periods = Array(
'sunday', 'sunday',
'saturday', 'saturday',
'weekday' 'weekday'
); );
   
function service_period($date = "") function service_period($date = "") {
{  
  if (isset($_REQUEST['service_period'])) {
if (isset($_SESSION['service_period'])) return $_SESSION['service_period']; return $_REQUEST['service_period'];
$override = getServiceOverride($date); }
if ($override['service_id']){  
return $override['service_id']; $override = getServiceOverride($date);
} if (isset($override['service_id'])) {
  return strtolower($override['service_id']);
switch (date('w',($date != "" ? $date : time()))) { }
case 0: $date = ($date != "" ? $date : time());
return 'sunday'; $dow = date('w', $date);
case 6:  
return 'saturday'; switch ($dow) {
default: case 0:
return 'weekday'; return 'sunday';
} case 6:
} return 'saturday';
function midnight_seconds() default:
{ return 'weekday';
// from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html }
if (isset($_SESSION['time'])) { }
$time = strtotime($_SESSION['time']);  
return (date("G", $time) * 3600) + (date("i", $time) * 60) + date("s", $time); function service_ids($service_period, $date = "") {
} switch ($service_period) {
return (date("G") * 3600) + (date("i") * 60) + date("s"); case 'sunday':
} return Array("Sunday", "Sunday");
function midnight_seconds_to_time($seconds) case 'saturday':
{ return Array("Saturday", "Saturday");
if ($seconds > 0) { default:
$midnight = mktime(0, 0, 0, date("n") , date("j") , date("Y")); $date = ($date != "" ? $date : time());
return date("h:ia", $midnight + $seconds); // school holidays
} $ymd = date('Ymd', $date);
else { $dow = date('w', $date);
return ""; if (intval($ymd) < "20120203" && $dow != 0 && $dow != 6) {
} return Array("Weekday-SchoolVacation", "Weekday-SchoolVacation");
} } else {
?> return Array("Weekday", "Weekday");
  }
  }
  }
   
  function valid_service_ids() {
  return array_merge(service_ids(""), service_ids('saturday'), service_ids('sunday'));
  }
   
  function midnight_seconds($time = "") {
  // from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html
  if ($time != "") {
  return (date("G", $time) * 3600) + (date("i", $time) * 60) + date("s", $time);
  }
  if (isset($_SESSION['time'])) {
  $time = strtotime($_SESSION['time']);
  return (date("G", $time) * 3600) + (date("i", $time) * 60) + date("s", $time);
  }
  return (date("G") * 3600) + (date("i") * 60) + date("s");
  }
   
  function midnight_seconds_to_time($seconds) {
  if ($seconds > 0) {
  $midnight = mktime(0, 0, 0, date("n"), date("j"), date("Y"));
  return date("h:ia", $midnight + $seconds);
  } else {
  return "";
  }
  }
   
  if ($GTFSREnabled) {
  $serviceAlertCause = Array(
  "UNKNOWN_CAUSE" => "Unknown cause",
  "OTHER_CAUSE" => "Other cause",
  "TECHNICAL_PROBLEM" => "Technical problem",
  "STRIKE" => "Strike",
  "DEMONSTRATION" => "Demonstration",
  "ACCIDENT" => "Accident",
  "HOLIDAY" => "Holiday",
  "WEATHER" => "Weather",
  "MAINTENANCE" => "Maintenance",
  "CONSTRUCTION" => "Construction",
  "POLICE_ACTIVITY" => "Police activity",
  "MEDICAL_EMERGENCY" => "Medical emergency"
  );
  $serviceAlertEffect = Array(
  "NO_SERVICE" => "No service",
  "REDUCED_SERVICE" => "Reduced service",
  "SIGNIFICANT_DELAYS" => "Significant delays",
  "DETOUR" => "Detour",
  "ADDITIONAL_SERVICE" => "Additional service",
  "MODIFIED_SERVICE" => "Modified service",
  "OTHER_EFFECT" => "Other effect",
  "UNKNOWN_EFFECT" => "Unknown effect",
  "STOP_MOVED" => "Stop moved");
   
  set_include_path(get_include_path() . PATH_SEPARATOR . ($basePath . "lib/Protobuf-PHP/library/DrSlump/"));
   
  include_once("Protobuf.php");
  include_once("Protobuf/Message.php");
  include_once("Protobuf/Registry.php");
  include_once("Protobuf/Descriptor.php");
  include_once("Protobuf/Field.php");
   
  include_once($basePath . "lib/Protobuf-PHP/gtfs-realtime.php");
  include_once("Protobuf/CodecInterface.php");
  include_once("Protobuf/Codec/PhpArray.php");
  include_once("Protobuf/Codec/Binary.php");
  include_once("Protobuf/Codec/Binary/Writer.php");
  include_once("Protobuf/Codec/Json.php");
   
  function getServiceAlerts($filter_class = "", $filter_id = "") {
  /*
   
  also need last modified epoch of client gtfs
   
  - add,remove,patch,inform (null)
  - stop
  - trip
  - network
  - classes (WHERE=)
  - route (short_name or route_id)
  - street
  - stop
  - trip
  Currently support:
  network inform
  trip patch: stop remove
  street inform: route inform, trip inform, stop inform
  route patch: trip remove
  */
  $current_alerts = getCurrentAlerts();
  $informed_count = 0;
  if (sizeof($current_alerts) > 0) {
   
  $fm = new transit_realtime\FeedMessage();
  $fh = new transit_realtime\FeedHeader();
  $fh->setGtfsRealtimeVersion(1);
  $fh->setTimestamp(time());
  $fm->setHeader($fh);
  foreach ($current_alerts as $current_alert) {
  $affectsFilteredEntities = false;
  $fe = new transit_realtime\FeedEntity();
  $fe->setId($current_alert['id']);
  $fe->setIsDeleted(false);
  $alert = new transit_realtime\Alert();
  $tr = new transit_realtime\TimeRange();
  $tr->setStart($current_alert['start']);
  $tr->setEnd($current_alert['end']);
  $alert->addActivePeriod($tr);
  $informedEntities = getInformedAlerts($current_alert['id'], $filter_class, $filter_id);
  if (sizeof($informedEntities) > 0) {
   
  $affectsFilteredEntities = true;
  foreach ($informedEntities as $informedEntity) {
  $informed_count++;
  $informed = Array();
  $es = new transit_realtime\EntitySelector();
  if ($informedEntity['informed_class'] == "agency") {
  $es->setAgencyId($informedEntity['informed_id']);
  }
  if ($informedEntity['informed_class'] == "stop") {
  $es->setStopId($informedEntity['informed_id']);
  }
  if ($informedEntity['informed_class'] == "route") {
  $es->setRouteId($informedEntity['informed_id']);
  }
  if ($informedEntity['informed_class'] == "trip") {
  $td = new transit_realtime\TripDescriptor();
  $td->setTripId($informedEntity['informed_id']);
  $es->setTrip($td);
  }
  $alert->addInformedEntity($es);
  }
  }
  if ($current_alert['cause'] != "") {
  $alert->setCause(constant("transit_realtime\Alert\Cause::" . $current_alert['cause']));
  }
  if ($current_alert['effect'] != "") {
  $alert->setEffect(constant("transit_realtime\Alert\Effect::" . $current_alert['effect']));
  }
  if ($current_alert['url'] != "") {
  $tsUrl = new transit_realtime\TranslatedString();
  $tUrl = new transit_realtime\TranslatedString\Translation();
  $tUrl->setText($current_alert['url']);
  $tUrl->setLanguage("en");
  $tsUrl->addTranslation($tUrl);
  $alert->setUrl($tsUrl);
  }
  if ($current_alert['header'] != "") {
  $tsHeaderText = new transit_realtime\TranslatedString();
  $tHeaderText = new transit_realtime\TranslatedString\Translation();
  $tHeaderText->setText($current_alert['header']);
  $tHeaderText->setLanguage("en");
  $tsHeaderText->addTranslation($tHeaderText);
  $alert->setHeaderText($tsHeaderText);
  }
  if ($current_alert['description'] != "") {
  $tsDescriptionText = new transit_realtime\TranslatedString();
  $tDescriptionText = new transit_realtime\TranslatedString\Translation();
  $tDescriptionText->setText(trim($current_alert['description']));
  $tDescriptionText->setLanguage("en");
  $tsDescriptionText->addTranslation($tDescriptionText);
  $alert->setDescriptionText($tsDescriptionText);
  }
  $fe->setAlert($alert);
  if ($affectsFilteredEntities) {
  $fm->addEntity($fe);
  }
  }
  if ($informed_count > 0) {
  return $fm;
  } else {
  return null;
  }
  } else
  return null;
  }
   
  function getServiceAlertsAsArray($filter_class = "", $filter_id = "") {
   
  $alerts = getServiceAlerts($filter_class, $filter_id);
  if ($alerts != null) {
  $codec = new DrSlump\Protobuf\Codec\PhpArray();
   
  return $codec->encode($alerts);
  } else {
  return null;
  }
  }
   
  function getServiceAlertsAsBinary($filter_class = "", $filter_id = "") {
  $codec = new DrSlump\Protobuf\Codec\Binary();
  return $codec->encode(getServiceAlerts($filter_class, $filter_id));
  }
   
  function getServiceAlertsAsJSON($filter_class = "", $filter_id = "") {
  $codec = new DrSlump\Protobuf\Codec\Json();
  return $codec->encode(getServiceAlerts($filter_class, $filter_id));
  }
   
  function getServiceAlertsByClass() {
  $return = Array();
  $alerts = getServiceAlertsAsArray("", "");
  foreach ($alerts['entities'] as $entity) {
  foreach ($entity['informed'] as $informed) {
  foreach ($informed as $key => $value) {
  if (strpos("_id", $key) > 0) {
  $parts = explode($key);
  $class = $parts[0];
  $id = $value;
  }
  }
  $return[$class][$id][] = $entity;
  }
  }
  }
   
  function getTripUpdates($filter_class = "", $filter_id = "") {
  $fm = new transit_realtime\FeedMessage();
  $fh = new transit_realtime\FeedHeader();
  $fh->setGtfsRealtimeVersion(1);
  $fh->setTimestamp(time());
  $fm->setHeader($fh);
  foreach (getCurrentAlerts() as $alert) {
  $informedEntities = getInformedAlerts($alert['id'], $_REQUEST['filter_class'], $_REQUEST['filter_id']);
  $stops = Array();
  $routestrips = Array();
  if (sizeof($informedEntities) > 0) {
  if ($informedEntity['informed_class'] == "stop" && $informed["x-action"] == "remove") {
  $stops[] = $informedEntity['informed_id'];
  }
  if (($informedEntity['informed_class'] == "route" || $informedEntity['informed_class'] == "trip") && $informed["x-action"] == "patch") {
  $routestrips[] = Array("id" => $informedEntity['informed_id'],
  "type" => $informedEntity['informed_class']);
  }
  }
  foreach ($routestrips as $routetrip) {
  $fe = new transit_realtime\FeedEntity();
  $fe->setId($alert['id'] . $routetrip['id']);
  $fe->setIsDeleted(false);
  $tu = new transit_realtime\TripUpdate();
  $td = new transit_realtime\TripDescriptor();
  if ($routetrip['type'] == "route") {
  $td->setRouteId($routetrip['id']);
  } else if ($routetrip['type'] == "trip") {
  $td->setTripId($routetrip['id']);
  }
  $tu->setTrip($td);
  foreach ($stops as $stop) {
  $stu = new transit_realtime\TripUpdate\StopTimeUpdate();
  $stu->setStopId($stop);
  $stu->setScheduleRelationship(transit_realtime\TripUpdate\StopTimeUpdate\ScheduleRelationship::SKIPPED);
  $tu->addStopTimeUpdate($stu);
  }
  $fe->setTripUpdate($tu);
  $fm->addEntity($fe);
  }
  }
  return $fm;
  }
   
  function getTripUpdatesAsArray($filter_class = "", $filter_id = "") {
  $codec = new DrSlump\Protobuf\Codec\PhpArray();
  return $codec->encode(getTripUpdates($filter_class, $filter_id));
  }
   
  function getTripUpdatesAsBinary($filter_class = "", $filter_id = "") {
  $codec = new DrSlump\Protobuf\Codec\Binary();
  return $codec->encode(getTripUpdates($filter_class, $filter_id));
  }
   
  function getTripUpdatesAsJSON($filter_class = "", $filter_id = "") {
  $codec = new DrSlump\Protobuf\Codec\Json();
  return $codec->encode(getTripUpdates($filter_class, $filter_id));
  }
   
  }
   
<?php <?php
   
  /*
  * Copyright 2010,2011 Alexander Sadleir
   
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
   
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
   
date_default_timezone_set('Australia/ACT'); date_default_timezone_set('Australia/ACT');
$debugOkay = Array( $debugOkay = Array(
"session", "session",
"json", "json",
"phperror", "phperror",
"awsotp", "awsotp",
//"squallotp", //"squallotp",
"vanilleotp", //"vanilleotp",
"database", "database",
"other" "other"
); );
  $GTFSREnabled = true;
$cloudmadeAPIkey = "daa03470bb8740298d4b10e3f03d63e6"; $cloudmadeAPIkey = "daa03470bb8740298d4b10e3f03d63e6";
$googleMapsAPIkey = "ABQIAAAA95XYXN0cki3Yj_Sb71CFvBTPaLd08ONybQDjcH_VdYtHHLgZvRTw2INzI_m17_IoOUqH3RNNmlTk1Q"; $googleMapsAPIkey = "ABQIAAAA95XYXN0cki3Yj_Sb71CFvBTPaLd08ONybQDjcH_VdYtHHLgZvRTw2INzI_m17_IoOUqH3RNNmlTk1Q";
$otpAPIurl = 'http://localhost:8080/opentripplanner-api-webapp/'; $otpAPIurl = 'http://localhost:8080/opentripplanner-api-webapp/';
if (isDebug("awsotp") || php_uname('n') == "maxious.xen.prgmr.com") { if (isDebug("awsotp") || php_uname('n') == "maxious.xen.prgmr.com" || strstr(php_uname('n'),"actbus")) {
$otpAPIurl = 'http://bus-main.lambdacomplex.org:8080/opentripplanner-api-webapp/'; $otpAPIurl = 'http://bus-main.lambdacomplex.org:8080/opentripplanner-api-webapp/';
} }
if (isDebug("dotcloudotp") || php_uname('n') == "actbus-www") { if (isDebug("dotcloudotp") || php_uname('n') == "actbus-www") {
$otpAPIurl = 'http://otp.actbus.dotcloud.com/opentripplanner-api-webapp/'; $otpAPIurl = 'http://otp.actbus.dotcloud.com/opentripplanner-api-webapp/';
} }
if (isDebug("squallotp")) { if (isDebug("squallotp")) {
$otpAPIurl = 'http://10.0.1.108:5080/opentripplanner-api-webapp/'; $otpAPIurl = 'http://10.0.1.108:5080/opentripplanner-api-webapp/';
} }
if (isDebug("vanilleotp")) { if (isDebug("vanilleotp")) {
$otpAPIurl = 'http://10.0.1.135:8080/opentripplanner-api-webapp/'; $otpAPIurl = 'http://10.0.1.135:8080/opentripplanner-api-webapp/';
} }
if (isDebug("phperror")) error_reporting(E_ALL ^ E_NOTICE); if (isDebug("phperror"))
$labsPath = ""; error_reporting(E_ALL ^ E_NOTICE);
if (strstr($_SERVER['PHP_SELF'],"labs")) $labsPath = "../"; $basePath = "";
  if (strstr($_SERVER['PHP_SELF'], "labs/")
  || strstr($_SERVER['PHP_SELF'], "myway/")
  || strstr($_SERVER['PHP_SELF'], "lib/")
  || strstr($_SERVER['PHP_SELF'], "geo/")
  || strstr($_SERVER['PHP_SELF'], "include/")
  || strstr($_SERVER['PHP_SELF'], "rtpis/")) {
  $basePath = "../";
  }
   
  function isDebugServer() {
   
  return php_sapi_name() == "cli" || strstr(php_uname('n'),"actbus") || isset($_SERVER['SERVER_NAME']) && ( $_SERVER['SERVER_NAME'] == "azusa" || $_SERVER['SERVER_NAME'] == "vanille"
  || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" || $_SERVER['SERVER_NAME'] == "192.168.1.8" || $_SERVER['SERVER_NAME'] == "192.168.178.24");
  }
   
  if (isset($_SERVER['SERVER_NAME']) && $_SERVER['SERVER_NAME'] == "maxious.xen.prgmr.com") {
  // Set the exception handler
  require $basePath."/lib/amon-php/amon.php";
  Amon::setup_exception_handler();
  }
   
include_once ("common-geo.inc.php"); include_once ("common-geo.inc.php");
include_once ("common-net.inc.php"); include_once ("common-net.inc.php");
include_once ("common-transit.inc.php"); include_once ("common-transit.inc.php");
include_once ("common-db.inc.php"); if (!strstr($_SERVER['PHP_SELF'], "feedback")) {
  include_once ("common-db.inc.php");
  }
   
include_once ("common-request.inc.php"); include_once ("common-request.inc.php");
include_once ("common-session.inc.php"); include_once ("common-session.inc.php");
  include_once ("common-auth.inc.php");
include_once ("common-template.inc.php"); include_once ("common-template.inc.php");
   
function isDebugServer() function isAnalyticsOn() {
{ $user_agent = $_SERVER['HTTP_USER_AGENT'];
return $_SERVER['SERVER_NAME'] == "10.0.1.154" || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1" || !$_SERVER['SERVER_NAME']; return !isDebugServer() && !preg_match('/cloudkick/i', $user_agent) && !preg_match('/googlebot/i', $user_agent) &&
} !preg_match('/baidu/i', $user_agent);
function isAnalyticsOn() }
{  
return !isDebugServer(); function isDebug($debugReason = "other") {
} global $debugOkay;
function isDebug($debugReason = "other") return in_array($debugReason, $debugOkay, false) && isDebugServer();
{ }
global $debugOkay;  
return in_array($debugReason, $debugOkay, false) && isDebugServer(); function debug($msg, $debugReason = "other") {
} if (isDebug($debugReason))
function debug($msg, $debugReason = "other") echo "\n<!-- " . date(DATE_RFC822) . "\n $msg -->\n";
{ }
if (isDebug($debugReason)) echo "\n<!-- " . date(DATE_RFC822) . "\n $msg -->\n"; function isIOSDevice() {
} return strstr($_SERVER['HTTP_USER_AGENT'], 'iPhone') || strstr($_SERVER['HTTP_USER_AGENT'], 'iPod') || strstr($_SERVER['HTTP_USER_AGENT'], 'iPad');
function isJQueryMobileDevice() }
{ function isJQueryMobileDevice() {
// http://forum.jquery.com/topic/what-is-the-best-way-to-detect-all-useragents-which-can-handle-jquery-mobile#14737000002087897 // http://forum.jquery.com/topic/what-is-the-best-way-to-detect-all-useragents-which-can-handle-jquery-mobile#14737000002087897
$user_agent = $_SERVER['HTTP_USER_AGENT']; $user_agent = $_SERVER['HTTP_USER_AGENT'];
return preg_match('/iphone/i', $user_agent) || preg_match('/android/i', $user_agent) || preg_match('/webos/i', $user_agent) || preg_match('/ios/i', $user_agent) || preg_match('/bada/i', $user_agent) || preg_match('/maemo/i', $user_agent) || preg_match('/meego/i', $user_agent) || preg_match('/fennec/i', $user_agent) || (preg_match('/symbian/i', $user_agent) && preg_match('/s60/i', $user_agent) && $browser['majorver'] >= 5) || (preg_match('/symbian/i', $user_agent) && preg_match('/platform/i', $user_agent) && $browser['majorver'] >= 3) || (preg_match('/blackberry/i', $user_agent) && $browser['majorver'] >= 5) || (preg_match('/opera mobile/i', $user_agent) && $browser['majorver'] >= 10) || (preg_match('/opera mini/i', $user_agent) && $browser['majorver'] >= 5); return preg_match('/iphone/i', $user_agent) || preg_match('/android/i', $user_agent) || preg_match('/webos/i', $user_agent) || preg_match('/ios/i', $user_agent) || preg_match('/bada/i', $user_agent) || preg_match('/maemo/i', $user_agent) || preg_match('/meego/i', $user_agent) || preg_match('/fennec/i', $user_agent) || (preg_match('/symbian/i', $user_agent) && preg_match('/s60/i', $user_agent) && $browser['majorver'] >= 5) || (preg_match('/symbian/i', $user_agent) && preg_match('/platform/i', $user_agent) && $browser['majorver'] >= 3) || (preg_match('/blackberry/i', $user_agent) && $browser['majorver'] >= 5) || (preg_match('/opera mobile/i', $user_agent) && $browser['majorver'] >= 10) || (preg_match('/opera mini/i', $user_agent) && $browser['majorver'] >= 5);
} }
function isFastDevice()  
{  
$ua = $_SERVER['HTTP_USER_AGENT']; function array_flatten($a, $f = array()) {
$fastDevices = Array( if (!$a || !is_array($a))
"Mozilla/5.0 (X11;", return '';
"Mozilla/5.0 (Windows;", foreach ($a as $k => $v) {
"Mozilla/5.0 (iP", if (is_array($v))
"Mozilla/5.0 (Linux; U; Android", $f = array_flatten($v, $f);
"Mozilla/4.0 (compatible; MSIE" else
); $f[$k] = $v;
$slowDevices = Array( }
"J2ME", return $f;
"MIDP", }
"Opera/",  
"Mozilla/2.0 (compatible;", function remove_spaces($string) {
"Mozilla/3.0 (compatible;" return str_replace(' ', '', $string);
); }
return true;  
} function object2array($object) {
function array_flatten($a, $f = array()) if (is_object($object)) {
{ foreach ($object as $key => $value) {
if (!$a || !is_array($a)) return ''; $array[$key] = $value;
foreach ($a as $k => $v) { }
if (is_array($v)) $f = array_flatten($v, $f); } else {
else $f[$k] = $v; $array = $object;
} }
return $f; return $array;
} }
function remove_spaces($string)  
{ function startsWith($haystack, $needle, $case = true) {
return str_replace(' ', '', $string); if ($case) {
} return (strcmp(substr($haystack, 0, strlen($needle)), $needle) === 0);
function object2array($object) }
{ return (strcasecmp(substr($haystack, 0, strlen($needle)), $needle) === 0);
if (is_object($object)) { }
foreach ($object as $key => $value) {  
$array[$key] = $value; function endsWith($haystack, $needle, $case = true) {
} if ($case) {
} return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);
else { }
$array = $object; return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);
} }
return $array;  
} function sksort(&$array, $subkey = "id", $sort_ascending = false) {
function startsWith($haystack, $needle, $case = true) if (count($array))
{ $temp_array[key($array)] = array_shift($array);
if ($case) { foreach ($array as $key => $val) {
return (strcmp(substr($haystack, 0, strlen($needle)) , $needle) === 0); $offset = 0;
} $found = false;
return (strcasecmp(substr($haystack, 0, strlen($needle)) , $needle) === 0); foreach ($temp_array as $tmp_key => $tmp_val) {
} if (!$found and strtolower($val[$subkey]) > strtolower($tmp_val[$subkey])) {
  $temp_array = array_merge((array) array_slice($temp_array, 0, $offset), array(
function endsWith($haystack, $needle, $case = true) $key => $val
{ ), array_slice($temp_array, $offset));
if ($case) { $found = true;
return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)) , $needle) === 0); }
} $offset++;
return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)) , $needle) === 0); }
} if (!$found)
function bracketsMeanNewLine($input) $temp_array = array_merge($temp_array, array(
{ $key => $val
return str_replace(")", "</small>", str_replace("(", "<br><small>", $input)); ));
} }
function sksort(&$array, $subkey = "id", $sort_ascending = false) if ($sort_ascending)
{ $array = array_reverse($temp_array);
if (count($array)) $temp_array[key($array) ] = array_shift($array); else
foreach ($array as $key => $val) { $array = $temp_array;
$offset = 0; }
$found = false;  
foreach ($temp_array as $tmp_key => $tmp_val) { function sktimesort(&$array, $subkey = "id", $sort_ascending = false) {
if (!$found and strtolower($val[$subkey]) > strtolower($tmp_val[$subkey])) { if (count($array))
$temp_array = array_merge((array)array_slice($temp_array, 0, $offset) , array( $temp_array[key($array)] = array_shift($array);
$key => $val foreach ($array as $key => $val) {
) , array_slice($temp_array, $offset)); $offset = 0;
$found = true; $found = false;
} foreach ($temp_array as $tmp_key => $tmp_val) {
$offset++; if (!$found and strtotime($val[$subkey]) > strtotime($tmp_val[$subkey])) {
} $temp_array = array_merge((array) array_slice($temp_array, 0, $offset), array(
if (!$found) $temp_array = array_merge($temp_array, array( $key => $val
$key => $val ), array_slice($temp_array, $offset));
)); $found = true;
} }
if ($sort_ascending) $array = array_reverse($temp_array); $offset++;
else $array = $temp_array; }
} if (!$found)
function sktimesort(&$array, $subkey = "id", $sort_ascending = false) $temp_array = array_merge($temp_array, array(
{ $key => $val
if (count($array)) $temp_array[key($array) ] = array_shift($array); ));
foreach ($array as $key => $val) { }
$offset = 0; if ($sort_ascending && isset($temp_array))
$found = false; $array = array_reverse($temp_array);
foreach ($temp_array as $tmp_key => $tmp_val) { else
if (!$found and strtotime($val[$subkey]) > strtotime($tmp_val[$subkey])) { $array = $temp_array;
$temp_array = array_merge((array)array_slice($temp_array, 0, $offset) , array( }
$key => $val  
) , array_slice($temp_array, $offset)); function r_implode($glue, $pieces) {
$found = true; foreach ($pieces as $r_pieces) {
} if (is_array($r_pieces)) {
$offset++; $retVal[] = r_implode($glue, $r_pieces);
} } else {
if (!$found) $temp_array = array_merge($temp_array, array( $retVal[] = $r_pieces;
$key => $val }
)); }
} return implode($glue, $retVal);
if ($sort_ascending && isset($temp_array)) $array = array_reverse($temp_array); }
else $array = $temp_array;  
}  
function r_implode( $glue, $pieces )  
{  
foreach( $pieces as $r_pieces )  
{  
if( is_array( $r_pieces ) )  
{  
$retVal[] = r_implode( $glue, $r_pieces );  
}  
else  
{  
$retVal[] = $r_pieces;  
}  
}  
return implode( $glue, $retVal );  
}  
?>  
   
<?php <?php
function getRoute($routeID)  
{ /*
global $conn; * Copyright 2010,2011 Alexander Sadleir
$query = "Select * from routes where route_id = :routeID LIMIT 1";  
debug($query, "database"); Licensed under the Apache License, Version 2.0 (the "License");
$query = $conn->prepare($query); you may not use this file except in compliance with the License.
$query->bindParam(":routeID", $routeID); You may obtain a copy of the License at
$query->execute();  
if (!$query) { http://www.apache.org/licenses/LICENSE-2.0
databaseError($conn->errorInfo());  
return Array(); Unless required by applicable law or agreed to in writing, software
} distributed under the License is distributed on an "AS IS" BASIS,
return $query->fetch(PDO::FETCH_ASSOC); WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
} See the License for the specific language governing permissions and
  limitations under the License.
function getRouteByFullName($routeFullName) */
{  
global $conn; function getRoute($routeID) {
$query = "Select * from routes where route_short_name||route_long_name = :routeFullName LIMIT 1"; global $conn;
debug($query, "database"); $query = "Select * from routes where route_id = :routeID LIMIT 1";
$query = $conn->prepare($query); debug($query, "database");
$query->bindParam(":routeFullName", $routeFullName); $query = $conn->prepare($query);
$query->execute(); $query->bindParam(":routeID", $routeID);
if (!$query) { $query->execute();
databaseError($conn->errorInfo()); if (!$query) {
return Array(); databaseError($conn->errorInfo());
} return Array();
return $query->fetch(PDO::FETCH_ASSOC); }
} return $query->fetch(PDO :: FETCH_ASSOC);
  }
function getRoutes()  
{ function getRoutesByShortName($routeShortName) {
global $conn; global $conn;
$query = "Select * from routes order by route_short_name;"; $query = "Select distinct route_id, route_short_name from routes where route_short_name = :routeShortName";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->execute(); $query->bindParam(":routeShortName", $routeShortName);
if (!$query) { $query->execute();
databaseError($conn->errorInfo()); if (!$query) {
return Array(); databaseError($conn->errorInfo());
} return Array();
return $query->fetchAll(); }
} return $query->fetchAll();
function getRoutesByNumber($routeNumber = "") }
{  
global $conn; function getRouteHeadsigns($routeID) {
if ($routeNumber != "") { global $conn;
$query = "Select distinct routes.route_id,routes.route_short_name,routes.route_long_name,service_id from routes join trips on trips.route_id = $query = "select stops.stop_name, trip_headsign, direction_id,max(service_id) as service_id, count(*)
routes.route_id join stop_times on stop_times.trip_id = trips.trip_id from routes join trips on trips.route_id = routes.route_id
where route_short_name = :routeNumber OR route_short_name LIKE :routeNumber2 order by route_short_name;"; join stop_times on stop_times.trip_id = trips.trip_id join stops on
} stop_times.stop_id = stops.stop_id where trips.route_id = :routeID
else { and stop_times.stop_sequence = 1 group by stops.stop_name, trip_headsign, direction_id having count(*) > 2";
$query = "SELECT DISTINCT route_short_name from routes order by route_short_name"; debug($query, "database");
} $query = $conn->prepare($query);
debug($query, "database"); $query->bindParam(":routeID", $routeID);
$query = $conn->prepare($query); $query->execute();
if ($routeNumber != "") { if (!$query) {
$query->bindParam(":routeNumber", $routeNumber); databaseError($conn->errorInfo());
$routeNumber2 = "% ".$routeNumber; return Array();
$query->bindParam(":routeNumber2", $routeNumber2); }
} $results = $query->fetchAll();
$query->execute(); if (is_array($results)) {
if (!$query) { return $results;
databaseError($conn->errorInfo()); } else {
return Array(); return Array($results);
} }
return $query->fetchAll(); }
} function getRouteDescription($routeID, $directionID) {
function getRoutesByNumberSeries($routeNumberSeries = "") $trip = getRouteNextTrip($routeID, $directionID);
{ $start = getTripStartingPoint($trip['trip_id']);
global $conn; $end = getTripDestination($trip['trip_id']);
if (strlen($routeNumberSeries) == 1) { return "From ".$start['stop_name']." to ".$end['stop_name'];
return getRoutesByNumber($routeNumberSeries); }
} function getRouteByFullName($routeFullName) {
$seriesMin = substr($routeNumberSeries, 0, -1) . "0"; global $conn;
$seriesMax = substr($routeNumberSeries, 0, -1) . "9"; $query = "Select * from routes where route_short_name||route_long_name = :routeFullName LIMIT 1";
$query = "Select distinct routes.route_id,routes.route_short_name,routes.route_long_name,service_id from routes join trips on trips.route_id = debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":routeFullName", $routeFullName);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetch(PDO :: FETCH_ASSOC);
  }
   
  function getRoutes() {
  global $conn;
  $query = "Select * from routes order by route_short_name;";
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchAll();
  }
   
  function getRoutesByNumberSeries($routeNumberSeries = "") {
  global $conn;
  if (strlen($routeNumberSeries) == 1) {
  return getRoute($routeNumberSeries);
  }
  $seriesMin = substr($routeNumberSeries, 0, -1) . "0";
  $seriesMax = substr($routeNumberSeries, 0, -1) . "9";
  $query = "Select distinct routes.route_id,routes.route_short_name,routes.route_long_name,service_id from routes join trips on trips.route_id =
routes.route_id join stop_times on stop_times.trip_id = trips.trip_id where to_number(route_short_name, 'FM999') between :seriesMin and :seriesMax OR route_short_name LIKE :routeNumberSeries order by route_short_name;"; routes.route_id join stop_times on stop_times.trip_id = trips.trip_id where to_number(route_short_name, 'FM999') between :seriesMin and :seriesMax OR route_short_name LIKE :routeNumberSeries order by route_short_name;";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":seriesMin", $seriesMin); $query->bindParam(":seriesMin", $seriesMin);
$query->bindParam(":seriesMax", $seriesMax); $query->bindParam(":seriesMax", $seriesMax);
$routeNumberSeries = "% ".substr($routeNumberSeries, 0, -1)."%"; $routeNumberSeries = "% " . substr($routeNumberSeries, 0, -1) . "%";
$query->bindParam(":routeNumberSeries", $routeNumberSeries); $query->bindParam(":routeNumberSeries", $routeNumberSeries);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetchAll(); return $query->fetchAll();
} }
function getRouteNextTrip($routeID)  
{ function getRouteNextTrip($routeID, $directionID) {
global $conn; global $conn;
$query = "select * from routes join trips on trips.route_id = routes.route_id  
join stop_times on stop_times.trip_id = trips.trip_id where $query = "select routes.route_id,routes.route_url,direction_id,trips.trip_id,trip_headsign,departure_time,service_id from routes join trips on trips.route_id = routes.route_id
arrival_time > :currentTime and routes.route_id = :routeID order by join stop_times on stop_times.trip_id = trips.trip_id where arrival_time between :currentTime and :futureTime
  and routes.route_id = :routeID and trips.direction_id = :directionID order by
arrival_time limit 1"; arrival_time limit 1";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":currentTime", current_time()); $query->bindParam(":currentTime", current_time());
$query->bindParam(":routeID", $routeID); $futureTime = current_time(strtotime(current_time() ." +2h"));
$query->execute(); if (date("h",strtotime(current_time()) > 22)) $futureTime = "23:59:59";
if (!$query) { $query->bindParam(":futureTime", $futureTime);
databaseError($conn->errorInfo()); $query->bindParam(":routeID", $routeID);
return Array(); $query->bindParam(":directionID", $directionID);
} $query->execute();
$r = $query->fetch(PDO::FETCH_ASSOC); databaseError($conn->errorInfo());
  if (!$query) {
// past last trip of the day special case databaseError($conn->errorInfo());
if (sizeof($r) < 16) { return Array();
$query = "select * from routes join trips on trips.route_id = routes.route_id }
join stop_times on stop_times.trip_id = trips.trip_id where routes.route_id = :routeID order by $r = $query->fetch(PDO :: FETCH_ASSOC);
  return $r;
  }
   
  function getRouteFirstTrip($routeID,$directionID) {
  global $conn;
   
  $query = "select * from routes join trips on trips.route_id = routes.route_id
  join stop_times on stop_times.trip_id = trips.trip_id where routes.route_id = :routeID
  and trips.direction_id = :directionID order by
arrival_time DESC limit 1"; arrival_time DESC limit 1";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":routeID", $routeID); $query->bindParam(":routeID", $routeID);
$query->execute();  
if (!$query) { $query->bindParam(":directionID", $directionID);
databaseError($conn->errorInfo()); $query->execute();
return Array(); if (!$query) {
} databaseError($conn->errorInfo());
  return Array();
$r = $query->fetch(PDO::FETCH_ASSOC); }
}  
return $r; $r = $query->fetch(PDO :: FETCH_ASSOC);
} return $r;
function getTimeInterpolatedRouteAtStop($routeID, $stop_id) }
{  
$nextTrip = getRouteNextTrip($routeID); function getRouteAtStop($routeID, $directionID, $stop_id) {
if ($nextTrip['trip_id']) { $nextTrip = getRouteNextTrip($routeID, $directionID);
foreach (getTimeInterpolatedTrip($nextTrip['trip_id']) as $tripStop) { if ($nextTrip['trip_id']) {
if ($tripStop['stop_id'] == $stop_id) return $tripStop; foreach (getTripStopTimes($nextTrip['trip_id']) as $tripStop) {
} if ($tripStop['stop_id'] == $stop_id)
} return $tripStop;
return Array(); }
} }
function getRouteTrips($routeID) return Array();
{ }
global $conn;  
$query = "select routes.route_id,trips.trip_id,service_id,arrival_time, stop_id, stop_sequence from routes join trips on trips.route_id = routes.route_id function getRouteTrips($routeID, $directionID = "", $service_period = "") {
join stop_times on stop_times.trip_id = trips.trip_id where routes.route_id = :routeID and stop_sequence = '1' order by global $conn;
  if ($service_period == "")
  $service_period = service_period();
  $service_ids = service_ids($service_period);
  $sidA = $service_ids[0];
  $sidB = $service_ids[1];
  $directionSQL = "";
  if ($directionID != "")
  $directionSQL = " and direction_id = :directionID ";
  $query = "select routes.route_id,trips.trip_id,service_id,arrival_time, stop_id, stop_sequence from routes join trips on trips.route_id = routes.route_id
  join stop_times on stop_times.trip_id = trips.trip_id where (service_id=:service_periodA OR service_id=:service_periodB)
  AND (routes.route_id = :routeID) " . $directionSQL . " and stop_sequence = '1' order by
arrival_time "; arrival_time ";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":routeID", $routeID); $query->bindParam(":routeID", $routeID);
$query->execute(); $query->bindParam(":service_periodA", $sidA);
if (!$query) { $query->bindParam(":service_periodB", $sidB);
databaseError($conn->errorInfo()); if ($directionSQL != "")
return Array(); $query->bindParam(":directionID", $directionID);
} $query->execute();
return $query->fetchAll(); if (!$query) {
} databaseError($conn->errorInfo());
function getRoutesByDestination($destination = "", $service_period = "") return Array();
{ }
global $conn; return $query->fetchAll();
if ($service_period == "") $service_period = service_period(); }
if ($destination != "") {  
$query = "SELECT DISTINCT trips.route_id,route_short_name,route_long_name, service_id function getRoutesByDestination($destination = "", $service_period = "") {
  global $conn;
  if ($service_period == "")
  $service_period = service_period();
  $service_ids = service_ids($service_period);
  $sidA = $service_ids[0];
  $sidB = $service_ids[1];
  if ($destination != "") {
  /* $query = "SELECT DISTINCT trips.route_id,route_short_name,route_long_name, service_id
FROM stop_times join trips on trips.trip_id = FROM stop_times join trips on trips.trip_id =
stop_times.trip_id join routes on trips.route_id = routes.route_id stop_times.trip_id join routes on trips.route_id = routes.route_id
WHERE route_long_name = :destination AND service_id=:service_period order by route_short_name"; WHERE route_long_name = :destination AND (service_id=:service_periodA OR service_id=:service_periodB)
} order by route_short_name";*/
else { $query = "select route_id, direction_id, stop_name, b.trip_id, b.stop_sequence from (select route_id, direction_id, max(stop_sequence) as stop_sequence, max(a.trip_id) as trip_id from stop_times inner join (SELECT route_id, direction_id, max(trip_id) as trip_id
$query = "SELECT DISTINCT route_long_name from trips group by route_id,direction_id) as a on stop_times.trip_id = a.trip_id group by route_id, direction_id) as b inner join stop_times on b.trip_id = stop_times.trip_id inner join stops on stop_times.stop_id = stops.stop_id where stop_times.stop_sequence = b.stop_sequence and stop_name = :destination order by route_id;";
FROM stop_times join trips on trips.trip_id = } else {
stop_times.trip_id join routes on trips.route_id = routes.route_id $query = "select stop_name from (select route_id, direction_id, max(stop_sequence) as stop_sequence, max(a.trip_id) as trip_id from stop_times inner join (SELECT route_id, direction_id, max(trip_id) as trip_id
WHERE service_id= :service_period order by route_long_name"; from trips group by route_id,direction_id) as a on stop_times.trip_id = a.trip_id group by route_id, direction_id) as b inner join stop_times on b.trip_id = stop_times.trip_id inner join stops on stop_times.stop_id = stops.stop_id where stop_times.stop_sequence = b.stop_sequence group by stop_name order by stop_name;";
} }
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":service_period", $service_period);  
if ($destination != "") $query->bindParam(":destination", $destination); //$query->bindParam(":service_periodA", $sidA);
$query->execute(); //$query->bindParam(":service_periodB", $sidB);
if (!$query) { if ($destination != "")
databaseError($conn->errorInfo()); $query->bindParam(":destination", $destination);
return Array(); $query->execute();
} if (!$query) {
return $query->fetchAll(); databaseError($conn->errorInfo());
} return Array();
function getRoutesBySuburb($suburb, $service_period = "") }
{ return $query->fetchAll();
if ($service_period == "") $service_period = service_period(); }
global $conn;  
$query = "SELECT DISTINCT service_id,trips.route_id,route_short_name,route_long_name function getRoutesBySuburb($suburb, $service_period = "") {
  if ($service_period == "")
  $service_period = service_period();
  $service_ids = service_ids($service_period);
  $sidA = $service_ids[0];
  $sidB = $service_ids[1];
   
  global $conn;
  $query = "SELECT DISTINCT service_id,trips.route_id,route_short_name,route_long_name
FROM stop_times join trips on trips.trip_id = stop_times.trip_id FROM stop_times join trips on trips.trip_id = stop_times.trip_id
join routes on trips.route_id = routes.route_id join routes on trips.route_id = routes.route_id
join stops on stops.stop_id = stop_times.stop_id join stops on stops.stop_id = stop_times.stop_id
WHERE zone_id LIKE ':suburb AND service_id=:service_period ORDER BY route_short_name"; WHERE stop_desc LIKE :suburb AND (service_id=:service_periodA OR service_id=:service_periodB)
debug($query, "database"); ORDER BY route_short_name";
$query = $conn->prepare($query); debug($query, "database");
$query->bindParam(":service_period", $service_period); $query = $conn->prepare($query);
$suburb = "%" . $suburb . ";%"; $query->bindParam(":service_periodA", $sidA);
$query->bindParam(":suburb", $suburb); $query->bindParam(":service_periodB", $sidB);
$query->execute(); $suburb = "%Suburb: %" . $suburb . "%";
if (!$query) { $query->bindParam(":suburb", $suburb);
databaseError($conn->errorInfo()); $query->execute();
return Array();  
} databaseError($conn->errorInfo());
return $query->fetchAll();  
} return $query->fetchAll();
function getRoutesNearby($lat, $lng, $limit = "", $distance = 500) }
{  
if ($service_period == "") $service_period = service_period(); function getRoutesNearby($lat, $lng, $limit = "", $distance = 500) {
if ($limit != "") $limitSQL = " LIMIT :limit "; // if ($service_period == "")
global $conn; $service_period = service_period();
$query = "SELECT service_id,trips.route_id,route_short_name,route_long_name,min(stops.stop_id) as stop_id, $service_ids = service_ids($service_period);
  $sidA = $service_ids[0];
  $sidB = $service_ids[1];
  $limitSQL = "";
  if ($limit != "")
  $limitSQL = " LIMIT :limit ";
  global $conn;
  $query = "SELECT service_id,trips.route_id,trips.direction_id,route_short_name,route_long_name,min(stops.stop_id) as stop_id,
min(ST_Distance(position, ST_GeographyFromText('SRID=4326;POINT($lng $lat)'), FALSE)) as distance min(ST_Distance(position, ST_GeographyFromText('SRID=4326;POINT($lng $lat)'), FALSE)) as distance
FROM stop_times FROM stop_times
join trips on trips.trip_id = stop_times.trip_id join trips on trips.trip_id = stop_times.trip_id
join routes on trips.route_id = routes.route_id join routes on trips.route_id = routes.route_id
join stops on stops.stop_id = stop_times.stop_id join stops on stops.stop_id = stop_times.stop_id
WHERE service_id=:service_period WHERE (service_id=:service_periodA OR service_id=:service_periodB)
AND ST_DWithin(position, ST_GeographyFromText('SRID=4326;POINT($lng $lat)'), :distance, FALSE) AND ST_DWithin(position, ST_GeographyFromText('SRID=4326;POINT($lng $lat)'), :distance, FALSE)
group by service_id,trips.route_id,route_short_name,route_long_name group by service_id,trips.route_id,trips.direction_id,route_short_name,route_long_name
order by distance $limitSQL"; order by distance $limitSQL";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":service_period", $service_period); $query->bindParam(":service_periodA", $sidA);
$query->bindParam(":distance", $distance); $query->bindParam(":service_periodB", $sidB);
if ($limit != "") $query->bindParam(":limit", $limit); $query->bindParam(":distance", $distance);
$query->execute(); if ($limit != "")
if (!$query) { $query->bindParam(":limit", $limit);
databaseError($conn->errorInfo()); $query->execute();
return Array(); if (!$query) {
} databaseError($conn->errorInfo());
return $query->fetchAll(); return Array();
} }
?> return $query->fetchAll();
  }
   
<?php <?php
function getServiceOverride($date="") {  
global $conn; /*
$query = "Select * from calendar_dates where date = :date and exception_type = '1' LIMIT 1"; * Copyright 2010,2011 Alexander Sadleir
debug($query,"database");  
$query = $conn->prepare($query); // Create a prepared statement Licensed under the Apache License, Version 2.0 (the "License");
$query->bindParam(":date", date("Ymd",($date != "" ? $date : time()))); you may not use this file except in compliance with the License.
$query->execute(); You may obtain a copy of the License at
if (!$query) {  
databaseError($conn->errorInfo()); http://www.apache.org/licenses/LICENSE-2.0
return Array();  
} Unless required by applicable law or agreed to in writing, software
return $query->fetch(PDO::FETCH_ASSOC); distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
   
  function getServiceOverride($date = "") {
  global $conn;
  $query = "Select * from calendar_dates where date = :date and exception_type = '1' LIMIT 1";
  // debug($query,"database");
  $query = $conn->prepare($query); // Create a prepared statement
  $date = date("Ymd", ($date != "" ? $date : time()));
  $query->bindParam(":date", $date);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetch(PDO :: FETCH_ASSOC);
} }
?>  
  function getServiceAlert($alertID) {
  global $conn;
  $query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts where id = :servicealert_id";
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":servicealert_id", $alertID);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetch(PDO :: FETCH_ASSOC);
  }
   
  function updateServiceAlert($alertID, $alert) {
  global $conn;
  $query = 'update servicealerts_alerts set start=:start, "end"=:end, header=:header, description=:description, url=:url, cause=:cause, effect=:effect where id = :servicealert_id';
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindValue(":servicealert_id", $alertID);
  $query->bindValue(":start", $alert['startdate']);
  $query->bindValue(":end", $alert['enddate']);
  $query->bindValue(":header", $alert['header']);
  $query->bindValue(":description", $alert['description']);
  $query->bindValue(":url", $alert['url']);
  $query->bindValue(":cause", $alert['cause']);
  $query->bindValue(":effect", $alert['effect']);
  $query->execute();
   
  print_r($conn->errorInfo());
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetch(PDO :: FETCH_ASSOC);
  }
   
  function addServiceAlert($alert) {
  global $conn;
  $query = 'INSERT INTO servicealerts_alerts (start, "end", header, description, url,cause,effect) VALUES (:start, :end, :header, :description, :url,:cause,:effect) ';
  debug($query, "database");
  $query = $conn->prepare($query);
  //print_r($alert);
  $query->bindValue(":start", $alert['startdate']);
  $query->bindValue(":end", $alert['enddate']);
  $query->bindValue(":header", $alert['header']);
  $query->bindValue(":description", $alert['description']);
  $query->bindValue(":url", $alert['url']);
  $query->bindValue(":cause", $alert['cause']);
  $query->bindValue(":effect", $alert['effect']);
  $query->execute();
   
  print_r($conn->errorInfo());
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetch(PDO :: FETCH_ASSOC);
  }
   
  function getCurrentAlerts() {
  global $conn;
  $query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts where NOW() > start and NOW() < \"end\"";
  // debug($query, "database");
  $query = $conn->prepare($query);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchAll();
  }
   
  function getFutureAlerts() {
  global $conn;
  $query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts where NOW() < \"end\"";
  // debug($query, "database");
  $query = $conn->prepare($query);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchAll();
  }
  function getAllAlerts() {
  global $conn;
  $query = "SELECT id,extract('epoch' from start) as start, extract('epoch' from \"end\") as \"end\",cause,effect,header,description,url from servicealerts_alerts";
  // debug($query, "database");
  $query = $conn->prepare($query);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchAll();
  }
   
  function getInformedAlerts($id, $filter_class, $filter_id) {
   
  global $conn;
  //echo "$id, $filter_class, $filter_id\n";
  $query = "SELECT * from servicealerts_informed where servicealert_id = :servicealert_id";
   
  if ($filter_class != "") {
  $query .= " AND informed_class = :informed_class ";
  }
  if ($filter_id != "") {
  $query .= " AND informed_id = :informed_id ";
  }
  // debug($query, "database");
  $query = $conn->prepare($query);
  if ($filter_class != "") {
  $query->bindParam(":informed_class", $filter_class);
  }
  if ($filter_id != "") {
  $query->bindParam(":informed_id", $filter_id);
  }
  $query->bindParam(":servicealert_id", $id);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchAll();
  }
   
  function deleteInformedAlert($serviceAlertID, $class, $id) {
  global $conn;
  $query = 'DELETE from servicealerts_informed where servicealert_id = :servicealert_id and informed_class = :informed_class AND informed_id = :informed_id';
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":servicealert_id", $serviceAlertID);
  $query->bindParam(":informed_class", $class);
  $query->bindParam(":informed_id", $id);
  $query->execute();
  print_r($conn->errorInfo());
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return null;
  }
   
  function addInformedAlert($serviceAlertID, $class, $id, $action) {
  global $conn;
  $query = 'INSERT INTO servicealerts_informed (servicealert_id , informed_class , informed_id, informed_action)
  VALUES(:servicealert_id ,:informed_class, :informed_id, :informed_action)';
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":servicealert_id", $serviceAlertID);
  $query->bindParam(":informed_class", $class);
  $query->bindParam(":informed_id", $id);
  $query->bindParam(":informed_action", $action);
  $query->execute();
   
  print_r($conn->errorInfo());
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return null;
  }
   
<?php <?php
function getStop($stopID)  
{ /*
global $conn; * Copyright 2010,2011 Alexander Sadleir
$query = "Select * from stops where stop_id = :stopID LIMIT 1";  
debug($query, "database"); Licensed under the Apache License, Version 2.0 (the "License");
$query = $conn->prepare($query); you may not use this file except in compliance with the License.
$query->bindParam(":stopID", $stopID); You may obtain a copy of the License at
$query->execute();  
if (!$query) { http://www.apache.org/licenses/LICENSE-2.0
databaseError($conn->errorInfo());  
return Array(); Unless required by applicable law or agreed to in writing, software
} distributed under the License is distributed on an "AS IS" BASIS,
return $query->fetch(PDO::FETCH_ASSOC); WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
} See the License for the specific language governing permissions and
function getStops($timingPointsOnly = false, $firstLetter = "", $startsWith = "") limitations under the License.
{ */
global $conn;  
$conditions = Array(); function getStop($stopID) {
if ($timingPointsOnly) $conditions[] = "substr(stop_code,1,2) != 'Wj'"; global $conn;
if ($firstLetter != "") $conditions[] = "substr(stop_name,1,1) = :firstLetter"; $query = "Select * from stops where stop_id = :stopID LIMIT 1";
if ($startsWith != "") $conditions[] = "stop_name like :startsWith"; debug($query, "database");
$query = "Select * from stops"; $query = $conn->prepare($query);
if (sizeof($conditions) > 0) { $query->bindParam(":stopID", $stopID);
if (sizeof($conditions) > 1) { $query->execute();
$query.= " Where " . implode(" AND ", $conditions) . " "; if (!$query) {
} databaseError($conn->errorInfo());
else { return Array();
$query.= " Where " . $conditions[0] . " "; }
} return $query->fetch(PDO :: FETCH_ASSOC);
} }
$query.= " order by stop_name;";  
$query = $conn->prepare($query); function getStops($firstLetter = "", $startsWith = "") {
if ($firstLetter != "") $query->bindParam(":firstLetter", $firstLetter); global $conn;
  $conditions = Array();
if ($startsWith != "") { if ($firstLetter != "")
$startsWith = $startsWith."%"; $conditions[] = "substr(stop_name,1,1) = :firstLetter";
$query->bindParam(":startsWith", $startsWith); if ($startsWith != "")
  $conditions[] = "stop_name like :startsWith";
  $query = "Select * from stops";
  if (sizeof($conditions) > 0) {
  if (sizeof($conditions) > 1) {
  $query .= " Where " . implode(" AND ", $conditions) . " ";
  } else {
  $query .= " Where " . $conditions[0] . " ";
} }
$query->execute(); }
if (!$query) { $query .= " order by stop_name;";
databaseError($conn->errorInfo()); debug($query, "database");
return Array(); $query = $conn->prepare($query);
} if ($firstLetter != "")
return $query->fetchAll(); $query->bindParam(":firstLetter", $firstLetter);
}  
function getNearbyStops($lat, $lng, $limit = "", $distance = 1000) if ($startsWith != "") {
{ $startsWith = $startsWith . "%";
if ($lat == null || $lng == null) return Array(); $query->bindParam(":startsWith", $startsWith);
if ($limit != "") $limitSQL = " LIMIT :limit "; }
global $conn; $query->execute();
$query = "Select *, ST_Distance(position, ST_GeographyFromText('SRID=4326;POINT($lng $lat)'), FALSE) as distance if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchAll();
  }
   
  function getNearbyStops($lat, $lng, $limit = "", $distance = 1000) {
  if ($lat == null || $lng == null)
  return Array();
  if ($limit != "")
  $limitSQL = " LIMIT :limit ";
  global $conn;
  $query = "Select *, ST_Distance(position, ST_GeographyFromText('SRID=4326;POINT($lng $lat)'), FALSE) as distance
from stops WHERE ST_DWithin(position, ST_GeographyFromText('SRID=4326;POINT($lng $lat)'), :distance, FALSE) from stops WHERE ST_DWithin(position, ST_GeographyFromText('SRID=4326;POINT($lng $lat)'), :distance, FALSE)
order by distance $limitSQL;"; order by distance $limitSQL;";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":distance", $distance); $query->bindParam(":distance", $distance);
$query->bindParam(":limit", $limit); $query->bindParam(":limit", $limit);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetchAll(); return $query->fetchAll();
} }
function getStopsBySuburb($suburb)  
{ function getStopsByName($name) {
global $conn; global $conn;
$query = "Select * from stops where zone_id LIKE :suburb order by stop_name;"; $query = "Select * from stops where stop_name LIKE :name;";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$suburb = "%" . $suburb . ";%"; $name = $name . "%";
$query->bindParam(":suburb", $suburb); $query->bindParam(":name", $name);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetchAll(); return $query->fetchAll();
} }
function getStopsByStopCode($stop_code,$startsWith = "")  
{ function getStopsBySuburb($suburb) {
global $conn; global $conn;
$query = "Select * from stops where stop_code = :stop_code OR stop_code LIKE :stop_code2"; $query = "Select * from stops where stop_desc LIKE :suburb order by stop_name;";
if ($startsWith != "") $query .= " AND stop_name like :startsWith"; debug($query, "database");
  $query = $conn->prepare($query);
debug($query, "database"); $suburb = "%<br>Suburb: %" . $suburb . "%";
$query = $conn->prepare($query); $query->bindParam(":suburb", $suburb);
  $query->execute();
$query->bindParam(":stop_code", $stop_code); if (!$query) {
$stop_code2 = $stop_code . "%"; databaseError($conn->errorInfo());
$query->bindParam(":stop_code2", $stop_code2); return Array();
if ($startsWith != "") { }
$startsWith = $startsWith."%"; return $query->fetchAll();
$query->bindParam(":startsWith", $startsWith); }
}  
$query->execute(); function getStopsByStopCode($stop_code, $startsWith = "") {
if (!$query) { global $conn;
databaseError($conn->errorInfo()); $query = "Select * from stops where (stop_code = :stop_code OR stop_code LIKE :stop_code2)";
return Array(); if ($startsWith != "")
} $query .= " AND stop_name like :startsWith";
return $query->fetchAll();  
} debug($query, "database");
function getStopRoutes($stopID, $service_period) $query = $conn->prepare($query);
{  
if ($service_period == "") $service_period = service_period(); $query->bindParam(":stop_code", $stop_code);
global $conn; $stop_code2 = $stop_code . "%";
$query = "SELECT service_id,trips.route_id,route_short_name,route_long_name $query->bindParam(":stop_code2", $stop_code2);
  if ($startsWith != "") {
  $startsWith = $startsWith . "%";
  $query->bindParam(":startsWith", $startsWith);
  }
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchAll();
  }
   
  function getStopRoutes($stopID, $service_period) {
  if ($service_period == "") {
  $service_period = service_period();
  }
  $service_ids = service_ids($service_period);
  $sidA = $service_ids[0];
  $sidB = $service_ids[1];
  global $conn;
  $query = "SELECT distinct service_id,trips.route_id,route_short_name,route_long_name
FROM stop_times join trips on trips.trip_id = FROM stop_times join trips on trips.trip_id =
stop_times.trip_id join routes on trips.route_id = routes.route_id WHERE stop_id = :stopID AND service_id=:service_period"; stop_times.trip_id join routes on trips.route_id = routes.route_id WHERE stop_id = :stopID
debug($query, "database"); AND (service_id=:service_periodA OR service_id=:service_periodB)";
$query = $conn->prepare($query); debug($query, "database");
$query->bindParam(":service_period", $service_period); $query = $conn->prepare($query);
$query->bindParam(":stopID", $stopID); $query->bindParam(":service_periodA", $sidA);
$query->execute(); $query->bindParam(":service_periodB", $sidB);
if (!$query) { $query->bindParam(":stopID", $stopID);
databaseError($conn->errorInfo()); $query->execute();
return Array(); if (!$query) {
} databaseError($conn->errorInfo());
return $query->fetchAll(); return Array();
} }
function getStopTrips($stopID, $service_period = "", $afterTime = "", $limit = "") return $query->fetchAll();
{ }
if ($service_period == "") $service_period = service_period();  
if ($limit != "") $limitSQL = " LIMIT :limit "; function getStopTrips($stopID, $service_period = "", $afterTime = "", $limit = "", $route_short_name = "") {
global $conn; if ($service_period == "") {
if ($afterTime != "") { $service_period = service_period();
$query = " SELECT stop_times.trip_id,stop_times.arrival_time,stop_times.stop_id,stop_sequence,service_id,trips.route_id,route_short_name,route_long_name, end_times.arrival_time as end_time }
  $service_ids = service_ids($service_period);
  $sidA = $service_ids[0];
  $sidB = $service_ids[1];
  $limitSQL = "";
  if ($limit != "")
  $limitSQL .= " LIMIT :limit ";
   
  global $conn;
  if ($afterTime != "") {
  $query = " SELECT stop_times.trip_id,stop_times.arrival_time,stop_times.stop_id,stop_sequence,service_id,trips.route_id,trips.direction_id,trips.trip_headsign,route_short_name,route_long_name,end_times.arrival_time as end_time
FROM stop_times FROM stop_times
join trips on trips.trip_id = join trips on trips.trip_id =
stop_times.trip_id stop_times.trip_id
join routes on trips.route_id = routes.route_id , (SELECT trip_id,max(arrival_time) as arrival_time from stop_times join routes on trips.route_id = routes.route_id , (SELECT trip_id,max(arrival_time) as arrival_time from stop_times
WHERE stop_times.arrival_time IS NOT NULL group by trip_id) as end_times WHERE stop_times.arrival_time IS NOT NULL group by trip_id) as end_times
WHERE stop_times.stop_id = :stopID WHERE stop_times.stop_id = :stopID
AND stop_times.trip_id = end_times.trip_id AND stop_times.trip_id = end_times.trip_id
AND service_id=:service_period AND (service_id=:service_periodA OR service_id=:service_periodB) " . ($route_short_name != "" ? " AND route_short_name = :route_short_name " : "") . "
AND end_times.arrival_time > :afterTime AND end_times.arrival_time > :afterTime
ORDER BY end_time $limitSQL"; ORDER BY end_time $limitSQL";
} } else {
else { $query = "SELECT stop_times.trip_id,arrival_time,stop_times.stop_id,stop_sequence,service_id,trips.route_id,route_short_name,route_long_name
$query = "SELECT stop_times.trip_id,arrival_time,stop_times.stop_id,stop_sequence,service_id,trips.route_id,route_short_name,route_long_name  
FROM stop_times FROM stop_times
join trips on trips.trip_id = join trips on trips.trip_id =
stop_times.trip_id stop_times.trip_id
join routes on trips.route_id = routes.route_id join routes on trips.route_id = routes.route_id
WHERE stop_times.stop_id = :stopID WHERE stop_times.stop_id = :stopID
AND service_id=:service_period AND (service_id=:service_periodA OR service_id=:service_periodB) " . ($route_short_name != "" ? " AND route_short_name = :route_short_name " : "") . "
ORDER BY arrival_time $limitSQL"; ORDER BY arrival_time $limitSQL";
} }
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":service_period", $service_period); $query->bindParam(":service_periodA", $sidA);
$query->bindParam(":stopID", $stopID); $query->bindParam(":service_periodB", $sidB);
if ($limit != "") $query->bindParam(":limit", $limit); $query->bindParam(":stopID", $stopID);
if ($afterTime != "") $query->bindParam(":afterTime", $afterTime); if ($limit != "")
$query->execute(); $query->bindParam(":limit", $limit);
if (!$query) { if ($afterTime != "")
databaseError($conn->errorInfo()); $query->bindParam(":afterTime", $afterTime);
return Array(); if ($route_short_name != "")
} $query->bindParam(":route_short_name", $route_short_name);
return $query->fetchAll(); $query->execute();
} if (!$query) {
function getStopTripsWithTimes($stopID, $time = "", $service_period = "", $time_range = "", $limit = "") databaseError($conn->errorInfo());
{ return Array();
if ($service_period == "") $service_period = service_period(); }
if ($time_range == "") $time_range = (24 * 60 * 60); return $query->fetchAll();
if ($time == "") $time = current_time(); }
if ($limit == "") $limit = 10;  
$trips = getStopTrips($stopID, $service_period, $time); function getStopTripsWithTimes($stopID, $time = "", $service_period = "", $time_range = "", $limit = "") {
$timedTrips = Array(); if ($service_period == "")
if ($trips && sizeof($trips) > 0) { $service_period = service_period();
foreach ($trips as $trip) { if ($time_range == "")
if ($trip['arrival_time'] != "") { $time_range = (24 * 60 * 60);
if (strtotime($trip['arrival_time']) > strtotime($time) and strtotime($trip['arrival_time']) < (strtotime($time) + $time_range)) { if ($time == "")
$timedTrips[] = $trip; $time = current_time();
} if ($limit == "")
} $limit = 10;
else { $trips = getStopTrips($stopID, $service_period, $time);
$timedTrip = getTimeInterpolatedTripAtStop($trip['trip_id'], $trip['stop_sequence']); $timedTrips = Array();
if ($timedTrip['arrival_time'] > $time and strtotime($timedTrip['arrival_time']) < (strtotime($time) + $time_range)) { if ($trips && sizeof($trips) > 0) {
$timedTrips[] = $timedTrip; foreach ($trips as $trip) {
} if ($trip['arrival_time'] != "") {
} if (strtotime($trip['arrival_time']) > strtotime($time) and strtotime($trip['arrival_time']) < (strtotime($time) + $time_range)) {
if (sizeof($timedTrips) > $limit) break; $timedTrips[] = $trip;
} }
sktimesort($timedTrips, "arrival_time", true); } else {
  $timedTrip = getTripAtStop($trip['trip_id'], $trip['stop_sequence']);
  if ($timedTrip['arrival_time'] > $time and strtotime($timedTrip['arrival_time']) < (strtotime($time) + $time_range)) {
  $timedTrips[] = $timedTrip;
  }
  }
  if (sizeof($timedTrips) > $limit)
  break;
} }
return $timedTrips; sktimesort($timedTrips, "arrival_time", true);
} }
?> return $timedTrips;
  }
   
<?php <?php
function getTrip($tripID)  
{ /*
global $conn; * Copyright 2010,2011 Alexander Sadleir
$query = "Select * from trips  
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
   
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
   
  function getTrip($tripID) {
  global $conn;
  $query = "Select * from trips
join routes on trips.route_id = routes.route_id join routes on trips.route_id = routes.route_id
where trip_id = :tripID where trip_id = :tripID
LIMIT 1"; LIMIT 1";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array();  
} return Array();
return $query->fetch(PDO::FETCH_ASSOC); }
} return $query->fetch(PDO :: FETCH_ASSOC);
function getTripShape($tripID) }
{ function getTripStops($tripID) {
global $conn; global $conn;
$query = "SELECT ST_AsKML(ST_MakeLine(geometry(a.position))) as the_route $query = "SELECT stops.stop_id, stop_name, ST_AsKML(position) as positionkml,
FROM (SELECT position,  
stop_sequence, trips.trip_id stop_sequence, trips.trip_id
FROM stop_times FROM stop_times
join trips on trips.trip_id = stop_times.trip_id join trips on trips.trip_id = stop_times.trip_id
join stops on stops.stop_id = stop_times.stop_id join stops on stops.stop_id = stop_times.stop_id
WHERE trips.trip_id = :tripID ORDER BY stop_sequence) as a group by a.trip_id"; WHERE trips.trip_id = :tripID ORDER BY stop_sequence";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetchColumn(0); return $query->fetchAll();
} }
function getTimeInterpolatedTrip($tripID, $range = "")  
{ function getTripHasStop($tripID, $stopID) {
global $conn; global $conn;
$query = "SELECT stop_times.trip_id,arrival_time,stop_times.stop_id,stop_lat,stop_lon,stop_name,stop_code, $query = "SELECT stop_id
  FROM stop_times
  join trips on trips.trip_id = stop_times.trip_id
  WHERE trips.trip_id = :tripID and stop_times.stop_id = :stopID";
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":tripID", $tripID);
  $query->bindParam(":stopID", $stopID);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return ($query->fetchColumn() > 0);
  }
   
  function getTripShape($tripID) {
  // todo, use shapes table if shape_id specified
  global $conn;
  $query = "SELECT ST_AsKML(ST_MakeLine(geometry(a.shape_pt))) as the_route
  FROM (SELECT shapes.shape_id,shape_pt from shapes
  inner join trips on shapes.shape_id = trips.shape_id
  WHERE trips.trip_id = :tripID ORDER BY shape_pt_sequence) as a group by a.shape_id";
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":tripID", $tripID);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  return $query->fetchColumn(0);
  }
   
  function getTripStopTimes($tripID) {
  global $conn;
  $query = "SELECT stop_times.trip_id,trip_headsign,arrival_time,stop_times.stop_id
  ,stop_lat,stop_lon,stop_name,stop_desc,stop_code,
stop_sequence,service_id,trips.route_id,route_short_name,route_long_name stop_sequence,service_id,trips.route_id,route_short_name,route_long_name
FROM stop_times FROM stop_times
join trips on trips.trip_id = stop_times.trip_id join trips on trips.trip_id = stop_times.trip_id
join routes on trips.route_id = routes.route_id join routes on trips.route_id = routes.route_id
join stops on stops.stop_id = stop_times.stop_id join stops on stops.stop_id = stop_times.stop_id
WHERE trips.trip_id = :tripID $range ORDER BY stop_sequence"; WHERE trips.trip_id = :tripID ORDER BY stop_sequence";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
$stopTimes = $query->fetchAll(); $stopTimes = $query->fetchAll();
$cur_timepoint = Array(); return $stopTimes;
$next_timepoint = Array(); }
$distance_between_timepoints = 0.0;  
$distance_traveled_between_timepoints = 0.0; function getTripAtStop($tripID, $stop_sequence) {
$rv = Array(); global $conn;
foreach ($stopTimes as $i => $stopTime) { foreach (getTripStopTimes($tripID) as $tripStop) {
if ($stopTime['arrival_time'] != "") { if ($tripStop['stop_sequence'] == $stop_sequence)
// is timepoint return $tripStop;
$cur_timepoint = $stopTime; }
$distance_between_timepoints = 0.0; return Array();
$distance_traveled_between_timepoints = 0.0; }
if ($i + 1 < sizeof($stopTimes)) {  
$k = $i + 1; function getTripStartTime($tripID) {
$distance_between_timepoints+= distance($stopTimes[$k - 1]["stop_lat"], $stopTimes[$k - 1]["stop_lon"], $stopTimes[$k]["stop_lat"], $stopTimes[$k]["stop_lon"]); global $conn;
while ($stopTimes[$k]["arrival_time"] == "" && $k + 1 < sizeof($stopTimes)) { $query = "Select * from stop_times
$k+= 1;  
//echo "k".$k;  
$distance_between_timepoints+= distance($stopTimes[$k - 1]["stop_lat"], $stopTimes[$k - 1]["stop_lon"], $stopTimes[$k]["stop_lat"], $stopTimes[$k]["stop_lon"]);  
}  
$next_timepoint = $stopTimes[$k];  
$rv[] = $stopTime;  
}  
}  
else {  
// is untimed point  
//echo "i".$i;  
$distance_traveled_between_timepoints+= distance($stopTimes[$i - 1]["stop_lat"], $stopTimes[$i - 1]["stop_lon"], $stopTimes[$i]["stop_lat"], $stopTimes[$i]["stop_lon"]);  
//echo "$distance_traveled_between_timepoints / $distance_between_timepoints<br>";  
$distance_percent = $distance_traveled_between_timepoints / $distance_between_timepoints;  
if ($next_timepoint["arrival_time"] != "") {  
$total_time = strtotime($next_timepoint["arrival_time"]) - strtotime($cur_timepoint["arrival_time"]);  
//echo strtotime($next_timepoint["arrival_time"])." - ".strtotime($cur_timepoint["arrival_time"])."<br>";  
$time_estimate = ($distance_percent * $total_time) + strtotime($cur_timepoint["arrival_time"]);  
$stopTime["arrival_time"] = date("H:i:s", $time_estimate);  
}  
else {  
$stopTime["arrival_time"] = $cur_timepoint["arrival_time"];  
}  
$rv[] = $stopTime;  
//var_dump($rv);  
   
}  
}  
return $rv;  
}  
function getTripPreviousTimePoint($tripID, $stop_sequence)  
{  
global $conn;  
$query = " SELECT trip_id,stop_id,  
stop_sequence  
FROM stop_times  
WHERE trip_id = :tripID and stop_sequence < :stop_sequence  
and stop_times.arrival_time IS NOT NULL ORDER BY stop_sequence DESC LIMIT 1";  
debug($query, "database");  
$query = $conn->prepare($query);  
$query->bindParam(":tripID", $tripID);  
$query->bindParam(":stop_sequence", $stop_sequence);  
$query->execute();  
if (!$query) {  
databaseError($conn->errorInfo());  
return Array();  
}  
return $query->fetch(PDO::FETCH_ASSOC);  
}  
function getTripNextTimePoint($tripID, $stop_sequence)  
{  
global $conn;  
$query = " SELECT trip_id,stop_id,  
stop_sequence  
FROM stop_times  
WHERE trip_id = :tripID and stop_sequence > :stop_sequence  
and stop_times.arrival_time IS NOT NULL ORDER BY stop_sequence LIMIT 1";  
debug($query, "database");  
$query = $conn->prepare($query);  
$query->bindParam(":tripID", $tripID);  
$query->bindParam(":stop_sequence", $stop_sequence);  
$query->execute();  
if (!$query) {  
databaseError($conn->errorInfo());  
return Array();  
}  
return $query->fetch(PDO::FETCH_ASSOC);  
}  
function getTimeInterpolatedTripAtStop($tripID, $stop_sequence)  
{  
global $conn;  
// limit interpolation to between nearest actual points.  
$prevTimePoint = getTripPreviousTimePoint($tripID, $stop_sequence);  
$nextTimePoint = getTripNextTimePoint($tripID, $stop_sequence);  
//echo " prev {$lowestDelta['stop_sequence']} next {$nextTimePoint['stop_sequence']} ";  
$range = "";  
if ($prevTimePoint != "") $range .= " AND stop_sequence >= '{$prevTimePoint['stop_sequence']}'";  
if ($nextTimePoint != "") $range .= " AND stop_sequence <= '{$nextTimePoint['stop_sequence']}'";  
foreach (getTimeInterpolatedTrip($tripID, $range) as $tripStop) {  
if ($tripStop['stop_sequence'] == $stop_sequence) return $tripStop;  
}  
return Array();  
}  
function getTripStartTime($tripID)  
{  
global $conn;  
$query = "Select * from stop_times  
where trip_id = :tripID where trip_id = :tripID
AND arrival_time IS NOT NULL AND arrival_time IS NOT NULL
AND stop_sequence = '1'"; AND stop_sequence = '1'";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":tripID", $tripID); $query->bindParam(":tripID", $tripID);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
$r = $query->fetch(PDO::FETCH_ASSOC); $r = $query->fetch(PDO :: FETCH_ASSOC);
return $r['arrival_time']; return $r['arrival_time'];
} }
function getActiveTrips($time)  
{ function getTripEndTime($tripID) {
global $conn; global $conn;
if ($time == "") $time = current_time(); $query = "SELECT trip_id,max(arrival_time) as arrival_time from stop_times
$query = "Select distinct stop_times.trip_id, start_times.arrival_time as start_time, end_times.arrival_time as end_time from stop_times, (SELECT trip_id,arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL WHERE stop_times.arrival_time IS NOT NULL and trip_id = :tripID group by trip_id";
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":tripID", $tripID);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  $r = $query->fetch(PDO :: FETCH_ASSOC);
  return $r['arrival_time'];
  }
  function getTripStartingPoint($tripID) {
  global $conn;
  $query = "SELECT stops.stop_id, stops.stop_name, stops.stop_desc
  from stop_times inner join stops on stop_times.stop_id = stops.stop_id
  WHERE trip_id = :tripID and stop_sequence = '1' limit 1";
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":tripID", $tripID);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  $r = $query->fetch(PDO :: FETCH_ASSOC);
  return $r;
  }
   
  function getTripDestination($tripID) {
  global $conn;
  $query = "SELECT stops.stop_id, stops.stop_name, stops.stop_desc
  from stop_times inner join stops on stop_times.stop_id = stops.stop_id
  WHERE trip_id = :tripID order by stop_sequence desc limit 1";
  debug($query, "database");
  $query = $conn->prepare($query);
  $query->bindParam(":tripID", $tripID);
  $query->execute();
  if (!$query) {
  databaseError($conn->errorInfo());
  return Array();
  }
  $r = $query->fetch(PDO :: FETCH_ASSOC);
  return $r;
  }
   
  function getActiveTrips($time) {
  global $conn;
  if ($time == "")
  $time = current_time();
  $query = "Select distinct stop_times.trip_id, start_times.arrival_time as start_time, end_times.arrival_time as end_time from stop_times, (SELECT trip_id,arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL
AND stop_sequence = '1') as start_times, (SELECT trip_id,max(arrival_time) as arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL group by trip_id) as end_times AND stop_sequence = '1') as start_times, (SELECT trip_id,max(arrival_time) as arrival_time from stop_times WHERE stop_times.arrival_time IS NOT NULL group by trip_id) as end_times
WHERE start_times.trip_id = end_times.trip_id AND stop_times.trip_id = end_times.trip_id AND :time > start_times.arrival_time AND :time < end_times.arrival_time"; WHERE start_times.trip_id = end_times.trip_id AND stop_times.trip_id = end_times.trip_id AND :time > start_times.arrival_time AND :time < end_times.arrival_time";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":time", $time); $query->bindParam(":time", $time);
$query->execute(); $query->execute();
if (!$query) { if (!$query) {
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
return Array(); return Array();
} }
return $query->fetchAll(); return $query->fetchAll();
} }
function viaPoints($tripID, $stop_sequence = "")  
{ function viaPoints($tripID, $stop_sequence = "") {
global $conn; global $conn;
$query = "SELECT stops.stop_id, stop_name, arrival_time $query = "SELECT stops.stop_id, stop_name, arrival_time
FROM stop_times join stops on stops.stop_id = stop_times.stop_id FROM stop_times join stops on stops.stop_id = stop_times.stop_id
WHERE stop_times.trip_id = :tripID WHERE stop_times.trip_id = :tripID
" . ($stop_sequence != "" ? " AND stop_sequence > :stop_sequence " : "") . "AND substr(stop_code,1,2) != 'Wj' ORDER BY stop_sequence"; " . ($stop_sequence != "" ? " AND stop_sequence > :stop_sequence " : "") . " ORDER BY stop_sequence";
debug($query, "database"); debug($query, "database");
$query = $conn->prepare($query); $query = $conn->prepare($query);
if ($stop_sequence != "") $query->bindParam(":stop_sequence", $stop_sequence); if ($stop_sequence != "")
$query->bindParam(":tripID", $tripID); $query->bindParam(":stop_sequence", $stop_sequence);
$query->execute(); $query->bindParam(":tripID", $tripID);
if (!$query) { $query->execute();
databaseError($conn->errorInfo()); if (!$query) {
return Array(); databaseError($conn->errorInfo());
} return Array();
return $query->fetchAll(); }
} return $query->fetchAll();
function viaPointNames($tripid, $stop_sequence = "") }
{  
$viaPointNames = Array();  
foreach (viaPoints($tripid, $stop_sequence) as $point) {  
$viaPointNames[] = $point['stop_name'];  
}  
if (sizeof($viaPointNames) > 0) {  
return r_implode(", ", $viaPointNames);  
}  
else {  
return "";  
}  
}  
?>  
file:a/index.php -> file:b/index.php
<?php <?php
  /*
  * Copyright 2010,2011 Alexander Sadleir
   
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at
   
  http://www.apache.org/licenses/LICENSE-2.0
   
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
  */
include ('include/common.inc.php'); include ('include/common.inc.php');
include_header("bus.lambdacomplex.org", "index", false) include_header("bus.lambdacomplex.org", "index", false)
?> ?>
<div data-role="page"> <div data-role="page">
<div data-role="content"> <div data-role="content">
<div id="jqm-homeheader"> <div id="jqm-homeheader">
<h1>busness time</h1><br><small>Canberra Bus Timetables and Trip Planner</small> <h1>busness time</h1><br><small>Canberra Bus Timetables and Trip Planner</small>
</div> </div>
<a name="maincontent" id="maincontent"></a> <a name="maincontent" id="maincontent"></a>
<a href="tripPlanner.php" data-role="button" data-icon="navigation">Launch Trip Planner...</a> <a href="tripPlanner.php" data-role="button" data-icon="navigation">Launch Trip Planner...</a>
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
<li data-role="list-divider">Timetables - Stops</li> <li data-role="list-divider">Timetables - Stops</li>
<li><a href="stopList.php">Major (Timing Point) Stops</a></li> <li><a href="stopList.php">Stops By Name</a></li>
<li><a href="stopList.php?allstops=yes">All Stops</a></li> <li><a href="stopList.php?bysuburbs=yes">Stops By Suburb</a></li>
<li><a href="stopList.php?bysuburbs=yes">Stops By Suburb</a></li> <li><a class="nearby" href="stopList.php?nearby=yes">Nearby Stops</a></li>
<li><a class="nearby" href="stopList.php?nearby=yes">Nearby Stops</a></li> </ul>
</ul> <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> <li data-role="list-divider">Timetables - Routes</li>
<li data-role="list-divider">Timetables - Routes</li> <li><a href="routeList.php">Routes By Final Destination</a></li>
<li><a href="routeList.php">Routes By Final Destination</a></li> <li><a href="routeList.php?bynumber=yes">Routes By Number</a></li>
<li><a href="routeList.php?bynumber=yes">Routes By Number</a></li> <li><a href="routeList.php?bysuburbs=yes">Routes By Suburb</a></li>
<li><a href="routeList.php?bysuburbs=yes">Routes By Suburb</a></li> <li><a class="nearby" href="routeList.php?nearby=yes">Nearby Routes</a></li>
<li><a class="nearby" href="routeList.php?nearby=yes">Nearby Routes</a></li> </ul>
</ul> <!--<a href="labs/index.php" data-role="button" data-icon="beaker">Busness R&amp;D</a>-->
<?php <a href="myway/index.php" data-role="button">MyWay Balance and Timeliness Survey Results</a>
echo timePlaceSettings(); <?php
echo ' <a href="labs/index.php" data-role="button" data-icon="beaker">Busness R&amp;D</a>'; include_footer(true)
include_footer(true) ?>
?>  
   
directory:b/js/FlashCanvas (new)
 
//Flotr 0.2.0-alpha Copyright (c) 2009 Bas Wenneker, <http://solutoire.com>, MIT License.  
var Flotr={version:"0.2.0-alpha",author:"Bas Wenneker",website:"http://www.solutoire.com",_registeredTypes:{lines:"drawSeriesLines",points:"drawSeriesPoints",bars:"drawSeriesBars",candles:"drawSeriesCandles",pie:"drawSeriesPie"},register:function(A,B){Flotr._registeredTypes[A]=B+""},draw:function(B,D,A,C){C=C||Flotr.Graph;return new C(B,D,A)},getSeries:function(A){return A.collect(function(C){var B,C=(C.data)?Object.clone(C):{data:C};for(B=C.data.length-1;B>-1;--B){C.data[B][1]=(C.data[B][1]===null?null:parseFloat(C.data[B][1]))}return C})},merge:function(D,B){var A=B||{};for(var C in D){A[C]=(D[C]!=null&&typeof (D[C])=="object"&&!(D[C].constructor==Array||D[C].constructor==RegExp)&&!Object.isElement(D[C]))?Flotr.merge(D[C],B[C]):A[C]=D[C]}return A},getTickSize:function(E,D,A,B){var H=(A-D)/E;var G=Flotr.getMagnitude(H);var C=H/G;var F=10;if(C<1.5){F=1}else{if(C<2.25){F=2}else{if(C<3){F=((B==0)?2:2.5)}else{if(C<7.5){F=5}}}}return F*G},defaultTickFormatter:function(A){return A+""},defaultTrackFormatter:function(A){return"("+A.x+", "+A.y+")"},defaultPieLabelFormatter:function(A){return(A.fraction*100).toFixed(2)+"%"},getMagnitude:function(A){return Math.pow(10,Math.floor(Math.log(A)/Math.LN10))},toPixel:function(A){return Math.floor(A)+0.5},toRad:function(A){return -A*(Math.PI/180)},parseColor:function(D){if(D instanceof Flotr.Color){return D}var A,C=Flotr.Color;if((A=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(D))){return new C(parseInt(A[1]),parseInt(A[2]),parseInt(A[3]))}if((A=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(D))){return new C(parseInt(A[1]),parseInt(A[2]),parseInt(A[3]),parseFloat(A[4]))}if((A=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(D))){return new C(parseFloat(A[1])*2.55,parseFloat(A[2])*2.55,parseFloat(A[3])*2.55)}if((A=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(D))){return new C(parseFloat(A[1])*2.55,parseFloat(A[2])*2.55,parseFloat(A[3])*2.55,parseFloat(A[4]))}if((A=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(D))){return new C(parseInt(A[1],16),parseInt(A[2],16),parseInt(A[3],16))}if((A=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(D))){return new C(parseInt(A[1]+A[1],16),parseInt(A[2]+A[2],16),parseInt(A[3]+A[3],16))}var B=D.strip().toLowerCase();if(B=="transparent"){return new C(255,255,255,0)}return((A=C.lookupColors[B]))?new C(A[0],A[1],A[2]):false},extractColor:function(B){var A;do{A=B.getStyle("background-color").toLowerCase();if(!(A==""||A=="transparent")){break}B=B.up(0)}while(!B.nodeName.match(/^body$/i));return(A=="rgba(0, 0, 0, 0)")?"transparent":A}};Flotr.Graph=Class.create({initialize:function(B,C,A){this.el=$(B);if(!this.el){throw"The target container doesn't exist"}this.data=C;this.series=Flotr.getSeries(C);this.setOptions(A);this.lastMousePos={pageX:null,pageY:null};this.selection={first:{x:-1,y:-1},second:{x:-1,y:-1}};this.prevSelection=null;this.selectionInterval=null;this.ignoreClick=false;this.prevHit=null;this.constructCanvas();this.initEvents();this.findDataRanges();this.calculateTicks(this.axes.x);this.calculateTicks(this.axes.x2);this.calculateTicks(this.axes.y);this.calculateTicks(this.axes.y2);this.calculateSpacing();this.draw();this.insertLegend();if(this.options.spreadsheet.show){this.constructTabs()}},setOptions:function(B){var P={colors:["#00A8F0","#C0D800","#CB4B4B","#4DA74D","#9440ED"],title:null,subtitle:null,legend:{show:true,noColumns:1,labelFormatter:Prototype.K,labelBoxBorderColor:"#CCCCCC",labelBoxWidth:14,labelBoxHeight:10,labelBoxMargin:5,container:null,position:"nw",margin:5,backgroundColor:null,backgroundOpacity:0.85},xaxis:{ticks:null,showLabels:true,labelsAngle:0,title:null,titleAngle:0,noTicks:5,tickFormatter:Flotr.defaultTickFormatter,tickDecimals:null,min:null,max:null,autoscaleMargin:0,color:null},x2axis:{},yaxis:{ticks:null,showLabels:true,labelsAngle:0,title:null,titleAngle:90,noTicks:5,tickFormatter:Flotr.defaultTickFormatter,tickDecimals:null,min:null,max:null,autoscaleMargin:0,color:null},y2axis:{titleAngle:270},points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#FFFFFF",fillOpacity:0.4},lines:{show:false,lineWidth:2,fill:false,fillColor:null,fillOpacity:0.4},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,fillOpacity:0.4,horizontal:false,stacked:false},candles:{show:false,lineWidth:1,wickLineWidth:1,candleWidth:0.6,fill:true,upFillColor:"#00A8F0",downFillColor:"#CB4B4B",fillOpacity:0.5,barcharts:false},pie:{show:false,lineWidth:1,fill:true,fillColor:null,fillOpacity:0.6,explode:6,sizeRatio:0.6,startAngle:Math.PI/4,labelFormatter:Flotr.defaultPieLabelFormatter,pie3D:false,pie3DviewAngle:(Math.PI/2*0.8),pie3DspliceThickness:20},grid:{color:"#545454",backgroundColor:null,tickColor:"#DDDDDD",labelMargin:3,verticalLines:true,horizontalLines:true,outlineWidth:2},selection:{mode:null,color:"#B6D9FF",fps:20},mouse:{track:false,position:"se",relative:false,trackFormatter:Flotr.defaultTrackFormatter,margin:5,lineColor:"#FF3F19",trackDecimals:1,sensibility:2,radius:3},shadowSize:4,defaultType:"lines",HtmlText:true,fontSize:7.5,spreadsheet:{show:false,tabGraphLabel:"Graph",tabDataLabel:"Data",toolbarDownload:"Download CSV",toolbarSelectAll:"Select all"}};P.x2axis=Object.extend(Object.clone(P.xaxis),P.x2axis);P.y2axis=Object.extend(Object.clone(P.yaxis),P.y2axis);this.options=Flotr.merge((B||{}),P);this.axes={x:{options:this.options.xaxis,n:1},x2:{options:this.options.x2axis,n:2},y:{options:this.options.yaxis,n:1},y2:{options:this.options.y2axis,n:2}};var H=[],C=[],K=this.series.length,N=this.series.length,D=this.options.colors,A=[],G=0,M,J,I,O,E;for(J=N-1;J>-1;--J){M=this.series[J].color;if(M!=null){--N;if(Object.isNumber(M)){H.push(M)}else{A.push(Flotr.parseColor(M))}}}for(J=H.length-1;J>-1;--J){N=Math.max(N,H[J]+1)}for(J=0;C.length<N;){M=(D.length==J)?new Flotr.Color(100,100,100):Flotr.parseColor(D[J]);var F=G%2==1?-1:1;var L=1+F*Math.ceil(G/2)*0.2;M.scale(L,L,L);C.push(M);if(++J>=D.length){J=0;++G}}for(J=0,I=0;J<K;++J){O=this.series[J];if(O.color==null){O.color=C[I++].toString()}else{if(Object.isNumber(O.color)){O.color=C[O.color].toString()}}if(!O.xaxis){O.xaxis=this.axes.x}if(O.xaxis==1){O.xaxis=this.axes.x}else{if(O.xaxis==2){O.xaxis=this.axes.x2}}if(!O.yaxis){O.yaxis=this.axes.y}if(O.yaxis==1){O.yaxis=this.axes.y}else{if(O.yaxis==2){O.yaxis=this.axes.y2}}O.lines=Object.extend(Object.clone(this.options.lines),O.lines);O.points=Object.extend(Object.clone(this.options.points),O.points);O.bars=Object.extend(Object.clone(this.options.bars),O.bars);O.candles=Object.extend(Object.clone(this.options.candles),O.candles);O.pie=Object.extend(Object.clone(this.options.pie),O.pie);O.mouse=Object.extend(Object.clone(this.options.mouse),O.mouse);if(O.shadowSize==null){O.shadowSize=this.options.shadowSize}}},constructCanvas:function(){var C=this.el,B,D,A;this.canvas=C.select(".flotr-canvas")[0];this.overlay=C.select(".flotr-overlay")[0];C.childElements().invoke("remove");C.setStyle({position:"relative",cursor:"default"});this.canvasWidth=C.getWidth();this.canvasHeight=C.getHeight();B={width:this.canvasWidth,height:this.canvasHeight};if(this.canvasWidth<=0||this.canvasHeight<=0){throw"Invalid dimensions for plot, width = "+this.canvasWidth+", height = "+this.canvasHeight}if(!this.canvas){D=this.canvas=new Element("canvas",B);D.className="flotr-canvas";D=D.writeAttribute("style","position:absolute;left:0px;top:0px;")}else{D=this.canvas.writeAttribute(B)}C.insert(D);if(Prototype.Browser.IE){D=window.G_vmlCanvasManager.initElement(D)}this.ctx=D.getContext("2d");if(!this.overlay){A=this.overlay=new Element("canvas",B);A.className="flotr-overlay";A=A.writeAttribute("style","position:absolute;left:0px;top:0px;")}else{A=this.overlay.writeAttribute(B)}C.insert(A);if(Prototype.Browser.IE){A=window.G_vmlCanvasManager.initElement(A)}this.octx=A.getContext("2d");if(window.CanvasText){CanvasText.enable(this.ctx);CanvasText.enable(this.octx);this.textEnabled=true}},getTextDimensions:function(F,C,B,D){if(!F){return{width:0,height:0}}if(!this.options.HtmlText&&this.textEnabled){var E=this.ctx.getTextBounds(F,C);return{width:E.width+2,height:E.height+6}}else{var A=this.el.insert('<div style="position:absolute;top:-10000px;'+B+'" class="'+D+' flotr-dummy-div">'+F+"</div>").select(".flotr-dummy-div")[0];dim=A.getDimensions();A.remove();return dim}},loadDataGrid:function(){if(this.seriesData){return this.seriesData}var A=this.series;var B=[];for(i=0;i<A.length;++i){A[i].data.each(function(D){var C=D[0],F=D[1];if(r=B.find(function(G){return G[0]==C})){r[i+1]=F}else{var E=[];E[0]=C;E[i+1]=F;B.push(E)}})}B=B.sortBy(function(C){return C[0]});return this.seriesData=B},showTab:function(B,C){var A="canvas, .flotr-labels, .flotr-legend, .flotr-legend-bg, .flotr-title, .flotr-subtitle";switch(B){case"graph":this.datagrid.up().hide();this.el.select(A).invoke("show");this.tabs.data.removeClassName("selected");this.tabs.graph.addClassName("selected");break;case"data":this.constructDataGrid();this.datagrid.up().show();this.el.select(A).invoke("hide");this.tabs.data.addClassName("selected");this.tabs.graph.removeClassName("selected");break}},constructTabs:function(){var A=new Element("div",{className:"flotr-tabs-group",style:"position:absolute;left:0px;top:"+this.canvasHeight+"px;width:"+this.canvasWidth+"px;"});this.el.insert({bottom:A});this.tabs={graph:new Element("div",{className:"flotr-tab selected",style:"float:left;"}).update(this.options.spreadsheet.tabGraphLabel),data:new Element("div",{className:"flotr-tab",style:"float:left;"}).update(this.options.spreadsheet.tabDataLabel)};A.insert(this.tabs.graph).insert(this.tabs.data);this.el.setStyle({height:this.canvasHeight+this.tabs.data.getHeight()+2+"px"});this.tabs.graph.observe("click",(function(){this.showTab("graph")}).bind(this));this.tabs.data.observe("click",(function(){this.showTab("data")}).bind(this))},constructDataGrid:function(){if(this.datagrid){return this.datagrid}var D,B,L=this.series,J=this.loadDataGrid();var K=this.datagrid=new Element("table",{className:"flotr-datagrid",style:"height:100px;"});var C=["<colgroup><col />"];var F=['<tr class="first-row">'];F.push("<th>&nbsp;</th>");for(D=0;D<L.length;++D){F.push('<th scope="col">'+(L[D].label||String.fromCharCode(65+D))+"</th>");C.push("<col />")}F.push("</tr>");for(B=0;B<J.length;++B){F.push("<tr>");for(D=0;D<L.length+1;++D){var M="td";var G=(J[B][D]!=null?Math.round(J[B][D]*100000)/100000:"");if(D==0){M="th";var I;if(this.options.xaxis.ticks){var E=this.options.xaxis.ticks.find(function(N){return N[0]==J[B][D]});if(E){I=E[1]}}else{I=this.options.xaxis.tickFormatter(G)}if(I){G=I}}F.push("<"+M+(M=="th"?' scope="row"':"")+">"+G+"</"+M+">")}F.push("</tr>")}C.push("</colgroup>");K.update(C.join("")+F.join(""));if(!Prototype.Browser.IE){K.select("td").each(function(N){N.observe("mouseover",function(O){N=O.element();var P=N.previousSiblings();K.select("th[scope=col]")[P.length-1].addClassName("hover");K.select("colgroup col")[P.length].addClassName("hover")});N.observe("mouseout",function(){K.select("colgroup col.hover, th.hover").each(function(O){O.removeClassName("hover")})})})}var H=new Element("div",{className:"flotr-datagrid-toolbar"}).insert(new Element("button",{type:"button",className:"flotr-datagrid-toolbar-button"}).update(this.options.spreadsheet.toolbarDownload).observe("click",this.downloadCSV.bind(this))).insert(new Element("button",{type:"button",className:"flotr-datagrid-toolbar-button"}).update(this.options.spreadsheet.toolbarSelectAll).observe("click",this.selectAllData.bind(this)));var A=new Element("div",{className:"flotr-datagrid-container",style:"left:0px;top:0px;width:"+this.canvasWidth+"px;height:"+this.canvasHeight+"px;overflow:auto;"});A.insert(H);K.wrap(A.hide());this.el.insert(A);return K},selectAllData:function(){if(this.tabs){var B,A,E,D,C=this.constructDataGrid();this.showTab("data");(function(){if((E=C.ownerDocument)&&(D=E.defaultView)&&D.getSelection&&E.createRange&&(B=window.getSelection())&&B.removeAllRanges){A=E.createRange();A.selectNode(C);B.removeAllRanges();B.addRange(A)}else{if(document.body&&document.body.createTextRange&&(A=document.body.createTextRange())){A.moveToElementText(C);A.select()}}}).defer();return true}else{return false}},downloadCSV:function(){var D,A='"x"',C=this.series,E=this.loadDataGrid();for(D=0;D<C.length;++D){A+='%09"'+(C[D].label||String.fromCharCode(65+D))+'"'}A+="%0D%0A";for(D=0;D<E.length;++D){if(this.options.xaxis.ticks){var B=this.options.xaxis.ticks.find(function(F){return F[0]==E[D][0]});if(B){E[D][0]=B[1]}}else{E[D][0]=this.options.xaxis.tickFormatter(E[D][0])}A+=E[D].join("%09")+"%0D%0A"}if(Prototype.Browser.IE){A=A.gsub("%09","\t").gsub("%0A","\n").gsub("%0D","\r");window.open().document.write(A)}else{window.open("data:text/csv,"+A)}},initEvents:function(){this.overlay.stopObserving();this.overlay.observe("mousedown",this.mouseDownHandler.bind(this));this.overlay.observe("mousemove",this.mouseMoveHandler.bind(this));this.overlay.observe("click",this.clickHandler.bind(this))},findDataRanges:function(){var J=this.series,G=this.axes;G.x.datamin=0;G.x.datamax=0;G.x2.datamin=0;G.x2.datamax=0;G.y.datamin=0;G.y.datamax=0;G.y2.datamin=0;G.y2.datamax=0;if(J.length>0){var C,A,D,H,F,B,I,E;for(C=0;C<J.length;++C){B=J[C].data,I=J[C].xaxis,E=J[C].yaxis;if(B.length>0&&!J[C].hide){if(!I.used){I.datamin=I.datamax=B[0][0]}if(!E.used){E.datamin=E.datamax=B[0][1]}I.used=true;E.used=true;for(D=B.length-1;D>-1;--D){H=B[D][0];if(H<I.datamin){I.datamin=H}else{if(H>I.datamax){I.datamax=H}}for(A=1;A<B[D].length;A++){F=B[D][A];if(F<E.datamin){E.datamin=F}else{if(F>E.datamax){E.datamax=F}}}}}}}this.findXAxesValues();this.calculateRange(G.x);this.extendXRangeIfNeededByBar(G.x);if(G.x2.used){this.calculateRange(G.x2);this.extendXRangeIfNeededByBar(G.x2)}this.calculateRange(G.y);this.extendYRangeIfNeededByBar(G.y);if(G.y2.used){this.calculateRange(G.y2);this.extendYRangeIfNeededByBar(G.y2)}},calculateRange:function(D){var F=D.options,C=F.min!=null?F.min:D.datamin,A=F.max!=null?F.max:D.datamax,E;if(A-C==0){var B=(A==0)?1:0.01;C-=B;A+=B}D.tickSize=Flotr.getTickSize(F.noTicks,C,A,F.tickDecimals);if(F.min==null){E=F.autoscaleMargin;if(E!=0){C-=D.tickSize*E;if(C<0&&D.datamin>=0){C=0}C=D.tickSize*Math.floor(C/D.tickSize)}}if(F.max==null){E=F.autoscaleMargin;if(E!=0){A+=D.tickSize*E;if(A>0&&D.datamax<=0){A=0}A=D.tickSize*Math.ceil(A/D.tickSize)}}D.min=C;D.max=A},extendXRangeIfNeededByBar:function(A){if(A.options.max==null){var D=A.max,B,I,F,E,H=[],C=null;for(B=0;B<this.series.length;++B){I=this.series[B];F=I.bars;E=I.candles;if(I.axis==A&&(F.show||E.show)){if(!F.horizontal&&(F.barWidth+A.datamax>D)||(E.candleWidth+A.datamax>D)){D=A.max+I.bars.barWidth}if(F.stacked&&F.horizontal){for(j=0;j<I.data.length;j++){if(I.bars.show&&I.bars.stacked){var G=I.data[j][0];H[G]=(H[G]||0)+I.data[j][1];C=I}}for(j=0;j<H.length;j++){D=Math.max(H[j],D)}}}}A.lastSerie=C;A.max=D}},extendYRangeIfNeededByBar:function(A){if(A.options.max==null){var D=A.max,B,I,F,E,H=[],C=null;for(B=0;B<this.series.length;++B){I=this.series[B];F=I.bars;E=I.candles;if(I.yaxis==A&&F.show&&!I.hide){if(F.horizontal&&(F.barWidth+A.datamax>D)||(E.candleWidth+A.datamax>D)){D=A.max+F.barWidth}if(F.stacked&&!F.horizontal){for(j=0;j<I.data.length;j++){if(I.bars.show&&I.bars.stacked){var G=I.data[j][0];H[G]=(H[G]||0)+I.data[j][1];C=I}}for(j=0;j<H.length;j++){D=Math.max(H[j],D)}}}}A.lastSerie=C;A.max=D}},findXAxesValues:function(){for(i=this.series.length-1;i>-1;--i){s=this.series[i];s.xaxis.values=s.xaxis.values||[];for(j=s.data.length-1;j>-1;--j){s.xaxis.values[s.data[j][0]]={}}}},calculateTicks:function(D){var B=D.options,E,H;D.ticks=[];if(B.ticks){var G=B.ticks,I,F;if(Object.isFunction(G)){G=G({min:D.min,max:D.max})}for(E=0;E<G.length;++E){I=G[E];if(typeof (I)=="object"){H=I[0];F=(I.length>1)?I[1]:B.tickFormatter(H)}else{H=I;F=B.tickFormatter(H)}D.ticks[E]={v:H,label:F}}}else{var A=D.tickSize*Math.ceil(D.min/D.tickSize),C;for(E=0;A+E*D.tickSize<=D.max;++E){H=A+E*D.tickSize;C=B.tickDecimals;if(C==null){C=1-Math.floor(Math.log(D.tickSize)/Math.LN10)}if(C<0){C=0}H=H.toFixed(C);D.ticks.push({v:H,label:B.tickFormatter(H)})}}},calculateSpacing:function(){var L=this.axes,N=this.options,H=this.series,D=N.grid.labelMargin,M=L.x,A=L.x2,J=L.y,K=L.y2,F=2,G,E,C,I;[M,A,J,K].each(function(P){var O="";if(P.options.showLabels){for(G=0;G<P.ticks.length;++G){C=P.ticks[G].label.length;if(C>O.length){O=P.ticks[G].label}}}P.maxLabel=this.getTextDimensions(O,{size:N.fontSize,angle:Flotr.toRad(P.options.labelsAngle)},"font-size:smaller;","flotr-grid-label");P.titleSize=this.getTextDimensions(P.options.title,{size:N.fontSize*1.2,angle:Flotr.toRad(P.options.titleAngle)},"font-weight:bold;","flotr-axis-title")},this);I=this.getTextDimensions(N.title,{size:N.fontSize*1.5},"font-size:1em;font-weight:bold;","flotr-title");this.titleHeight=I.height;I=this.getTextDimensions(N.subtitle,{size:N.fontSize},"font-size:smaller;","flotr-subtitle");this.subtitleHeight=I.height;if(N.show){F=Math.max(F,N.points.radius+N.points.lineWidth/2)}for(E=0;E<N.length;++E){if(H[E].points.show){F=Math.max(F,H[E].points.radius+H[E].points.lineWidth/2)}}var B=this.plotOffset={left:0,right:0,top:0,bottom:0};B.left=B.right=B.top=B.bottom=F;B.bottom+=(M.options.showLabels?(M.maxLabel.height+D):0)+(M.options.title?(M.titleSize.height+D):0);B.top+=(A.options.showLabels?(A.maxLabel.height+D):0)+(A.options.title?(A.titleSize.height+D):0)+this.subtitleHeight+this.titleHeight;B.left+=(J.options.showLabels?(J.maxLabel.width+D):0)+(J.options.title?(J.titleSize.width+D):0);B.right+=(K.options.showLabels?(K.maxLabel.width+D):0)+(K.options.title?(K.titleSize.width+D):0);B.top=Math.floor(B.top);this.plotWidth=this.canvasWidth-B.left-B.right;this.plotHeight=this.canvasHeight-B.bottom-B.top;M.scale=this.plotWidth/(M.max-M.min);A.scale=this.plotWidth/(A.max-A.min);J.scale=this.plotHeight/(J.max-J.min);K.scale=this.plotHeight/(K.max-K.min)},draw:function(){this.drawGrid();this.drawLabels();this.drawTitles();if(this.series.length){this.el.fire("flotr:beforedraw",[this.series,this]);for(var A=0;A<this.series.length;A++){if(!this.series[A].hide){this.drawSeries(this.series[A])}}}this.el.fire("flotr:afterdraw",[this.series,this])},tHoz:function(A,B){B=B||this.axes.x;return(A-B.min)*B.scale},tVert:function(B,A){A=A||this.axes.y;return this.plotHeight-(B-A.min)*A.scale},drawGrid:function(){var B,E=this.options,A=this.ctx;if(E.grid.verticalLines||E.grid.horizontalLines){this.el.fire("flotr:beforegrid",[this.axes.x,this.axes.y,E,this])}A.save();A.translate(this.plotOffset.left,this.plotOffset.top);if(E.grid.backgroundColor!=null){A.fillStyle=E.grid.backgroundColor;A.fillRect(0,0,this.plotWidth,this.plotHeight)}A.lineWidth=1;A.strokeStyle=E.grid.tickColor;A.beginPath();if(E.grid.verticalLines){for(var D=0;D<this.axes.x.ticks.length;++D){B=this.axes.x.ticks[D].v;if((B==this.axes.x.min||B==this.axes.x.max)&&E.grid.outlineWidth!=0){continue}A.moveTo(Math.floor(this.tHoz(B))+A.lineWidth/2,0);A.lineTo(Math.floor(this.tHoz(B))+A.lineWidth/2,this.plotHeight)}}if(E.grid.horizontalLines){for(var C=0;C<this.axes.y.ticks.length;++C){B=this.axes.y.ticks[C].v;if((B==this.axes.y.min||B==this.axes.y.max)&&E.grid.outlineWidth!=0){continue}A.moveTo(0,Math.floor(this.tVert(B))+A.lineWidth/2);A.lineTo(this.plotWidth,Math.floor(this.tVert(B))+A.lineWidth/2)}}A.stroke();if(E.grid.outlineWidth!=0){A.lineWidth=E.grid.outlineWidth;A.strokeStyle=E.grid.color;A.lineJoin="round";A.strokeRect(0,0,this.plotWidth,this.plotHeight)}A.restore();if(E.grid.verticalLines||E.grid.horizontalLines){this.el.fire("flotr:aftergrid",[this.axes.x,this.axes.y,E,this])}},drawLabels:function(){var C=0,D,B,E,F,G,J=this.options,I=this.ctx,H=this.axes;for(E=0;E<H.x.ticks.length;++E){if(H.x.ticks[E].label){++C}}B=this.plotWidth/C;if(!J.HtmlText&&this.textEnabled){var A={size:J.fontSize,adjustAlign:true};D=H.x;A.color=D.options.color||J.grid.color;for(E=0;E<D.ticks.length&&D.options.showLabels&&D.used;++E){G=D.ticks[E];if(!G.label||G.label.length==0){continue}A.angle=Flotr.toRad(D.options.labelsAngle);A.halign="c";A.valign="t";I.drawText(G.label,this.plotOffset.left+this.tHoz(G.v,D),this.plotOffset.top+this.plotHeight+J.grid.labelMargin,A)}D=H.x2;A.color=D.options.color||J.grid.color;for(E=0;E<D.ticks.length&&D.options.showLabels&&D.used;++E){G=D.ticks[E];if(!G.label||G.label.length==0){continue}A.angle=Flotr.toRad(D.options.labelsAngle);A.halign="c";A.valign="b";I.drawText(G.label,this.plotOffset.left+this.tHoz(G.v,D),this.plotOffset.top+J.grid.labelMargin,A)}D=H.y;A.color=D.options.color||J.grid.color;for(E=0;E<D.ticks.length&&D.options.showLabels&&D.used;++E){G=D.ticks[E];if(!G.label||G.label.length==0){continue}A.angle=Flotr.toRad(D.options.labelsAngle);A.halign="r";A.valign="m";I.drawText(G.label,this.plotOffset.left-J.grid.labelMargin,this.plotOffset.top+this.tVert(G.v,D),A)}D=H.y2;A.color=D.options.color||J.grid.color;for(E=0;E<D.ticks.length&&D.options.showLabels&&D.used;++E){G=D.ticks[E];if(!G.label||G.label.length==0){continue}A.angle=Flotr.toRad(D.options.labelsAngle);A.halign="l";A.valign="m";I.drawText(G.label,this.plotOffset.left+this.plotWidth+J.grid.labelMargin,this.plotOffset.top+this.tVert(G.v,D),A);I.save();I.strokeStyle=A.color;I.beginPath();I.moveTo(this.plotOffset.left+this.plotWidth-8,this.plotOffset.top+this.tVert(G.v,D));I.lineTo(this.plotOffset.left+this.plotWidth,this.plotOffset.top+this.tVert(G.v,D));I.stroke();I.restore()}}else{if(H.x.options.showLabels||H.x2.options.showLabels||H.y.options.showLabels||H.y2.options.showLabels){F=['<div style="font-size:smaller;color:'+J.grid.color+';" class="flotr-labels">'];D=H.x;if(D.options.showLabels){for(E=0;E<D.ticks.length;++E){G=D.ticks[E];if(!G.label||G.label.length==0){continue}F.push('<div style="position:absolute;top:'+(this.plotOffset.top+this.plotHeight+J.grid.labelMargin)+"px;left:"+(this.plotOffset.left+this.tHoz(G.v,D)-B/2)+"px;width:"+B+"px;text-align:center;"+(D.options.color?("color:"+D.options.color+";"):"")+'" class="flotr-grid-label">'+G.label+"</div>")}}D=H.x2;if(D.options.showLabels&&D.used){for(E=0;E<D.ticks.length;++E){G=D.ticks[E];if(!G.label||G.label.length==0){continue}F.push('<div style="position:absolute;top:'+(this.plotOffset.top-J.grid.labelMargin-D.maxLabel.height)+"px;left:"+(this.plotOffset.left+this.tHoz(G.v,D)-B/2)+"px;width:"+B+"px;text-align:center;"+(D.options.color?("color:"+D.options.color+";"):"")+'" class="flotr-grid-label">'+G.label+"</div>")}}D=H.y;if(D.options.showLabels){for(E=0;E<D.ticks.length;++E){G=D.ticks[E];if(!G.label||G.label.length==0){continue}F.push('<div style="position:absolute;top:'+(this.plotOffset.top+this.tVert(G.v,D)-D.maxLabel.height/2)+"px;left:0;width:"+(this.plotOffset.left-J.grid.labelMargin)+"px;text-align:right;"+(D.options.color?("color:"+D.options.color+";"):"")+'" class="flotr-grid-label">'+G.label+"</div>")}}D=H.y2;if(D.options.showLabels&&D.used){I.save();I.strokeStyle=D.options.color||J.grid.color;I.beginPath();for(E=0;E<D.ticks.length;++E){G=D.ticks[E];if(!G.label||G.label.length==0){continue}F.push('<div style="position:absolute;top:'+(this.plotOffset.top+this.tVert(G.v,D)-D.maxLabel.height/2)+"px;right:0;width:"+(this.plotOffset.right-J.grid.labelMargin)+"px;text-align:left;"+(D.options.color?("color:"+D.options.color+";"):"")+'" class="flotr-grid-label">'+G.label+"</div>");I.moveTo(this.plotOffset.left+this.plotWidth-8,this.plotOffset.top+this.tVert(G.v,D));I.lineTo(this.plotOffset.left+this.plotWidth,this.plotOffset.top+this.tVert(G.v,D))}I.stroke();I.restore()}F.push("</div>");this.el.insert(F.join(""))}}},drawTitles:function(){var D,C=this.options,F=C.grid.labelMargin,B=this.ctx,A=this.axes;if(!C.HtmlText&&this.textEnabled){var E={size:C.fontSize,color:C.grid.color,halign:"c"};if(C.subtitle){B.drawText(C.subtitle,this.plotOffset.left+this.plotWidth/2,this.titleHeight+this.subtitleHeight-2,E)}E.weight=1.5;E.size*=1.5;if(C.title){B.drawText(C.title,this.plotOffset.left+this.plotWidth/2,this.titleHeight-2,E)}E.weight=1.8;E.size*=0.8;E.adjustAlign=true;if(A.x.options.title&&A.x.used){E.halign="c";E.valign="t";E.angle=Flotr.toRad(A.x.options.titleAngle);B.drawText(A.x.options.title,this.plotOffset.left+this.plotWidth/2,this.plotOffset.top+A.x.maxLabel.height+this.plotHeight+2*F,E)}if(A.x2.options.title&&A.x2.used){E.halign="c";E.valign="b";E.angle=Flotr.toRad(A.x2.options.titleAngle);B.drawText(A.x2.options.title,this.plotOffset.left+this.plotWidth/2,this.plotOffset.top-A.x2.maxLabel.height-2*F,E)}if(A.y.options.title&&A.y.used){E.halign="r";E.valign="m";E.angle=Flotr.toRad(A.y.options.titleAngle);B.drawText(A.y.options.title,this.plotOffset.left-A.y.maxLabel.width-2*F,this.plotOffset.top+this.plotHeight/2,E)}if(A.y2.options.title&&A.y2.used){E.halign="l";E.valign="m";E.angle=Flotr.toRad(A.y2.options.titleAngle);B.drawText(A.y2.options.title,this.plotOffset.left+this.plotWidth+A.y2.maxLabel.width+2*F,this.plotOffset.top+this.plotHeight/2,E)}}else{D=['<div style="color:'+C.grid.color+';" class="flotr-titles">'];if(C.title){D.push('<div style="position:absolute;top:0;left:'+this.plotOffset.left+"px;font-size:1em;font-weight:bold;text-align:center;width:"+this.plotWidth+'px;" class="flotr-title">'+C.title+"</div>")}if(C.subtitle){D.push('<div style="position:absolute;top:'+this.titleHeight+"px;left:"+this.plotOffset.left+"px;font-size:smaller;text-align:center;width:"+this.plotWidth+'px;" class="flotr-subtitle">'+C.subtitle+"</div>")}D.push("</div>");D.push('<div class="flotr-axis-title" style="font-weight:bold;">');if(A.x.options.title&&A.x.used){D.push('<div style="position:absolute;top:'+(this.plotOffset.top+this.plotHeight+C.grid.labelMargin+A.x.titleSize.height)+"px;left:"+this.plotOffset.left+"px;width:"+this.plotWidth+'px;text-align:center;" class="flotr-axis-title">'+A.x.options.title+"</div>")}if(A.x2.options.title&&A.x2.used){D.push('<div style="position:absolute;top:0;left:'+this.plotOffset.left+"px;width:"+this.plotWidth+'px;text-align:center;" class="flotr-axis-title">'+A.x2.options.title+"</div>")}if(A.y.options.title&&A.y.used){D.push('<div style="position:absolute;top:'+(this.plotOffset.top+this.plotHeight/2-A.y.titleSize.height/2)+'px;left:0;text-align:right;" class="flotr-axis-title">'+A.y.options.title+"</div>")}if(A.y2.options.title&&A.y2.used){D.push('<div style="position:absolute;top:'+(this.plotOffset.top+this.plotHeight/2-A.y.titleSize.height/2)+'px;right:0;text-align:right;" class="flotr-axis-title">'+A.y2.options.title+"</div>")}D.push("</div>");this.el.insert(D.join(""))}},drawSeries:function(A){A=A||this.series;var C=false;for(var B in Flotr._registeredTypes){if(A[B]&&A[B].show){this[Flotr._registeredTypes[B]](A);C=true}}if(!C){this[Flotr._registeredTypes[this.options.defaultType]](A)}},plotLine:function(I,F){var O=this.ctx,A=I.xaxis,K=I.yaxis,J=this.tHoz.bind(this),M=this.tVert.bind(this),H=I.data;if(H.length<2){return }var E=J(H[0][0],A),D=M(H[0][1],K)+F;O.beginPath();O.moveTo(E,D);for(var G=0;G<H.length-1;++G){var C=H[G][0],N=H[G][1],B=H[G+1][0],L=H[G+1][1];if(N===null||L===null){continue}if(N<=L&&N<K.min){if(L<K.min){continue}C=(K.min-N)/(L-N)*(B-C)+C;N=K.min}else{if(L<=N&&L<K.min){if(N<K.min){continue}B=(K.min-N)/(L-N)*(B-C)+C;L=K.min}}if(N>=L&&N>K.max){if(L>K.max){continue}C=(K.max-N)/(L-N)*(B-C)+C;N=K.max}else{if(L>=N&&L>K.max){if(N>K.max){continue}B=(K.max-N)/(L-N)*(B-C)+C;L=K.max}}if(C<=B&&C<A.min){if(B<A.min){continue}N=(A.min-C)/(B-C)*(L-N)+N;C=A.min}else{if(B<=C&&B<A.min){if(C<A.min){continue}L=(A.min-C)/(B-C)*(L-N)+N;B=A.min}}if(C>=B&&C>A.max){if(B>A.max){continue}N=(A.max-C)/(B-C)*(L-N)+N;C=A.max}else{if(B>=C&&B>A.max){if(C>A.max){continue}L=(A.max-C)/(B-C)*(L-N)+N;B=A.max}}if(E!=J(C,A)||D!=M(N,K)+F){O.moveTo(J(C,A),M(N,K)+F)}E=J(B,A);D=M(L,K)+F;O.lineTo(E,D)}O.stroke()},plotLineArea:function(J,D){var S=J.data;if(S.length<2){return }var L,G=0,N=this.ctx,Q=J.xaxis,B=J.yaxis,E=this.tHoz.bind(this),M=this.tVert.bind(this),H=Math.min(Math.max(0,B.min),B.max),F=true;N.beginPath();for(var O=0;O<S.length-1;++O){var R=S[O][0],C=S[O][1],P=S[O+1][0],A=S[O+1][1];if(R<=P&&R<Q.min){if(P<Q.min){continue}C=(Q.min-R)/(P-R)*(A-C)+C;R=Q.min}else{if(P<=R&&P<Q.min){if(R<Q.min){continue}A=(Q.min-R)/(P-R)*(A-C)+C;P=Q.min}}if(R>=P&&R>Q.max){if(P>Q.max){continue}C=(Q.max-R)/(P-R)*(A-C)+C;R=Q.max}else{if(P>=R&&P>Q.max){if(R>Q.max){continue}A=(Q.max-R)/(P-R)*(A-C)+C;P=Q.max}}if(F){N.moveTo(E(R,Q),M(H,B)+D);F=false}if(C>=B.max&&A>=B.max){N.lineTo(E(R,Q),M(B.max,B)+D);N.lineTo(E(P,Q),M(B.max,B)+D);continue}else{if(C<=B.min&&A<=B.min){N.lineTo(E(R,Q),M(B.min,B)+D);N.lineTo(E(P,Q),M(B.min,B)+D);continue}}var I=R,K=P;if(C<=A&&C<B.min&&A>=B.min){R=(B.min-C)/(A-C)*(P-R)+R;C=B.min}else{if(A<=C&&A<B.min&&C>=B.min){P=(B.min-C)/(A-C)*(P-R)+R;A=B.min}}if(C>=A&&C>B.max&&A<=B.max){R=(B.max-C)/(A-C)*(P-R)+R;C=B.max}else{if(A>=C&&A>B.max&&C<=B.max){P=(B.max-C)/(A-C)*(P-R)+R;A=B.max}}if(R!=I){L=(C<=B.min)?L=B.min:B.max;N.lineTo(E(I,Q),M(L,B)+D);N.lineTo(E(R,Q),M(L,B)+D)}N.lineTo(E(R,Q),M(C,B)+D);N.lineTo(E(P,Q),M(A,B)+D);if(P!=K){L=(A<=B.min)?B.min:B.max;N.lineTo(E(K,Q),M(L,B)+D);N.lineTo(E(P,Q),M(L,B)+D)}G=Math.max(P,K)}N.lineTo(E(G,Q),M(H,B)+D);N.closePath();N.fill()},drawSeriesLines:function(C){C=C||this.series;var B=this.ctx;B.save();B.translate(this.plotOffset.left,this.plotOffset.top);B.lineJoin="round";var D=C.lines.lineWidth;var A=C.shadowSize;if(A>0){B.lineWidth=A/2;var E=D/2+B.lineWidth/2;B.strokeStyle="rgba(0,0,0,0.1)";this.plotLine(C,E+A/2);B.strokeStyle="rgba(0,0,0,0.2)";this.plotLine(C,E);if(C.lines.fill){B.fillStyle="rgba(0,0,0,0.05)";this.plotLineArea(C,E+A/2)}}B.lineWidth=D;B.strokeStyle=C.color;if(C.lines.fill){B.fillStyle=C.lines.fillColor!=null?C.lines.fillColor:Flotr.parseColor(C.color).scale(null,null,null,C.lines.fillOpacity).toString();this.plotLineArea(C,0)}this.plotLine(C,0);B.restore()},drawSeriesPoints:function(C){var B=this.ctx;B.save();B.translate(this.plotOffset.left,this.plotOffset.top);var D=C.lines.lineWidth;var A=C.shadowSize;if(A>0){B.lineWidth=A/2;B.strokeStyle="rgba(0,0,0,0.1)";this.plotPointShadows(C,A/2+B.lineWidth/2,C.points.radius);B.strokeStyle="rgba(0,0,0,0.2)";this.plotPointShadows(C,B.lineWidth/2,C.points.radius)}B.lineWidth=C.points.lineWidth;B.strokeStyle=C.color;B.fillStyle=C.points.fillColor!=null?C.points.fillColor:C.color;this.plotPoints(C,C.points.radius,C.points.fill);B.restore()},plotPoints:function(C,E,I){var A=C.xaxis,F=C.yaxis,J=this.ctx,D,B=C.data;for(D=B.length-1;D>-1;--D){var H=B[D][0],G=B[D][1];if(H<A.min||H>A.max||G<F.min||G>F.max){continue}J.beginPath();J.arc(this.tHoz(H,A),this.tVert(G,F),E,0,2*Math.PI,true);if(I){J.fill()}J.stroke()}},plotPointShadows:function(D,B,F){var A=D.xaxis,G=D.yaxis,J=this.ctx,E,C=D.data;for(E=C.length-1;E>-1;--E){var I=C[E][0],H=C[E][1];if(I<A.min||I>A.max||H<G.min||H>G.max){continue}J.beginPath();J.arc(this.tHoz(I,A),this.tVert(H,G)+B,F,0,Math.PI,false);J.stroke()}},drawSeriesBars:function(B){var A=this.ctx,D=B.bars.barWidth,C=Math.min(B.bars.lineWidth,D);A.save();A.translate(this.plotOffset.left,this.plotOffset.top);A.lineJoin="miter";A.lineWidth=C;A.strokeStyle=B.color;this.plotBarsShadows(B,D,0,B.bars.fill);if(B.bars.fill){A.fillStyle=B.bars.fillColor!=null?B.bars.fillColor:Flotr.parseColor(B.color).scale(null,null,null,B.bars.fillOpacity).toString()}this.plotBars(B,D,0,B.bars.fill);A.restore()},plotBars:function(K,N,D,Q){var U=K.data;if(U.length<1){return }var S=K.xaxis,B=K.yaxis,P=this.ctx,F=this.tHoz.bind(this),O=this.tVert.bind(this);for(var R=0;R<U.length;R++){var J=U[R][0],I=U[R][1];var E=true,L=true,A=true;var H=0;if(K.bars.stacked){S.values.each(function(W,V){if(V==J){H=W.stack||0;W.stack=H+I}})}if(K.bars.horizontal){var C=H,T=J+H,G=I,M=I+N}else{var C=J,T=J+N,G=H,M=I+H}if(T<S.min||C>S.max||M<B.min||G>B.max){continue}if(C<S.min){C=S.min;E=false}if(T>S.max){T=S.max;if(S.lastSerie!=K&&K.bars.horizontal){L=false}}if(G<B.min){G=B.min}if(M>B.max){M=B.max;if(B.lastSerie!=K&&!K.bars.horizontal){L=false}}if(Q){P.beginPath();P.moveTo(F(C,S),O(G,B)+D);P.lineTo(F(C,S),O(M,B)+D);P.lineTo(F(T,S),O(M,B)+D);P.lineTo(F(T,S),O(G,B)+D);P.fill()}if(K.bars.lineWidth!=0&&(E||A||L)){P.beginPath();P.moveTo(F(C,S),O(G,B)+D);P[E?"lineTo":"moveTo"](F(C,S),O(M,B)+D);P[L?"lineTo":"moveTo"](F(T,S),O(M,B)+D);P[A?"lineTo":"moveTo"](F(T,S),O(G,B)+D);P.stroke()}}},plotBarsShadows:function(I,K,C){var T=I.data;if(T.length<1){return }var R=I.xaxis,A=I.yaxis,P=this.ctx,D=this.tHoz.bind(this),M=this.tVert.bind(this),N=this.options.shadowSize;for(var Q=0;Q<T.length;Q++){var H=T[Q][0],G=T[Q][1];var E=0;if(I.bars.stacked){R.values.each(function(V,U){if(U==H){E=V.stackShadow||0;V.stackShadow=E+G}})}if(I.bars.horizontal){var B=E,S=H+E,F=G,J=G+K}else{var B=H,S=H+K,F=E,J=G+E}if(S<R.min||B>R.max||J<A.min||F>A.max){continue}if(B<R.min){B=R.min}if(S>R.max){S=R.max}if(F<A.min){F=A.min}if(J>A.max){J=A.max}var O=D(S,R)-D(B,R)-((D(S,R)+N<=this.plotWidth)?0:N);var L=Math.max(0,M(F,A)-M(J,A)-((M(F,A)+N<=this.plotHeight)?0:N));P.fillStyle="rgba(0,0,0,0.05)";P.fillRect(Math.min(D(B,R)+N,this.plotWidth),Math.min(M(J,A)+N,this.plotWidth),O,L)}},drawSeriesCandles:function(B){var A=this.ctx,C=B.candles.candleWidth;A.save();A.translate(this.plotOffset.left,this.plotOffset.top);A.lineJoin="miter";A.lineWidth=B.candles.lineWidth;this.plotCandlesShadows(B,C/2);this.plotCandles(B,C/2);A.restore()},plotCandles:function(K,D){var W=K.data;if(W.length<1){return }var T=K.xaxis,B=K.yaxis,P=this.ctx,E=this.tHoz.bind(this),O=this.tVert.bind(this);for(var S=0;S<W.length;S++){var U=W[S],J=U[0],L=U[1],I=U[2],X=U[3],N=U[4];var C=J,V=J+K.candles.candleWidth,G=Math.max(B.min,X),M=Math.min(B.max,I),A=Math.max(B.min,Math.min(L,N)),R=Math.min(B.max,Math.max(L,N));if(V<T.min||C>T.max||M<B.min||G>B.max){continue}var Q=K.candles[L>N?"downFillColor":"upFillColor"];if(K.candles.fill&&!K.candles.barcharts){P.fillStyle=Flotr.parseColor(Q).scale(null,null,null,K.candles.fillOpacity).toString();P.fillRect(E(C,T),O(R,B)+D,E(V,T)-E(C,T),O(A,B)-O(R,B))}if(K.candles.lineWidth||K.candles.wickLineWidth){var J,H,F=(K.candles.wickLineWidth%2)/2;J=Math.floor(E((C+V)/2),T)+F;P.save();P.strokeStyle=Q;P.lineWidth=K.candles.wickLineWidth;P.lineCap="butt";if(K.candles.barcharts){P.beginPath();P.moveTo(J,Math.floor(O(M,B)+D));P.lineTo(J,Math.floor(O(G,B)+D));H=Math.floor(O(L,B)+D)+0.5;P.moveTo(Math.floor(E(C,T))+F,H);P.lineTo(J,H);H=Math.floor(O(N,B)+D)+0.5;P.moveTo(Math.floor(E(V,T))+F,H);P.lineTo(J,H)}else{P.strokeRect(E(C,T),O(R,B)+D,E(V,T)-E(C,T),O(A,B)-O(R,B));P.beginPath();P.moveTo(J,Math.floor(O(R,B)+D));P.lineTo(J,Math.floor(O(M,B)+D));P.moveTo(J,Math.floor(O(A,B)+D));P.lineTo(J,Math.floor(O(G,B)+D))}P.stroke();P.restore()}}},plotCandlesShadows:function(H,C){var T=H.data;if(T.length<1||H.candles.barcharts){return }var Q=H.xaxis,A=H.yaxis,D=this.tHoz.bind(this),M=this.tVert.bind(this),N=this.options.shadowSize;for(var P=0;P<T.length;P++){var R=T[P],G=R[0],I=R[1],F=R[2],U=R[3],K=R[4];var B=G,S=G+H.candles.candleWidth,E=Math.max(A.min,Math.min(I,K)),J=Math.min(A.max,Math.max(I,K));if(S<Q.min||B>Q.max||J<A.min||E>A.max){continue}var O=D(S,Q)-D(B,Q)-((D(S,Q)+N<=this.plotWidth)?0:N);var L=Math.max(0,M(E,A)-M(J,A)-((M(E,A)+N<=this.plotHeight)?0:N));this.ctx.fillStyle="rgba(0,0,0,0.05)";this.ctx.fillRect(Math.min(D(B,Q)+N,this.plotWidth),Math.min(M(J,A)+N,this.plotWidth),O,L)}},drawSeriesPie:function(G){if(!this.options.pie.drawn){var K=this.ctx,C=this.options,E=G.pie.lineWidth,I=G.shadowSize,R=G.data,D=(Math.min(this.canvasWidth,this.canvasHeight)*G.pie.sizeRatio)/2,H=[];var L=1;var P=Math.sin(G.pie.viewAngle)*G.pie.spliceThickness/L;var M={size:C.fontSize*1.2,color:C.grid.color,weight:1.5};var Q={x:(this.canvasWidth+this.plotOffset.left)/2,y:(this.canvasHeight-this.plotOffset.bottom)/2};var O=this.series.collect(function(T,S){if(T.pie.show){return{name:(T.label||T.data[0][1]),value:[S,T.data[0][1]],explode:T.pie.explode}}});var B=O.pluck("value").pluck(1).inject(0,function(S,T){return S+T});var F=0,N=G.pie.startAngle,J=0;var A=O.collect(function(S){N+=F;J=parseFloat(S.value[1]);F=J/B;return{name:S.name,fraction:F,x:S.value[0],y:J,explode:S.explode,startAngle:2*N*Math.PI,endAngle:2*(N+F)*Math.PI}});K.save();if(I>0){A.each(function(V){var S=(V.startAngle+V.endAngle)/2;var T=Q.x+Math.cos(S)*V.explode+I;var U=Q.y+Math.sin(S)*V.explode+I;this.plotSlice(T,U,D,V.startAngle,V.endAngle,false,L);K.fillStyle="rgba(0,0,0,0.1)";K.fill()},this)}if(C.HtmlText){H=['<div style="color:'+this.options.grid.color+'" class="flotr-labels">']}A.each(function(c,X){var W=(c.startAngle+c.endAngle)/2;var V=C.colors[X];var Y=Q.x+Math.cos(W)*c.explode;var U=Q.y+Math.sin(W)*c.explode;this.plotSlice(Y,U,D,c.startAngle,c.endAngle,false,L);if(G.pie.fill){K.fillStyle=Flotr.parseColor(V).scale(null,null,null,G.pie.fillOpacity).toString();K.fill()}K.lineWidth=E;K.strokeStyle=V;K.stroke();var b=C.pie.labelFormatter(c);var S=(Math.cos(W)<0);var a=Y+Math.cos(W)*(G.pie.explode+D);var Z=U+Math.sin(W)*(G.pie.explode+D);if(c.fraction&&b){if(C.HtmlText){var T="position:absolute;top:"+(Z-5)+"px;";if(S){T+="right:"+(this.canvasWidth-a)+"px;text-align:right;"}else{T+="left:"+a+"px;text-align:left;"}H.push('<div style="'+T+'" class="flotr-grid-label">'+b+"</div>")}else{M.halign=S?"r":"l";K.drawText(b,a,Z+M.size/2,M)}}},this);if(C.HtmlText){H.push("</div>");this.el.insert(H.join(""))}K.restore();C.pie.drawn=true}},plotSlice:function(B,H,A,E,D,F,G){var C=this.ctx;G=G||1;C.save();C.scale(1,G);C.beginPath();C.moveTo(B,H);C.arc(B,H,A,E,D,F);C.lineTo(B,H);C.closePath();C.restore()},plotPie:function(){},insertLegend:function(){if(!this.options.legend.show){return }var H=this.series,I=this.plotOffset,B=this.options,b=[],A=false,O=this.ctx,R;var Q=H.findAll(function(c){return(c.label&&!c.hide)}).size();if(Q){if(!B.HtmlText&&this.textEnabled){var T={size:B.fontSize*1.1,color:B.grid.color};var M=B.legend.position,N=B.legend.margin,L=B.legend.labelBoxWidth,Z=B.legend.labelBoxHeight,S=B.legend.labelBoxMargin,W=I.left+N,U=I.top+N;var a=0;for(R=H.length-1;R>-1;--R){if(!H[R].label||H[R].hide){continue}var E=B.legend.labelFormatter(H[R].label);a=Math.max(a,O.measureText(E,T))}var K=Math.round(L+S*3+a),C=Math.round(Q*(S+Z)+S);if(M.charAt(0)=="s"){U=I.top+this.plotHeight-(N+C)}if(M.charAt(1)=="e"){W=I.left+this.plotWidth-(N+K)}var P=Flotr.parseColor(B.legend.backgroundColor||"rgb(240,240,240)").scale(null,null,null,B.legend.backgroundOpacity||0.1).toString();O.fillStyle=P;O.fillRect(W,U,K,C);O.strokeStyle=B.legend.labelBoxBorderColor;O.strokeRect(Flotr.toPixel(W),Flotr.toPixel(U),K,C);var G=W+S;var F=U+S;for(R=0;R<H.length;R++){if(!H[R].label||H[R].hide){continue}var E=B.legend.labelFormatter(H[R].label);O.fillStyle=H[R].color;O.fillRect(G,F,L-1,Z-1);O.strokeStyle=B.legend.labelBoxBorderColor;O.lineWidth=1;O.strokeRect(Math.ceil(G)-1.5,Math.ceil(F)-1.5,L+2,Z+2);O.drawText(E,G+L+S,F+(Z+T.size-O.fontDescent(T))/2,T);F+=Z+S}}else{for(R=0;R<H.length;++R){if(!H[R].label||H[R].hide){continue}if(R%B.legend.noColumns==0){b.push(A?"</tr><tr>":"<tr>");A=true}var E=B.legend.labelFormatter(H[R].label);b.push('<td class="flotr-legend-color-box"><div style="border:1px solid '+B.legend.labelBoxBorderColor+';padding:1px"><div style="width:'+B.legend.labelBoxWidth+"px;height:"+B.legend.labelBoxHeight+"px;background-color:"+H[R].color+'"></div></div></td><td class="flotr-legend-label">'+E+"</td>")}if(A){b.push("</tr>")}if(b.length>0){var V='<table style="font-size:smaller;color:'+B.grid.color+'">'+b.join("")+"</table>";if(B.legend.container!=null){$(B.legend.container).update(V)}else{var D="";var M=B.legend.position,N=B.legend.margin;if(M.charAt(0)=="n"){D+="top:"+(N+I.top)+"px;"}else{if(M.charAt(0)=="s"){D+="bottom:"+(N+I.bottom)+"px;"}}if(M.charAt(1)=="e"){D+="right:"+(N+I.right)+"px;"}else{if(M.charAt(1)=="w"){D+="left:"+(N+I.left)+"px;"}}var J=this.el.insert('<div class="flotr-legend" style="position:absolute;z-index:2;'+D+'">'+V+"</div>").select("div.flotr-legend").first();if(B.legend.backgroundOpacity!=0){var Y=B.legend.backgroundColor;if(Y==null){var X=(B.grid.backgroundColor!=null)?B.grid.backgroundColor:Flotr.extractColor(J);Y=Flotr.parseColor(X).adjust(null,null,null,1).toString()}this.el.insert('<div class="flotr-legend-bg" style="position:absolute;width:'+J.getWidth()+"px;height:"+J.getHeight()+"px;"+D+"background-color:"+Y+';"> </div>').select("div.flotr-legend-bg").first().setStyle({opacity:B.legend.backgroundOpacity})}}}}}},getEventPosition:function(C){var G=this.overlay.cumulativeOffset(),F=(C.pageX-G.left-this.plotOffset.left),E=(C.pageY-G.top-this.plotOffset.top),D=0,B=0;if(C.pageX==null&&C.clientX!=null){var H=document.documentElement,A=document.body;D=C.clientX+(H&&H.scrollLeft||A.scrollLeft||0);B=C.clientY+(H&&H.scrollTop||A.scrollTop||0)}else{D=C.pageX;B=C.pageY}return{x:this.axes.x.min+F/this.axes.x.scale,x2:this.axes.x2.min+F/this.axes.x2.scale,y:this.axes.y.max-E/this.axes.y.scale,y2:this.axes.y2.max-E/this.axes.y2.scale,relX:F,relY:E,absX:D,absY:B}},clickHandler:function(A){if(this.ignoreClick){this.ignoreClick=false;return }this.el.fire("flotr:click",[this.getEventPosition(A),this])},mouseMoveHandler:function(A){var B=this.getEventPosition(A);this.lastMousePos.pageX=B.absX;this.lastMousePos.pageY=B.absY;if(this.selectionInterval==null&&(this.options.mouse.track||this.series.any(function(C){return C.mouse&&C.mouse.track}))){this.hit(B)}this.el.fire("flotr:mousemove",[A,B,this])},mouseDownHandler:function(C){if(C.isRightClick()){C.stop();var B=this.overlay;B.hide();function A(){B.show();$(document).stopObserving("mousemove",A)}$(document).observe("mousemove",A);return }if(!this.options.selection.mode||!C.isLeftClick()){return }this.setSelectionPos(this.selection.first,C);if(this.selectionInterval!=null){clearInterval(this.selectionInterval)}this.lastMousePos.pageX=null;this.selectionInterval=setInterval(this.updateSelection.bind(this),1000/this.options.selection.fps);this.mouseUpHandler=this.mouseUpHandler.bind(this);$(document).observe("mouseup",this.mouseUpHandler)},fireSelectEvent:function(){var A=this.axes,F=this.selection,C=(F.first.x<=F.second.x)?F.first.x:F.second.x,B=(F.first.x<=F.second.x)?F.second.x:F.first.x,E=(F.first.y>=F.second.y)?F.first.y:F.second.y,D=(F.first.y>=F.second.y)?F.second.y:F.first.y;C=A.x.min+C/A.x.scale;B=A.x.min+B/A.x.scale;E=A.y.max-E/A.y.scale;D=A.y.max-D/A.y.scale;this.el.fire("flotr:select",[{x1:C,y1:E,x2:B,y2:D},this])},mouseUpHandler:function(A){$(document).stopObserving("mouseup",this.mouseUpHandler);A.stop();if(this.selectionInterval!=null){clearInterval(this.selectionInterval);this.selectionInterval=null}this.setSelectionPos(this.selection.second,A);this.clearSelection();if(this.selectionIsSane()){this.drawSelection();this.fireSelectEvent();this.ignoreClick=true}},setSelectionPos:function(D,B){var A=this.options,C=$(this.overlay).cumulativeOffset();if(A.selection.mode.indexOf("x")==-1){D.x=(D==this.selection.first)?0:this.plotWidth}else{D.x=B.pageX-C.left-this.plotOffset.left;D.x=Math.min(Math.max(0,D.x),this.plotWidth)}if(A.selection.mode.indexOf("y")==-1){D.y=(D==this.selection.first)?0:this.plotHeight}else{D.y=B.pageY-C.top-this.plotOffset.top;D.y=Math.min(Math.max(0,D.y),this.plotHeight)}},updateSelection:function(){if(this.lastMousePos.pageX==null){return }this.setSelectionPos(this.selection.second,this.lastMousePos);this.clearSelection();if(this.selectionIsSane()){this.drawSelection()}},clearSelection:function(){if(this.prevSelection==null){return }var G=this.prevSelection,E=this.octx,C=this.plotOffset,A=Math.min(G.first.x,G.second.x),F=Math.min(G.first.y,G.second.y),B=Math.abs(G.second.x-G.first.x),D=Math.abs(G.second.y-G.first.y);E.clearRect(A+C.left-E.lineWidth,F+C.top-E.lineWidth,B+E.lineWidth*2,D+E.lineWidth*2);this.prevSelection=null},setSelection:function(G){var B=this.options,H=this.axes.x,A=this.axes.y,F=yaxis.scale,D=xaxis.scale,E=B.selection.mode.indexOf("x")!=-1,C=B.selection.mode.indexOf("y")!=-1;this.clearSelection();this.selection.first.y=E?0:(A.max-G.y1)*F;this.selection.second.y=E?this.plotHeight:(A.max-G.y2)*F;this.selection.first.x=C?0:(G.x1-H.min)*D;this.selection.second.x=C?this.plotWidth:(G.x2-H.min)*D;this.drawSelection();this.fireSelectEvent()},drawSelection:function(){var C=this.prevSelection,F=this.selection,H=this.octx,I=this.options,A=this.plotOffset;if(C!=null&&F.first.x==C.first.x&&F.first.y==C.first.y&&F.second.x==C.second.x&&F.second.y==C.second.y){return }H.strokeStyle=Flotr.parseColor(I.selection.color).scale(null,null,null,0.8).toString();H.lineWidth=1;H.lineJoin="round";H.fillStyle=Flotr.parseColor(I.selection.color).scale(null,null,null,0.4).toString();this.prevSelection={first:{x:F.first.x,y:F.first.y},second:{x:F.second.x,y:F.second.y}};var E=Math.min(F.first.x,F.second.x),D=Math.min(F.first.y,F.second.y),G=Math.abs(F.second.x-F.first.x),B=Math.abs(F.second.y-F.first.y);H.fillRect(E+A.left,D+A.top,G,B);H.strokeRect(E+A.left,D+A.top,G,B)},selectionIsSane:function(){var A=this.selection;return Math.abs(A.second.x-A.first.x)>=5&&Math.abs(A.second.y-A.first.y)>=5},clearHit:function(){if(this.prevHit){var B=this.options,A=this.plotOffset,C=this.prevHit;this.octx.clearRect(this.tHoz(C.x)+A.left-B.points.radius*2,this.tVert(C.y)+A.top-B.points.radius*2,B.points.radius*3+B.points.lineWidth*3,B.points.radius*3+B.points.lineWidth*3);this.prevHit=null}},hit:function(I){var G=this.series,C=this.options,R=this.prevHit,H=this.plotOffset,D=this.octx,S,A,M,Q,L={dist:Number.MAX_VALUE,x:null,y:null,relX:I.relX,relY:I.relY,absX:I.absX,absY:I.absY,mouse:null};for(Q=0;Q<G.length;Q++){s=G[Q];if(!s.mouse.track){continue}S=s.data;A=(s.xaxis.scale*s.mouse.sensibility);M=(s.yaxis.scale*s.mouse.sensibility);for(var P=0,B,E;P<S.length;P++){if(S[P][1]===null){continue}B=Math.pow(s.xaxis.scale*(S[P][0]-I.x),2);E=Math.pow(s.yaxis.scale*(S[P][1]-I.y),2);if(B<A&&E<M&&Math.sqrt(B+E)<L.dist){L.dist=Math.sqrt(B+E);L.x=S[P][0];L.y=S[P][1];L.mouse=s.mouse}}}if(L.mouse&&L.mouse.track&&!R||(R&&(L.x!=R.x||L.y!=R.y))){var K=this.mouseTrack||this.el.select(".flotr-mouse-value")[0],F="",J=C.mouse.position,N=C.mouse.margin,O="opacity:0.7;background-color:#000;color:#fff;display:none;position:absolute;padding:2px 8px;-moz-border-radius:4px;border-radius:4px;white-space:nowrap;";if(!C.mouse.relative){if(J.charAt(0)=="n"){F+="top:"+(N+H.top)+"px;"}else{if(J.charAt(0)=="s"){F+="bottom:"+(N+H.bottom)+"px;"}}if(J.charAt(1)=="e"){F+="right:"+(N+H.right)+"px;"}else{if(J.charAt(1)=="w"){F+="left:"+(N+H.left)+"px;"}}}else{if(J.charAt(0)=="n"){F+="bottom:"+(N-H.top-this.tVert(L.y)+this.canvasHeight)+"px;"}else{if(J.charAt(0)=="s"){F+="top:"+(N+H.top+this.tVert(L.y))+"px;"}}if(J.charAt(1)=="e"){F+="left:"+(N+H.left+this.tHoz(L.x))+"px;"}else{if(J.charAt(1)=="w"){F+="right:"+(N-H.left-this.tHoz(L.x)+this.canvasWidth)+"px;"}}}O+=F;if(!K){this.el.insert('<div class="flotr-mouse-value" style="'+O+'"></div>');K=this.mouseTrack=this.el.select(".flotr-mouse-value").first()}else{this.mouseTrack=K.setStyle(O)}if(L.x!==null&&L.y!==null){K.show();this.clearHit();if(L.mouse.lineColor!=null){D.save();D.translate(H.left,H.top);D.lineWidth=C.points.lineWidth;D.strokeStyle=L.mouse.lineColor;D.fillStyle="#ffffff";D.beginPath();D.arc(this.tHoz(L.x),this.tVert(L.y),C.mouse.radius,0,2*Math.PI,true);D.fill();D.stroke();D.restore()}this.prevHit=L;var T=L.mouse.trackDecimals;if(T==null||T<0){T=0}K.innerHTML=L.mouse.trackFormatter({x:L.x.toFixed(T),y:L.y.toFixed(T)});K.fire("flotr:hit",[L,this])}else{if(R){K.hide();this.clearHit()}}}},saveImage:function(D,C,A,B){var E=null;switch(D){case"jpeg":case"jpg":E=Canvas2Image.saveAsJPEG(this.canvas,B,C,A);break;default:case"png":E=Canvas2Image.saveAsPNG(this.canvas,B,C,A);break;case"bmp":E=Canvas2Image.saveAsBMP(this.canvas,B,C,A);break}if(Object.isElement(E)&&B){this.restoreCanvas();this.canvas.hide();this.overlay.hide();this.el.insert(E.setStyle({position:"absolute"}))}},restoreCanvas:function(){this.canvas.show();this.overlay.show();this.el.select("img").invoke("remove")}});Flotr.Color=Class.create({initialize:function(E,D,B,C){this.rgba=["r","g","b","a"];var A=4;while(-1<--A){this[this.rgba[A]]=arguments[A]||((A==3)?1:0)}this.normalize()},adjust:function(D,C,E,B){var A=4;while(-1<--A){if(arguments[A]!=null){this[this.rgba[A]]+=arguments[A]}}return this.normalize()},clone:function(){return new Flotr.Color(this.r,this.b,this.g,this.a)},limit:function(B,A,C){return Math.max(Math.min(B,C),A)},normalize:function(){var A=this.limit;this.r=A(parseInt(this.r),0,255);this.g=A(parseInt(this.g),0,255);this.b=A(parseInt(this.b),0,255);this.a=A(this.a,0,1);return this},scale:function(D,C,E,B){var A=4;while(-1<--A){if(arguments[A]!=null){this[this.rgba[A]]*=arguments[A]}}return this.normalize()},distance:function(B){if(!B){return }B=new Flotr.parseColor(B);var C=0;var A=3;while(-1<--A){C+=Math.abs(this[this.rgba[A]]-B[this.rgba[A]])}return C},toString:function(){return(this.a>=1)?"rgb("+[this.r,this.g,this.b].join(",")+")":"rgba("+[this.r,this.g,this.b,this.a].join(",")+")"}});Flotr.Color.lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]};Flotr.Date={format:function(F,E){if(!F){return }var A=function(H){H=H.toString();return H.length==1?"0"+H:H};var D=[];var C=false;for(var B=0;B<E.length;++B){var G=E.charAt(B);if(C){switch(G){case"h":G=F.getUTCHours().toString();break;case"H":G=A(F.getUTCHours());break;case"M":G=A(F.getUTCMinutes());break;case"S":G=A(F.getUTCSeconds());break;case"d":G=F.getUTCDate().toString();break;case"m":G=(F.getUTCMonth()+1).toString();break;case"y":G=F.getUTCFullYear().toString();break;case"b":G=Flotr.Date.monthNames[F.getUTCMonth()];break}D.push(G);C=false}else{if(G=="%"){C=true}else{D.push(G)}}}return D.join("")},timeUnits:{second:1000,minute:60*1000,hour:60*60*1000,day:24*60*60*1000,month:30*24*60*60*1000,year:365.2425*24*60*60*1000},spec:[[1,"second"],[2,"second"],[5,"second"],[10,"second"],[30,"second"],[1,"minute"],[2,"minute"],[5,"minute"],[10,"minute"],[30,"minute"],[1,"hour"],[2,"hour"],[4,"hour"],[8,"hour"],[12,"hour"],[1,"day"],[2,"day"],[3,"day"],[0.25,"month"],[0.5,"month"],[1,"month"],[2,"month"],[3,"month"],[6,"month"],[1,"year"]],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]};  
//Flotr 0.2.0-alpha Copyright (c) 2009 Bas Wenneker, <http://solutoire.com>, MIT License.  
//  
//Radar chart added by Ryan Simmons  
//  
/* $Id: flotr.js 82 2009-01-12 19:19:31Z fabien.menager $ */  
 
var Flotr = {  
version: '0.2.0-alpha',  
author: 'Bas Wenneker',  
website: 'http://www.solutoire.com',  
/**  
* An object of the default registered graph types. Use Flotr.register(type, functionName)  
* to add your own type.  
*/  
_registeredTypes:{  
'lines': 'drawSeriesLines',  
'points': 'drawSeriesPoints',  
'bars': 'drawSeriesBars',  
'candles': 'drawSeriesCandles',  
'pie': 'drawSeriesPie',  
'radar':'drawSeriesRadar'  
},  
/**  
* Can be used to register your own chart type. Default types are 'lines', 'points' and 'bars'.  
* This is still experimental.  
* @todo Test and confirm.  
* @param {String} type - type of chart, like 'pies', 'bars' etc.  
* @param {String} functionName - Name of the draw function, like 'drawSeriesPies', 'drawSeriesBars' etc.  
*/  
register: function(type, functionName){  
Flotr._registeredTypes[type] = functionName+'';  
},  
/**  
* Draws the graph. This function is here for backwards compatibility with Flotr version 0.1.0alpha.  
* You could also draw graphs by directly calling Flotr.Graph(element, data, options).  
* @param {Element} el - element to insert the graph into  
* @param {Object} data - an array or object of dataseries  
* @param {Object} options - an object containing options  
* @param {Class} _GraphKlass_ - (optional) Class to pass the arguments to, defaults to Flotr.Graph  
* @return {Class} returns a new graph object and of course draws the graph.  
*/  
draw: function(el, data, options, _GraphKlass_){  
_GraphKlass_ = _GraphKlass_ || Flotr.Graph;  
return new _GraphKlass_(el, data, options);  
},  
/**  
* Collects dataseries from input and parses the series into the right format. It returns an Array  
* of Objects each having at least the 'data' key set.  
* @param {Array/Object} data - Object or array of dataseries  
* @return {Array} Array of Objects parsed into the right format ({(...,) data: [[x1,y1], [x2,y2], ...] (, ...)})  
*/  
getSeries: function(data){  
return data.collect(function(serie){  
var i, serie = (serie.data) ? Object.clone(serie) : {'data': serie};  
for (i = serie.data.length-1; i > -1; --i) {  
serie.data[i][1] = (serie.data[i][1] === null ? null : parseFloat(serie.data[i][1]));  
}  
return serie;  
});  
},  
/**  
* Recursively merges two objects.  
* @param {Object} src - source object (likely the object with the least properties)  
* @param {Object} dest - destination object (optional, object with the most properties)  
* @return {Object} recursively merged Object  
*/  
merge: function(src, dest){  
var result = dest || {};  
for(var i in src){  
result[i] = (src[i] != null && typeof(src[i]) == 'object' && !(src[i].constructor == Array || src[i].constructor == RegExp) && !Object.isElement(src[i])) ? Flotr.merge(src[i], dest[i]) : result[i] = src[i];  
}  
return result;  
},  
/**  
* Function calculates the ticksize and returns it.  
* @param {Integer} noTicks - number of ticks  
* @param {Integer} min - lower bound integer value for the current axis  
* @param {Integer} max - upper bound integer value for the current axis  
* @param {Integer} decimals - number of decimals for the ticks  
* @return {Integer} returns the ticksize in pixels  
*/  
getTickSize: function(noTicks, min, max, decimals){  
var delta = (max - min) / noTicks;  
var magn = Flotr.getMagnitude(delta);  
 
// Norm is between 1.0 and 10.0.  
var norm = delta / magn;  
 
var tickSize = 10;  
if(norm < 1.5) tickSize = 1;  
else if(norm < 2.25) tickSize = 2;  
else if(norm < 3) tickSize = ((decimals == 0) ? 2 : 2.5);  
else if(norm < 7.5) tickSize = 5;  
 
return tickSize * magn;  
},  
/**  
* Default tick formatter.  
* @param {String/Integer} val - tick value integer  
* @return {String} formatted tick string  
*/  
defaultTickFormatter: function(val){  
return val+'';  
},  
/**  
* Formats the mouse tracker values.  
* @param {Object} obj - Track value Object {x:..,y:..}  
* @return {String} Formatted track string  
*/  
defaultTrackFormatter: function(obj){  
return '('+obj.x+', '+obj.y+')';  
},  
defaultPieLabelFormatter: function(slice) {  
return (slice.fraction*100).toFixed(2)+'%';  
},  
/**  
* Returns the magnitude of the input value.  
* @param {Integer/Float} x - integer or float value  
* @return {Integer/Float} returns the magnitude of the input value  
*/  
getMagnitude: function(x){  
return Math.pow(10, Math.floor(Math.log(x) / Math.LN10));  
},  
toPixel: function(val){  
return Math.floor(val)+0.5;//((val-Math.round(val) < 0.4) ? (Math.floor(val)-0.5) : val);  
},  
toRad: function(angle){  
return -angle * (Math.PI/180);  
},  
/**  
* Parses a color string and returns a corresponding Color.  
* @param {String} str - string thats representing a color  
* @return {Color} returns a Color object or false  
*/  
parseColor: function(str){  
if (str instanceof Flotr.Color) return str;  
 
var result, Color = Flotr.Color;  
 
// rgb(num,num,num)  
if((result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str)))  
return new Color(parseInt(result[1]), parseInt(result[2]), parseInt(result[3]));  
 
// rgba(num,num,num,num)  
if((result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str)))  
return new Color(parseInt(result[1]), parseInt(result[2]), parseInt(result[3]), parseFloat(result[4]));  
 
// rgb(num%,num%,num%)  
if((result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str)))  
return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55);  
 
// rgba(num%,num%,num%,num)  
if((result = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str)))  
return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55, parseFloat(result[4]));  
 
// #a0b1c2  
if((result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str)))  
return new Color(parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16));  
 
// #fff  
if((result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str)))  
return new Color(parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16));  
 
// Otherwise, we're most likely dealing with a named color.  
var name = str.strip().toLowerCase();  
if(name == 'transparent'){  
return new Color(255, 255, 255, 0);  
}  
return ((result = Color.lookupColors[name])) ? new Color(result[0], result[1], result[2]) : false;  
},  
/**  
* Extracts the background-color of the passed element.  
* @param {Element} element  
* @return {String} color string  
*/  
extractColor: function(element){  
var color;  
// Loop until we find an element with a background color and stop when we hit the body element.  
do {  
color = element.getStyle('background-color').toLowerCase();  
if(!(color == '' || color == 'transparent')) break;  
element = element.up(0);  
} while(!element.nodeName.match(/^body$/i));  
 
// Catch Safari's way of signaling transparent.  
return (color == 'rgba(0, 0, 0, 0)') ? 'transparent' : color;  
}  
};  
/**  
* Flotr Graph class that plots a graph on creation.  
 
*/  
Flotr.Graph = Class.create({  
/**  
* Flotr Graph constructor.  
* @param {Element} el - element to insert the graph into  
* @param {Object} data - an array or object of dataseries  
* @param {Object} options - an object containing options  
*/  
initialize: function(el, data, options){  
this.el = $(el);  
 
if (!this.el) throw 'The target container doesn\'t exist';  
 
this.data = data;  
this.series = Flotr.getSeries(data);  
this.setOptions(options);  
 
// Initialize some variables  
this.lastMousePos = { pageX: null, pageY: null };  
this.selection = { first: { x: -1, y: -1}, second: { x: -1, y: -1} };  
this.prevSelection = null;  
this.selectionInterval = null;  
this.ignoreClick = false;  
this.prevHit = null;  
 
// Create and prepare canvas.  
this.constructCanvas();  
 
// Add event handlers for mouse tracking, clicking and selection  
this.initEvents();  
 
this.findDataRanges();  
this.calculateTicks(this.axes.x);  
this.calculateTicks(this.axes.x2);  
this.calculateTicks(this.axes.y);  
this.calculateTicks(this.axes.y2);  
 
this.calculateSpacing();  
this.draw();  
this.insertLegend();  
 
// Graph and Data tabs  
if (this.options.spreadsheet.show)  
this.constructTabs();  
},  
/**  
* Sets options and initializes some variables and color specific values, used by the constructor.  
* @param {Object} opts - options object  
*/  
setOptions: function(opts){  
var options = {  
colors: ['#00A8F0', '#C0D800', '#CB4B4B', '#4DA74D', '#9440ED'], //=> The default colorscheme. When there are > 5 series, additional colors are generated.  
title: null,  
subtitle: null,  
legend: {  
show: true, // => setting to true will show the legend, hide otherwise  
noColumns: 1, // => number of colums in legend table // @todo: doesn't work for HtmlText = false  
labelFormatter: Prototype.K, // => fn: string -> string  
labelBoxBorderColor: '#CCCCCC', // => border color for the little label boxes  
labelBoxWidth: 14,  
labelBoxHeight: 10,  
labelBoxMargin: 5,  
container: null, // => container (as jQuery object) to put legend in, null means default on top of graph  
position: 'nw', // => position of default legend container within plot  
margin: 5, // => distance from grid edge to default legend container within plot  
backgroundColor: null, // => null means auto-detect  
backgroundOpacity: 0.85// => set to 0 to avoid background, set to 1 for a solid background  
},  
xaxis: {  
ticks: null, // => format: either [1, 3] or [[1, 'a'], 3]  
showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise  
labelsAngle: 0, // => Labels' angle, in degrees  
title: null, // => axis title  
titleAngle: 0, // => axis title's angle, in degrees  
noTicks: 5, // => number of ticks for automagically generated ticks  
tickFormatter: Flotr.defaultTickFormatter, // => fn: number -> string  
tickDecimals: null, // => no. of decimals, null means auto  
min: null, // => min. value to show, null means set automatically  
max: null, // => max. value to show, null means set automatically  
autoscaleMargin: 0, // => margin in % to add if auto-setting min/max  
color: null  
},  
x2axis: {},  
yaxis: {  
ticks: null, // => format: either [1, 3] or [[1, 'a'], 3]  
showLabels: true, // => setting to true will show the axis ticks labels, hide otherwise  
labelsAngle: 0, // => Labels' angle, in degrees  
title: null, // => axis title  
titleAngle: 90, // => axis title's angle, in degrees  
noTicks: 5, // => number of ticks for automagically generated ticks  
tickFormatter: Flotr.defaultTickFormatter, // => fn: number -> string  
tickDecimals: null, // => no. of decimals, null means auto  
min: null, // => min. value to show, null means set automatically  
max: null, // => max. value to show, null means set automatically  
autoscaleMargin: 0, // => margin in % to add if auto-setting min/max  
color: null  
},  
y2axis: {  
titleAngle: 270  
},  
points: {  
show: false, // => setting to true will show points, false will hide  
radius: 3, // => point radius (pixels)  
lineWidth: 2, // => line width in pixels  
fill: true, // => true to fill the points with a color, false for (transparent) no fill  
fillColor: '#FFFFFF', // => fill color  
fillOpacity: 0.4  
},  
lines: {  
show: false, // => setting to true will show lines, false will hide  
lineWidth: 2, // => line width in pixels  
fill: false, // => true to fill the area from the line to the x axis, false for (transparent) no fill  
fillColor: null, // => fill color  
fillOpacity: 0.4 // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill  
},  
radar: {  
show: false, // => setting to true will show radar chart, false will hide  
lineWidth: 2, // => line width in pixels  
fill: false, // => true to fill the area from the line to the x axis, false for (transparent) no fill  
fillColor: null, // => fill color  
fillOpacity: 0.4 // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill  
},  
bars: {  
show: false, // => setting to true will show bars, false will hide  
lineWidth: 2, // => in pixels  
barWidth: 1, // => in units of the x axis  
fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill  
fillColor: null, // => fill color  
fillOpacity: 0.4, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill  
horizontal: false,  
stacked: false  
},  
candles: {  
show: false, // => setting to true will show candle sticks, false will hide  
lineWidth: 1, // => in pixels  
wickLineWidth: 1, // => in pixels  
candleWidth: 0.6, // => in units of the x axis  
fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill  
upFillColor: '#00A8F0',// => up sticks fill color  
downFillColor: '#CB4B4B',// => down sticks fill color  
fillOpacity: 0.5, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill  
barcharts: false // => draw as barcharts (not standard bars but financial barcharts)  
},  
pie: {  
show: false, // => setting to true will show bars, false will hide  
lineWidth: 1, // => in pixels  
fill: true, // => true to fill the area from the line to the x axis, false for (transparent) no fill  
fillColor: null, // => fill color  
fillOpacity: 0.6, // => opacity of the fill color, set to 1 for a solid fill, 0 hides the fill  
explode: 6,  
sizeRatio: 0.6,  
startAngle: Math.PI/4,  
labelFormatter: Flotr.defaultPieLabelFormatter,  
pie3D: false,  
pie3DviewAngle: (Math.PI/2 * 0.8),  
pie3DspliceThickness: 20  
},  
grid: {  
color: '#545454', // => primary color used for outline and labels  
backgroundColor: null, // => null for transparent, else color  
tickColor: '#DDDDDD', // => color used for the ticks  
labelMargin: 3, // => margin in pixels  
verticalLines: true, // => whether to show gridlines in vertical direction  
horizontalLines: true, // => whether to show gridlines in horizontal direction  
outlineWidth: 2 // => width of the grid outline/border in pixels  
},  
selection: {  
mode: null, // => one of null, 'x', 'y' or 'xy'  
color: '#B6D9FF', // => selection box color  
fps: 20 // => frames-per-second  
},  
mouse: {  
track: false, // => true to track the mouse, no tracking otherwise  
position: 'se', // => position of the value box (default south-east)  
relative: false, // => next to the mouse cursor  
trackFormatter: Flotr.defaultTrackFormatter, // => formats the values in the value box  
margin: 5, // => margin in pixels of the valuebox  
lineColor: '#FF3F19', // => line color of points that are drawn when mouse comes near a value of a series  
trackDecimals: 1, // => decimals for the track values  
sensibility: 2, // => the lower this number, the more precise you have to aim to show a value  
radius: 3 // => radius of the track point  
},  
radarChartMode: false, // => true to render radar grid / and setup scaling for radar chart  
shadowSize: 4, // => size of the 'fake' shadow  
defaultType: 'lines', // => default series type  
HtmlText: true, // => wether to draw the text using HTML or on the canvas  
fontSize: 7.5, // => canvas' text font size  
spreadsheet: {  
show: false, // => show the data grid using two tabs  
tabGraphLabel: 'Graph',  
tabDataLabel: 'Data',  
toolbarDownload: 'Download CSV', // @todo: add language support  
toolbarSelectAll: 'Select all'  
}  
}  
 
options.x2axis = Object.extend(Object.clone(options.xaxis), options.x2axis);  
options.y2axis = Object.extend(Object.clone(options.yaxis), options.y2axis);  
this.options = Flotr.merge((opts || {}), options);  
 
this.axes = {  
x: {options: this.options.xaxis, n: 1},  
x2: {options: this.options.x2axis, n: 2},  
y: {options: this.options.yaxis, n: 1},  
y2: {options: this.options.y2axis, n: 2}  
};  
 
// Initialize some variables used throughout this function.  
var assignedColors = [],  
colors = [],  
ln = this.series.length,  
neededColors = this.series.length,  
oc = this.options.colors,  
usedColors = [],  
variation = 0,  
c, i, j, s, tooClose;  
 
// Collect user-defined colors from series.  
for(i = neededColors - 1; i > -1; --i){  
c = this.series[i].color;  
if(c != null){  
--neededColors;  
if(Object.isNumber(c)) assignedColors.push(c);  
else usedColors.push(Flotr.parseColor(c));  
}  
}  
 
// Calculate the number of colors that need to be generated.  
for(i = assignedColors.length - 1; i > -1; --i)  
neededColors = Math.max(neededColors, assignedColors[i] + 1);  
 
// Generate needed number of colors.  
for(i = 0; colors.length < neededColors;){  
c = (oc.length == i) ? new Flotr.Color(100, 100, 100) : Flotr.parseColor(oc[i]);  
 
// Make sure each serie gets a different color.  
var sign = variation % 2 == 1 ? -1 : 1;  
var factor = 1 + sign * Math.ceil(variation / 2) * 0.2;  
c.scale(factor, factor, factor);  
 
/**  
* @todo if we're getting too close to something else, we should probably skip this one  
*/  
colors.push(c);  
 
if(++i >= oc.length){  
i = 0;  
++variation;  
}  
}  
 
// Fill the options with the generated colors.  
for(i = 0, j = 0; i < ln; ++i){  
s = this.series[i];  
 
// Assign the color.  
if(s.color == null){  
s.color = colors[j++].toString();  
}else if(Object.isNumber(s.color)){  
s.color = colors[s.color].toString();  
}  
 
if (!s.xaxis) s.xaxis = this.axes.x;  
if (s.xaxis == 1) s.xaxis = this.axes.x;  
else if (s.xaxis == 2) s.xaxis = this.axes.x2;  
 
if (!s.yaxis) s.yaxis = this.axes.y;  
if (s.yaxis == 1) s.yaxis = this.axes.y;  
else if (s.yaxis == 2) s.yaxis = this.axes.y2;  
 
// Apply missing options to the series.  
s.lines = Object.extend(Object.clone(this.options.lines), s.lines);  
s.points = Object.extend(Object.clone(this.options.points), s.points);  
s.bars = Object.extend(Object.clone(this.options.bars), s.bars);  
s.candles = Object.extend(Object.clone(this.options.candles), s.candles);  
s.pie = Object.extend(Object.clone(this.options.pie), s.pie);  
s.radar = Object.extend(Object.clone(this.options.radar), s.radar);  
s.mouse = Object.extend(Object.clone(this.options.mouse), s.mouse);  
 
if(s.shadowSize == null) s.shadowSize = this.options.shadowSize;  
}  
},  
/**  
* Initializes the canvas and it's overlay canvas element. When the browser is IE, this makes use  
* of excanvas. The overlay canvas is inserted for displaying interactions. After the canvas elements  
* are created, the elements are inserted into the container element.  
*/  
constructCanvas: function(){  
var el = this.el,  
size, c, oc;  
 
this.canvas = el.select('.flotr-canvas')[0];  
this.overlay = el.select('.flotr-overlay')[0];  
 
el.childElements().invoke('remove');  
 
// For positioning labels and overlay.  
el.setStyle({position:'relative', cursor:'default'});  
 
this.canvasWidth = el.getWidth();  
this.canvasHeight = el.getHeight();  
size = {'width': this.canvasWidth, 'height': this.canvasHeight};  
 
if(this.canvasWidth <= 0 || this.canvasHeight <= 0){  
throw 'Invalid dimensions for plot, width = ' + this.canvasWidth + ', height = ' + this.canvasHeight;  
}  
 
// Insert main canvas.  
if (!this.canvas) {  
c = this.canvas = new Element('canvas', size);  
c.className = 'flotr-canvas';  
c = c.writeAttribute('style', 'position:absolute;left:0px;top:0px;');  
} else {  
c = this.canvas.writeAttribute(size);  
}  
el.insert(c);  
 
if(Prototype.Browser.IE){  
c = window.G_vmlCanvasManager.initElement(c);  
}  
this.ctx = c.getContext('2d');  
 
// Insert overlay canvas for interactive features.  
if (!this.overlay) {  
oc = this.overlay = new Element('canvas', size);  
oc.className = 'flotr-overlay';  
oc = oc.writeAttribute('style', 'position:absolute;left:0px;top:0px;');  
} else {  
oc = this.overlay.writeAttribute(size);  
}  
el.insert(oc);  
 
if(Prototype.Browser.IE){  
oc = window.G_vmlCanvasManager.initElement(oc);  
}  
this.octx = oc.getContext('2d');  
 
// Enable text functions  
if (window.CanvasText) {  
CanvasText.enable(this.ctx);  
CanvasText.enable(this.octx);  
this.textEnabled = true;  
}  
},  
getTextDimensions: function(text, canvasStyle, HtmlStyle, className) {  
if (!text) return {width:0, height:0};  
 
if (!this.options.HtmlText && this.textEnabled) {  
var bounds = this.ctx.getTextBounds(text, canvasStyle);  
return {  
width: bounds.width+2,  
height: bounds.height+6  
};  
}  
else {  
var dummyDiv = this.el.insert('<div style="position:absolute;top:-10000px;'+HtmlStyle+'" class="'+className+' flotr-dummy-div">' + text + '</div>').select(".flotr-dummy-div")[0];  
dim = dummyDiv.getDimensions();  
dummyDiv.remove();  
return dim;  
}  
},  
loadDataGrid: function(){  
if (this.seriesData) return this.seriesData;  
 
var s = this.series;  
var dg = [];  
 
/* The data grid is a 2 dimensions array. There is a row for each X value.  
* Each row contains the x value and the corresponding y value for each serie ('undefined' if there isn't one)  
**/  
for(i = 0; i < s.length; ++i){  
s[i].data.each(function(v) {  
var x = v[0],  
y = v[1];  
if (r = dg.find(function(row) {return row[0] == x})) {  
r[i+1] = y;  
}  
else {  
var newRow = [];  
newRow[0] = x;  
newRow[i+1] = y  
dg.push(newRow);  
}  
});  
}  
 
// The data grid is sorted by x value  
dg = dg.sortBy(function(v) {  
return v[0];  
});  
return this.seriesData = dg;  
},  
 
// @todo: make a tab manager (Flotr.Tabs)  
showTab: function(tabName, onComplete){  
var elementsClassNames = 'canvas, .flotr-labels, .flotr-legend, .flotr-legend-bg, .flotr-title, .flotr-subtitle';  
switch(tabName) {  
case 'graph':  
this.datagrid.up().hide();  
this.el.select(elementsClassNames).invoke('show');  
this.tabs.data.removeClassName('selected');  
this.tabs.graph.addClassName('selected');  
break;  
case 'data':  
this.constructDataGrid();  
this.datagrid.up().show();  
this.el.select(elementsClassNames).invoke('hide');  
this.tabs.data.addClassName('selected');  
this.tabs.graph.removeClassName('selected');  
break;  
}  
},  
constructTabs: function(){  
var tabsContainer = new Element('div', {className:'flotr-tabs-group', style:'position:absolute;left:0px;top:'+this.canvasHeight+'px;width:'+this.canvasWidth+'px;'});  
this.el.insert({bottom: tabsContainer});  
this.tabs = {  
graph: new Element('div', {className:'flotr-tab selected', style:'float:left;'}).update(this.options.spreadsheet.tabGraphLabel),  
data: new Element('div', {className:'flotr-tab', style:'float:left;'}).update(this.options.spreadsheet.tabDataLabel)  
}  
 
tabsContainer.insert(this.tabs.graph).insert(this.tabs.data);  
 
this.el.setStyle({height: this.canvasHeight+this.tabs.data.getHeight()+2+'px'});  
 
this.tabs.graph.observe('click', (function() {this.showTab('graph')}).bind(this));  
this.tabs.data.observe('click', (function() {this.showTab('data')}).bind(this));  
},  
 
// @todo: make a spreadsheet manager (Flotr.Spreadsheet)  
constructDataGrid: function(){  
// If the data grid has already been built, nothing to do here  
if (this.datagrid) return this.datagrid;  
 
var i, j,  
s = this.series,  
datagrid = this.loadDataGrid();  
 
var t = this.datagrid = new Element('table', {className:'flotr-datagrid', style:'height:100px;'});  
var colgroup = ['<colgroup><col />'];  
 
// First row : series' labels  
var html = ['<tr class="first-row">'];  
html.push('<th>&nbsp;</th>');  
for (i = 0; i < s.length; ++i) {  
html.push('<th scope="col">'+(s[i].label || String.fromCharCode(65+i))+'</th>');  
colgroup.push('<col />');  
}  
html.push('</tr>');  
 
// Data rows  
for (j = 0; j < datagrid.length; ++j) {  
html.push('<tr>');  
for (i = 0; i < s.length+1; ++i) {  
var tag = 'td';  
var content = (datagrid[j][i] != null ? Math.round(datagrid[j][i]*100000)/100000 : '');  
 
if (i == 0) {  
tag = 'th';  
var label;  
if(this.options.xaxis.ticks) {  
var tick = this.options.xaxis.ticks.find(function (x) { return x[0] == datagrid[j][i] });  
if (tick) label = tick[1];  
}  
else {  
label = this.options.xaxis.tickFormatter(content);  
}  
 
if (label) content = label;  
}  
 
html.push('<'+tag+(tag=='th'?' scope="row"':'')+'>'+content+'</'+tag+'>');  
}  
html.push('</tr>');  
}  
colgroup.push('</colgroup>');  
t.update(colgroup.join('')+html.join(''));  
 
if (!Prototype.Browser.IE) {  
t.select('td').each(function(td) {  
td.observe('mouseover', function(e){  
td = e.element();  
var siblings = td.previousSiblings();  
 
t.select('th[scope=col]')[siblings.length-1].addClassName('hover');  
t.select('colgroup col')[siblings.length].addClassName('hover');  
});  
 
td.observe('mouseout', function(){  
t.select('colgroup col.hover, th.hover').each(function(e){e.removeClassName('hover')});  
});  
});  
}  
 
var toolbar = new Element('div', {className: 'flotr-datagrid-toolbar'}).  
insert(new Element('button', {type:'button', className:'flotr-datagrid-toolbar-button'}).update(this.options.spreadsheet.toolbarDownload).observe('click', this.downloadCSV.bind(this))).  
insert(new Element('button', {type:'button', className:'flotr-datagrid-toolbar-button'}).update(this.options.spreadsheet.toolbarSelectAll).observe('click', this.selectAllData.bind(this)));  
 
var container = new Element('div', {className:'flotr-datagrid-container', style:'left:0px;top:0px;width:'+this.canvasWidth+'px;height:'+this.canvasHeight+'px;overflow:auto;'});  
container.insert(toolbar);  
t.wrap(container.hide());  
 
this.el.insert(container);  
return t;  
},  
selectAllData: function(){  
if (this.tabs) {  
var selection, range, doc, win, node = this.constructDataGrid();  
 
this.showTab('data');  
 
// deferred to be able to select the table  
(function () {  
if ((doc = node.ownerDocument) && (win = doc.defaultView) &&  
win.getSelection && doc.createRange &&  
(selection = window.getSelection()) &&  
selection.removeAllRanges) {  
range = doc.createRange();  
range.selectNode(node);  
selection.removeAllRanges();  
selection.addRange(range);  
}  
else if (document.body && document.body.createTextRange &&  
(range = document.body.createTextRange())) {  
range.moveToElementText(node);  
range.select();  
}  
}).defer();  
return true;  
}  
else return false;  
},  
downloadCSV: function(){  
var i, csv = '"x"',  
series = this.series,  
dg = this.loadDataGrid();  
 
for (i = 0; i < series.length; ++i) {  
csv += '%09"'+(series[i].label || String.fromCharCode(65+i))+'"'; // \t  
}  
csv += "%0D%0A"; // \r\n  
 
for (i = 0; i < dg.length; ++i) {  
if (this.options.xaxis.ticks) {  
var tick = this.options.xaxis.ticks.find(function (x) { return x[0] == dg[i][0] });  
if (tick) dg[i][0] = tick[1];  
} else {  
dg[i][0] = this.options.xaxis.tickFormatter(dg[i][0]);  
}  
csv += dg[i].join('%09')+"%0D%0A"; // \t and \r\n  
}  
if (Prototype.Browser.IE) {  
csv = csv.gsub('%09', '\t').gsub('%0A', '\n').gsub('%0D', '\r');  
window.open().document.write(csv);  
}  
else {  
window.open('data:text/csv,'+csv);  
}  
},  
/**  
* Initializes event some handlers.  
*/  
initEvents: function () {  
//@todo: maybe stopObserving with only flotr functions  
this.overlay.stopObserving();  
this.overlay.observe('mousedown', this.mouseDownHandler.bind(this));  
this.overlay.observe('mousemove', this.mouseMoveHandler.bind(this));  
this.overlay.observe('click', this.clickHandler.bind(this));  
},  
/**  
* Function determines the min and max values for the xaxis and yaxis.  
*/  
findDataRanges: function(){  
var s = this.series,  
a = this.axes;  
 
a.x.datamin = 0; a.x.datamax = 0;  
a.x2.datamin = 0; a.x2.datamax = 0;  
a.y.datamin = 0; a.y.datamax = 0;  
a.y2.datamin = 0; a.y2.datamax = 0;  
 
if(s.length > 0){  
var i, j, h, x, y, data, xaxis, yaxis;  
 
// Get datamin, datamax start values  
for(i = 0; i < s.length; ++i) {  
data = s[i].data,  
xaxis = s[i].xaxis,  
yaxis = s[i].yaxis;  
 
if (data.length > 0 && !s[i].hide) {  
if (!xaxis.used) xaxis.datamin = xaxis.datamax = data[0][0];  
if (!yaxis.used) yaxis.datamin = yaxis.datamax = data[0][1];  
xaxis.used = true;  
yaxis.used = true;  
 
for(h = data.length - 1; h > -1; --h){  
x = data[h][0];  
if(x < xaxis.datamin) xaxis.datamin = x;  
else if(x > xaxis.datamax) xaxis.datamax = x;  
 
for(j = 1; j < data[h].length; j++){  
y = data[h][j];  
if(y < yaxis.datamin) yaxis.datamin = y;  
else if(y > yaxis.datamax) yaxis.datamax = y;  
}  
}  
}  
if (this.options.radarChartMode) {  
xaxis.datamin = yaxis.datamin = - yaxis.datamax;  
xaxis.datamax = yaxis.datamax;  
if (!this.options.radarChartSides) this.options.radarChartSides = data.length;  
}  
}  
}  
 
this.findXAxesValues();  
 
this.calculateRange(a.x);  
this.extendXRangeIfNeededByBar(a.x);  
 
if (a.x2.used) {  
this.calculateRange(a.x2);  
this.extendXRangeIfNeededByBar(a.x2);  
}  
 
this.calculateRange(a.y);  
this.extendYRangeIfNeededByBar(a.y);  
 
if (a.y2.used) {  
this.calculateRange(a.y2);  
this.extendYRangeIfNeededByBar(a.y2);  
}  
},  
/**  
* Calculates the range of an axis to apply autoscaling.  
*/  
calculateRange: function(axis){  
var o = axis.options,  
min = o.min != null ? o.min : axis.datamin,  
max = o.max != null ? o.max : axis.datamax,  
margin;  
 
if(max - min == 0.0){  
var widen = (max == 0.0) ? 1.0 : 0.01;  
min -= widen;  
max += widen;  
}  
axis.tickSize = Flotr.getTickSize(o.noTicks, ((this.options.radarChartMode) ? 0 : min), max, o.tickDecimals);  
 
// Autoscaling.  
if(o.min == null){  
// Add a margin.  
margin = o.autoscaleMargin;  
if(margin != 0){  
min -= axis.tickSize * margin;  
 
// Make sure we don't go below zero if all values are positive.  
if(min < 0 && axis.datamin >= 0) min = 0;  
min = axis.tickSize * Math.floor(min / axis.tickSize);  
}  
}  
if(o.max == null){  
margin = o.autoscaleMargin;  
if(margin != 0){  
max += axis.tickSize * margin;  
if(max > 0 && axis.datamax <= 0) max = 0;  
max = axis.tickSize * Math.ceil(max / axis.tickSize);  
}  
}  
axis.min = min;  
axis.max = max;  
},  
/**  
* Bar series autoscaling in x direction.  
*/  
extendXRangeIfNeededByBar: function(axis){  
if(axis.options.max == null){  
var newmax = axis.max,  
i, s, b, c,  
stackedSums = [],  
lastSerie = null;  
 
for(i = 0; i < this.series.length; ++i){  
s = this.series[i];  
b = s.bars;  
c = s.candles;  
if(s.axis == axis && (b.show || c.show)) {  
if (!b.horizontal && (b.barWidth + axis.datamax > newmax) || (c.candleWidth + axis.datamax > newmax)){  
newmax = axis.max + s.bars.barWidth;  
}  
if(b.stacked && b.horizontal){  
for (j = 0; j < s.data.length; j++) {  
if (s.bars.show && s.bars.stacked) {  
var x = s.data[j][0];  
stackedSums[x] = (stackedSums[x] || 0) + s.data[j][1];  
lastSerie = s;  
}  
}  
 
for (j = 0; j < stackedSums.length; j++) {  
newmax = Math.max(stackedSums[j], newmax);  
}  
}  
}  
}  
axis.lastSerie = lastSerie;  
axis.max = newmax;  
}  
},  
/**  
* Bar series autoscaling in y direction.  
*/  
extendYRangeIfNeededByBar: function(axis){  
if(axis.options.max == null){  
var newmax = axis.max,  
i, s, b, c,  
stackedSums = [],  
lastSerie = null;  
 
for(i = 0; i < this.series.length; ++i){  
s = this.series[i];  
b = s.bars;  
c = s.candles;  
if (s.yaxis == axis && b.show && !s.hide) {  
if (b.horizontal && (b.barWidth + axis.datamax > newmax) || (c.candleWidth + axis.datamax > newmax)){  
newmax = axis.max + b.barWidth;  
}  
if(b.stacked && !b.horizontal){  
for (j = 0; j < s.data.length; j++) {  
if (s.bars.show && s.bars.stacked) {  
var x = s.data[j][0];  
stackedSums[x] = (stackedSums[x] || 0) + s.data[j][1];  
lastSerie = s;  
}  
}  
 
for (j = 0; j < stackedSums.length; j++) {  
newmax = Math.max(stackedSums[j], newmax);  
}  
}  
}  
}  
axis.lastSerie = lastSerie;  
axis.max = newmax;  
}  
},  
/**  
* Find every values of the x axes  
*/  
findXAxesValues: function(){  
for(i = this.series.length-1; i > -1 ; --i){  
s = this.series[i];  
s.xaxis.values = s.xaxis.values || [];  
for (j = s.data.length-1; j > -1 ; --j){  
s.xaxis.values[s.data[j][0]] = {};  
}  
}  
},  
/**  
* Calculate axis ticks.  
* @param {Object} axis - axis object  
* @param {Object} o - axis options  
*/  
calculateTicks: function(axis){  
var o = axis.options, i, v;  
 
axis.ticks = [];  
if(o.ticks){  
var ticks = o.ticks, t, label;  
 
if(Object.isFunction(ticks)){  
ticks = ticks({min: axis.min, max: axis.max});  
}  
 
// Clean up the user-supplied ticks, copy them over.  
for(i = 0; i < ticks.length; ++i){  
t = ticks[i];  
if(typeof(t) == 'object'){  
v = t[0];  
label = (t.length > 1) ? t[1] : o.tickFormatter(v);  
}else{  
v = t;  
label = o.tickFormatter(v);  
}  
axis.ticks[i] = { v: v, label: label };  
}  
}  
else {  
// Round to nearest multiple of tick size.  
var start = axis.tickSize * Math.ceil(axis.min / axis.tickSize),  
decimals;  
 
// Then store all possible ticks.  
for(i = 0; start + i * axis.tickSize <= axis.max; ++i){  
v = start + i * axis.tickSize;  
 
// Round (this is always needed to fix numerical instability).  
decimals = o.tickDecimals;  
if(decimals == null) decimals = 1 - Math.floor(Math.log(axis.tickSize) / Math.LN10);  
if(decimals < 0) decimals = 0;  
 
v = v.toFixed(decimals);  
axis.ticks.push({ v: v, label: o.tickFormatter(v) });  
}  
}  
},  
/**  
* Calculates axis label sizes.  
*/  
calculateSpacing: function(){  
var a = this.axes,  
options = this.options,  
series = this.series,  
margin = options.grid.labelMargin,  
x = a.x,  
x2 = a.x2,  
y = a.y,  
y2 = a.y2,  
maxOutset = 2,  
i, j, l, dim;  
 
// Labels width and height  
[x, x2, y, y2].each(function(axis) {  
var maxLabel = '';  
 
if (axis.options.showLabels) {  
for(i = 0; i < axis.ticks.length; ++i){  
l = axis.ticks[i].label.length;  
if(l > maxLabel.length){  
maxLabel = axis.ticks[i].label;  
}  
}  
}  
axis.maxLabel = this.getTextDimensions(maxLabel, {size:options.fontSize, angle: Flotr.toRad(axis.options.labelsAngle)}, 'font-size:smaller;', 'flotr-grid-label');  
axis.titleSize = this.getTextDimensions(axis.options.title, {size: options.fontSize*1.2, angle: Flotr.toRad(axis.options.titleAngle)}, 'font-weight:bold;', 'flotr-axis-title');  
}, this);  
 
// Title height  
dim = this.getTextDimensions(options.title, {size: options.fontSize*1.5}, 'font-size:1em;font-weight:bold;', 'flotr-title');  
this.titleHeight = dim.height;  
 
// Subtitle height  
dim = this.getTextDimensions(options.subtitle, {size: options.fontSize}, 'font-size:smaller;', 'flotr-subtitle');  
this.subtitleHeight = dim.height;  
 
// Grid outline line width.  
if(options.show){  
maxOutset = Math.max(maxOutset, options.points.radius + options.points.lineWidth/2);  
}  
for(j = 0; j < options.length; ++j){  
if (series[j].points.show){  
maxOutset = Math.max(maxOutset, series[j].points.radius + series[j].points.lineWidth/2);  
}  
}  
 
var p = this.plotOffset = {left: 0, right: 0, top: 0, bottom: 0};  
p.left = p.right = p.top = p.bottom = maxOutset;  
 
p.bottom += (x.options.showLabels ? (x.maxLabel.height + margin) : 0) +  
(x.options.title ? (x.titleSize.height + margin) : 0);  
 
p.top += (x2.options.showLabels ? (x2.maxLabel.height + margin) : 0) +  
(x2.options.title ? (x2.titleSize.height + margin) : 0) + this.subtitleHeight + this.titleHeight +  
this.options.radarChartMode ? (y.options.showLabels ? (y.maxLabel.height + margin) : 0) : 0;  
 
p.left += (y.options.showLabels ? (y.maxLabel.width + margin) : 0) +  
(y.options.title ? (y.titleSize.width + margin) : 0);  
 
p.right += (y2.options.showLabels ? (y2.maxLabel.width + margin) : 0) +  
(y2.options.title ? (y2.titleSize.width + margin) : 0) +  
this.options.radarChartMode ? (x.options.showLabels ? (x.maxLabel.width + margin) : 0) : 0;  
 
p.top = Math.floor(p.top); // In order the outline not to be blured  
 
this.plotWidth = this.canvasWidth - p.left - p.right;  
this.plotHeight = this.canvasHeight - p.bottom - p.top;  
 
x.scale = this.plotWidth / (x.max - x.min);  
x2.scale = this.plotWidth / (x2.max - x2.min);  
y.scale = this.plotHeight / (y.max - y.min);  
y2.scale = this.plotHeight / (y2.max - y2.min);  
},  
/**  
* Draws grid, labels and series.  
*/  
draw: function() {  
this.drawGrid();  
this.drawLabels();  
this.drawTitles();  
 
if(this.series.length){  
this.el.fire('flotr:beforedraw', [this.series, this]);  
for(var i = 0; i < this.series.length; i++){  
if (!this.series[i].hide)  
this.drawSeries(this.series[i]);  
}  
}  
this.el.fire('flotr:afterdraw', [this.series, this]);  
},  
/**  
* Translates absolute horizontal x coordinates to relative coordinates.  
* @param {Integer} x - absolute integer x coordinate  
* @return {Integer} translated relative x coordinate  
*/  
tHoz: function(x, axis){  
axis = axis || this.axes.x;  
return (x - axis.min) * axis.scale;  
},  
/**  
* Translates absolute vertical x coordinates to relative coordinates.  
* @param {Integer} y - absolute integer y coordinate  
* @return {Integer} translated relative y coordinate  
*/  
tVert: function(y, axis){  
axis = axis || this.axes.y;  
return this.plotHeight - (y - axis.min) * axis.scale;  
},  
/**  
* Draws a grid for the graph.  
*/  
drawGrid: function(){  
if (this.options.radarChartMode) { // If we are in radar chart mode call drawRadarGrid instead and exit  
this.drawRadarGrid();  
return;  
}  
var v, o = this.options,  
ctx = this.ctx;  
if(o.grid.verticalLines || o.grid.horizontalLines){  
this.el.fire('flotr:beforegrid', [this.axes.x, this.axes.y, o, this]);  
}  
ctx.save();  
ctx.translate(this.plotOffset.left, this.plotOffset.top);  
 
// Draw grid background, if present in options.  
if(o.grid.backgroundColor != null){  
ctx.fillStyle = o.grid.backgroundColor;  
ctx.fillRect(0, 0, this.plotWidth, this.plotHeight);  
}  
 
// Draw grid lines in vertical direction.  
ctx.lineWidth = 1;  
ctx.strokeStyle = o.grid.tickColor;  
ctx.beginPath();  
if(o.grid.verticalLines){  
for(var i = 0; i < this.axes.x.ticks.length; ++i){  
v = this.axes.x.ticks[i].v;  
// Don't show lines on upper and lower bounds.  
if ((v == this.axes.x.min || v == this.axes.x.max) && o.grid.outlineWidth != 0)  
continue;  
 
ctx.moveTo(Math.floor(this.tHoz(v)) + ctx.lineWidth/2, 0);  
ctx.lineTo(Math.floor(this.tHoz(v)) + ctx.lineWidth/2, this.plotHeight);  
}  
}  
 
// Draw grid lines in horizontal direction.  
if(o.grid.horizontalLines){  
for(var j = 0; j < this.axes.y.ticks.length; ++j){  
v = this.axes.y.ticks[j].v;  
// Don't show lines on upper and lower bounds.  
if ((v == this.axes.y.min || v == this.axes.y.max) && o.grid.outlineWidth != 0)  
continue;  
 
ctx.moveTo(0, Math.floor(this.tVert(v)) + ctx.lineWidth/2);  
ctx.lineTo(this.plotWidth, Math.floor(this.tVert(v)) + ctx.lineWidth/2);  
}  
}  
ctx.stroke();  
 
// Draw axis/grid border.  
if(o.grid.outlineWidth != 0) {  
ctx.lineWidth = o.grid.outlineWidth;  
ctx.strokeStyle = o.grid.color;  
ctx.lineJoin = 'round';  
ctx.strokeRect(0, 0, this.plotWidth, this.plotHeight);  
}  
ctx.restore();  
if(o.grid.verticalLines || o.grid.horizontalLines){  
this.el.fire('flotr:aftergrid', [this.axes.x, this.axes.y, o, this]);  
}  
},  
/**  
* Draws a grid for the graph.  
*/  
drawRadarGrid: function(){  
 
var v, o = this.options,  
ctx = this.ctx;  
 
var sides = this.options.radarChartSides,  
degreesInRadiansForAngle = Math.PI * 2 / sides,  
nintyDegrees = Math.PI / 2;  
 
if(o.grid.verticalLines || o.grid.horizontalLines){  
this.el.fire('flotr:beforegrid', [this.axes.x, this.axes.y, o, this]);  
}  
ctx.save();  
ctx.translate(this.plotOffset.left, this.plotOffset.top);  
ctx.lineJoin = 'round';  
 
// Draw grid background, if present in options.  
if(o.grid.backgroundColor != null){  
ctx.fillStyle = o.grid.backgroundColor;  
ctx.fillRect(0, 0, this.plotWidth, this.plotHeight);  
}  
 
// Draw grid lines  
var regPoly = {};  
regPoly.xaxis = {};  
regPoly.yaxis = {};  
regPoly.xaxis.min = regPoly.yaxis.min = this.axes.x.min;  
regPoly.xaxis.max = regPoly.yaxis.max = this.axes.x.max;  
regPoly.xaxis.scale = this.plotWidth / (this.axes.x.max - this.axes.x.min);  
regPoly.yaxis.scale = this.plotHeight / (this.axes.x.max - this.axes.x.min);  
 
ctx.lineWidth = 1;  
ctx.strokeStyle = o.grid.tickColor;  
 
if(o.grid.horizontalLines){  
for(var j = 0; j < this.axes.y.ticks.length; ++j){  
v = this.axes.y.ticks[j].v;  
if (v < 0) continue;  
// Don't show lines on upper and lower bounds.  
if ((v == this.axes.y.min || v == this.axes.y.max) && o.grid.outlineWidth != 0)  
continue;  
regPoly.data = new Array();  
for (i = 0; i < sides; i++) {  
angle = nintyDegrees + (degreesInRadiansForAngle * i);  
regPoly.data[i] = [v * Math.cos(angle), v * Math.sin(angle)]  
}  
regPoly.data[sides] = regPoly.data[0];  
this.plotLine(regPoly,0);  
}  
}  
 
// Draw axis/grid border.  
if(o.grid.outlineWidth != 0) {  
ctx.lineWidth = o.grid.outlineWidth;  
ctx.strokeStyle = o.grid.color;  
regPoly.data = new Array();  
var radius = this.axes.x.max;  
for (i = 0; i < sides; i++) {  
angle = nintyDegrees + (degreesInRadiansForAngle * i);  
regPoly.data[i] = [radius * Math.cos(angle), radius * Math.sin(angle)]  
}  
regPoly.data[sides] = regPoly.data[0];  
this.plotLine(regPoly,0);  
}  
 
ctx.lineWidth = 1;  
ctx.strokeStyle = o.grid.tickColor;  
ctx.beginPath();  
 
if(o.grid.verticalLines){  
for(var i = 0; i < sides; ++i){  
ctx.moveTo(Math.floor(this.tHoz(0)) + ctx.lineWidth/2,  
Math.floor(this.tVert(0)) + ctx.lineWidth/2);  
ctx.lineTo(Math.floor(this.tHoz(regPoly.data[i][0])) + ctx.lineWidth/2,  
Math.floor(this.tVert(regPoly.data[i][1])) + ctx.lineWidth/2);  
}  
}  
 
ctx.stroke();  
 
ctx.restore();  
if(o.grid.verticalLines || o.grid.horizontalLines){  
this.el.fire('flotr:aftergrid', [this.axes.x, this.axes.y, o, this]);  
}  
},  
/**  
* Draws labels aroung radar chart  
*/  
drawRadarLabels:function(){  
var ctx = this.ctx,  
options = this.options,  
axis = this.axes.x,  
tick, minY = 0, maxY = 0,  
xOffset, yOffset;  
var style = {  
size: options.fontSize,  
adjustAlign: true  
};  
style.color = axis.options.color || options.grid.color;  
style.angle = Flotr.toRad(axis.options.labelsAngle);  
var radius = axis.max * 1,  
closeTo = axis.max * 0.1,  
sides = this.options.radarChartSides,  
degreesInRadiansForAngle = Math.PI * 2 / sides,  
nintyDegrees = Math.PI / 2,  
posdata = new Array();  
for (i = 0; i < sides; i++) {  
angle = nintyDegrees + (degreesInRadiansForAngle * i);  
posdata[i] = [radius * Math.cos(angle), radius * Math.sin(angle)];  
if (minY > posdata[i][1]) minY = posdata[i][1];  
if (maxY < posdata[i][1]) maxY = posdata[i][1];  
}  
for (i = 0; i < sides; i++) {  
tick = axis.ticks[i];  
if(!tick.label || tick.label.length == 0) continue;  
yOffset = 0;  
if (posdata[i][0] > 0) {  
style.halign = 'l';  
xOffset = options.grid.labelMargin;  
} else {  
style.halign = 'r';  
xOffset = - options.grid.labelMargin;  
}  
style.valign = 'm';  
 
if ((posdata[i][1] + closeTo) >= minY && (posdata[i][1] - closeTo) <= minY) {  
style.valign = 't' ;  
style.halign = 'c';  
yOffset = options.grid.labelMargin;  
};  
if (posdata[i][1] == maxY) {  
style.valign = 'b' ;  
style.halign = 'c';  
yOffset = - options.grid.labelMargin;  
}  
ctx.drawText(  
tick.label,  
this.plotOffset.left + this.tHoz(posdata[i][0]) + xOffset,  
this.plotOffset.top + this.tVert(posdata[i][1]) + yOffset,  
style  
);  
}  
 
},  
/**  
* Draws labels for x and y axis.  
*/  
drawLabels: function(){  
// Construct fixed width label boxes, which can be styled easily.  
var noLabels = 0, axis,  
xBoxWidth, i, html, tick,  
options = this.options,  
ctx = this.ctx,  
a = this.axes;  
 
for(i = 0; i < a.x.ticks.length; ++i){  
if (a.x.ticks[i].label) {  
++noLabels;  
}  
}  
xBoxWidth = this.plotWidth / noLabels;  
 
if (!options.HtmlText && this.textEnabled) {  
var style = {  
size: options.fontSize,  
adjustAlign: true  
};  
 
// Add x labels.  
if (options.radarChartMode) {  
this.drawRadarLabels();} else {  
axis = a.x;  
style.color = axis.options.color || options.grid.color;  
for(i = 0; i < axis.ticks.length && axis.options.showLabels && axis.used; ++i){  
tick = axis.ticks[i];  
if(!tick.label || tick.label.length == 0) continue;  
 
style.angle = Flotr.toRad(axis.options.labelsAngle);  
style.halign = 'c';  
style.valign = 't';  
 
ctx.drawText(  
tick.label,  
this.plotOffset.left + this.tHoz(tick.v, axis),  
this.plotOffset.top + this.plotHeight + options.grid.labelMargin,  
style  
);  
}}  
 
// Add x2 labels.  
axis = a.x2;  
style.color = axis.options.color || options.grid.color;  
for(i = 0; i < axis.ticks.length && axis.options.showLabels && axis.used; ++i){  
tick = axis.ticks[i];  
if(!tick.label || tick.label.length == 0) continue;  
 
style.angle = Flotr.toRad(axis.options.labelsAngle);  
style.halign = 'c';  
style.valign = 'b';  
 
ctx.drawText(  
tick.label,  
this.plotOffset.left + this.tHoz(tick.v, axis),  
this.plotOffset.top + options.grid.labelMargin,  
style  
);  
}  
 
// Add y labels.  
axis = a.y;  
style.color = axis.options.color || options.grid.color;  
for(i = 0; i < axis.ticks.length && axis.options.showLabels && axis.used; ++i){  
tick = axis.ticks[i];  
if (!tick.label || tick.label.length == 0 || (tick.v < 0 && this.options.radarChartMode)) continue;  
 
style.angle = Flotr.toRad(axis.options.labelsAngle);  
style.halign = 'r';  
style.valign = 'm';  
 
ctx.drawText(  
tick.label,  
this.plotOffset.left + (this.options.radarChartMode ? this.tHoz(0) : 0) - options.grid.labelMargin,  
this.plotOffset.top + this.tVert(tick.v, axis),  
style  
);  
}  
 
// Add y2 labels.  
axis = a.y2;  
style.color = axis.options.color || options.grid.color;  
for(i = 0; i < axis.ticks.length && axis.options.showLabels && axis.used; ++i){  
tick = axis.ticks[i];  
if (!tick.label || tick.label.length == 0) continue;  
 
style.angle = Flotr.toRad(axis.options.labelsAngle);  
style.halign = 'l';  
style.valign = 'm';  
 
ctx.drawText(  
tick.label,  
this.plotOffset.left + this.plotWidth + options.grid.labelMargin,  
this.plotOffset.top + this.tVert(tick.v, axis),  
style  
);  
 
ctx.save();  
ctx.strokeStyle = style.color;  
ctx.beginPath();  
ctx.moveTo(this.plotOffset.left + this.plotWidth - 8, this.plotOffset.top + this.tVert(tick.v, axis));  
ctx.lineTo(this.plotOffset.left + this.plotWidth, this.plotOffset.top + this.tVert(tick.v, axis));  
ctx.stroke();  
ctx.restore();  
}  
}  
else if (a.x.options.showLabels ||  
a.x2.options.showLabels ||  
a.y.options.showLabels ||  
a.y2.options.showLabels) {  
html = ['<div style="font-size:smaller;color:' + options.grid.color + ';" class="flotr-labels">'];  
 
// Add x labels.  
axis = a.x;  
if (axis.options.showLabels){  
for(i = 0; i < axis.ticks.length; ++i){  
tick = axis.ticks[i];  
if(!tick.label || tick.label.length == 0) continue;  
html.push('<div style="position:absolute;top:' + (this.plotOffset.top + this.plotHeight + options.grid.labelMargin) + 'px;left:' + (this.plotOffset.left + this.tHoz(tick.v, axis) - xBoxWidth/2) + 'px;width:' + xBoxWidth + 'px;text-align:center;'+(axis.options.color?('color:'+axis.options.color+';'):'')+'" class="flotr-grid-label">' + tick.label + '</div>');  
}  
}  
 
// Add x2 labels.  
axis = a.x2;  
if (axis.options.showLabels && axis.used){  
for(i = 0; i < axis.ticks.length; ++i){  
tick = axis.ticks[i];  
if(!tick.label || tick.label.length == 0) continue;  
html.push('<div style="position:absolute;top:' + (this.plotOffset.top - options.grid.labelMargin - axis.maxLabel.height) + 'px;left:' + (this.plotOffset.left + this.tHoz(tick.v, axis) - xBoxWidth/2) + 'px;width:' + xBoxWidth + 'px;text-align:center;'+(axis.options.color?('color:'+axis.options.color+';'):'')+'" class="flotr-grid-label">' + tick.label + '</div>');  
}  
}  
 
// Add y labels.  
axis = a.y;  
if (axis.options.showLabels){  
for(i = 0; i < axis.ticks.length; ++i){  
tick = axis.ticks[i];  
if (!tick.label || tick.label.length == 0) continue;  
html.push('<div style="position:absolute;top:' + (this.plotOffset.top + this.tVert(tick.v, axis) - axis.maxLabel.height/2) + 'px;left:0;width:' + (this.plotOffset.left - options.grid.labelMargin) + 'px;text-align:right;'+(axis.options.color?('color:'+axis.options.color+';'):'')+'" class="flotr-grid-label">' + tick.label + '</div>');  
}  
}  
 
// Add y2 labels.  
axis = a.y2;  
if (axis.options.showLabels && axis.used){  
ctx.save();  
ctx.strokeStyle = axis.options.color || options.grid.color;  
ctx.beginPath();  
 
for(i = 0; i < axis.ticks.length; ++i){  
tick = axis.ticks[i];  
if (!tick.label || tick.label.length == 0) continue;  
html.push('<div style="position:absolute;top:' + (this.plotOffset.top + this.tVert(tick.v, axis) - axis.maxLabel.height/2) + 'px;right:0;width:' + (this.plotOffset.right - options.grid.labelMargin) + 'px;text-align:left;'+(axis.options.color?('color:'+axis.options.color+';'):'')+'" class="flotr-grid-label">' + tick.label + '</div>');  
 
ctx.moveTo(this.plotOffset.left + this.plotWidth - 8, this.plotOffset.top + this.tVert(tick.v, axis));  
ctx.lineTo(this.plotOffset.left + this.plotWidth, this.plotOffset.top + this.tVert(tick.v, axis));  
}  
ctx.stroke();  
ctx.restore();  
}  
 
html.push('</div>');  
this.el.insert(html.join(''));  
}  
},  
/**  
* Draws the title and the subtitle  
*/  
drawTitles: function(){  
var html,  
options = this.options,  
margin = options.grid.labelMargin,  
ctx = this.ctx,  
a = this.axes;  
 
if (!options.HtmlText && this.textEnabled) {  
var style = {  
size: options.fontSize,  
color: options.grid.color,  
halign: 'c'  
};  
 
// Add subtitle  
if (options.subtitle){  
ctx.drawText(  
options.subtitle,  
this.plotOffset.left + this.plotWidth/2,  
this.titleHeight + this.subtitleHeight - 2,  
style  
);  
}  
 
style.weight = 1.5;  
style.size *= 1.5;  
 
// Add title  
if (options.title){  
ctx.drawText(  
options.title,  
this.plotOffset.left + this.plotWidth/2,  
this.titleHeight - 2,  
style  
);  
}  
 
style.weight = 1.8;  
style.size *= 0.8;  
style.adjustAlign = true;  
 
// Add x axis title  
if (a.x.options.title && a.x.used){  
style.halign = 'c';  
style.valign = 't';  
style.angle = Flotr.toRad(a.x.options.titleAngle);  
ctx.drawText(  
a.x.options.title,  
this.plotOffset.left + this.plotWidth/2,  
this.plotOffset.top + a.x.maxLabel.height + this.plotHeight + 2 * margin,  
style  
);  
}  
 
// Add x2 axis title  
if (a.x2.options.title && a.x2.used){  
style.halign = 'c';  
style.valign = 'b';  
style.angle = Flotr.toRad(a.x2.options.titleAngle);  
ctx.drawText(  
a.x2.options.title,  
this.plotOffset.left + this.plotWidth/2,  
this.plotOffset.top - a.x2.maxLabel.height - 2 * margin,  
style  
);  
}  
 
// Add y axis title  
if (a.y.options.title && a.y.used){  
style.halign = 'r';  
style.valign = 'm';  
style.angle = Flotr.toRad(a.y.options.titleAngle);  
ctx.drawText(  
a.y.options.title,  
this.plotOffset.left - a.y.maxLabel.width - 2 * margin,  
this.plotOffset.top + this.plotHeight / 2,  
style  
);  
}  
 
// Add y2 axis title  
if (a.y2.options.title && a.y2.used){  
style.halign = 'l';  
style.valign = 'm';  
style.angle = Flotr.toRad(a.y2.options.titleAngle);  
ctx.drawText(  
a.y2.options.title,  
this.plotOffset.left + this.plotWidth + a.y2.maxLabel.width + 2 * margin,  
this.plotOffset.top + this.plotHeight / 2,  
style  
);  
}  
}  
else {  
html = ['<div style="color:'+options.grid.color+';" class="flotr-titles">'];  
 
// Add title  
if (options.title){  
html.push('<div style="position:absolute;top:0;left:'+this.plotOffset.left+'px;font-size:1em;font-weight:bold;text-align:center;width:'+this.plotWidth+'px;" class="flotr-title">'+options.title+'</div>');  
}  
 
// Add subtitle  
if (options.subtitle){  
html.push('<div style="position:absolute;top:'+this.titleHeight+'px;left:'+this.plotOffset.left+'px;font-size:smaller;text-align:center;width:'+this.plotWidth+'px;" class="flotr-subtitle">'+options.subtitle+'</div>');  
}  
html.push('</div>');  
 
 
html.push('<div class="flotr-axis-title" style="font-weight:bold;">');  
// Add x axis title  
if (a.x.options.title && a.x.used){  
html.push('<div style="position:absolute;top:' + (this.plotOffset.top + this.plotHeight + options.grid.labelMargin + a.x.titleSize.height) + 'px;left:' + this.plotOffset.left + 'px;width:' + this.plotWidth + 'px;text-align:center;" class="flotr-axis-title">' + a.x.options.title + '</div>');  
}  
 
// Add x2 axis title  
if (a.x2.options.title && a.x2.used){  
html.push('<div style="position:absolute;top:0;left:' + this.plotOffset.left + 'px;width:' + this.plotWidth + 'px;text-align:center;" class="flotr-axis-title">' + a.x2.options.title + '</div>');  
}  
 
// Add y axis title  
if (a.y.options.title && a.y.used){  
html.push('<div style="position:absolute;top:' + (this.plotOffset.top + this.plotHeight/2 - a.y.titleSize.height/2) + 'px;left:0;text-align:right;" class="flotr-axis-title">' + a.y.options.title + '</div>');  
}  
 
// Add y2 axis title  
if (a.y2.options.title && a.y2.used){  
html.push('<div style="position:absolute;top:' + (this.plotOffset.top + this.plotHeight/2 - a.y.titleSize.height/2) + 'px;right:0;text-align:right;" class="flotr-axis-title">' + a.y2.options.title + '</div>');  
}  
html.push('</div>');  
 
this.el.insert(html.join(''));  
}  
},  
/**  
* Actually draws the graph.  
* @param {Object} series - series to draw  
*/  
drawSeries: function(series){  
series = series || this.series;  
 
var drawn = false;  
for(var type in Flotr._registeredTypes){  
if(series[type] && series[type].show){  
this[Flotr._registeredTypes[type]](series);  
drawn = true;  
}  
}  
 
if(!drawn){  
this[Flotr._registeredTypes[this.options.defaultType]](series);  
}  
},  
 
plotLine: function(series, offset){  
var ctx = this.ctx,  
xa = series.xaxis,  
ya = series.yaxis,  
tHoz = this.tHoz.bind(this),  
tVert = this.tVert.bind(this),  
data = series.data;  
 
if(data.length < 2) return;  
 
var prevx = tHoz(data[0][0], xa),  
prevy = tVert(data[0][1], ya) + offset;  
ctx.beginPath();  
ctx.moveTo(prevx, prevy);  
for(var i = 0; i < data.length - 1; ++i){  
var x1 = data[i][0], y1 = data[i][1],  
x2 = data[i+1][0], y2 = data[i+1][1];  
 
// To allow empty values  
if (y1 === null || y2 === null) continue;  
 
/**  
* Clip with ymin.  
*/  
if(y1 <= y2 && y1 < ya.min){  
/**  
* Line segment is outside the drawing area.  
*/  
if(y2 < ya.min) continue;  
 
/**  
* Compute new intersection point.  
*/  
x1 = (ya.min - y1) / (y2 - y1) * (x2 - x1) + x1;  
y1 = ya.min;  
}else if(y2 <= y1 && y2 < ya.min){  
if(y1 < ya.min) continue;  
x2 = (ya.min - y1) / (y2 - y1) * (x2 - x1) + x1;  
y2 = ya.min;  
}  
 
/**  
* Clip with ymax.  
*/  
if(y1 >= y2 && y1 > ya.max) {  
if(y2 > ya.max) continue;  
x1 = (ya.max - y1) / (y2 - y1) * (x2 - x1) + x1;  
y1 = ya.max;  
}  
else if(y2 >= y1 && y2 > ya.max){  
if(y1 > ya.max) continue;  
x2 = (ya.max - y1) / (y2 - y1) * (x2 - x1) + x1;  
y2 = ya.max;  
}  
 
/**  
* Clip with xmin.  
*/  
if(x1 <= x2 && x1 < xa.min){  
if(x2 < xa.min) continue;  
y1 = (xa.min - x1) / (x2 - x1) * (y2 - y1) + y1;  
x1 = xa.min;  
}else if(x2 <= x1 && x2 < xa.min){  
if(x1 < xa.min) continue;  
y2 = (xa.min - x1) / (x2 - x1) * (y2 - y1) + y1;  
x2 = xa.min;  
}  
 
/**  
* Clip with xmax.  
*/  
if(x1 >= x2 && x1 > xa.max){  
if (x2 > xa.max) continue;  
y1 = (xa.max - x1) / (x2 - x1) * (y2 - y1) + y1;  
x1 = xa.max;  
}else if(x2 >= x1 && x2 > xa.max){  
if(x1 > xa.max) continue;  
y2 = (xa.max - x1) / (x2 - x1) * (y2 - y1) + y1;  
x2 = xa.max;  
}  
 
if(prevx != tHoz(x1, xa) || prevy != tVert(y1, ya) + offset)  
ctx.moveTo(tHoz(x1, xa), tVert(y1, ya) + offset);  
 
prevx = tHoz(x2, xa);  
prevy = tVert(y2, ya) + offset;  
ctx.lineTo(prevx, prevy);  
}  
ctx.stroke();  
},  
/**  
* Function used to fill  
* @param {Object} data  
*/  
plotLineArea: function(series, offset){  
var data = series.data;  
if(data.length < 2) return;  
 
var top, lastX = 0,  
ctx = this.ctx,  
xa = series.xaxis,  
ya = series.yaxis,  
tHoz = this.tHoz.bind(this),  
tVert = this.tVert.bind(this),  
bottom = Math.min(Math.max(0, ya.min), ya.max),  
first = true;  
 
ctx.beginPath();  
for(var i = 0; i < data.length - 1; ++i){  
 
var x1 = data[i][0], y1 = data[i][1],  
x2 = data[i+1][0], y2 = data[i+1][1];  
 
if(x1 <= x2 && x1 < xa.min){  
if(x2 < xa.min) continue;  
y1 = (xa.min - x1) / (x2 - x1) * (y2 - y1) + y1;  
x1 = xa.min;  
}else if(x2 <= x1 && x2 < xa.min){  
if(x1 < xa.min) continue;  
y2 = (xa.min - x1) / (x2 - x1) * (y2 - y1) + y1;  
x2 = xa.min;  
}  
 
if(x1 >= x2 && x1 > xa.max){  
if(x2 > xa.max) continue;  
y1 = (xa.max - x1) / (x2 - x1) * (y2 - y1) + y1;  
x1 = xa.max;  
}else if(x2 >= x1 && x2 > xa.max){  
if (x1 > xa.max) continue;  
y2 = (xa.max - x1) / (x2 - x1) * (y2 - y1) + y1;  
x2 = xa.max;  
}  
 
if(first){  
ctx.moveTo(tHoz(x1, xa), tVert(bottom, ya) + offset);  
first = false;  
}  
 
/**  
* Now check the case where both is outside.  
*/  
if(y1 >= ya.max && y2 >= ya.max){  
ctx.lineTo(tHoz(x1, xa), tVert(ya.max, ya) + offset);  
ctx.lineTo(tHoz(x2, xa), tVert(ya.max, ya) + offset);  
continue;  
}else if(y1 <= ya.min && y2 <= ya.min){  
ctx.lineTo(tHoz(x1, xa), tVert(ya.min, ya) + offset);  
ctx.lineTo(tHoz(x2, xa), tVert(ya.min, ya) + offset);  
continue;  
}  
 
/**  
* Else it's a bit more complicated, there might  
* be two rectangles and two triangles we need to fill  
* in; to find these keep track of the current x values.  
*/  
var x1old = x1, x2old = x2;  
 
/**  
* And clip the y values, without shortcutting.  
* Clip with ymin.  
*/  
if(y1 <= y2 && y1 < ya.min && y2 >= ya.min){  
x1 = (ya.min - y1) / (y2 - y1) * (x2 - x1) + x1;  
y1 = ya.min;  
}else if(y2 <= y1 && y2 < ya.min && y1 >= ya.min){  
x2 = (ya.min - y1) / (y2 - y1) * (x2 - x1) + x1;  
y2 = ya.min;  
}  
 
/**  
* Clip with ymax.  
*/  
if(y1 >= y2 && y1 > ya.max && y2 <= ya.max){  
x1 = (ya.max - y1) / (y2 - y1) * (x2 - x1) + x1;  
y1 = ya.max;  
}else if(y2 >= y1 && y2 > ya.max && y1 <= ya.max){  
x2 = (ya.max - y1) / (y2 - y1) * (x2 - x1) + x1;  
y2 = ya.max;  
}  
 
/**  
* If the x value was changed we got a rectangle to fill.  
*/  
if(x1 != x1old){  
top = (y1 <= ya.min) ? top = ya.min : ya.max;  
ctx.lineTo(tHoz(x1old, xa), tVert(top, ya) + offset);  
ctx.lineTo(tHoz(x1, xa), tVert(top, ya) + offset);  
}  
 
/**  
* Fill the triangles.  
*/  
ctx.lineTo(tHoz(x1, xa), tVert(y1, ya) + offset);  
ctx.lineTo(tHoz(x2, xa), tVert(y2, ya) + offset);  
 
/**  
* Fill the other rectangle if it's there.  
*/  
if(x2 != x2old){  
top = (y2 <= ya.min) ? ya.min : ya.max;  
ctx.lineTo(tHoz(x2old, xa), tVert(top, ya) + offset);  
ctx.lineTo(tHoz(x2, xa), tVert(top, ya) + offset);  
}  
 
lastX = Math.max(x2, x2old);  
}  
 
ctx.lineTo(tHoz(lastX, xa), tVert(bottom, ya) + offset);  
ctx.closePath();  
ctx.fill();  
},  
/**  
* Function: (private) drawSeriesLines  
*  
* Function draws lines series in the canvas element.  
*  
* Parameters:  
* series - Series with options.lines.show = true.  
*  
* Returns:  
* void  
*/  
drawSeriesLines: function(series){  
series = series || this.series;  
var ctx = this.ctx;  
ctx.save();  
ctx.translate(this.plotOffset.left, this.plotOffset.top);  
ctx.lineJoin = 'round';  
 
var lw = series.lines.lineWidth;  
var sw = series.shadowSize;  
 
if(sw > 0){  
ctx.lineWidth = sw / 2;  
 
var offset = lw/2 + ctx.lineWidth/2;  
 
ctx.strokeStyle = "rgba(0,0,0,0.1)";  
this.plotLine(series, offset + sw/2);  
 
ctx.strokeStyle = "rgba(0,0,0,0.2)";  
this.plotLine(series, offset);  
 
if(series.lines.fill) {  
ctx.fillStyle = "rgba(0,0,0,0.05)";  
this.plotLineArea(series, offset + sw/2);  
}  
}  
 
ctx.lineWidth = lw;  
ctx.strokeStyle = series.color;  
if(series.lines.fill){  
ctx.fillStyle = series.lines.fillColor != null ? series.lines.fillColor : Flotr.parseColor(series.color).scale(null, null, null, series.lines.fillOpacity).toString();  
this.plotLineArea(series, 0);  
}  
 
this.plotLine(series, 0);  
ctx.restore();  
},  
/**  
* Function: drawSeriesPoints  
*  
* Function draws point series in the canvas element.  
*  
* Parameters:  
* series - Series with options.points.show = true.  
*  
* Returns:  
* void  
*/  
drawSeriesPoints: function(series) {  
var ctx = this.ctx;  
 
ctx.save();  
ctx.translate(this.plotOffset.left, this.plotOffset.top);  
 
var lw = series.lines.lineWidth;  
var sw = series.shadowSize;  
 
if(sw > 0){  
ctx.lineWidth = sw / 2;  
 
ctx.strokeStyle = 'rgba(0,0,0,0.1)';  
this.plotPointShadows(series, sw/2 + ctx.lineWidth/2, series.points.radius);  
 
ctx.strokeStyle = 'rgba(0,0,0,0.2)';  
this.plotPointShadows(series, ctx.lineWidth/2, series.points.radius);  
}  
 
ctx.lineWidth = series.points.lineWidth;  
ctx.strokeStyle = series.color;  
ctx.fillStyle = series.points.fillColor != null ? series.points.fillColor : series.color;  
this.plotPoints(series, series.points.radius, series.points.fill);  
ctx.restore();  
},  
plotPoints: function (series, radius, fill) {  
var xa = series.xaxis,  
ya = series.yaxis,  
ctx = this.ctx, i,  
data = series.data;  
 
for(i = data.length - 1; i > -1; --i){  
var x = data[i][0], y = data[i][1];  
if(x < xa.min || x > xa.max || y < ya.min || y > ya.max)  
continue;  
 
ctx.beginPath();  
ctx.arc(this.tHoz(x, xa), this.tVert(y, ya), radius, 0, 2 * Math.PI, true);  
if(fill) ctx.fill();  
ctx.stroke();  
}  
},  
plotPointShadows: function(series, offset, radius){  
var xa = series.xaxis,  
ya = series.yaxis,  
ctx = this.ctx, i,  
data = series.data;  
 
for(i = data.length - 1; i > -1; --i){  
var x = data[i][0], y = data[i][1];  
if (x < xa.min || x > xa.max || y < ya.min || y > ya.max)  
continue;  
ctx.beginPath();  
ctx.arc(this.tHoz(x, xa), this.tVert(y, ya) + offset, radius, 0, Math.PI, false);  
ctx.stroke();  
}  
},  
/**  
* Function: drawSeriesBars  
*  
* Function draws bar series in the canvas element.  
*  
* Parameters:  
* series - Series with options.bars.show = true.  
*  
* Returns:  
* void  
*/  
drawSeriesBars: function(series) {  
var ctx = this.ctx,  
bw = series.bars.barWidth,  
lw = Math.min(series.bars.lineWidth, bw);  
 
ctx.save();  
ctx.translate(this.plotOffset.left, this.plotOffset.top);  
ctx.lineJoin = 'miter';  
 
/**  
* @todo linewidth not interpreted the right way.  
*/  
ctx.lineWidth = lw;  
ctx.strokeStyle = series.color;  
 
this.plotBarsShadows(series, bw, 0, series.bars.fill);  
 
if(series.bars.fill){  
ctx.fillStyle = series.bars.fillColor != null ? series.bars.fillColor : Flotr.parseColor(series.color).scale(null, null, null, series.bars.fillOpacity).toString();  
}  
 
this.plotBars(series, bw, 0, series.bars.fill);  
ctx.restore();  
},  
plotBars: function(series, barWidth, offset, fill){  
var data = series.data;  
if(data.length < 1) return;  
 
var xa = series.xaxis,  
ya = series.yaxis,  
ctx = this.ctx,  
tHoz = this.tHoz.bind(this),  
tVert = this.tVert.bind(this);  
 
for(var i = 0; i < data.length; i++){  
var x = data[i][0],  
y = data[i][1];  
var drawLeft = true, drawTop = true, drawRight = true;  
 
// Stacked bars  
var stackOffset = 0;  
if(series.bars.stacked) {  
xa.values.each(function(o, v) {  
if (v == x) {  
stackOffset = o.stack || 0;  
o.stack = stackOffset + y;  
}  
});  
}  
 
// @todo: fix horizontal bars support  
// Horizontal bars  
if(series.bars.horizontal)  
var left = stackOffset, right = x + stackOffset, bottom = y, top = y + barWidth;  
else  
var left = x, right = x + barWidth, bottom = stackOffset, top = y + stackOffset;  
 
if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)  
continue;  
 
if(left < xa.min){  
left = xa.min;  
drawLeft = false;  
}  
 
if(right > xa.max){  
right = xa.max;  
if (xa.lastSerie != series && series.bars.horizontal)  
drawTop = false;  
}  
 
if(bottom < ya.min)  
bottom = ya.min;  
 
if(top > ya.max){  
top = ya.max;  
if (ya.lastSerie != series && !series.bars.horizontal)  
drawTop = false;  
}  
 
/**  
* Fill the bar.  
*/  
if(fill){  
ctx.beginPath();  
ctx.moveTo(tHoz(left, xa), tVert(bottom, ya) + offset);  
ctx.lineTo(tHoz(left, xa), tVert(top, ya) + offset);  
ctx.lineTo(tHoz(right, xa), tVert(top, ya) + offset);  
ctx.lineTo(tHoz(right, xa), tVert(bottom, ya) + offset);  
ctx.fill();  
}  
 
/**  
* Draw bar outline/border.  
*/  
if(series.bars.lineWidth != 0 && (drawLeft || drawRight || drawTop)){  
ctx.beginPath();  
ctx.moveTo(tHoz(left, xa), tVert(bottom, ya) + offset);  
 
ctx[drawLeft ?'lineTo':'moveTo'](tHoz(left, xa), tVert(top, ya) + offset);  
ctx[drawTop ?'lineTo':'moveTo'](tHoz(right, xa), tVert(top, ya) + offset);  
ctx[drawRight?'lineTo':'moveTo'](tHoz(right, xa), tVert(bottom, ya) + offset);  
 
ctx.stroke();  
}  
}  
},  
plotBarsShadows: function(series, barWidth, offset){  
var data = series.data;  
if(data.length < 1) return;  
 
var xa = series.xaxis,  
ya = series.yaxis,  
ctx = this.ctx,  
tHoz = this.tHoz.bind(this),  
tVert = this.tVert.bind(this),  
sw = this.options.shadowSize;  
 
for(var i = 0; i < data.length; i++){  
var x = data[i][0],  
y = data[i][1];  
 
// Stacked bars  
var stackOffset = 0;  
if(series.bars.stacked) {  
xa.values.each(function(o, v) {  
if (v == x) {  
stackOffset = o.stackShadow || 0;  
o.stackShadow = stackOffset + y;  
}  
});  
}  
 
// Horizontal bars  
if(series.bars.horizontal)  
var left = stackOffset, right = x + stackOffset, bottom = y, top = y + barWidth;  
else  
var left = x, right = x + barWidth, bottom = stackOffset, top = y + stackOffset;  
 
if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)  
continue;  
 
if(left < xa.min) left = xa.min;  
if(right > xa.max) right = xa.max;  
if(bottom < ya.min) bottom = ya.min;  
if(top > ya.max) top = ya.max;  
 
var width = tHoz(right, xa)-tHoz(left, xa)-((tHoz(right, xa)+sw <= this.plotWidth) ? 0 : sw);  
var height = Math.max(0, tVert(bottom, ya)-tVert(top, ya)-((tVert(bottom, ya)+sw <= this.plotHeight) ? 0 : sw));  
 
ctx.fillStyle = 'rgba(0,0,0,0.05)';  
ctx.fillRect(Math.min(tHoz(left, xa)+sw, this.plotWidth), Math.min(tVert(top, ya)+sw, this.plotWidth), width, height);  
}  
},  
/**  
* Function: drawSeriesCandles  
*  
* Function draws candles series in the canvas element.  
*  
* Parameters:  
* series - Series with options.candles.show = true.  
*  
* Returns:  
* void  
*/  
drawSeriesCandles: function(series) {  
var ctx = this.ctx,  
bw = series.candles.candleWidth;  
 
ctx.save();  
ctx.translate(this.plotOffset.left, this.plotOffset.top);  
ctx.lineJoin = 'miter';  
 
/**  
* @todo linewidth not interpreted the right way.  
*/  
ctx.lineWidth = series.candles.lineWidth;  
this.plotCandlesShadows(series, bw/2);  
this.plotCandles(series, bw/2);  
 
ctx.restore();  
},  
plotCandles: function(series, offset){  
var data = series.data;  
if(data.length < 1) return;  
 
var xa = series.xaxis,  
ya = series.yaxis,  
ctx = this.ctx,  
tHoz = this.tHoz.bind(this),  
tVert = this.tVert.bind(this);  
 
for(var i = 0; i < data.length; i++){  
var d = data[i],  
x = d[0],  
open = d[1],  
high = d[2],  
low = d[3],  
close = d[4];  
 
var left = x,  
right = x + series.candles.candleWidth,  
bottom = Math.max(ya.min, low),  
top = Math.min(ya.max, high),  
bottom2 = Math.max(ya.min, Math.min(open, close)),  
top2 = Math.min(ya.max, Math.max(open, close));  
 
if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)  
continue;  
 
var color = series.candles[open>close?'downFillColor':'upFillColor'];  
/**  
* Fill the candle.  
*/  
if(series.candles.fill && !series.candles.barcharts){  
ctx.fillStyle = Flotr.parseColor(color).scale(null, null, null, series.candles.fillOpacity).toString();  
ctx.fillRect(tHoz(left, xa), tVert(top2, ya) + offset, tHoz(right, xa) - tHoz(left, xa), tVert(bottom2, ya) - tVert(top2, ya));  
}  
 
/**  
* Draw candle outline/border, high, low.  
*/  
if(series.candles.lineWidth || series.candles.wickLineWidth){  
var x, y, pixelOffset = (series.candles.wickLineWidth % 2) / 2;  
 
x = Math.floor(tHoz((left + right) / 2), xa) + pixelOffset;  
 
ctx.save();  
ctx.strokeStyle = color;  
ctx.lineWidth = series.candles.wickLineWidth;  
ctx.lineCap = 'butt';  
 
if (series.candles.barcharts) {  
ctx.beginPath();  
 
ctx.moveTo(x, Math.floor(tVert(top, ya) + offset));  
ctx.lineTo(x, Math.floor(tVert(bottom, ya) + offset));  
 
y = Math.floor(tVert(open, ya) + offset)+0.5;  
ctx.moveTo(Math.floor(tHoz(left, xa))+pixelOffset, y);  
ctx.lineTo(x, y);  
 
y = Math.floor(tVert(close, ya) + offset)+0.5;  
ctx.moveTo(Math.floor(tHoz(right, xa))+pixelOffset, y);  
ctx.lineTo(x, y);  
}  
else {  
ctx.strokeRect(tHoz(left, xa), tVert(top2, ya) + offset, tHoz(right, xa) - tHoz(left, xa), tVert(bottom2, ya) - tVert(top2, ya));  
 
ctx.beginPath();  
ctx.moveTo(x, Math.floor(tVert(top2, ya) + offset));  
ctx.lineTo(x, Math.floor(tVert(top, ya) + offset));  
ctx.moveTo(x, Math.floor(tVert(bottom2, ya) + offset));  
ctx.lineTo(x, Math.floor(tVert(bottom, ya) + offset));  
}  
 
ctx.stroke();  
ctx.restore();  
}  
}  
},  
plotCandlesShadows: function(series, offset){  
var data = series.data;  
if(data.length < 1 || series.candles.barcharts) return;  
 
var xa = series.xaxis,  
ya = series.yaxis,  
tHoz = this.tHoz.bind(this),  
tVert = this.tVert.bind(this),  
sw = this.options.shadowSize;  
 
for(var i = 0; i < data.length; i++){  
var d = data[i],  
x = d[0],  
open = d[1],  
high = d[2],  
low = d[3],  
close = d[4];  
 
var left = x,  
right = x + series.candles.candleWidth,  
bottom = Math.max(ya.min, Math.min(open, close)),  
top = Math.min(ya.max, Math.max(open, close));  
 
if(right < xa.min || left > xa.max || top < ya.min || bottom > ya.max)  
continue;  
 
var width = tHoz(right, xa)-tHoz(left, xa)-((tHoz(right, xa)+sw <= this.plotWidth) ? 0 : sw);  
var height = Math.max(0, tVert(bottom, ya)-tVert(top, ya)-((tVert(bottom, ya)+sw <= this.plotHeight) ? 0 : sw));  
 
this.ctx.fillStyle = 'rgba(0,0,0,0.05)';  
this.ctx.fillRect(Math.min(tHoz(left, xa)+sw, this.plotWidth), Math.min(tVert(top, ya)+sw, this.plotWidth), width, height);  
}  
},  
/**  
* Function: drawSeriesRadar  
*  
* Function draws a radar chart on the canvas element.  
*  
* Parameters:  
* series - Series with options.radar.show = true.  
*  
* Returns:  
* void  
*/  
drawSeriesRadar: function(series) {  
var ctx = this.ctx,  
options = this.options, sides= series.data.length;  
 
var degreesInRadiansForAngle = Math.PI * 2 / sides,  
nintyDegrees = Math.PI / 2;  
 
var poly = {};  
 
/*  
Draw radar grid  
 
poly.xaxis = series.xaxis;  
poly.yaxis = series.yaxis;  
ctx.save();  
ctx.translate(this.plotOffset.left, this.plotOffset.top);  
ctx.lineJoin = 'round';  
for (radius = 20; radius <= 100; radius += 20) {  
poly.data = new Array();  
for (i = 0; i < sides; i++) {  
angle = nintyDegrees + (degreesInRadiansForAngle * i);  
poly.data[i] = [radius * Math.cos(angle), radius * Math.sin(angle)]  
}  
poly.data[sides] = poly.data[0];  
this.plotLine(poly,0);}  
 
var outside = poly.data;  
for (i = 0; i < sides; i++) {  
poly.data = new Array();  
poly.data[0] = [0,0];  
poly.data[1] = outside[i];  
this.plotLine(poly,0);  
}  
*/  
 
/*  
Convert Series data into X, Y co-ordinates  
*/  
if (!series.dataInRadarFormat) {  
poly.data = new Array();  
for (i = 0; i < sides; i++) {  
angle = nintyDegrees + (degreesInRadiansForAngle * i);  
poly.data[i] = [series.data[i][1] * Math.cos(angle), series.data[i][1] * Math.sin(angle), series.data[i][0], series.data[i][1]]  
}  
poly.data[sides] = poly.data[0];  
series.data = poly.data;  
series.lines = series.radar;  
series.lines.show = false;  
series.dataInRadarFormat = true;  
}  
 
this.drawSeriesLines(series);  
 
},  
 
 
/**  
* Function: drawSeriesPie  
*  
* Function draws a pie in the canvas element.  
*  
* Parameters:  
* series - Series with options.pie.show = true.  
*  
* Returns:  
* void  
*/  
drawSeriesPie: function(series) {  
if (!this.options.pie.drawn) {  
var ctx = this.ctx,  
options = this.options,  
lw = series.pie.lineWidth,  
sw = series.shadowSize,  
data = series.data,  
radius = (Math.min(this.canvasWidth, this.canvasHeight) * series.pie.sizeRatio) / 2,  
html = [];  
 
var vScale = 1;//Math.cos(series.pie.viewAngle);  
var plotTickness = Math.sin(series.pie.viewAngle)*series.pie.spliceThickness / vScale;  
 
var style = {  
size: options.fontSize*1.2,  
color: options.grid.color,  
weight: 1.5  
};  
 
var center = {  
x: (this.canvasWidth+this.plotOffset.left)/2,  
y: (this.canvasHeight-this.plotOffset.bottom)/2  
};  
 
// Pie portions  
var portions = this.series.collect(function(hash, index){  
if (hash.pie.show)  
return {  
name: (hash.label || hash.data[0][1]),  
value: [index, hash.data[0][1]],  
explode: hash.pie.explode  
};  
});  
 
// Sum of the portions' angles  
var sum = portions.pluck('value').pluck(1).inject(0, function(acc, n) { return acc + n; });  
 
var fraction = 0.0,  
angle = series.pie.startAngle,  
value = 0.0;  
 
var slices = portions.collect(function(slice){  
angle += fraction;  
value = parseFloat(slice.value[1]); // @warning : won't support null values !!  
fraction = value/sum;  
return {  
name: slice.name,  
fraction: fraction,  
x: slice.value[0],  
y: value,  
explode: slice.explode,  
startAngle: 2 * angle * Math.PI,  
endAngle: 2 * (angle + fraction) * Math.PI  
};  
});  
 
ctx.save();  
 
if(sw > 0){  
slices.each(function (slice) {  
var bisection = (slice.startAngle + slice.endAngle) / 2;  
 
var xOffset = center.x + Math.cos(bisection) * slice.explode + sw;  
var yOffset = center.y + Math.sin(bisection) * slice.explode + sw;  
 
this.plotSlice(xOffset, yOffset, radius, slice.startAngle, slice.endAngle, false, vScale);  
 
ctx.fillStyle = 'rgba(0,0,0,0.1)';  
ctx.fill();  
}, this);  
}  
 
if (options.HtmlText) {  
html = ['<div style="color:' + this.options.grid.color + '" class="flotr-labels">'];  
}  
 
slices.each(function (slice, index) {  
var bisection = (slice.startAngle + slice.endAngle) / 2;  
var color = options.colors[index];  
 
var xOffset = center.x + Math.cos(bisection) * slice.explode;  
var yOffset = center.y + Math.sin(bisection) * slice.explode;  
 
this.plotSlice(xOffset, yOffset, radius, slice.startAngle, slice.endAngle, false, vScale);  
 
if(series.pie.fill){  
ctx.fillStyle = Flotr.parseColor(color).scale(null, null, null, series.pie.fillOpacity).toString();  
ctx.fill();  
}  
ctx.lineWidth = lw;  
ctx.strokeStyle = color;  
ctx.stroke();  
 
/*ctx.save();  
ctx.scale(1, vScale);  
 
ctx.moveTo(xOffset, yOffset);  
ctx.beginPath();  
ctx.lineTo(xOffset, yOffset+plotTickness);  
ctx.lineTo(xOffset+Math.cos(slice.startAngle)*radius, yOffset+Math.sin(slice.startAngle)*radius+plotTickness);  
ctx.lineTo(xOffset+Math.cos(slice.startAngle)*radius, yOffset+Math.sin(slice.startAngle)*radius);  
ctx.lineTo(xOffset, yOffset);  
ctx.closePath();  
ctx.fill();ctx.stroke();  
 
ctx.moveTo(xOffset, yOffset);  
ctx.beginPath();  
ctx.lineTo(xOffset, yOffset+plotTickness);  
ctx.lineTo(xOffset+Math.cos(slice.endAngle)*radius, yOffset+Math.sin(slice.endAngle)*radius+plotTickness);  
ctx.lineTo(xOffset+Math.cos(slice.endAngle)*radius, yOffset+Math.sin(slice.endAngle)*radius);  
ctx.lineTo(xOffset, yOffset);  
ctx.closePath();  
ctx.fill();ctx.stroke();  
 
ctx.moveTo(xOffset+Math.cos(slice.startAngle)*radius, yOffset+Math.sin(slice.startAngle)*radius);  
ctx.beginPath();  
ctx.lineTo(xOffset+Math.cos(slice.startAngle)*radius, yOffset+Math.sin(slice.startAngle)*radius+plotTickness);  
ctx.arc(xOffset, yOffset+plotTickness, radius, slice.startAngle, slice.endAngle, false);  
ctx.lineTo(xOffset+Math.cos(slice.endAngle)*radius, yOffset+Math.sin(slice.endAngle)*radius);  
ctx.arc(xOffset, yOffset, radius, slice.endAngle, slice.startAngle, true);  
ctx.closePath();  
ctx.fill();ctx.stroke();  
 
ctx.scale(1, 1/vScale);  
this.plotSlice(xOffset, yOffset+plotTickness, radius, slice.startAngle, slice.endAngle, false, vScale);  
ctx.stroke();  
if(series.pie.fill){  
ctx.fillStyle = Flotr.parseColor(color).scale(null, null, null, series.pie.fillOpacity).toString();  
ctx.fill();  
}  
 
ctx.restore();*/  
 
var label = options.pie.labelFormatter(slice);  
 
var textAlignRight = (Math.cos(bisection) < 0);  
var distX = xOffset + Math.cos(bisection) * (series.pie.explode + radius);  
var distY = yOffset + Math.sin(bisection) * (series.pie.explode + radius);  
 
if (slice.fraction && label) {  
if (options.HtmlText) {  
var divStyle = 'position:absolute;top:' + (distY - 5) + 'px;'; //@todo: change  
if (textAlignRight) {  
divStyle += 'right:'+(this.canvasWidth - distX)+'px;text-align:right;';  
}  
else {  
divStyle += 'left:'+distX+'px;text-align:left;';  
}  
html.push('<div style="' + divStyle + '" class="flotr-grid-label">' + label + '</div>');  
}  
else {  
style.halign = textAlignRight ? 'r' : 'l';  
ctx.drawText(  
label,  
distX,  
distY + style.size / 2,  
style  
);  
}  
}  
}, this);  
 
if (options.HtmlText) {  
html.push('</div>');  
this.el.insert(html.join(''));  
}  
 
ctx.restore();  
options.pie.drawn = true;  
}  
},  
plotSlice: function(x, y, radius, startAngle, endAngle, fill, vScale) {  
var ctx = this.ctx;  
vScale = vScale || 1;  
 
ctx.save();  
ctx.scale(1, vScale);  
ctx.beginPath();  
ctx.moveTo(x, y);  
ctx.arc (x, y, radius, startAngle, endAngle, fill);  
ctx.lineTo(x, y);  
ctx.closePath();  
ctx.restore();  
},  
plotPie: function() {},  
/**  
* Function: insertLegend  
*  
* Function adds a legend div to the canvas container or draws it on the canvas.  
*  
* Parameters:  
* none  
*  
* Returns:  
* void  
*/  
insertLegend: function(){  
if(!this.options.legend.show)  
return;  
 
var series = this.series,  
plotOffset = this.plotOffset,  
options = this.options,  
fragments = [],  
rowStarted = false,  
ctx = this.ctx,  
i;  
 
var noLegendItems = series.findAll(function(s) {return (s.label && !s.hide)}).size();  
 
if (noLegendItems) {  
if (!options.HtmlText && this.textEnabled) {  
var style = {  
size: options.fontSize*1.1,  
color: options.grid.color  
};  
 
// @todo: take css into account  
//var dummyDiv = this.el.insert('<div class="flotr-legend" style="position:absolute;top:-10000px;"></div>');  
 
var p = options.legend.position,  
m = options.legend.margin,  
lbw = options.legend.labelBoxWidth,  
lbh = options.legend.labelBoxHeight,  
lbm = options.legend.labelBoxMargin,  
offsetX = plotOffset.left + m,  
offsetY = plotOffset.top + m;  
 
// We calculate the labels' max width  
var labelMaxWidth = 0;  
for(i = series.length - 1; i > -1; --i){  
if(!series[i].label || series[i].hide) continue;  
var label = options.legend.labelFormatter(series[i].label);  
labelMaxWidth = Math.max(labelMaxWidth, ctx.measureText(label, style));  
}  
 
var legendWidth = Math.round(lbw + lbm*3 + labelMaxWidth),  
legendHeight = Math.round(noLegendItems*(lbm+lbh) + lbm);  
 
if(p.charAt(0) == 's') offsetY = plotOffset.top + this.plotHeight - (m + legendHeight);  
if(p.charAt(1) == 'e') offsetX = plotOffset.left + this.plotWidth - (m + legendWidth);  
 
// Legend box  
var color = Flotr.parseColor(options.legend.backgroundColor || 'rgb(240,240,240)').scale(null, null, null, options.legend.backgroundOpacity || 0.1).toString();  
 
ctx.fillStyle = color;  
ctx.fillRect(offsetX, offsetY, legendWidth, legendHeight);  
ctx.strokeStyle = options.legend.labelBoxBorderColor;  
ctx.strokeRect(Flotr.toPixel(offsetX), Flotr.toPixel(offsetY), legendWidth, legendHeight);  
 
// Legend labels  
var x = offsetX + lbm;  
var y = offsetY + lbm;  
for(i = 0; i < series.length; i++){  
if(!series[i].label || series[i].hide) continue;  
var label = options.legend.labelFormatter(series[i].label);  
 
ctx.fillStyle = series[i].color;  
ctx.fillRect(x, y, lbw-1, lbh-1);  
 
ctx.strokeStyle = options.legend.labelBoxBorderColor;  
ctx.lineWidth = 1;  
ctx.strokeRect(Math.ceil(x)-1.5, Math.ceil(y)-1.5, lbw+2, lbh+2);  
 
// Legend text  
ctx.drawText(  
label,  
x + lbw + lbm,  
y + (lbh + style.size - ctx.fontDescent(style))/2,  
style  
);  
 
y += lbh + lbm;  
}  
}  
else {  
for(i = 0; i < series.length; ++i){  
if(!series[i].label || series[i].hide) continue;  
 
if(i % options.legend.noColumns == 0){  
fragments.push(rowStarted ? '</tr><tr>' : '<tr>');  
rowStarted = true;  
}  
 
var label = options.legend.labelFormatter(series[i].label);  
 
fragments.push('<td class="flotr-legend-color-box"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:' + options.legend.labelBoxWidth + 'px;height:' + options.legend.labelBoxHeight + 'px;background-color:' + series[i].color + '"></div></div></td>' +  
'<td class="flotr-legend-label">' + label + '</td>');  
}  
if(rowStarted) fragments.push('</tr>');  
 
if(fragments.length > 0){  
var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>';  
if(options.legend.container != null){  
$(options.legend.container).update(table);  
}else{  
var pos = '';  
var p = options.legend.position, m = options.legend.margin;  
 
if(p.charAt(0) == 'n') pos += 'top:' + (m + plotOffset.top) + 'px;';  
else if(p.charAt(0) == 's') pos += 'bottom:' + (m + plotOffset.bottom) + 'px;';  
if(p.charAt(1) == 'e') pos += 'right:' + (m + plotOffset.right) + 'px;';  
else if(p.charAt(1) == 'w') pos += 'left:' + (m + plotOffset.left) + 'px;';  
 
var div = this.el.insert('<div class="flotr-legend" style="position:absolute;z-index:2;' + pos +'">' + table + '</div>').select('div.flotr-legend').first();  
 
if(options.legend.backgroundOpacity != 0.0){  
/**  
* Put in the transparent background separately to avoid blended labels and  
* label boxes.  
*/  
var c = options.legend.backgroundColor;  
if(c == null){  
var tmp = (options.grid.backgroundColor != null) ? options.grid.backgroundColor : Flotr.extractColor(div);  
c = Flotr.parseColor(tmp).adjust(null, null, null, 1).toString();  
}  
this.el.insert('<div class="flotr-legend-bg" style="position:absolute;width:' + div.getWidth() + 'px;height:' + div.getHeight() + 'px;' + pos +'background-color:' + c + ';"> </div>').select('div.flotr-legend-bg').first().setStyle({  
'opacity': options.legend.backgroundOpacity  
});  
}  
}  
}  
}  
}  
},  
/**  
* Function: getEventPosition  
*  
* Calculates the coordinates from a mouse event object.  
*  
* Parameters:  
* event - Mouse Event object.  
*  
* Returns:  
* Object with x and y coordinates of the mouse.  
*/  
getEventPosition: function (event){  
var offset = this.overlay.cumulativeOffset(),  
rx = (event.pageX - offset.left - this.plotOffset.left),  
ry = (event.pageY - offset.top - this.plotOffset.top),  
ax = 0, ay = 0  
 
if(event.pageX == null && event.clientX != null){  
var de = document.documentElement, b = document.body;  
ax = event.clientX + (de && de.scrollLeft || b.scrollLeft || 0);  
ay = event.clientY + (de && de.scrollTop || b.scrollTop || 0);  
}else{  
ax = event.pageX;  
ay = event.pageY;  
}  
 
return {  
x: this.axes.x.min + rx / this.axes.x.scale,  
x2: this.axes.x2.min + rx / this.axes.x2.scale,  
y: this.axes.y.max - ry / this.axes.y.scale,  
y2: this.axes.y2.max - ry / this.axes.y2.scale,  
relX: rx,  
relY: ry,  
absX: ax,  
absY: ay  
};  
},  
/**  
* Function: clickHandler  
*  
* Handler observes the 'click' event and fires the 'flotr:click' event.  
*  
* Parameters:  
* event - 'click' Event object.  
*  
* Returns:  
* void  
*/  
clickHandler: function(event){  
if(this.ignoreClick){  
this.ignoreClick = false;  
return;  
}  
this.el.fire('flotr:click', [this.getEventPosition(event), this]);  
},  
/**  
* Function: mouseMoveHandler  
*  
* Handler observes mouse movement over the graph area. Fires the  
* 'flotr:mousemove' event.  
*  
* Parameters:  
* event - 'mousemove' Event object.  
*  
* Returns:  
* void  
*/  
mouseMoveHandler: function(event){  
var pos = this.getEventPosition(event);  
 
this.lastMousePos.pageX = pos.absX;  
this.lastMousePos.pageY = pos.absY;  
if(this.selectionInterval == null && (this.options.mouse.track || this.series.any(function(s){return s.mouse && s.mouse.track;}))){  
this.hit(pos);  
}  
 
this.el.fire('flotr:mousemove', [event, pos, this]);  
},  
/**  
* Function: mouseDownHandler  
*  
* Handler observes the 'mousedown' event.  
*  
* Parameters:  
* event - 'mousedown' Event object.  
*  
* Returns:  
* void  
*/  
mouseDownHandler: function (event){  
if(event.isRightClick()) {  
event.stop();  
var overlay = this.overlay;  
overlay.hide();  
 
function cancelContextMenu () {  
overlay.show();  
$(document).stopObserving('mousemove', cancelContextMenu);  
}  
$(document).observe('mousemove', cancelContextMenu);  
return;  
}  
 
if(!this.options.selection.mode || !event.isLeftClick()) return;  
 
this.setSelectionPos(this.selection.first, event);  
if(this.selectionInterval != null){  
clearInterval(this.selectionInterval);  
}  
this.lastMousePos.pageX = null;  
this.selectionInterval = setInterval(this.updateSelection.bind(this), 1000/this.options.selection.fps);  
 
this.mouseUpHandler = this.mouseUpHandler.bind(this);  
$(document).observe('mouseup', this.mouseUpHandler);  
},  
/**  
* Function: (private) fireSelectEvent  
*  
* Fires the 'flotr:select' event when the user made a selection.  
*  
* Parameters:  
* none  
*  
* Returns:  
* void  
*/  
fireSelectEvent: function(){  
var a = this.axes, selection = this.selection,  
x1 = (selection.first.x <= selection.second.x) ? selection.first.x : selection.second.x,  
x2 = (selection.first.x <= selection.second.x) ? selection.second.x : selection.first.x,  
y1 = (selection.first.y >= selection.second.y) ? selection.first.y : selection.second.y,  
y2 = (selection.first.y >= selection.second.y) ? selection.second.y : selection.first.y;  
 
x1 = a.x.min + x1 / a.x.scale;  
x2 = a.x.min + x2 / a.x.scale;  
y1 = a.y.max - y1 / a.y.scale;  
y2 = a.y.max - y2 / a.y.scale;  
 
this.el.fire('flotr:select', [{x1:x1, y1:y1, x2:x2, y2:y2}, this]);  
},  
/**  
* Function: (private) mouseUpHandler  
*  
* Handler observes the mouseup event for the document.  
*  
* Parameters:  
* event - 'mouseup' Event object.  
*  
* Returns:  
* void  
*/  
mouseUpHandler: function(event){  
$(document).stopObserving('mouseup', this.mouseUpHandler);  
event.stop();  
 
if(this.selectionInterval != null){  
clearInterval(this.selectionInterval);  
this.selectionInterval = null;  
}  
 
this.setSelectionPos(this.selection.second, event);  
this.clearSelection();  
 
if(this.selectionIsSane()){  
this.drawSelection();  
this.fireSelectEvent();  
this.ignoreClick = true;  
}  
},  
/**  
* Function: setSelectionPos  
*  
* Calculates the position of the selection.  
*  
* Parameters:  
* pos - Position object.  
* event - Event object.  
*  
* Returns:  
* void  
*/  
setSelectionPos: function(pos, event) {  
var options = this.options,  
offset = $(this.overlay).cumulativeOffset();  
 
if(options.selection.mode.indexOf('x') == -1){  
pos.x = (pos == this.selection.first) ? 0 : this.plotWidth;  
}else{  
pos.x = event.pageX - offset.left - this.plotOffset.left;  
pos.x = Math.min(Math.max(0, pos.x), this.plotWidth);  
}  
 
if (options.selection.mode.indexOf('y') == -1){  
pos.y = (pos == this.selection.first) ? 0 : this.plotHeight;  
}else{  
pos.y = event.pageY - offset.top - this.plotOffset.top;  
pos.y = Math.min(Math.max(0, pos.y), this.plotHeight);  
}  
},  
/**  
* Function: updateSelection  
*  
* Updates (draws) the selection box.  
*  
* Parameters:  
* none  
*  
* Returns:  
* void  
*/  
updateSelection: function(){  
if(this.lastMousePos.pageX == null) return;  
 
this.setSelectionPos(this.selection.second, this.lastMousePos);  
this.clearSelection();  
 
if(this.selectionIsSane()) this.drawSelection();  
},  
/**  
* Function: clearSelection  
*  
* Removes the selection box from the overlay canvas.  
*  
* Parameters:  
* none  
*  
* Returns:  
* void  
*/  
clearSelection: function() {  
if(this.prevSelection == null) return;  
 
var prevSelection = this.prevSelection,  
octx = this.octx,  
plotOffset = this.plotOffset,  
x = Math.min(prevSelection.first.x, prevSelection.second.x),  
y = Math.min(prevSelection.first.y, prevSelection.second.y),  
w = Math.abs(prevSelection.second.x - prevSelection.first.x),  
h = Math.abs(prevSelection.second.y - prevSelection.first.y);  
 
octx.clearRect(x + plotOffset.left - octx.lineWidth,  
y + plotOffset.top - octx.lineWidth,  
w + octx.lineWidth*2,  
h + octx.lineWidth*2);  
 
this.prevSelection = null;  
},  
/**  
* Function: setSelection  
*  
* Allows the user the manually select an area.  
*  
* Parameters:  
* area - Object with coordinates to select.  
*  
* Returns:  
* void  
*/  
setSelection: function(area){  
var options = this.options,  
xa = this.axes.x,  
ya = this.axes.y,  
vertScale = yaxis.scale,  
hozScale = xaxis.scale,  
selX = options.selection.mode.indexOf('x') != -1,  
selY = options.selection.mode.indexOf('y') != -1;  
 
this.clearSelection();  
 
this.selection.first.y = selX ? 0 : (ya.max - area.y1) * vertScale;  
this.selection.second.y = selX ? this.plotHeight : (ya.max - area.y2) * vertScale;  
this.selection.first.x = selY ? 0 : (area.x1 - xa.min) * hozScale;  
this.selection.second.x = selY ? this.plotWidth : (area.x2 - xa.min) * hozScale;  
 
this.drawSelection();  
this.fireSelectEvent();  
},  
/**  
* Function: (private) drawSelection  
*  
* Draws the selection box.  
*  
* Parameters:  
* none  
*  
* Returns:  
* void  
*/  
drawSelection: function() {  
var prevSelection = this.prevSelection,  
selection = this.selection,  
octx = this.octx,  
options = this.options,  
plotOffset = this.plotOffset;  
 
if(prevSelection != null &&  
selection.first.x == prevSelection.first.x &&  
selection.first.y == prevSelection.first.y &&  
selection.second.x == prevSelection.second.x &&  
selection.second.y == prevSelection.second.y)  
return;  
 
octx.strokeStyle = Flotr.parseColor(options.selection.color).scale(null, null, null, 0.8).toString();  
octx.lineWidth = 1;  
octx.lineJoin = 'round';  
octx.fillStyle = Flotr.parseColor(options.selection.color).scale(null, null, null, 0.4).toString();  
 
this.prevSelection = {  
first: { x: selection.first.x, y: selection.first.y },  
second: { x: selection.second.x, y: selection.second.y }  
};  
 
var x = Math.min(selection.first.x, selection.second.x),  
y = Math.min(selection.first.y, selection.second.y),  
w = Math.abs(selection.second.x - selection.first.x),  
h = Math.abs(selection.second.y - selection.first.y);  
 
octx.fillRect(x + plotOffset.left, y + plotOffset.top, w, h);  
octx.strokeRect(x + plotOffset.left, y + plotOffset.top, w, h);  
},  
/**  
* Function: (private) selectionIsSane  
*  
* Determines whether or not the selection is sane and should be drawn.  
*  
* Parameters:  
* none  
*  
* Returns:  
* boolean - True when sane, false otherwise.  
*/  
selectionIsSane: function(){  
var selection = this.selection;  
return Math.abs(selection.second.x - selection.first.x) >= 5 &&  
Math.abs(selection.second.y - selection.first.y) >= 5;  
},  
/**  
* Function: clearHit  
*  
* Removes the mouse tracking point from the overlay.  
*  
* Parameters:  
* none  
*  
* Returns:  
* void  
*/  
clearHit: function(){  
if(this.prevHit){  
var options = this.options,  
plotOffset = this.plotOffset,  
prevHit = this.prevHit;  
 
this.octx.clearRect(  
this.tHoz(prevHit.x) + plotOffset.left - options.points.radius*2,  
this.tVert(prevHit.y) + plotOffset.top - options.points.radius*2,  
options.points.radius*3 + options.points.lineWidth*3,  
options.points.radius*3 + options.points.lineWidth*3  
);  
this.prevHit = null;  
}  
},  
/**  
* Function: hit  
*  
* Retrieves the nearest data point from the mouse cursor. If it's within  
* a certain range, draw a point on the overlay canvas and display the x and y  
* value of the data.  
*  
* Parameters:  
* mouse - Object that holds the relative x and y coordinates of the cursor.  
*  
* Returns:  
* void  
*/  
hit: function(mouse){  
var series = this.series,  
options = this.options,  
prevHit = this.prevHit,  
plotOffset = this.plotOffset,  
octx = this.octx,  
data, xsens, ysens,  
/**  
* Nearest data element.  
*/  
i, n = {  
dist:Number.MAX_VALUE,  
x:null,  
y:null,  
relX:mouse.relX,  
relY:mouse.relY,  
absX:mouse.absX,  
absY:mouse.absY,  
mouse:null,  
radarData:null  
};  
 
for(i = 0; i < series.length; i++){  
s = series[i];  
if(!s.mouse.track) continue;  
data = s.data;  
xsens = (s.xaxis.scale*s.mouse.sensibility);  
ysens = (s.yaxis.scale*s.mouse.sensibility);  
 
for(var j = 0, xpow, ypow; j < data.length; j++){  
if (data[j][1] === null) continue;  
xpow = Math.pow(s.xaxis.scale*(data[j][0] - mouse.x), 2);  
ypow = Math.pow(s.yaxis.scale*(data[j][1] - mouse.y), 2);  
if(xpow < xsens && ypow < ysens && Math.sqrt(xpow+ypow) < n.dist){  
n.dist = Math.sqrt(xpow+ypow);  
n.x = data[j][0];  
n.y = data[j][1];  
n.radarLabel = data[j][2];  
n.radarData = data[j][3];  
n.mouse = s.mouse;  
}  
}  
}  
 
if(n.mouse && n.mouse.track && !prevHit || (prevHit && (n.x != prevHit.x || n.y != prevHit.y))){  
var mt = this.mouseTrack || this.el.select(".flotr-mouse-value")[0],  
pos = '',  
p = options.mouse.position,  
m = options.mouse.margin,  
elStyle = 'opacity:0.7;background-color:#000;color:#fff;display:none;position:absolute;padding:2px 8px;-moz-border-radius:4px;border-radius:4px;white-space:nowrap;';  
 
if (!options.mouse.relative) { // absolute to the canvas  
if(p.charAt(0) == 'n') pos += 'top:' + (m + plotOffset.top) + 'px;';  
else if(p.charAt(0) == 's') pos += 'bottom:' + (m + plotOffset.bottom) + 'px;';  
if(p.charAt(1) == 'e') pos += 'right:' + (m + plotOffset.right) + 'px;';  
else if(p.charAt(1) == 'w') pos += 'left:' + (m + plotOffset.left) + 'px;';  
}  
else { // relative to the mouse  
if(p.charAt(0) == 'n') pos += 'bottom:' + (m - plotOffset.top - this.tVert(n.y) + this.canvasHeight) + 'px;';  
else if(p.charAt(0) == 's') pos += 'top:' + (m + plotOffset.top + this.tVert(n.y)) + 'px;';  
if(p.charAt(1) == 'e') pos += 'left:' + (m + plotOffset.left + this.tHoz(n.x)) + 'px;';  
else if(p.charAt(1) == 'w') pos += 'right:' + (m - plotOffset.left - this.tHoz(n.x) + this.canvasWidth) + 'px;';  
}  
 
elStyle += pos;  
 
if(!mt){  
this.el.insert('<div class="flotr-mouse-value" style="'+elStyle+'"></div>');  
mt = this.mouseTrack = this.el.select('.flotr-mouse-value').first();  
}  
else {  
this.mouseTrack = mt.setStyle(elStyle);  
}  
 
if(n.x !== null && n.y !== null){  
mt.show();  
 
this.clearHit();  
if(n.mouse.lineColor != null){  
octx.save();  
octx.translate(plotOffset.left, plotOffset.top);  
octx.lineWidth = options.points.lineWidth;  
octx.strokeStyle = n.mouse.lineColor;  
octx.fillStyle = '#ffffff';  
octx.beginPath();  
octx.arc(this.tHoz(n.x), this.tVert(n.y), options.mouse.radius, 0, 2 * Math.PI, true);  
octx.fill();  
octx.stroke();  
octx.restore();  
}  
this.prevHit = n;  
 
var decimals = n.mouse.trackDecimals;  
if(decimals == null || decimals < 0) decimals = 0;  
 
mt.innerHTML = n.mouse.trackFormatter({x: n.x.toFixed(decimals), y: n.y.toFixed(decimals),  
radarLabel: n.radarLabel, radarData: n.radarData.toFixed(decimals)});  
mt.fire('flotr:hit', [n, this]);  
}  
else if(prevHit){  
mt.hide();  
this.clearHit();  
}  
}  
},  
saveImage: function (type, width, height, replaceCanvas) {  
var image = null;  
switch (type) {  
case 'jpeg':  
case 'jpg': image = Canvas2Image.saveAsJPEG(this.canvas, replaceCanvas, width, height); break;  
default:  
case 'png': image = Canvas2Image.saveAsPNG(this.canvas, replaceCanvas, width, height); break;  
case 'bmp': image = Canvas2Image.saveAsBMP(this.canvas, replaceCanvas, width, height); break;  
}  
if (Object.isElement(image) && replaceCanvas) {  
this.restoreCanvas();  
this.canvas.hide();  
this.overlay.hide();  
this.el.insert(image.setStyle({position: 'absolute'}));  
}  
},  
restoreCanvas: function() {  
this.canvas.show();  
this.overlay.show();  
this.el.select('img').invoke('remove');  
}  
});  
 
Flotr.Color = Class.create({  
initialize: function(r, g, b, a){  
this.rgba = ['r','g','b','a'];  
var x = 4;  
while(-1<--x){  
this[this.rgba[x]] = arguments[x] || ((x==3) ? 1.0 : 0);  
}  
this.normalize();  
},  
 
adjust: function(rd, gd, bd, ad) {  
var x = 4;  
while(-1<--x){  
if(arguments[x] != null)  
this[this.rgba[x]] += arguments[x];  
}  
return this.normalize();  
},  
 
clone: function(){  
return new Flotr.Color(this.r, this.b, this.g, this.a);  
},  
 
limit: function(val,minVal,maxVal){  
return Math.max(Math.min(val, maxVal), minVal);  
},  
 
normalize: function(){  
var limit = this.limit;  
this.r = limit(parseInt(this.r), 0, 255);  
this.g = limit(parseInt(this.g), 0, 255);  
this.b = limit(parseInt(this.b), 0, 255);  
this.a = limit(this.a, 0, 1);  
return this;  
},  
 
scale: function(rf, gf, bf, af){  
var x = 4;  
while(-1<--x){  
if(arguments[x] != null)  
this[this.rgba[x]] *= arguments[x];  
}  
return this.normalize();  
},  
 
distance: function(color){  
if (!color) return;  
color = new Flotr.parseColor(color);  
var dist = 0;  
var x = 3;  
while(-1<--x){  
dist += Math.abs(this[this.rgba[x]] - color[this.rgba[x]]);  
}  
return dist;  
},  
 
toString: function(){  
return (this.a >= 1.0) ? 'rgb('+[this.r,this.g,this.b].join(',')+')' : 'rgba('+[this.r,this.g,this.b,this.a].join(',')+')';  
}  
});  
 
Flotr.Color.lookupColors = {  
aqua:[0,255,255],  
azure:[240,255,255],  
beige:[245,245,220],  
black:[0,0,0],  
blue:[0,0,255],  
brown:[165,42,42],  
cyan:[0,255,255],  
darkblue:[0,0,139],  
darkcyan:[0,139,139],  
darkgrey:[169,169,169],  
darkgreen:[0,100,0],  
darkkhaki:[189,183,107],  
darkmagenta:[139,0,139],  
darkolivegreen:[85,107,47],  
darkorange:[255,140,0],  
darkorchid:[153,50,204],  
darkred:[139,0,0],  
darksalmon:[233,150,122],  
darkviolet:[148,0,211],  
fuchsia:[255,0,255],  
gold:[255,215,0],  
green:[0,128,0],  
indigo:[75,0,130],  
khaki:[240,230,140],  
lightblue:[173,216,230],  
lightcyan:[224,255,255],  
lightgreen:[144,238,144],  
lightgrey:[211,211,211],  
lightpink:[255,182,193],  
lightyellow:[255,255,224],  
lime:[0,255,0],  
magenta:[255,0,255],  
maroon:[128,0,0],  
navy:[0,0,128],  
olive:[128,128,0],  
orange:[255,165,0],  
pink:[255,192,203],  
purple:[128,0,128],  
violet:[128,0,128],  
red:[255,0,0],  
silver:[192,192,192],  
white:[255,255,255],  
yellow:[255,255,0]  
};  
 
// not used yet  
Flotr.Date = {  
format: function(d, format) {  
if (!d) return;  
 
var leftPad = function(n) {  
n = n.toString();  
return n.length == 1 ? "0" + n : n;  
};  
 
var r = [];  
var escape = false;  
 
for (var i = 0; i < format.length; ++i) {  
var c = format.charAt(i);  
 
if (escape) {  
switch (c) {  
case 'h': c = d.getUTCHours().toString(); break;  
case 'H': c = leftPad(d.getUTCHours()); break;  
case 'M': c = leftPad(d.getUTCMinutes()); break;  
case 'S': c = leftPad(d.getUTCSeconds()); break;  
case 'd': c = d.getUTCDate().toString(); break;  
case 'm': c = (d.getUTCMonth() + 1).toString(); break;  
case 'y': c = d.getUTCFullYear().toString(); break;  
case 'b': c = Flotr.Date.monthNames[d.getUTCMonth()]; break;  
}  
r.push(c);  
escape = false;  
}  
else {  
if (c == "%")  
escape = true;  
else  
r.push(c);  
}  
}  
return r.join("");  
},  
timeUnits: {  
"second": 1000,  
"minute": 60 * 1000,  
"hour": 60 * 60 * 1000,  
"day": 24 * 60 * 60 * 1000,  
"month": 30 * 24 * 60 * 60 * 1000,  
"year": 365.2425 * 24 * 60 * 60 * 1000  
},  
// the allowed tick sizes, after 1 year we use an integer algorithm  
spec: [  
[1, "second"], [2, "second"], [5, "second"], [10, "second"], [30, "second"],  
[1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"], [30, "minute"],  
[1, "hour"], [2, "hour"], [4, "hour"], [8, "hour"], [12, "hour"],  
[1, "day"], [2, "day"], [3, "day"],  
[0.25, "month"], [0.5, "month"], [1, "month"], [2, "month"], [3, "month"], [6, "month"],  
[1, "year"]  
],  
monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]  
};  
 
file:a/js/flotr/lib/base64.js (deleted)
/* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp>  
* Version: 1.0  
* LastModified: Dec 25 1999  
* This library is free. You can redistribute it and/or modify it.  
*/  
 
/*  
* Interfaces:  
* b64 = base64encode(data);  
* data = base64decode(b64);  
*/  
 
(function() {  
 
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  
var base64DecodeChars = [  
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,  
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,  
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,  
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,  
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1];  
 
function base64encode(str) {  
var out, i, len;  
var c1, c2, c3;  
 
len = str.length;  
i = 0;  
out = "";  
while(i < len) {  
c1 = str.charCodeAt(i++) & 0xff;  
if(i == len)  
{  
out += base64EncodeChars.charAt(c1 >> 2);  
out += base64EncodeChars.charAt((c1 & 0x3) << 4);  
out += "==";  
break;  
}  
c2 = str.charCodeAt(i++);  
if(i == len)  
{  
out += base64EncodeChars.charAt(c1 >> 2);  
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));  
out += base64EncodeChars.charAt((c2 & 0xF) << 2);  
out += "=";  
break;  
}  
c3 = str.charCodeAt(i++);  
out += base64EncodeChars.charAt(c1 >> 2);  
out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));  
out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));  
out += base64EncodeChars.charAt(c3 & 0x3F);  
}  
return out;  
}  
 
function base64decode(str) {  
var c1, c2, c3, c4;  
var i, len, out;  
 
len = str.length;  
i = 0;  
out = "";  
while(i < len) {  
/* c1 */  
do {  
c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];  
} while(i < len && c1 == -1);  
if(c1 == -1)  
break;  
 
/* c2 */  
do {  
c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];  
} while(i < len && c2 == -1);  
if(c2 == -1)  
break;  
 
out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));  
 
/* c3 */  
do {  
c3 = str.charCodeAt(i++) & 0xff;  
if(c3 == 61)  
return out;  
c3 = base64DecodeChars[c3];  
} while(i < len && c3 == -1);  
if(c3 == -1)  
break;  
 
out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));  
 
/* c4 */  
do {  
c4 = str.charCodeAt(i++) & 0xff;  
if(c4 == 61)  
return out;  
c4 = base64DecodeChars[c4];  
} while(i < len && c4 == -1);  
if(c4 == -1)  
break;  
out += String.fromCharCode(((c3 & 0x03) << 6) | c4);  
}  
return out;  
}  
 
if (!window.btoa) window.btoa = base64encode;  
if (!window.atob) window.atob = base64decode;  
 
})();  
/*  
* Canvas2Image v0.1  
* Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com  
* MIT License [http://www.opensource.org/licenses/mit-license.php]  
*/  
 
var Canvas2Image = (function() {  
// check if we have canvas support  
var oCanvas = document.createElement("canvas");  
 
// no canvas, bail out.  
if (!oCanvas.getContext) {  
return {  
saveAsBMP : function(){},  
saveAsPNG : function(){},  
saveAsJPEG : function(){}  
}  
}  
 
var bHasImageData = !!(oCanvas.getContext("2d").getImageData);  
var bHasDataURL = !!(oCanvas.toDataURL);  
var bHasBase64 = !!(window.btoa);  
 
var strDownloadMime = "image/octet-stream";  
 
// ok, we're good  
var readCanvasData = function(oCanvas) {  
var iWidth = parseInt(oCanvas.width);  
var iHeight = parseInt(oCanvas.height);  
return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);  
}  
 
// base64 encodes either a string or an array of charcodes  
var encodeData = function(data) {  
var strData = "";  
if (typeof data == "string") {  
strData = data;  
} else {  
var aData = data;  
for (var i = 0; i < aData.length; i++) {  
strData += String.fromCharCode(aData[i]);  
}  
}  
return btoa(strData);  
}  
 
// creates a base64 encoded string containing BMP data  
// takes an imagedata object as argument  
var createBMP = function(oData) {  
var aHeader = [];  
 
var iWidth = oData.width;  
var iHeight = oData.height;  
 
aHeader.push(0x42); // magic 1  
aHeader.push(0x4D);  
 
var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes  
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);  
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);  
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);  
aHeader.push(iFileSize % 256);  
 
aHeader.push(0); // reserved  
aHeader.push(0);  
aHeader.push(0); // reserved  
aHeader.push(0);  
 
aHeader.push(54); // data offset  
aHeader.push(0);  
aHeader.push(0);  
aHeader.push(0);  
 
var aInfoHeader = [];  
aInfoHeader.push(40); // info header size  
aInfoHeader.push(0);  
aInfoHeader.push(0);  
aInfoHeader.push(0);  
 
var iImageWidth = iWidth;  
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);  
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);  
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);  
aInfoHeader.push(iImageWidth % 256);  
 
var iImageHeight = iHeight;  
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);  
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);  
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);  
aInfoHeader.push(iImageHeight % 256);  
 
aInfoHeader.push(1); // num of planes  
aInfoHeader.push(0);  
 
aInfoHeader.push(24); // num of bits per pixel  
aInfoHeader.push(0);  
 
aInfoHeader.push(0); // compression = none  
aInfoHeader.push(0);  
aInfoHeader.push(0);  
aInfoHeader.push(0);  
 
var iDataSize = iWidth*iHeight*3;  
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);  
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);  
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);  
aInfoHeader.push(iDataSize % 256);  
 
for (var i = 0; i < 16; i++) {  
aInfoHeader.push(0); // these bytes not used  
}  
 
var iPadding = (4 - ((iWidth * 3) % 4)) % 4;  
 
var aImgData = oData.data;  
 
var strPixelData = "";  
var y = iHeight;  
do {  
var iOffsetY = iWidth*(y-1)*4;  
var strPixelRow = "";  
for (var x=0;x<iWidth;x++) {  
var iOffsetX = 4*x;  
 
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);  
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);  
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);  
}  
for (var c=0;c<iPadding;c++) {  
strPixelRow += String.fromCharCode(0);  
}  
strPixelData += strPixelRow;  
} while (--y);  
 
return encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);  
}  
 
// sends the generated file to the client  
var saveFile = function(strData) {  
if (!window.open(strData)) {  
document.location.href = strData;  
}  
}  
 
var makeDataURI = function(strData, strMime) {  
return "data:" + strMime + ";base64," + strData;  
}  
 
// generates a <img> object containing the imagedata  
var makeImageObject = function(strSource) {  
var oImgElement = document.createElement("img");  
oImgElement.src = strSource;  
return oImgElement;  
}  
 
var scaleCanvas = function(oCanvas, iWidth, iHeight) {  
if (iWidth && iHeight) {  
var oSaveCanvas = document.createElement("canvas");  
 
oSaveCanvas.width = iWidth;  
oSaveCanvas.height = iHeight;  
oSaveCanvas.style.width = iWidth+"px";  
oSaveCanvas.style.height = iHeight+"px";  
 
var oSaveCtx = oSaveCanvas.getContext("2d");  
 
oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iWidth);  
 
return oSaveCanvas;  
}  
return oCanvas;  
}  
 
return {  
saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {  
if (!bHasDataURL) {  
return false;  
}  
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);  
var strData = oScaledCanvas.toDataURL("image/png");  
if (bReturnImg) {  
return makeImageObject(strData);  
} else {  
saveFile(strData.replace("image/png", strDownloadMime));  
}  
return true;  
},  
 
saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {  
if (!bHasDataURL) {  
return false;  
}  
 
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);  
var strMime = "image/jpeg";  
var strData = oScaledCanvas.toDataURL(strMime);  
 
// check if browser actually supports jpeg by looking for the mime type in the data uri.  
// if not, return false  
if (strData.indexOf(strMime) != 5) {  
return false;  
}  
 
if (bReturnImg) {  
return makeImageObject(strData);  
} else {  
saveFile(strData.replace(strMime, strDownloadMime));  
}  
return true;  
},  
 
saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {  
if (!(bHasImageData && bHasBase64)) {  
return false;  
}  
 
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);  
 
var oData = readCanvasData(oScaledCanvas);  
var strImgData = createBMP(oData);  
if (bReturnImg) {  
return makeImageObject(makeDataURI(strImgData, "image/bmp"));  
} else {  
saveFile(makeDataURI(strImgData, strDownloadMime));  
}  
return true;  
}  
};  
 
})();  
/**  
* This code is released to the public domain by Jim Studt, 2007.  
* He may keep some sort of up to date copy at http://www.federated.com/~jim/canvastext/  
 
* A partial support for accentuated letters as been added too.  
*/  
var CanvasText = {  
/** The letters definition. It is a list of letters,  
* with their width, and the coordinates of points compositing them.  
* The syntax for the points is : [x, y], null value means "pen up"  
*/  
letters: {  
'\n':{ width: -1, points: [] },  
' ': { width: 10, points: [] },  
'!': { width: 10, points: [[5,21],[5,7],null,[5,2],[4,1],[5,0],[6,1],[5,2]] },  
'"': { width: 16, points: [[4,21],[4,14],null,[12,21],[12,14]] },  
'#': { width: 21, points: [[11,25],[4,-7],null,[17,25],[10,-7],null,[4,12],[18,12],null,[3,6],[17,6]] },  
'$': { width: 20, points: [[8,25],[8,-4],null,[12,25],[12,-4],null,[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] },  
'%': { width: 24, points: [[21,21],[3,0],null,[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],null,[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]] },  
'&': { width: 26, points: [[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]] },  
'\'':{ width: 10, points: [[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]] },  
'(': { width: 14, points: [[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]] },  
')': { width: 14, points: [[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]] },  
'*': { width: 16, points: [[8,21],[8,9],null,[3,18],[13,12],null,[13,18],[3,12]] },  
'+': { width: 26, points: [[13,18],[13,0],null,[4,9],[22,9]] },  
',': { width: 10, points: [[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] },  
'-': { width: 26, points: [[4,9],[22,9]] },  
'.': { width: 10, points: [[5,2],[4,1],[5,0],[6,1],[5,2]] },  
'/': { width: 22, points: [[20,25],[2,-7]] },  
'0': { width: 20, points: [[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]] },  
'1': { width: 20, points: [[6,17],[8,18],[11,21],[11,0]] },  
'2': { width: 20, points: [[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]] },  
'3': { width: 20, points: [[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },  
'4': { width: 20, points: [[13,21],[3,7],[18,7],null,[13,21],[13,0]] },  
'5': { width: 20, points: [[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },  
'6': { width: 20, points: [[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]] },  
'7': { width: 20, points: [[17,21],[7,0],null,[3,21],[17,21]] },  
'8': { width: 20, points: [[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]] },  
'9': { width: 20, points: [[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]] },  
':': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],null,[5,2],[4,1],[5,0],[6,1],[5,2]] },  
';': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],null,[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] },  
'<': { width: 24, points: [[20,18],[4,9],[20,0]] },  
'=': { width: 26, points: [[4,12],[22,12],null,[4,6],[22,6]] },  
'>': { width: 24, points: [[4,18],[20,9],[4,0]] },  
'?': { width: 18, points: [[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],null,[9,2],[8,1],[9,0],[10,1],[9,2]] },  
'@': { width: 27, points: [[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],null,[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],null,[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],null,[19,16],[18,8],[18,6],[19,5]] },  
'A': { width: 18, points: [[9,21],[1,0],null,[9,21],[17,0],null,[4,7],[14,7]] },  
'B': { width: 21, points: [[4,21],[4,0],null,[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],null,[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]] },  
'C': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]] },  
'D': { width: 21, points: [[4,21],[4,0],null,[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]] },  
'E': { width: 19, points: [[4,21],[4,0],null,[4,21],[17,21],null,[4,11],[12,11],null,[4,0],[17,0]] },  
'F': { width: 18, points: [[4,21],[4,0],null,[4,21],[17,21],null,[4,11],[12,11]] },  
'G': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],null,[13,8],[18,8]] },  
'H': { width: 22, points: [[4,21],[4,0],null,[18,21],[18,0],null,[4,11],[18,11]] },  
'I': { width: 8, points: [[4,21],[4,0]] },  
'J': { width: 16, points: [[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]] },  
'K': { width: 21, points: [[4,21],[4,0],null,[18,21],[4,7],null,[9,12],[18,0]] },  
'L': { width: 17, points: [[4,21],[4,0],null,[4,0],[16,0]] },  
'M': { width: 24, points: [[4,21],[4,0],null,[4,21],[12,0],null,[20,21],[12,0],null,[20,21],[20,0]] },  
'N': { width: 22, points: [[4,21],[4,0],null,[4,21],[18,0],null,[18,21],[18,0]] },  
'O': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]] },  
'P': { width: 21, points: [[4,21],[4,0],null,[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]] },  
'Q': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],null,[12,4],[18,-2]] },  
'R': { width: 21, points: [[4,21],[4,0],null,[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],null,[11,11],[18,0]] },  
'S': { width: 20, points: [[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] },  
'T': { width: 16, points: [[8,21],[8,0],null,[1,21],[15,21]] },  
'U': { width: 22, points: [[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]] },  
'V': { width: 18, points: [[1,21],[9,0],null,[17,21],[9,0]] },  
'W': { width: 24, points: [[2,21],[7,0],null,[12,21],[7,0],null,[12,21],[17,0],null,[22,21],[17,0]] },  
'X': { width: 20, points: [[3,21],[17,0],null,[17,21],[3,0]] },  
'Y': { width: 18, points: [[1,21],[9,11],[9,0],null,[17,21],[9,11]] },  
'Z': { width: 20, points: [[17,21],[3,0],null,[3,21],[17,21],null,[3,0],[17,0]] },  
'[': { width: 14, points: [[4,25],[4,-7],null,[5,25],[5,-7],null,[4,25],[11,25],null,[4,-7],[11,-7]] },  
'\\':{ width: 14, points: [[0,21],[14,-3]] },  
']': { width: 14, points: [[9,25],[9,-7],null,[10,25],[10,-7],null,[3,25],[10,25],null,[3,-7],[10,-7]] },  
'^': { width: 14, points: [[3,10],[8,18],[13,10]] },  
'_': { width: 16, points: [[0,-2],[16,-2]] },  
'`': { width: 10, points: [[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]] },  
'a': { width: 19, points: [[15,14],[15,0],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },  
'b': { width: 19, points: [[4,21],[4,0],null,[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] },  
'c': { width: 18, points: [[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },  
'd': { width: 19, points: [[15,21],[15,0],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },  
'e': { width: 18, points: [[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },  
'f': { width: 12, points: [[10,21],[8,21],[6,20],[5,17],[5,0],null,[2,14],[9,14]] },  
'g': { width: 19, points: [[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },  
'h': { width: 19, points: [[4,21],[4,0],null,[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] },  
'i': { width: 8, points: [[3,21],[4,20],[5,21],[4,22],[3,21],null,[4,14],[4,0]] },  
'j': { width: 10, points: [[5,21],[6,20],[7,21],[6,22],[5,21],null,[6,14],[6,-3],[5,-6],[3,-7],[1,-7]] },  
'k': { width: 17, points: [[4,21],[4,0],null,[14,14],[4,4],null,[8,8],[15,0]] },  
'l': { width: 8, points: [[4,21],[4,0]] },  
'm': { width: 30, points: [[4,14],[4,0],null,[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],null,[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]] },  
'n': { width: 19, points: [[4,14],[4,0],null,[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] },  
'o': { width: 19, points: [[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]] },  
'p': { width: 19, points: [[4,14],[4,-7],null,[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] },  
'q': { width: 19, points: [[15,14],[15,-7],null,[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },  
'r': { width: 13, points: [[4,14],[4,0],null,[4,8],[5,11],[7,13],[9,14],[12,14]] },  
's': { width: 17, points: [[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]] },  
't': { width: 12, points: [[5,21],[5,4],[6,1],[8,0],[10,0],null,[2,14],[9,14]] },  
'u': { width: 19, points: [[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],null,[15,14],[15,0]] },  
'v': { width: 16, points: [[2,14],[8,0],null,[14,14],[8,0]] },  
'w': { width: 22, points: [[3,14],[7,0],null,[11,14],[7,0],null,[11,14],[15,0],null,[19,14],[15,0]] },  
'x': { width: 17, points: [[3,14],[14,0],null,[14,14],[3,0]] },  
'y': { width: 16, points: [[2,14],[8,0],null,[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]] },  
'z': { width: 17, points: [[14,14],[3,0],null,[3,14],[14,14],null,[3,0],[14,0]] },  
'{': { width: 14, points: [[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],null,[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],null,[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]] },  
'|': { width: 8, points: [[4,25],[4,-7]] },  
'}': { width: 14, points: [[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],null,[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],null,[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]] },  
'~': { width: 24, points: [[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],null,[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]] },  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
},  
 
specialchars: {  
'pi': { width: 19, points: [[6,14],[6,0],null,[14,14],[14,0],null,[2,13],[6,16],[13,13],[17,16]] }  
},  
 
/** Diacritics, used to draw accentuated letters */  
diacritics: {  
 
 
'`': { entity: 'grave', points: [[7,22],[12,19]] },  
'^': { entity: 'circ', points: [[5.5,19],[9.5,23],[12.5,19]] },  
 
'~': { entity: 'tilde', points: [[4,18],[7,22],[10,18],[13,22]] }  
},  
 
/** The default font styling */  
style: {  
size: 8, // font height in pixels  
font: null, // not yet implemented  
color: '#000000', //  
weight: 1, // float, 1 for 'normal'  
halign: 'l', // l: left, r: right, c: center  
valign: 'b', // t: top, m: middle, b: bottom  
adjustAlign: false, // modifies the alignments if the angle is different from 0 to make the spin point always at the good position  
angle: 0, // in radians, anticlockwise  
tracking: 1, // space between the letters, float, 1 for 'normal'  
boundingBoxColor: '#ff0000', //null // color of the bounding box (null to hide), can be used for debug and font drawing  
originPointColor: '#000000' //null // color of the bounding box (null to hide), can be used for debug and font drawing  
},  
 
debug: false,  
_bufferLexemes: {},  
 
/** Get the letter data corresponding to a char  
* @param {String} ch - The char  
*/  
letter: function(ch) {  
return CanvasText.letters[ch];  
},  
 
parseLexemes: function(str) {  
if (CanvasText._bufferLexemes[str])  
return CanvasText._bufferLexemes[str];  
 
var i, c, matches = str.match(/&[A-Za-z]{2,5};|\s|./g);  
var result = [], chars = [];  
for (i = 0; i < matches.length; i++) {  
c = matches[i];  
if (c.length == 1)  
chars.push(c);  
else {  
var entity = c.substring(1, c.length-1);  
if (CanvasText.specialchars[entity])  
chars.push(entity);  
else  
chars = chars.concat(c.toArray());  
}  
}  
for (i = 0; i < chars.length; i++) {  
c = chars[i];  
if (c = CanvasText.letters[c] || CanvasText.specialchars[c])  
result.push(c);  
}  
return CanvasText._bufferLexemes[str] = result.compact();  
},  
 
/** Get the font ascent for a given style  
* @param {Object} style - The reference style  
*/  
ascent: function(style) {  
style = style || {};  
return (style.size || CanvasText.style.size);  
},  
 
/** Get the font descent for a given style  
* @param {Object} style - The reference style  
* */  
descent: function(style) {  
style = style || {};  
return 7.0*(style.size || CanvasText.style.size)/25.0;  
},  
 
/** Measure the text horizontal size  
* @param {String} str - The text  
* @param {Object} style - Text style  
* */  
measure: function(str, style) {  
if (!str) return;  
style = style || {};  
 
var i, width, lexemes = CanvasText.parseLexemes(str),  
total = 0;  
 
for (i = lexemes.length-1; i > -1; --i) {  
c = lexemes[i];  
width = (c.diacritic) ? CanvasText.letter(c.letter).width : c.width;  
total += width * (style.tracking || CanvasText.style.tracking) * (style.size || CanvasText.style.size) / 25.0;  
}  
return total;  
},  
 
getDimensions: function(str, style) {  
var width = CanvasText.measure(str, style),  
height = style.size || CanvasText.style.size,  
angle = style.angle || CanvasText.style.angle;  
 
if (style.angle == 0) return {width: width, height: height};  
return {  
width: Math.abs(Math.cos(angle) * width) + Math.abs(Math.sin(angle) * height),  
height: Math.abs(Math.sin(angle) * width) + Math.abs(Math.cos(angle) * height)  
}  
},  
 
getBestAlign: function(angle, style) {  
angle += CanvasText.getAngleFromAlign(style.halign, style.valign);  
var a = {h:'c', v:'m'};  
if (Math.round(Math.cos(angle)*1000)/1000 != 0)  
a.h = (Math.cos(angle) > 0 ? 'r' : 'l');  
 
if (Math.round(Math.sin(angle)*1000)/1000 != 0)  
a.v = (Math.sin(angle) > 0 ? 't' : 'b');  
return a;  
},  
 
getAngleFromAlign: function(halign, valign) {  
var pi = Math.PI, table = {  
'rm': 0,  
'rt': pi/4,  
'ct': pi/2,  
'lt': 3*(pi/4),  
'lm': pi,  
'lb': -3*(pi/4),  
'cb': -pi/2,  
'rb': -pi/4,  
'cm': 0  
}  
return table[halign+valign];  
},  
 
/** Draws serie of points at given coordinates  
* @param {Canvas context} ctx - The canvas context  
* @param {Array} points - The points to draw  
* @param {Number} x - The X coordinate  
* @param {Number} y - The Y coordinate  
* @param {Number} mag - The scale  
*/  
drawPoints: function (ctx, points, x, y, mag, offset) {  
var i, a, penUp = true, needStroke = 0;  
offset = offset || {x:0, y:0};  
 
ctx.beginPath();  
for (i = 0; i < points.length; i++) {  
a = points[i];  
if (!a) {  
penUp = true;  
continue;  
}  
if (penUp) {  
ctx.moveTo(x + a[0]*mag + offset.x, y - a[1]*mag + offset.y);  
penUp = false;  
}  
else {  
ctx.lineTo(x + a[0]*mag + offset.x, y - a[1]*mag + offset.y);  
}  
}  
ctx.stroke();  
},  
 
/** Draws a text at given coordinates and with a given style  
* @param {Canvas context} ctx - The canvas context  
* @param {String} str - The text to draw  
* @param {Number} xOrig - The X coordinate  
* @param {Number} yOrig - The Y coordinate  
* @param {Object} style - The font style  
*/  
draw: function(ctx, str, xOrig, yOrig, style) {  
if (!str) return;  
style = style || CanvasText.style;  
style.halign = style.halign || CanvasText.style.halign;  
style.valign = style.valign || CanvasText.style.valign;  
style.angle = style.angle || CanvasText.style.angle;  
style.size = style.size || CanvasText.style.size;  
style.adjustAlign = style.adjustAlign || CanvasText.style.adjustAlign;  
 
var i, c, total = 0,  
mag = style.size / 25.0,  
x = 0, y = 0,  
lexemes = CanvasText.parseLexemes(str);  
 
var offset = {x:0, y:0},  
measure = CanvasText.measure(str, style),  
align;  
 
if (style.adjustAlign) {  
align = CanvasText.getBestAlign(style.angle, style);  
style.halign = align.h;  
style.valign = align.v;  
}  
 
switch (style.halign) {  
case 'l': break;  
case 'c': offset.x = -measure / 2; break;  
case 'r': offset.x = -measure; break;  
}  
 
switch (style.valign) {  
case 'b': break;  
case 'm': offset.y = style.size / 2; break;  
case 't': offset.y = style.size; break;  
}  
 
ctx.save();  
ctx.translate(xOrig, yOrig);  
ctx.rotate(style.angle);  
ctx.lineCap = "round";  
ctx.lineWidth = 2.0 * mag * (style.weight || CanvasText.style.weight);  
ctx.strokeStyle = style.color || CanvasText.style.color;  
 
for (i = 0; i < lexemes.length; i++) {  
c = lexemes[i];  
if (c.width == -1) {  
x = 0;  
y = style.size * 1.4;  
continue;  
}  
 
var points = c.points,  
width = c.width;  
 
if (c.diacritic) {  
var dia = CanvasText.diacritics[c.diacritic];  
var char = CanvasText.letter(c.letter);  
 
CanvasText.drawPoints(ctx, dia.points, x, y - (c.letter.toUpperCase() == c.letter ? 3 : 0), mag, offset);  
points = char.points;  
width = char.width;  
}  
 
CanvasText.drawPoints(ctx, points, x, y, mag, offset);  
 
if (CanvasText.debug) {  
ctx.save();  
ctx.lineJoin = "miter";  
ctx.lineWidth = 0.5;  
ctx.strokeStyle = (style.boundingBoxColor || CanvasText.style.boundingBoxColor);  
ctx.strokeRect(x+offset.x, y+offset.y, width*mag, -style.size);  
 
ctx.fillStyle = (style.originPointColor || CanvasText.style.originPointColor);  
ctx.beginPath();  
ctx.arc(0, 0, 1.5, 0, Math.PI*2, true);  
ctx.fill();  
 
ctx.restore();  
}  
 
x += width*mag*(style.tracking || CanvasText.style.tracking);  
}  
ctx.restore();  
return total;  
},  
 
/** Enables the text function for a Canvas context  
* @param {Canvas context} ctx - The canvas context  
*/  
enable: function(ctx) {  
ctx.drawText = function(text, x, y, style) { return CanvasText.draw(ctx, text, x, y, style); };  
ctx.measureText = function(text, style) { return CanvasText.measure(text, style); };  
ctx.getTextBounds = function(text, style) { return CanvasText.getDimensions(text, style); };  
ctx.fontAscent = function(style) { return CanvasText.ascent(style); };  
ctx.fontDescent = function(style) { return CanvasText.descent(style); };  
}  
};  
// Copyright 2006 Google Inc.  
//  
// Licensed under the Apache License, Version 2.0 (the "License");  
// you may not use this file except in compliance with the License.  
// You may obtain a copy of the License at  
//  
// http://www.apache.org/licenses/LICENSE-2.0  
//  
// Unless required by applicable law or agreed to in writing, software  
// distributed under the License is distributed on an "AS IS" BASIS,  
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
// See the License for the specific language governing permissions and  
// limitations under the License.  
 
 
// Known Issues:  
//  
// * Patterns are not implemented.  
// * Radial gradient are not implemented. The VML version of these look very  
// different from the canvas one.  
// * Clipping paths are not implemented.  
// * Coordsize. The width and height attribute have higher priority than the  
// width and height style values which isn't correct.  
// * Painting mode isn't implemented.  
// * Canvas width/height should is using content-box by default. IE in  
// Quirks mode will draw the canvas using border-box. Either change your  
// doctype to HTML5  
// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)  
// or use Box Sizing Behavior from WebFX  
// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)  
// * Non uniform scaling does not correctly scale strokes.  
// * Optimize. There is always room for speed improvements.  
 
// Only add this code if we do not already have a canvas implementation  
if (!document.createElement('canvas').getContext) {  
 
(function() {  
 
// alias some functions to make (compiled) code shorter  
var m = Math;  
var mr = m.round;  
var ms = m.sin;  
var mc = m.cos;  
var abs = m.abs;  
var sqrt = m.sqrt;  
 
// this is used for sub pixel precision  
var Z = 10;  
var Z2 = Z / 2;  
 
/**  
* This funtion is assigned to the <canvas> elements as element.getContext().  
* @this {HTMLElement}  
* @return {CanvasRenderingContext2D_}  
*/  
function getContext() {  
return this.context_ ||  
(this.context_ = new CanvasRenderingContext2D_(this));  
}  
 
var slice = Array.prototype.slice;  
 
/**  
* Binds a function to an object. The returned function will always use the  
* passed in {@code obj} as {@code this}.  
*  
* Example:  
*  
* g = bind(f, obj, a, b)  
* g(c, d) // will do f.call(obj, a, b, c, d)  
*  
* @param {Function} f The function to bind the object to  
* @param {Object} obj The object that should act as this when the function  
* is called  
* @param {*} var_args Rest arguments that will be used as the initial  
* arguments when the function is called  
* @return {Function} A new function that has bound this  
*/  
function bind(f, obj, var_args) {  
var a = slice.call(arguments, 2);  
return function() {  
return f.apply(obj, a.concat(slice.call(arguments)));  
};  
}  
 
var G_vmlCanvasManager_ = {  
init: function(opt_doc) {  
if (/MSIE/.test(navigator.userAgent) && !window.opera) {  
var doc = opt_doc || document;  
// Create a dummy element so that IE will allow canvas elements to be  
// recognized.  
doc.createElement('canvas');  
doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));  
}  
},  
 
init_: function(doc) {  
// create xmlns  
if (!doc.namespaces['g_vml_']) {  
doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',  
'#default#VML');  
 
}  
if (!doc.namespaces['g_o_']) {  
doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',  
'#default#VML');  
}  
 
// Setup default CSS. Only add one style sheet per document  
if (!doc.styleSheets['ex_canvas_']) {  
var ss = doc.createStyleSheet();  
ss.owningElement.id = 'ex_canvas_';  
ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +  
// default size is 300x150 in Gecko and Opera  
'text-align:left;width:300px;height:150px}' +  
'g_vml_\\:*{behavior:url(#default#VML)}' +  
'g_o_\\:*{behavior:url(#default#VML)}';  
 
}  
 
// find all canvas elements  
var els = doc.getElementsByTagName('canvas');  
for (var i = 0; i < els.length; i++) {  
this.initElement(els[i]);  
}  
},  
 
/**  
* Public initializes a canvas element so that it can be used as canvas  
* element from now on. This is called automatically before the page is  
* loaded but if you are creating elements using createElement you need to  
* make sure this is called on the element.  
* @param {HTMLElement} el The canvas element to initialize.  
* @return {HTMLElement} the element that was created.  
*/  
initElement: function(el) {  
if (!el.getContext) {  
 
el.getContext = getContext;  
 
// Remove fallback content. There is no way to hide text nodes so we  
// just remove all childNodes. We could hide all elements and remove  
// text nodes but who really cares about the fallback content.  
el.innerHTML = '';  
 
// do not use inline function because that will leak memory  
el.attachEvent('onpropertychange', onPropertyChange);  
el.attachEvent('onresize', onResize);  
 
var attrs = el.attributes;  
if (attrs.width && attrs.width.specified) {  
// TODO: use runtimeStyle and coordsize  
// el.getContext().setWidth_(attrs.width.nodeValue);  
el.style.width = attrs.width.nodeValue + 'px';  
} else {  
el.width = el.clientWidth;  
}  
if (attrs.height && attrs.height.specified) {  
// TODO: use runtimeStyle and coordsize  
// el.getContext().setHeight_(attrs.height.nodeValue);  
el.style.height = attrs.height.nodeValue + 'px';  
} else {  
el.height = el.clientHeight;  
}  
//el.getContext().setCoordsize_()  
}  
return el;  
}  
};  
 
function onPropertyChange(e) {  
var el = e.srcElement;  
 
switch (e.propertyName) {  
case 'width':  
el.style.width = el.attributes.width.nodeValue + 'px';  
el.getContext().clearRect();  
break;  
case 'height':  
el.style.height = el.attributes.height.nodeValue + 'px';  
el.getContext().clearRect();  
break;  
}  
}  
 
function onResize(e) {  
var el = e.srcElement;  
if (el.firstChild) {  
el.firstChild.style.width = el.clientWidth + 'px';  
el.firstChild.style.height = el.clientHeight + 'px';  
}  
}  
 
G_vmlCanvasManager_.init();  
 
// precompute "00" to "FF"  
var dec2hex = [];  
for (var i = 0; i < 16; i++) {  
for (var j = 0; j < 16; j++) {  
dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);  
}  
}  
 
function createMatrixIdentity() {  
return [  
[1, 0, 0],  
[0, 1, 0],  
[0, 0, 1]  
];  
}  
 
function matrixMultiply(m1, m2) {  
var result = createMatrixIdentity();  
 
for (var x = 0; x < 3; x++) {  
for (var y = 0; y < 3; y++) {  
var sum = 0;  
 
for (var z = 0; z < 3; z++) {  
sum += m1[x][z] * m2[z][y];  
}  
 
result[x][y] = sum;  
}  
}  
return result;  
}  
 
function copyState(o1, o2) {  
o2.fillStyle = o1.fillStyle;  
o2.lineCap = o1.lineCap;  
o2.lineJoin = o1.lineJoin;  
o2.lineWidth = o1.lineWidth;  
o2.miterLimit = o1.miterLimit;  
o2.shadowBlur = o1.shadowBlur;  
o2.shadowColor = o1.shadowColor;  
o2.shadowOffsetX = o1.shadowOffsetX;  
o2.shadowOffsetY = o1.shadowOffsetY;  
o2.strokeStyle = o1.strokeStyle;  
o2.globalAlpha = o1.globalAlpha;  
o2.arcScaleX_ = o1.arcScaleX_;  
o2.arcScaleY_ = o1.arcScaleY_;  
o2.lineScale_ = o1.lineScale_;  
}  
 
function processStyle(styleString) {  
var str, alpha = 1;  
 
styleString = String(styleString);  
if (styleString.substring(0, 3) == 'rgb') {  
var start = styleString.indexOf('(', 3);  
var end = styleString.indexOf(')', start + 1);  
var guts = styleString.substring(start + 1, end).split(',');  
 
str = '#';  
for (var i = 0; i < 3; i++) {  
str += dec2hex[Number(guts[i])];  
}  
 
if (guts.length == 4 && styleString.substr(3, 1) == 'a') {  
alpha = guts[3];  
}  
} else {  
str = styleString;  
}  
 
return {color: str, alpha: alpha};  
}  
 
function processLineCap(lineCap) {  
switch (lineCap) {  
case 'butt':  
return 'flat';  
case 'round':  
return 'round';  
case 'square':  
default:  
return 'square';  
}  
}  
 
/**  
* This class implements CanvasRenderingContext2D interface as described by  
* the WHATWG.  
* @param {HTMLElement} surfaceElement The element that the 2D context should  
* be associated with  
*/  
function CanvasRenderingContext2D_(surfaceElement) {  
this.m_ = createMatrixIdentity();  
 
this.mStack_ = [];  
this.aStack_ = [];  
this.currentPath_ = [];  
 
// Canvas context properties  
this.strokeStyle = '#000';  
this.fillStyle = '#000';  
 
this.lineWidth = 1;  
this.lineJoin = 'miter';  
this.lineCap = 'butt';  
this.miterLimit = Z * 1;  
this.globalAlpha = 1;  
this.canvas = surfaceElement;  
 
var el = surfaceElement.ownerDocument.createElement('div');  
el.style.width = surfaceElement.clientWidth + 'px';  
el.style.height = surfaceElement.clientHeight + 'px';  
el.style.overflow = 'hidden';  
el.style.position = 'absolute';  
surfaceElement.appendChild(el);  
 
this.element_ = el;  
this.arcScaleX_ = 1;  
this.arcScaleY_ = 1;  
this.lineScale_ = 1;  
}  
 
var contextPrototype = CanvasRenderingContext2D_.prototype;  
contextPrototype.clearRect = function() {  
this.element_.innerHTML = '';  
};  
 
contextPrototype.beginPath = function() {  
// TODO: Branch current matrix so that save/restore has no effect  
// as per safari docs.  
this.currentPath_ = [];  
};  
 
contextPrototype.moveTo = function(aX, aY) {  
var p = this.getCoords_(aX, aY);  
this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y});  
this.currentX_ = p.x;  
this.currentY_ = p.y;  
};  
 
contextPrototype.lineTo = function(aX, aY) {  
var p = this.getCoords_(aX, aY);  
this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y});  
 
this.currentX_ = p.x;  
this.currentY_ = p.y;  
};  
 
contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,  
aCP2x, aCP2y,  
aX, aY) {  
var p = this.getCoords_(aX, aY);  
var cp1 = this.getCoords_(aCP1x, aCP1y);  
var cp2 = this.getCoords_(aCP2x, aCP2y);  
bezierCurveTo(this, cp1, cp2, p);  
};  
 
// Helper function that takes the already fixed cordinates.  
function bezierCurveTo(self, cp1, cp2, p) {  
self.currentPath_.push({  
type: 'bezierCurveTo',  
cp1x: cp1.x,  
cp1y: cp1.y,  
cp2x: cp2.x,  
cp2y: cp2.y,  
x: p.x,  
y: p.y  
});  
self.currentX_ = p.x;  
self.currentY_ = p.y;  
}  
 
contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {  
// the following is lifted almost directly from  
// http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes  
 
var cp = this.getCoords_(aCPx, aCPy);  
var p = this.getCoords_(aX, aY);  
 
var cp1 = {  
x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_),  
y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_)  
};  
var cp2 = {  
x: cp1.x + (p.x - this.currentX_) / 3.0,  
y: cp1.y + (p.y - this.currentY_) / 3.0  
};  
 
bezierCurveTo(this, cp1, cp2, p);  
};  
 
contextPrototype.arc = function(aX, aY, aRadius,  
aStartAngle, aEndAngle, aClockwise) {  
aRadius *= Z;  
var arcType = aClockwise ? 'at' : 'wa';  
 
var xStart = aX + mc(aStartAngle) * aRadius - Z2;  
var yStart = aY + ms(aStartAngle) * aRadius - Z2;  
 
var xEnd = aX + mc(aEndAngle) * aRadius - Z2;  
var yEnd = aY + ms(aEndAngle) * aRadius - Z2;  
 
// IE won't render arches drawn counter clockwise if xStart == xEnd.  
if (xStart == xEnd && !aClockwise) {  
xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something  
// that can be represented in binary  
}  
 
var p = this.getCoords_(aX, aY);  
var pStart = this.getCoords_(xStart, yStart);  
var pEnd = this.getCoords_(xEnd, yEnd);  
 
this.currentPath_.push({type: arcType,  
x: p.x,  
y: p.y,  
radius: aRadius,  
xStart: pStart.x,  
yStart: pStart.y,  
xEnd: pEnd.x,  
yEnd: pEnd.y});  
 
};  
 
contextPrototype.rect = function(aX, aY, aWidth, aHeight) {  
this.moveTo(aX, aY);  
this.lineTo(aX + aWidth, aY);  
this.lineTo(aX + aWidth, aY + aHeight);  
this.lineTo(aX, aY + aHeight);  
this.closePath();  
};  
 
contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {  
var oldPath = this.currentPath_;  
this.beginPath();  
 
this.moveTo(aX, aY);  
this.lineTo(aX + aWidth, aY);  
this.lineTo(aX + aWidth, aY + aHeight);  
this.lineTo(aX, aY + aHeight);  
this.closePath();  
this.stroke();  
 
this.currentPath_ = oldPath;  
};  
 
contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {  
var oldPath = this.currentPath_;  
this.beginPath();  
 
this.moveTo(aX, aY);  
this.lineTo(aX + aWidth, aY);  
this.lineTo(aX + aWidth, aY + aHeight);  
this.lineTo(aX, aY + aHeight);  
this.closePath();  
this.fill();  
 
this.currentPath_ = oldPath;  
};  
 
contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {  
var gradient = new CanvasGradient_('gradient');  
gradient.x0_ = aX0;  
gradient.y0_ = aY0;  
gradient.x1_ = aX1;  
gradient.y1_ = aY1;  
return gradient;  
};  
 
contextPrototype.createRadialGradient = function(aX0, aY0, aR0,  
aX1, aY1, aR1) {  
var gradient = new CanvasGradient_('gradientradial');  
gradient.x0_ = aX0;  
gradient.y0_ = aY0;  
gradient.r0_ = aR0;  
gradient.x1_ = aX1;  
gradient.y1_ = aY1;  
gradient.r1_ = aR1;  
return gradient;  
};  
 
contextPrototype.drawImage = function(image, var_args) {  
var dx, dy, dw, dh, sx, sy, sw, sh;  
 
// to find the original width we overide the width and height  
var oldRuntimeWidth = image.runtimeStyle.width;  
var oldRuntimeHeight = image.runtimeStyle.height;  
image.runtimeStyle.width = 'auto';  
image.runtimeStyle.height = 'auto';  
 
// get the original size  
var w = image.width;  
var h = image.height;  
 
// and remove overides  
image.runtimeStyle.width = oldRuntimeWidth;  
image.runtimeStyle.height = oldRuntimeHeight;  
 
if (arguments.length == 3) {  
dx = arguments[1];  
dy = arguments[2];  
sx = sy = 0;  
sw = dw = w;  
sh = dh = h;  
} else if (arguments.length == 5) {  
dx = arguments[1];  
dy = arguments[2];  
dw = arguments[3];  
dh = arguments[4];  
sx = sy = 0;  
sw = w;  
sh = h;  
} else if (arguments.length == 9) {  
sx = arguments[1];  
sy = arguments[2];  
sw = arguments[3];  
sh = arguments[4];  
dx = arguments[5];  
dy = arguments[6];  
dw = arguments[7];  
dh = arguments[8];  
} else {  
throw Error('Invalid number of arguments');  
}  
 
var d = this.getCoords_(dx, dy);  
 
var w2 = sw / 2;  
var h2 = sh / 2;  
 
var vmlStr = [];  
 
var W = 10;  
var H = 10;  
 
// For some reason that I've now forgotten, using divs didn't work  
vmlStr.push(' <g_vml_:group',  
' coordsize="', Z * W, ',', Z * H, '"',  
' coordorigin="0,0"' ,  
' style="width:', W, 'px;height:', H, 'px;position:absolute;');  
 
// If filters are necessary (rotation exists), create them  
// filters are bog-slow, so only create them if abbsolutely necessary  
// The following check doesn't account for skews (which don't exist  
// in the canvas spec (yet) anyway.  
 
if (this.m_[0][0] != 1 || this.m_[0][1]) {  
var filter = [];  
 
// Note the 12/21 reversal  
filter.push('M11=', this.m_[0][0], ',',  
'M12=', this.m_[1][0], ',',  
'M21=', this.m_[0][1], ',',  
'M22=', this.m_[1][1], ',',  
'Dx=', mr(d.x / Z), ',',  
'Dy=', mr(d.y / Z), '');  
 
// Bounding box calculation (need to minimize displayed area so that  
// filters don't waste time on unused pixels.  
var max = d;  
var c2 = this.getCoords_(dx + dw, dy);  
var c3 = this.getCoords_(dx, dy + dh);  
var c4 = this.getCoords_(dx + dw, dy + dh);  
 
max.x = m.max(max.x, c2.x, c3.x, c4.x);  
max.y = m.max(max.y, c2.y, c3.y, c4.y);  
 
vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),  
'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',  
filter.join(''), ", sizingmethod='clip');")  
} else {  
vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');  
}  
 
vmlStr.push(' ">' ,  
'<g_vml_:image src="', image.src, '"',  
' style="width:', Z * dw, 'px;',  
' height:', Z * dh, 'px;"',  
' cropleft="', sx / w, '"',  
' croptop="', sy / h, '"',  
' cropright="', (w - sx - sw) / w, '"',  
' cropbottom="', (h - sy - sh) / h, '"',  
' />',  
'</g_vml_:group>');  
 
this.element_.insertAdjacentHTML('BeforeEnd',  
vmlStr.join(''));  
};  
 
contextPrototype.stroke = function(aFill) {  
var lineStr = [];  
var lineOpen = false;  
var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);  
var color = a.color;  
var opacity = a.alpha * this.globalAlpha;  
 
var W = 10;  
var H = 10;  
 
lineStr.push('<g_vml_:shape',  
' filled="', !!aFill, '"',  
' style="position:absolute;width:', W, 'px;height:', H, 'px;"',  
' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',  
' stroked="', !aFill, '"',  
' path="');  
 
var newSeq = false;  
var min = {x: null, y: null};  
var max = {x: null, y: null};  
 
for (var i = 0; i < this.currentPath_.length; i++) {  
var p = this.currentPath_[i];  
var c;  
 
switch (p.type) {  
case 'moveTo':  
c = p;  
lineStr.push(' m ', mr(p.x), ',', mr(p.y));  
break;  
case 'lineTo':  
lineStr.push(' l ', mr(p.x), ',', mr(p.y));  
break;  
case 'close':  
lineStr.push(' x ');  
p = null;  
break;  
case 'bezierCurveTo':  
lineStr.push(' c ',  
mr(p.cp1x), ',', mr(p.cp1y), ',',  
mr(p.cp2x), ',', mr(p.cp2y), ',',  
mr(p.x), ',', mr(p.y));  
break;  
case 'at':  
case 'wa':  
lineStr.push(' ', p.type, ' ',  
mr(p.x - this.arcScaleX_ * p.radius), ',',  
mr(p.y - this.arcScaleY_ * p.radius), ' ',  
mr(p.x + this.arcScaleX_ * p.radius), ',',  
mr(p.y + this.arcScaleY_ * p.radius), ' ',  
mr(p.xStart), ',', mr(p.yStart), ' ',  
mr(p.xEnd), ',', mr(p.yEnd));  
break;  
}  
 
 
// TODO: Following is broken for curves due to  
// move to proper paths.  
 
// Figure out dimensions so we can do gradient fills  
// properly  
if (p) {  
if (min.x == null || p.x < min.x) {  
min.x = p.x;  
}  
if (max.x == null || p.x > max.x) {  
max.x = p.x;  
}  
if (min.y == null || p.y < min.y) {  
min.y = p.y;  
}  
if (max.y == null || p.y > max.y) {  
max.y = p.y;  
}  
}  
}  
lineStr.push(' ">');  
 
if (!aFill) {  
var lineWidth = this.lineScale_ * this.lineWidth;  
 
// VML cannot correctly render a line if the width is less than 1px.  
// In that case, we dilute the color to make the line look thinner.  
if (lineWidth < 1) {  
opacity *= lineWidth;  
}  
 
lineStr.push(  
'<g_vml_:stroke',  
' opacity="', opacity, '"',  
' joinstyle="', this.lineJoin, '"',  
' miterlimit="', this.miterLimit, '"',  
' endcap="', processLineCap(this.lineCap), '"',  
' weight="', lineWidth, 'px"',  
' color="', color, '" />'  
);  
} else if (typeof this.fillStyle == 'object') {  
var fillStyle = this.fillStyle;  
var angle = 0;  
var focus = {x: 0, y: 0};  
 
// additional offset  
var shift = 0;  
// scale factor for offset  
var expansion = 1;  
 
if (fillStyle.type_ == 'gradient') {  
var x0 = fillStyle.x0_ / this.arcScaleX_;  
var y0 = fillStyle.y0_ / this.arcScaleY_;  
var x1 = fillStyle.x1_ / this.arcScaleX_;  
var y1 = fillStyle.y1_ / this.arcScaleY_;  
var p0 = this.getCoords_(x0, y0);  
var p1 = this.getCoords_(x1, y1);  
var dx = p1.x - p0.x;  
var dy = p1.y - p0.y;  
angle = Math.atan2(dx, dy) * 180 / Math.PI;  
 
// The angle should be a non-negative number.  
if (angle < 0) {  
angle += 360;  
}  
 
// Very small angles produce an unexpected result because they are  
// converted to a scientific notation string.  
if (angle < 1e-6) {  
angle = 0;  
}  
} else {  
var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_);  
var width = max.x - min.x;  
var height = max.y - min.y;  
focus = {  
x: (p0.x - min.x) / width,  
y: (p0.y - min.y) / height  
};  
 
width /= this.arcScaleX_ * Z;  
height /= this.arcScaleY_ * Z;  
var dimension = m.max(width, height);  
shift = 2 * fillStyle.r0_ / dimension;  
expansion = 2 * fillStyle.r1_ / dimension - shift;  
}  
 
// We need to sort the color stops in ascending order by offset,  
// otherwise IE won't interpret it correctly.  
var stops = fillStyle.colors_;  
stops.sort(function(cs1, cs2) {  
return cs1.offset - cs2.offset;  
});  
 
var length = stops.length;  
var color1 = stops[0].color;  
var color2 = stops[length - 1].color;  
var opacity1 = stops[0].alpha * this.globalAlpha;  
var opacity2 = stops[length - 1].alpha * this.globalAlpha;  
 
var colors = [];  
for (var i = 0; i < length; i++) {  
var stop = stops[i];  
colors.push(stop.offset * expansion + shift + ' ' + stop.color);  
}  
 
// When colors attribute is used, the meanings of opacity and o:opacity2  
// are reversed.  
lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"',  
' method="none" focus="100%"',  
' color="', color1, '"',  
' color2="', color2, '"',  
' colors="', colors.join(','), '"',  
' opacity="', opacity2, '"',  
' g_o_:opacity2="', opacity1, '"',  
' angle="', angle, '"',  
' focusposition="', focus.x, ',', focus.y, '" />');  
} else {  
lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity,  
'" />');  
}  
 
lineStr.push('</g_vml_:shape>');  
 
this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));  
};  
 
contextPrototype.fill = function() {  
this.stroke(true);  
}  
 
contextPrototype.closePath = function() {  
this.currentPath_.push({type: 'close'});  
};  
 
/**  
* @private  
*/  
contextPrototype.getCoords_ = function(aX, aY) {  
var m = this.m_;  
return {  
x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,  
y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2  
}  
};  
 
contextPrototype.save = function() {  
var o = {};  
copyState(this, o);  
this.aStack_.push(o);  
this.mStack_.push(this.m_);  
this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);  
};  
 
contextPrototype.restore = function() {  
copyState(this.aStack_.pop(), this);  
this.m_ = this.mStack_.pop();  
};  
 
contextPrototype.translate = function(aX, aY) {  
var m1 = [  
[1, 0, 0],  
[0, 1, 0],  
[aX, aY, 1]  
];  
 
this.m_ = matrixMultiply(m1, this.m_);  
};  
 
contextPrototype.rotate = function(aRot) {  
var c = mc(aRot);  
var s = ms(aRot);  
 
var m1 = [  
[c, s, 0],  
[-s, c, 0],  
[0, 0, 1]  
];  
 
this.m_ = matrixMultiply(m1, this.m_);  
};  
 
contextPrototype.scale = function(aX, aY) {  
this.arcScaleX_ *= aX;  
this.arcScaleY_ *= aY;  
var m1 = [  
[aX, 0, 0],  
[0, aY, 0],  
[0, 0, 1]  
];  
 
var m = this.m_ = matrixMultiply(m1, this.m_);  
 
// Get the line scale.  
// Determinant of this.m_ means how much the area is enlarged by the  
// transformation. So its square root can be used as a scale factor  
// for width.  
var det = m[0][0] * m[1][1] - m[0][1] * m[1][0];  
this.lineScale_ = sqrt(abs(det));  
};  
 
/******** STUBS ********/  
contextPrototype.clip = function() {  
// TODO: Implement  
};  
 
contextPrototype.arcTo = function() {  
// TODO: Implement  
};  
 
contextPrototype.createPattern = function() {  
return new CanvasPattern_;  
};  
 
// Gradient / Pattern Stubs  
function CanvasGradient_(aType) {  
this.type_ = aType;  
this.x0_ = 0;  
this.y0_ = 0;  
this.r0_ = 0;  
this.x1_ = 0;  
this.y1_ = 0;  
this.r1_ = 0;  
this.colors_ = [];  
}  
 
CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {  
aColor = processStyle(aColor);  
this.colors_.push({offset: aOffset,  
color: aColor.color,  
alpha: aColor.alpha});  
};  
 
function CanvasPattern_() {}  
 
// set up externs  
G_vmlCanvasManager = G_vmlCanvasManager_;  
CanvasRenderingContext2D = CanvasRenderingContext2D_;  
CanvasGradient = CanvasGradient_;  
CanvasPattern = CanvasPattern_;  
 
})();  
 
} // if  
 
/* Prototype JavaScript framework, version 1.6.0.2  
* (c) 2005-2008 Sam Stephenson  
*  
* Prototype is freely distributable under the terms of an MIT-style license.  
* For details, see the Prototype web site: http://www.prototypejs.org/  
*  
*--------------------------------------------------------------------------*/  
 
var Prototype = {  
Version: '1.6.0.2',  
 
Browser: {  
IE: !!(window.attachEvent && !window.opera),  
Opera: !!window.opera,  
WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,  
Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,  
MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)  
},  
 
BrowserFeatures: {  
XPath: !!document.evaluate,  
ElementExtensions: !!window.HTMLElement,  
SpecificElementExtensions:  
document.createElement('div').__proto__ &&  
document.createElement('div').__proto__ !==  
document.createElement('form').__proto__  
},  
 
ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',  
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,  
 
emptyFunction: function() { },  
K: function(x) { return x }  
};  
 
if (Prototype.Browser.MobileSafari)  
Prototype.BrowserFeatures.SpecificElementExtensions = false;  
 
 
/* Based on Alex Arnell's inheritance implementation. */  
var Class = {  
create: function() {  
var parent = null, properties = $A(arguments);  
if (Object.isFunction(properties[0]))  
parent = properties.shift();  
 
function klass() {  
this.initialize.apply(this, arguments);  
}  
 
Object.extend(klass, Class.Methods);  
klass.superclass = parent;  
klass.subclasses = [];  
 
if (parent) {  
var subclass = function() { };  
subclass.prototype = parent.prototype;  
klass.prototype = new subclass;  
parent.subclasses.push(klass);  
}  
 
for (var i = 0; i < properties.length; i++)  
klass.addMethods(properties[i]);  
 
if (!klass.prototype.initialize)  
klass.prototype.initialize = Prototype.emptyFunction;  
 
klass.prototype.constructor = klass;  
 
return klass;  
}  
};  
 
Class.Methods = {  
addMethods: function(source) {  
var ancestor = this.superclass && this.superclass.prototype;  
var properties = Object.keys(source);  
 
if (!Object.keys({ toString: true }).length)  
properties.push("toString", "valueOf");  
 
for (var i = 0, length = properties.length; i < length; i++) {  
var property = properties[i], value = source[property];  
if (ancestor && Object.isFunction(value) &&  
value.argumentNames().first() == "$super") {  
var method = value, value = Object.extend((function(m) {  
return function() { return ancestor[m].apply(this, arguments) };  
})(property).wrap(method), {  
valueOf: function() { return method },  
toString: function() { return method.toString() }  
});  
}  
this.prototype[property] = value;  
}  
 
return this;  
}  
};  
 
var Abstract = { };  
 
Object.extend = function(destination, source) {  
for (var property in source)  
destination[property] = source[property];  
return destination;  
};  
 
Object.extend(Object, {  
inspect: function(object) {  
try {  
if (Object.isUndefined(object)) return 'undefined';  
if (object === null) return 'null';  
return object.inspect ? object.inspect() : String(object);  
} catch (e) {  
if (e instanceof RangeError) return '...';  
throw e;  
}  
},  
 
toJSON: function(object) {  
var type = typeof object;  
switch (type) {  
case 'undefined':  
case 'function':  
case 'unknown': return;  
case 'boolean': return object.toString();  
}  
 
if (object === null) return 'null';  
if (object.toJSON) return object.toJSON();  
if (Object.isElement(object)) return;  
 
var results = [];  
for (var property in object) {  
var value = Object.toJSON(object[property]);  
if (!Object.isUndefined(value))  
results.push(property.toJSON() + ': ' + value);  
}  
 
return '{' + results.join(', ') + '}';  
},  
 
toQueryString: function(object) {  
return $H(object).toQueryString();  
},  
 
toHTML: function(object) {  
return object && object.toHTML ? object.toHTML() : String.interpret(object);  
},  
 
keys: function(object) {  
var keys = [];  
for (var property in object)  
keys.push(property);  
return keys;  
},  
 
values: function(object) {  
var values = [];  
for (var property in object)  
values.push(object[property]);  
return values;  
},  
 
clone: function(object) {  
return Object.extend({ }, object);  
},  
 
isElement: function(object) {  
return object && object.nodeType == 1;  
},  
 
isArray: function(object) {  
return object != null && typeof object == "object" &&  
'splice' in object && 'join' in object;  
},  
 
isHash: function(object) {  
return object instanceof Hash;  
},  
 
isFunction: function(object) {  
return typeof object == "function";  
},  
 
isString: function(object) {  
return typeof object == "string";  
},  
 
isNumber: function(object) {  
return typeof object == "number";  
},  
 
isUndefined: function(object) {  
return typeof object == "undefined";  
}  
});  
 
Object.extend(Function.prototype, {  
argumentNames: function() {  
var names = this.toString().match(/^[\s\(]*function[^(]*\((.*?)\)/)[1].split(",").invoke("strip");  
return names.length == 1 && !names[0] ? [] : names;  
},  
 
bind: function() {  
if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;  
var __method = this, args = $A(arguments), object = args.shift();  
return function() {  
return __method.apply(object, args.concat($A(arguments)));  
}  
},  
 
bindAsEventListener: function() {  
var __method = this, args = $A(arguments), object = args.shift();  
return function(event) {  
return __method.apply(object, [event || window.event].concat(args));  
}  
},  
 
curry: function() {  
if (!arguments.length) return this;  
var __method = this, args = $A(arguments);  
return function() {  
return __method.apply(this, args.concat($A(arguments)));  
}  
},  
 
delay: function() {  
var __method = this, args = $A(arguments), timeout = args.shift() * 1000;  
return window.setTimeout(function() {  
return __method.apply(__method, args);  
}, timeout);  
},  
 
wrap: function(wrapper) {  
var __method = this;  
return function() {  
return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));  
}  
},  
 
methodize: function() {  
if (this._methodized) return this._methodized;  
var __method = this;  
return this._methodized = function() {  
return __method.apply(null, [this].concat($A(arguments)));  
};  
}  
});  
 
Function.prototype.defer = Function.prototype.delay.curry(0.01);  
 
Date.prototype.toJSON = function() {  
return '"' + this.getUTCFullYear() + '-' +  
(this.getUTCMonth() + 1).toPaddedString(2) + '-' +  
this.getUTCDate().toPaddedString(2) + 'T' +  
this.getUTCHours().toPaddedString(2) + ':' +  
this.getUTCMinutes().toPaddedString(2) + ':' +  
this.getUTCSeconds().toPaddedString(2) + 'Z"';  
};  
 
var Try = {  
these: function() {  
var returnValue;  
 
for (var i = 0, length = arguments.length; i < length; i++) {  
var lambda = arguments[i];  
try {  
returnValue = lambda();  
break;  
} catch (e) { }  
}  
 
return returnValue;  
}  
};  
 
RegExp.prototype.match = RegExp.prototype.test;  
 
RegExp.escape = function(str) {  
return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');  
};  
 
/*--------------------------------------------------------------------------*/  
 
var PeriodicalExecuter = Class.create({  
initialize: function(callback, frequency) {  
this.callback = callback;  
this.frequency = frequency;  
this.currentlyExecuting = false;  
 
this.registerCallback();  
},  
 
registerCallback: function() {  
this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);  
},  
 
execute: function() {  
this.callback(this);  
},  
 
stop: function() {  
if (!this.timer) return;  
clearInterval(this.timer);  
this.timer = null;  
},  
 
onTimerEvent: function() {  
if (!this.currentlyExecuting) {  
try {  
this.currentlyExecuting = true;  
this.execute();  
} finally {  
this.currentlyExecuting = false;  
}  
}  
}  
});  
Object.extend(String, {  
interpret: function(value) {  
return value == null ? '' : String(value);  
},  
specialChar: {  
'\b': '\\b',  
'\t': '\\t',  
'\n': '\\n',  
'\f': '\\f',  
'\r': '\\r',  
'\\': '\\\\'  
}  
});  
 
Object.extend(String.prototype, {  
gsub: function(pattern, replacement) {  
var result = '', source = this, match;  
replacement = arguments.callee.prepareReplacement(replacement);  
 
while (source.length > 0) {  
if (match = source.match(pattern)) {  
result += source.slice(0, match.index);  
result += String.interpret(replacement(match));  
source = source.slice(match.index + match[0].length);  
} else {  
result += source, source = '';  
}  
}  
return result;  
},  
 
sub: function(pattern, replacement, count) {  
replacement = this.gsub.prepareReplacement(replacement);  
count = Object.isUndefined(count) ? 1 : count;  
 
return this.gsub(pattern, function(match) {  
if (--count < 0) return match[0];  
return replacement(match);  
});  
},  
 
scan: function(pattern, iterator) {  
this.gsub(pattern, iterator);  
return String(this);  
},  
 
truncate: function(length, truncation) {  
length = length || 30;  
truncation = Object.isUndefined(truncation) ? '...' : truncation;  
return this.length > length ?  
this.slice(0, length - truncation.length) + truncation : String(this);  
},  
 
strip: function() {  
return this.replace(/^\s+/, '').replace(/\s+$/, '');  
},  
 
stripTags: function() {  
return this.replace(/<\/?[^>]+>/gi, '');  
},  
 
stripScripts: function() {  
return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');  
},  
 
extractScripts: function() {  
var matchAll = new RegExp(Prototype.ScriptFragment, 'img');  
var matchOne = new RegExp(Prototype.ScriptFragment, 'im');  
return (this.match(matchAll) || []).map(function(scriptTag) {  
return (scriptTag.match(matchOne) || ['', ''])[1];  
});  
},  
 
evalScripts: function() {  
return this.extractScripts().map(function(script) { return eval(script) });  
},  
 
escapeHTML: function() {  
var self = arguments.callee;  
self.text.data = this;  
return self.div.innerHTML;  
},  
 
unescapeHTML: function() {  
var div = new Element('div');  
div.innerHTML = this.stripTags();  
return div.childNodes[0] ? (div.childNodes.length > 1 ?  
$A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :  
div.childNodes[0].nodeValue) : '';  
},  
 
toQueryParams: function(separator) {  
var match = this.strip().match(/([^?#]*)(#.*)?$/);  
if (!match) return { };  
 
return match[1].split(separator || '&').inject({ }, function(hash, pair) {  
if ((pair = pair.split('='))[0]) {  
var key = decodeURIComponent(pair.shift());  
var value = pair.length > 1 ? pair.join('=') : pair[0];  
if (value != undefined) value = decodeURIComponent(value);  
 
if (key in hash) {  
if (!Object.isArray(hash[key])) hash[key] = [hash[key]];  
hash[key].push(value);  
}  
else hash[key] = value;  
}  
return hash;  
});  
},  
 
toArray: function() {  
return this.split('');  
},  
 
succ: function() {  
return this.slice(0, this.length - 1) +  
String.fromCharCode(this.charCodeAt(this.length - 1) + 1);  
},  
 
times: function(count) {  
return count < 1 ? '' : new Array(count + 1).join(this);  
},  
 
camelize: function() {  
var parts = this.split('-'), len = parts.length;  
if (len == 1) return parts[0];  
 
var camelized = this.charAt(0) == '-'  
? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)  
: parts[0];  
 
for (var i = 1; i < len; i++)  
camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);  
 
return camelized;  
},  
 
capitalize: function() {  
return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();  
},  
 
underscore: function() {  
return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();  
},  
 
dasherize: function() {  
return this.gsub(/_/,'-');  
},  
 
inspect: function(useDoubleQuotes) {  
var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {  
var character = String.specialChar[match[0]];  
return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);  
});  
if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';  
return "'" + escapedString.replace(/'/g, '\\\'') + "'";  
},  
 
toJSON: function() {  
return this.inspect(true);  
},  
 
unfilterJSON: function(filter) {  
return this.sub(filter || Prototype.JSONFilter, '#{1}');  
},  
 
isJSON: function() {  
var str = this;  
if (str.blank()) return false;  
str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');  
return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);  
},  
 
evalJSON: function(sanitize) {  
var json = this.unfilterJSON();  
try {  
if (!sanitize || json.isJSON()) return eval('(' + json + ')');  
} catch (e) { }  
throw new SyntaxError('Badly formed JSON string: ' + this.inspect());  
},  
 
include: function(pattern) {  
return this.indexOf(pattern) > -1;  
},  
 
startsWith: function(pattern) {  
return this.indexOf(pattern) === 0;  
},  
 
endsWith: function(pattern) {  
var d = this.length - pattern.length;  
return d >= 0 && this.lastIndexOf(pattern) === d;  
},  
 
empty: function() {  
return this == '';  
},  
 
blank: function() {  
return /^\s*$/.test(this);  
},  
 
interpolate: function(object, pattern) {  
return new Template(this, pattern).evaluate(object);  
}  
});  
 
if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {  
escapeHTML: function() {  
return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');  
},  
unescapeHTML: function() {  
return this.replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');  
}  
});  
 
String.prototype.gsub.prepareReplacement = function(replacement) {  
if (Object.isFunction(replacement)) return replacement;  
var template = new Template(replacement);  
return function(match) { return template.evaluate(match) };  
};  
 
String.prototype.parseQuery = String.prototype.toQueryParams;  
 
Object.extend(String.prototype.escapeHTML, {  
div: document.createElement('div'),  
text: document.createTextNode('')  
});  
 
with (String.prototype.escapeHTML) div.appendChild(text);  
 
var Template = Class.create({  
initialize: function(template, pattern) {  
this.template = template.toString();  
this.pattern = pattern || Template.Pattern;  
},  
 
evaluate: function(object) {  
if (Object.isFunction(object.toTemplateReplacements))  
object = object.toTemplateReplacements();  
 
return this.template.gsub(this.pattern, function(match) {  
if (object == null) return '';  
 
var before = match[1] || '';  
if (before == '\\') return match[2];  
 
var ctx = object, expr = match[3];  
var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;  
match = pattern.exec(expr);  
if (match == null) return before;  
 
while (match != null) {  
var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];  
ctx = ctx[comp];  
if (null == ctx || '' == match[3]) break;  
expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);  
match = pattern.exec(expr);  
}  
 
return before + String.interpret(ctx);  
});  
}  
});  
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;  
 
var $break = { };  
 
var Enumerable = {  
each: function(iterator, context) {  
var index = 0;  
iterator = iterator.bind(context);  
try {  
this._each(function(value) {  
iterator(value, index++);  
});  
} catch (e) {  
if (e != $break) throw e;  
}  
return this;  
},  
 
eachSlice: function(number, iterator, context) {  
iterator = iterator ? iterator.bind(context) : Prototype.K;  
var index = -number, slices = [], array = this.toArray();  
while ((index += number) < array.length)  
slices.push(array.slice(index, index+number));  
return slices.collect(iterator, context);  
},  
 
all: function(iterator, context) {  
iterator = iterator ? iterator.bind(context) : Prototype.K;  
var result = true;  
this.each(function(value, index) {  
result = result && !!iterator(value, index);  
if (!result) throw $break;  
});  
return result;  
},  
 
any: function(iterator, context) {  
iterator = iterator ? iterator.bind(context) : Prototype.K;  
var result = false;  
this.each(function(value, index) {  
if (result = !!iterator(value, index))  
throw $break;  
});  
return result;  
},  
 
collect: function(iterator, context) {  
iterator = iterator ? iterator.bind(context) : Prototype.K;  
var results = [];  
this.each(function(value, index) {  
results.push(iterator(value, index));  
});  
return results;  
},  
 
detect: function(iterator, context) {  
iterator = iterator.bind(context);  
var result;  
this.each(function(value, index) {  
if (iterator(value, index)) {  
result = value;  
throw $break;  
}  
});  
return result;  
},  
 
findAll: function(iterator, context) {  
iterator = iterator.bind(context);  
var results = [];  
this.each(function(value, index) {  
if (iterator(value, index))  
results.push(value);  
});  
return results;  
},  
 
grep: function(filter, iterator, context) {  
iterator = iterator ? iterator.bind(context) : Prototype.K;  
var results = [];  
 
if (Object.isString(filter))  
filter = new RegExp(filter);  
 
this.each(function(value, index) {  
if (filter.match(value))  
results.push(iterator(value, index));  
});  
return results;  
},  
 
include: function(object) {  
if (Object.isFunction(this.indexOf))  
if (this.indexOf(object) != -1) return true;  
 
var found = false;  
this.each(function(value) {  
if (value == object) {  
found = true;  
throw $break;  
}  
});  
return found;  
},  
 
inGroupsOf: function(number, fillWith) {  
fillWith = Object.isUndefined(fillWith) ? null : fillWith;  
return this.eachSlice(number, function(slice) {  
while(slice.length < number) slice.push(fillWith);  
return slice;  
});  
},  
 
inject: function(memo, iterator, context) {  
iterator = iterator.bind(context);  
this.each(function(value, index) {  
memo = iterator(memo, value, index);  
});  
return memo;  
},  
 
invoke: function(method) {  
var args = $A(arguments).slice(1);  
return this.map(function(value) {  
return value[method].apply(value, args);  
});  
},  
 
max: function(iterator, context) {  
iterator = iterator ? iterator.bind(context) : Prototype.K;  
var result;  
this.each(function(value, index) {  
value = iterator(value, index);  
if (result == null || value >= result)  
result = value;  
});  
return result;  
},  
 
min: function(iterator, context) {  
iterator = iterator ? iterator.bind(context) : Prototype.K;  
var result;  
this.each(function(value, index) {  
value = iterator(value, index);  
if (result == null || value < result)  
result = value;  
});  
return result;  
},  
 
partition: function(iterator, context) {  
iterator = iterator ? iterator.bind(context) : Prototype.K;  
var trues = [], falses = [];  
this.each(function(value, index) {  
(iterator(value, index) ?  
trues : falses).push(value);  
});  
return [trues, falses];  
},  
 
pluck: function(property) {  
var results = [];  
this.each(function(value) {  
results.push(value[property]);  
});  
return results;  
},  
 
reject: function(iterator, context) {  
iterator = iterator.bind(context);  
var results = [];  
this.each(function(value, index) {  
if (!iterator(value, index))  
results.push(value);  
});  
return results;  
},  
 
sortBy: function(iterator, context) {  
iterator = iterator.bind(context);  
return this.map(function(value, index) {  
return {value: value, criteria: iterator(value, index)};  
}).sort(function(left, right) {  
var a = left.criteria, b = right.criteria;  
return a < b ? -1 : a > b ? 1 : 0;  
}).pluck('value');  
},  
 
toArray: function() {  
return this.map();  
},  
 
zip: function() {  
var iterator = Prototype.K, args = $A(arguments);  
if (Object.isFunction(args.last()))  
iterator = args.pop();  
 
var collections = [this].concat(args).map($A);  
return this.map(function(value, index) {  
return iterator(collections.pluck(index));  
});  
},  
 
size: function() {  
return this.toArray().length;  
},  
 
inspect: function() {  
return '#<Enumerable:' + this.toArray().inspect() + '>';  
}  
};  
 
Object.extend(Enumerable, {  
map: Enumerable.collect,  
find: Enumerable.detect,  
select: Enumerable.findAll,  
filter: Enumerable.findAll,  
member: Enumerable.include,  
entries: Enumerable.toArray,  
every: Enumerable.all,  
some: Enumerable.any  
});  
function $A(iterable) {  
if (!iterable) return [];  
if (iterable.toArray) return iterable.toArray();  
var length = iterable.length || 0, results = new Array(length);  
while (length--) results[length] = iterable[length];  
return results;  
}  
 
if (Prototype.Browser.WebKit) {  
$A = function(iterable) {  
if (!iterable) return [];  
if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&  
iterable.toArray) return iterable.toArray();  
var length = iterable.length || 0, results = new Array(length);  
while (length--) results[length] = iterable[length];  
return results;  
};  
}  
 
Array.from = $A;  
 
Object.extend(Array.prototype, Enumerable);  
 
if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;  
 
Object.extend(Array.prototype, {  
_each: function(iterator) {  
for (var i = 0, length = this.length; i < length; i++)  
iterator(this[i]);  
},  
 
clear: function() {  
this.length = 0;  
return this;  
},  
 
first: function() {  
return this[0];  
},  
 
last: function() {  
return this[this.length - 1];  
},  
 
compact: function() {  
return this.select(function(value) {  
return value != null;  
});  
},  
 
flatten: function() {  
return this.inject([], function(array, value) {  
return array.concat(Object.isArray(value) ?  
value.flatten() : [value]);  
});  
},  
 
without: function() {  
var values = $A(arguments);  
return this.select(function(value) {  
return !values.include(value);  
});  
},  
 
reverse: function(inline) {  
return (inline !== false ? this : this.toArray())._reverse();  
},  
 
reduce: function() {  
return this.length > 1 ? this : this[0];  
},  
 
uniq: function(sorted) {  
return this.inject([], function(array, value, index) {  
if (0 == index || (sorted ? array.last() != value : !array.include(value)))  
array.push(value);  
return array;  
});  
},  
 
intersect: function(array) {  
return this.uniq().findAll(function(item) {  
return array.detect(function(value) { return item === value });  
});  
},  
 
clone: function() {  
return [].concat(this);  
},  
 
size: function() {  
return this.length;  
},  
 
inspect: function() {  
return '[' + this.map(Object.inspect).join(', ') + ']';  
},  
 
toJSON: function() {  
var results = [];  
this.each(function(object) {  
var value = Object.toJSON(object);  
if (!Object.isUndefined(value)) results.push(value);  
});  
return '[' + results.join(', ') + ']';  
}  
});  
 
// use native browser JS 1.6 implementation if available  
if (Object.isFunction(Array.prototype.forEach))  
Array.prototype._each = Array.prototype.forEach;  
 
if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {  
i || (i = 0);  
var length = this.length;  
if (i < 0) i = length + i;  
for (; i < length; i++)  
if (this[i] === item) return i;  
return -1;  
};  
 
if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {  
i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;  
var n = this.slice(0, i).reverse().indexOf(item);  
return (n < 0) ? n : i - n - 1;  
};  
 
Array.prototype.toArray = Array.prototype.clone;  
 
function $w(string) {  
if (!Object.isString(string)) return [];  
string = string.strip();  
return string ? string.split(/\s+/) : [];  
}  
 
if (Prototype.Browser.Opera){  
Array.prototype.concat = function() {  
var array = [];  
for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);  
for (var i = 0, length = arguments.length; i < length; i++) {  
if (Object.isArray(arguments[i])) {  
for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)  
array.push(arguments[i][j]);  
} else {  
array.push(arguments[i]);  
}  
}  
return array;  
};  
}  
Object.extend(Number.prototype, {  
toColorPart: function() {  
return this.toPaddedString(2, 16);  
},  
 
succ: function() {  
return this + 1;  
},  
 
times: function(iterator) {  
$R(0, this, true).each(iterator);  
return this;  
},  
 
toPaddedString: function(length, radix) {  
var string = this.toString(radix || 10);  
return '0'.times(length - string.length) + string;  
},  
 
toJSON: function() {  
return isFinite(this) ? this.toString() : 'null';  
}  
});  
 
$w('abs round ceil floor').each(function(method){  
Number.prototype[method] = Math[method].methodize();  
});  
function $H(object) {  
return new Hash(object);  
};  
 
var Hash = Class.create(Enumerable, (function() {  
 
function toQueryPair(key, value) {  
if (Object.isUndefined(value)) return key;  
return key + '=' + encodeURIComponent(String.interpret(value));  
}  
 
return {  
initialize: function(object) {  
this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);  
},  
 
_each: function(iterator) {  
for (var key in this._object) {  
var value = this._object[key], pair = [key, value];  
pair.key = key;  
pair.value = value;  
iterator(pair);  
}  
},  
 
set: function(key, value) {  
return this._object[key] = value;  
},  
 
get: function(key) {  
return this._object[key];  
},  
 
unset: function(key) {  
var value = this._object[key];  
delete this._object[key];  
return value;  
},  
 
toObject: function() {  
return Object.clone(this._object);  
},  
 
keys: function() {  
return this.pluck('key');  
},  
 
values: function() {  
return this.pluck('value');  
},  
 
index: function(value) {  
var match = this.detect(function(pair) {  
return pair.value === value;  
});  
return match && match.key;  
},  
 
merge: function(object) {  
return this.clone().update(object);  
},  
 
update: function(object) {  
return new Hash(object).inject(this, function(result, pair) {  
result.set(pair.key, pair.value);  
return result;  
});  
},  
 
toQueryString: function() {  
return this.map(function(pair) {  
var key = encodeURIComponent(pair.key), values = pair.value;  
 
if (values && typeof values == 'object') {  
if (Object.isArray(values))  
return values.map(toQueryPair.curry(key)).join('&');  
}  
return toQueryPair(key, values);  
}).join('&');  
},  
 
inspect: function() {  
return '#<Hash:{' + this.map(function(pair) {  
return pair.map(Object.inspect).join(': ');  
}).join(', ') + '}>';  
},  
 
toJSON: function() {  
return Object.toJSON(this.toObject());  
},  
 
clone: function() {  
return new Hash(this);  
}  
}  
})());  
 
Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;  
Hash.from = $H;  
var ObjectRange = Class.create(Enumerable, {  
initialize: function(start, end, exclusive) {  
this.start = start;  
this.end = end;  
this.exclusive = exclusive;  
},  
 
_each: function(iterator) {  
var value = this.start;  
while (this.include(value)) {  
iterator(value);  
value = value.succ();  
}  
},  
 
include: function(value) {  
if (value < this.start)  
return false;  
if (this.exclusive)  
return value < this.end;  
return value <= this.end;  
}  
});  
 
var $R = function(start, end, exclusive) {  
return new ObjectRange(start, end, exclusive);  
};  
 
var Ajax = {  
getTransport: function() {  
return Try.these(  
function() {return new XMLHttpRequest()},  
function() {return new ActiveXObject('Msxml2.XMLHTTP')},  
function() {return new ActiveXObject('Microsoft.XMLHTTP')}  
) || false;  
},  
 
activeRequestCount: 0  
};  
 
Ajax.Responders = {  
responders: [],  
 
_each: function(iterator) {  
this.responders._each(iterator);  
},  
 
register: function(responder) {  
if (!this.include(responder))  
this.responders.push(responder);  
},  
 
unregister: function(responder) {  
this.responders = this.responders.without(responder);  
},  
 
dispatch: function(callback, request, transport, json) {  
this.each(function(responder) {  
if (Object.isFunction(responder[callback])) {  
try {  
responder[callback].apply(responder, [request, transport, json]);  
} catch (e) { }  
}  
});  
}  
};  
 
Object.extend(Ajax.Responders, Enumerable);  
 
Ajax.Responders.register({  
onCreate: function() { Ajax.activeRequestCount++ },  
onComplete: function() { Ajax.activeRequestCount-- }  
});  
 
Ajax.Base = Class.create({  
initialize: function(options) {  
this.options = {  
method: 'post',  
asynchronous: true,  
contentType: 'application/x-www-form-urlencoded',  
encoding: 'UTF-8',  
parameters: '',  
evalJSON: true,  
evalJS: true  
};  
Object.extend(this.options, options || { });  
 
this.options.method = this.options.method.toLowerCase();  
 
if (Object.isString(this.options.parameters))  
this.options.parameters = this.options.parameters.toQueryParams();  
else if (Object.isHash(this.options.parameters))  
this.options.parameters = this.options.parameters.toObject();  
}  
});  
 
Ajax.Request = Class.create(Ajax.Base, {  
_complete: false,  
 
initialize: function($super, url, options) {  
$super(options);  
this.transport = Ajax.getTransport();  
this.request(url);  
},  
 
request: function(url) {  
this.url = url;  
this.method = this.options.method;  
var params = Object.clone(this.options.parameters);  
 
if (!['get', 'post'].include(this.method)) {  
// simulate other verbs over post  
params['_method'] = this.method;  
this.method = 'post';  
}  
 
this.parameters = params;  
 
if (params = Object.toQueryString(params)) {  
// when GET, append parameters to URL  
if (this.method == 'get')  
this.url += (this.url.include('?') ? '&' : '?') + params;  
else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))  
params += '&_=';  
}  
 
try {  
var response = new Ajax.Response(this);  
if (this.options.onCreate) this.options.onCreate(response);  
Ajax.Responders.dispatch('onCreate', this, response);  
 
this.transport.open(this.method.toUpperCase(), this.url,  
this.options.asynchronous);  
 
if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);  
 
this.transport.onreadystatechange = this.onStateChange.bind(this);  
this.setRequestHeaders();  
 
this.body = this.method == 'post' ? (this.options.postBody || params) : null;  
this.transport.send(this.body);  
 
/* Force Firefox to handle ready state 4 for synchronous requests */  
if (!this.options.asynchronous && this.transport.overrideMimeType)  
this.onStateChange();  
 
}  
catch (e) {  
this.dispatchException(e);  
}  
},  
 
onStateChange: function() {  
var readyState = this.transport.readyState;  
if (readyState > 1 && !((readyState == 4) && this._complete))  
this.respondToReadyState(this.transport.readyState);  
},  
 
setRequestHeaders: function() {  
var headers = {  
'X-Requested-With': 'XMLHttpRequest',  
'X-Prototype-Version': Prototype.Version,  
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'  
};  
 
if (this.method == 'post') {  
headers['Content-type'] = this.options.contentType +  
(this.options.encoding ? '; charset=' + this.options.encoding : '');  
 
/* Force "Connection: close" for older Mozilla browsers to work  
* around a bug where XMLHttpRequest sends an incorrect  
* Content-length header. See Mozilla Bugzilla #246651.  
*/  
if (this.transport.overrideMimeType &&  
(navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)  
headers['Connection'] = 'close';  
}  
 
// user-defined headers  
if (typeof this.options.requestHeaders == 'object') {  
var extras = this.options.requestHeaders;  
 
if (Object.isFunction(extras.push))  
for (var i = 0, length = extras.length; i < length; i += 2)  
headers[extras[i]] = extras[i+1];  
else  
$H(extras).each(function(pair) { headers[pair.key] = pair.value });  
}  
 
for (var name in headers)  
this.transport.setRequestHeader(name, headers[name]);  
},  
 
success: function() {  
var status = this.getStatus();  
return !status || (status >= 200 && status < 300);  
},  
 
getStatus: function() {  
try {  
return this.transport.status || 0;  
} catch (e) { return 0 }  
},  
 
respondToReadyState: function(readyState) {  
var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);  
 
if (state == 'Complete') {  
try {  
this._complete = true;  
(this.options['on' + response.status]  
|| this.options['on' + (this.success() ? 'Success' : 'Failure')]  
|| Prototype.emptyFunction)(response, response.headerJSON);  
} catch (e) {  
this.dispatchException(e);  
}  
 
var contentType = response.getHeader('Content-type');  
if (this.options.evalJS == 'force'  
|| (this.options.evalJS && this.isSameOrigin() && contentType  
&& contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))  
this.evalResponse();  
}  
 
try {  
(this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);  
Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);  
} catch (e) {  
this.dispatchException(e);  
}  
 
if (state == 'Complete') {  
// avoid memory leak in MSIE: clean up  
this.transport.onreadystatechange = Prototype.emptyFunction;  
}  
},  
 
isSameOrigin: function() {  
var m = this.url.match(/^\s*https?:\/\/[^\/]*/);  
return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({  
protocol: location.protocol,  
domain: document.domain,  
port: location.port ? ':' + location.port : ''  
}));  
},  
 
getHeader: function(name) {  
try {  
return this.transport.getResponseHeader(name) || null;  
} catch (e) { return null }  
},  
 
evalResponse: function() {  
try {  
return eval((this.transport.responseText || '').unfilterJSON());  
} catch (e) {  
this.dispatchException(e);  
}  
},  
 
dispatchException: function(exception) {  
(this.options.onException || Prototype.emptyFunction)(this, exception);  
Ajax.Responders.dispatch('onException', this, exception);  
}  
});  
 
Ajax.Request.Events =  
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];  
 
Ajax.Response = Class.create({  
initialize: function(request){  
this.request = request;  
var transport = this.transport = request.transport,  
readyState = this.readyState = transport.readyState;  
 
if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {  
this.status = this.getStatus();  
this.statusText = this.getStatusText();  
this.responseText = String.interpret(transport.responseText);  
this.headerJSON = this._getHeaderJSON();  
}  
 
if(readyState == 4) {  
var xml = transport.responseXML;  
this.responseXML = Object.isUndefined(xml) ? null : xml;  
this.responseJSON = this._getResponseJSON();  
}  
},  
 
status: 0,  
statusText: '',  
 
getStatus: Ajax.Request.prototype.getStatus,  
 
getStatusText: function() {  
try {  
return this.transport.statusText || '';  
} catch (e) { return '' }  
},  
 
getHeader: Ajax.Request.prototype.getHeader,  
 
getAllHeaders: function() {  
try {  
return this.getAllResponseHeaders();  
} catch (e) { return null }  
},  
 
getResponseHeader: function(name) {  
return this.transport.getResponseHeader(name);  
},  
 
getAllResponseHeaders: function() {  
return this.transport.getAllResponseHeaders();  
},  
 
_getHeaderJSON: function() {  
var json = this.getHeader('X-JSON');  
if (!json) return null;  
json = decodeURIComponent(escape(json));  
try {  
return json.evalJSON(this.request.options.sanitizeJSON ||  
!this.request.isSameOrigin());  
} catch (e) {  
this.request.dispatchException(e);  
}  
},  
 
_getResponseJSON: function() {  
var options = this.request.options;  
if (!options.evalJSON || (options.evalJSON != 'force' &&  
!(this.getHeader('Content-type') || '').include('application/json')) ||  
this.responseText.blank())  
return null;  
try {  
return this.responseText.evalJSON(options.sanitizeJSON ||  
!this.request.isSameOrigin());  
} catch (e) {  
this.request.dispatchException(e);  
}  
}  
});  
 
Ajax.Updater = Class.create(Ajax.Request, {  
initialize: function($super, container, url, options) {  
this.container = {  
success: (container.success || container),  
failure: (container.failure || (container.success ? null : container))  
};  
 
options = Object.clone(options);  
var onComplete = options.onComplete;  
options.onComplete = (function(response, json) {  
this.updateContent(response.responseText);  
if (Object.isFunction(onComplete)) onComplete(response, json);  
}).bind(this);  
 
$super(url, options);  
},  
 
updateContent: function(responseText) {  
var receiver = this.container[this.success() ? 'success' : 'failure'],  
options = this.options;  
 
if (!options.evalScripts) responseText = responseText.stripScripts();  
 
if (receiver = $(receiver)) {  
if (options.insertion) {  
if (Object.isString(options.insertion)) {  
var insertion = { }; insertion[options.insertion] = responseText;  
receiver.insert(insertion);  
}  
else options.insertion(receiver, responseText);  
}  
else receiver.update(responseText);  
}  
}  
});  
 
Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {  
initialize: function($super, container, url, options) {  
$super(options);  
this.onComplete = this.options.onComplete;  
 
this.frequency = (this.options.frequency || 2);  
this.decay = (this.options.decay || 1);  
 
this.updater = { };  
this.container = container;  
this.url = url;  
 
this.start();  
},  
 
start: function() {  
this.options.onComplete = this.updateComplete.bind(this);  
this.onTimerEvent();  
},  
 
stop: function() {  
this.updater.options.onComplete = undefined;  
clearTimeout(this.timer);  
(this.onComplete || Prototype.emptyFunction).apply(this, arguments);  
},  
 
updateComplete: function(response) {  
if (this.options.decay) {  
this.decay = (response.responseText == this.lastText ?  
this.decay * this.options.decay : 1);  
 
this.lastText = response.responseText;  
}  
this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);  
},  
 
onTimerEvent: function() {  
this.updater = new Ajax.Updater(this.container, this.url, this.options);  
}  
});  
function $(element) {  
if (arguments.length > 1) {  
for (var i = 0, elements = [], length = arguments.length; i < length; i++)  
elements.push($(arguments[i]));  
return elements;  
}  
if (Object.isString(element))  
element = document.getElementById(element);  
return Element.extend(element);  
}  
 
if (Prototype.BrowserFeatures.XPath) {  
document._getElementsByXPath = function(expression, parentElement) {  
var results = [];  
var query = document.evaluate(expression, $(parentElement) || document,  
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);  
for (var i = 0, length = query.snapshotLength; i < length; i++)  
results.push(Element.extend(query.snapshotItem(i)));  
return results;  
};  
}  
 
/*--------------------------------------------------------------------------*/  
 
if (!window.Node) var Node = { };  
 
if (!Node.ELEMENT_NODE) {  
// DOM level 2 ECMAScript Language Binding  
Object.extend(Node, {  
ELEMENT_NODE: 1,  
ATTRIBUTE_NODE: 2,  
TEXT_NODE: 3,  
CDATA_SECTION_NODE: 4,  
ENTITY_REFERENCE_NODE: 5,  
ENTITY_NODE: 6,  
PROCESSING_INSTRUCTION_NODE: 7,  
COMMENT_NODE: 8,  
DOCUMENT_NODE: 9,  
DOCUMENT_TYPE_NODE: 10,  
DOCUMENT_FRAGMENT_NODE: 11,  
NOTATION_NODE: 12  
});  
}  
 
(function() {  
var element = this.Element;  
this.Element = function(tagName, attributes) {  
attributes = attributes || { };  
tagName = tagName.toLowerCase();  
var cache = Element.cache;  
if (Prototype.Browser.IE && attributes.name) {  
tagName = '<' + tagName + ' name="' + attributes.name + '">';  
delete attributes.name;  
return Element.writeAttribute(document.createElement(tagName), attributes);  
}  
if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));  
return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);  
};  
Object.extend(this.Element, element || { });  
}).call(window);  
 
Element.cache = { };  
 
Element.Methods = {  
visible: function(element) {  
return $(element).style.display != 'none';  
},  
 
toggle: function(element) {  
element = $(element);  
Element[Element.visible(element) ? 'hide' : 'show'](element);  
return element;  
},  
 
hide: function(element) {  
$(element).style.display = 'none';  
return element;  
},  
 
show: function(element) {  
$(element).style.display = '';  
return element;  
},  
 
remove: function(element) {  
element = $(element);  
element.parentNode.removeChild(element);  
return element;  
},  
 
update: function(element, content) {  
element = $(element);  
if (content && content.toElement) content = content.toElement();  
if (Object.isElement(content)) return element.update().insert(content);  
content = Object.toHTML(content);  
element.innerHTML = content.stripScripts();  
content.evalScripts.bind(content).defer();  
return element;  
},  
 
replace: function(element, content) {  
element = $(element);  
if (content && content.toElement) content = content.toElement();  
else if (!Object.isElement(content)) {  
content = Object.toHTML(content);  
var range = element.ownerDocument.createRange();  
range.selectNode(element);  
content.evalScripts.bind(content).defer();  
content = range.createContextualFragment(content.stripScripts());  
}  
element.parentNode.replaceChild(content, element);  
return element;  
},  
 
insert: function(element, insertions) {  
element = $(element);  
 
if (Object.isString(insertions) || Object.isNumber(insertions) ||  
Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))  
insertions = {bottom:insertions};  
 
var content, insert, tagName, childNodes;  
 
for (var position in insertions) {  
content = insertions[position];  
position = position.toLowerCase();  
insert = Element._insertionTranslations[position];  
 
if (content && content.toElement) content = content.toElement();  
if (Object.isElement(content)) {  
insert(element, content);  
continue;  
}  
 
content = Object.toHTML(content);  
 
tagName = ((position == 'before' || position == 'after')  
? element.parentNode : element).tagName.toUpperCase();  
 
childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());  
 
if (position == 'top' || position == 'after') childNodes.reverse();  
childNodes.each(insert.curry(element));  
 
content.evalScripts.bind(content).defer();  
}  
 
return element;  
},  
 
wrap: function(element, wrapper, attributes) {  
element = $(element);  
if (Object.isElement(wrapper))  
$(wrapper).writeAttribute(attributes || { });  
else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);  
else wrapper = new Element('div', wrapper);  
if (element.parentNode)  
element.parentNode.replaceChild(wrapper, element);  
wrapper.appendChild(element);  
return wrapper;  
},  
 
inspect: function(element) {  
element = $(element);  
var result = '<' + element.tagName.toLowerCase();  
$H({'id': 'id', 'className': 'class'}).each(function(pair) {  
var property = pair.first(), attribute = pair.last();  
var value = (element[property] || '').toString();  
if (value) result += ' ' + attribute + '=' + value.inspect(true);  
});  
return result + '>';  
},  
 
recursivelyCollect: function(element, property) {  
element = $(element);  
var elements = [];  
while (element = element[property])  
if (element.nodeType == 1)  
elements.push(Element.extend(element));  
return elements;  
},  
 
ancestors: function(element) {  
return $(element).recursivelyCollect('parentNode');  
},  
 
descendants: function(element) {  
return $(element).select("*");  
},  
 
firstDescendant: function(element) {  
element = $(element).firstChild;  
while (element && element.nodeType != 1) element = element.nextSibling;  
return $(element);  
},  
 
immediateDescendants: function(element) {  
if (!(element = $(element).firstChild)) return [];  
while (element && element.nodeType != 1) element = element.nextSibling;  
if (element) return [element].concat($(element).nextSiblings());  
return [];  
},  
 
previousSiblings: function(element) {  
return $(element).recursivelyCollect('previousSibling');  
},  
 
nextSiblings: function(element) {  
return $(element).recursivelyCollect('nextSibling');  
},  
 
siblings: function(element) {  
element = $(element);  
return element.previousSiblings().reverse().concat(element.nextSiblings());  
},  
 
match: function(element, selector) {  
if (Object.isString(selector))  
selector = new Selector(selector);  
return selector.match($(element));  
},  
 
up: function(element, expression, index) {  
element = $(element);  
if (arguments.length == 1) return $(element.parentNode);  
var ancestors = element.ancestors();  
return Object.isNumber(expression) ? ancestors[expression] :  
Selector.findElement(ancestors, expression, index);  
},  
 
down: function(element, expression, index) {  
element = $(element);  
if (arguments.length == 1) return element.firstDescendant();  
return Object.isNumber(expression) ? element.descendants()[expression] :  
element.select(expression)[index || 0];  
},  
 
previous: function(element, expression, index) {  
element = $(element);  
if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));  
var previousSiblings = element.previousSiblings();  
return Object.isNumber(expression) ? previousSiblings[expression] :  
Selector.findElement(previousSiblings, expression, index);  
},  
 
next: function(element, expression, index) {  
element = $(element);  
if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));  
var nextSiblings = element.nextSiblings();  
return Object.isNumber(expression) ? nextSiblings[expression] :  
Selector.findElement(nextSiblings, expression, index);  
},  
 
select: function() {  
var args = $A(arguments), element = $(args.shift());  
return Selector.findChildElements(element, args);  
},  
 
adjacent: function() {  
var args = $A(arguments), element = $(args.shift());  
return Selector.findChildElements(element.parentNode, args).without(element);  
},  
 
identify: function(element) {  
element = $(element);  
var id = element.readAttribute('id'), self = arguments.callee;  
if (id) return id;  
do { id = 'anonymous_element_' + self.counter++ } while ($(id));  
element.writeAttribute('id', id);  
return id;  
},  
 
readAttribute: function(element, name) {  
element = $(element);  
if (Prototype.Browser.IE) {  
var t = Element._attributeTranslations.read;  
if (t.values[name]) return t.values[name](element, name);  
if (t.names[name]) name = t.names[name];  
if (name.include(':')) {  
return (!element.attributes || !element.attributes[name]) ? null :  
element.attributes[name].value;  
}  
}  
return element.getAttribute(name);  
},  
 
writeAttribute: function(element, name, value) {  
element = $(element);  
var attributes = { }, t = Element._attributeTranslations.write;  
 
if (typeof name == 'object') attributes = name;  
else attributes[name] = Object.isUndefined(value) ? true : value;  
 
for (var attr in attributes) {  
name = t.names[attr] || attr;  
value = attributes[attr];  
if (t.values[attr]) name = t.values[attr](element, value);  
if (value === false || value === null)  
element.removeAttribute(name);  
else if (value === true)  
element.setAttribute(name, name);  
else element.setAttribute(name, value);  
}  
return element;  
},  
 
getHeight: function(element) {  
return $(element).getDimensions().height;  
},  
 
getWidth: function(element) {  
return $(element).getDimensions().width;  
},  
 
classNames: function(element) {  
return new Element.ClassNames(element);  
},  
 
hasClassName: function(element, className) {  
if (!(element = $(element))) return;  
var elementClassName = element.className;  
return (elementClassName.length > 0 && (elementClassName == className ||  
new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));  
},  
 
addClassName: function(element, className) {  
if (!(element = $(element))) return;  
if (!element.hasClassName(className))  
element.className += (element.className ? ' ' : '') + className;  
return element;  
},  
 
removeClassName: function(element, className) {  
if (!(element = $(element))) return;  
element.className = element.className.replace(  
new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();  
return element;  
},  
 
toggleClassName: function(element, className) {  
if (!(element = $(element))) return;  
return element[element.hasClassName(className) ?  
'removeClassName' : 'addClassName'](className);  
},  
 
// removes whitespace-only text node children  
cleanWhitespace: function(element) {  
element = $(element);  
var node = element.firstChild;  
while (node) {  
var nextNode = node.nextSibling;  
if (node.nodeType == 3 && !/\S/.test(node.nodeValue))  
element.removeChild(node);  
node = nextNode;  
}  
return element;  
},  
 
empty: function(element) {  
return $(element).innerHTML.blank();  
},  
 
descendantOf: function(element, ancestor) {  
element = $(element), ancestor = $(ancestor);  
var originalAncestor = ancestor;  
 
if (element.compareDocumentPosition)  
return (element.compareDocumentPosition(ancestor) & 8) === 8;  
 
if (element.sourceIndex && !Prototype.Browser.Opera) {  
var e = element.sourceIndex, a = ancestor.sourceIndex,  
nextAncestor = ancestor.nextSibling;  
if (!nextAncestor) {  
do { ancestor = ancestor.parentNode; }  
while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);  
}  
if (nextAncestor && nextAncestor.sourceIndex)  
return (e > a && e < nextAncestor.sourceIndex);  
}  
 
while (element = element.parentNode)  
if (element == originalAncestor) return true;  
return false;  
},  
 
scrollTo: function(element) {  
element = $(element);  
var pos = element.cumulativeOffset();  
window.scrollTo(pos[0], pos[1]);  
return element;  
},  
 
getStyle: function(element, style) {  
element = $(element);  
style = style == 'float' ? 'cssFloat' : style.camelize();  
var value = element.style[style];  
if (!value) {  
var css = document.defaultView.getComputedStyle(element, null);  
value = css ? css[style] : null;  
}  
if (style == 'opacity') return value ? parseFloat(value) : 1.0;  
return value == 'auto' ? null : value;  
},  
 
getOpacity: function(element) {  
return $(element).getStyle('opacity');  
},  
 
setStyle: function(element, styles) {  
element = $(element);  
var elementStyle = element.style, match;  
if (Object.isString(styles)) {  
element.style.cssText += ';' + styles;  
return styles.include('opacity') ?  
element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;  
}  
for (var property in styles)  
if (property == 'opacity') element.setOpacity(styles[property]);  
else  
elementStyle[(property == 'float' || property == 'cssFloat') ?  
(Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :  
property] = styles[property];  
 
return element;  
},  
 
setOpacity: function(element, value) {  
element = $(element);  
element.style.opacity = (value == 1 || value === '') ? '' :  
(value < 0.00001) ? 0 : value;  
return element;  
},  
 
getDimensions: function(element) {  
element = $(element);  
var display = $(element).getStyle('display');  
if (display != 'none' && display != null) // Safari bug  
return {width: element.offsetWidth, height: element.offsetHeight};  
 
// All *Width and *Height properties give 0 on elements with display none,  
// so enable the element temporarily  
var els = element.style;  
var originalVisibility = els.visibility;  
var originalPosition = els.position;  
var originalDisplay = els.display;  
els.visibility = 'hidden';  
els.position = 'absolute';  
els.display = 'block';  
var originalWidth = element.clientWidth;  
var originalHeight = element.clientHeight;  
els.display = originalDisplay;  
els.position = originalPosition;  
els.visibility = originalVisibility;  
return {width: originalWidth, height: originalHeight};  
},  
 
makePositioned: function(element) {  
element = $(element);  
var pos = Element.getStyle(element, 'position');  
if (pos == 'static' || !pos) {  
element._madePositioned = true;  
element.style.position = 'relative';  
// Opera returns the offset relative to the positioning context, when an  
// element is position relative but top and left have not been defined  
if (window.opera) {  
element.style.top = 0;  
element.style.left = 0;  
}  
}  
return element;  
},  
 
undoPositioned: function(element) {  
element = $(element);  
if (element._madePositioned) {  
element._madePositioned = undefined;  
element.style.position =  
element.style.top =  
element.style.left =  
element.style.bottom =  
element.style.right = '';  
}  
return element;  
},  
 
makeClipping: function(element) {  
element = $(element);  
if (element._overflow) return element;  
element._overflow = Element.getStyle(element, 'overflow') || 'auto';  
if (element._overflow !== 'hidden')  
element.style.overflow = 'hidden';  
return element;  
},  
 
undoClipping: function(element) {  
element = $(element);  
if (!element._overflow) return element;  
element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;  
element._overflow = null;  
return element;  
},  
 
cumulativeOffset: function(element) {  
var valueT = 0, valueL = 0;  
do {  
valueT += element.offsetTop || 0;  
valueL += element.offsetLeft || 0;  
element = element.offsetParent;  
} while (element);  
return Element._returnOffset(valueL, valueT);  
},  
 
positionedOffset: function(element) {  
var valueT = 0, valueL = 0;  
do {  
valueT += element.offsetTop || 0;  
valueL += element.offsetLeft || 0;  
element = element.offsetParent;  
if (element) {  
if (element.tagName == 'BODY') break;  
var p = Element.getStyle(element, 'position');  
if (p !== 'static') break;  
}  
} while (element);  
return Element._returnOffset(valueL, valueT);  
},  
 
absolutize: function(element) {  
element = $(element);  
if (element.getStyle('position') == 'absolute') return;  
// Position.prepare(); // To be done manually by Scripty when it needs it.  
 
var offsets = element.positionedOffset();  
var top = offsets[1];  
var left = offsets[0];  
var width = element.clientWidth;  
var height = element.clientHeight;  
 
element._originalLeft = left - parseFloat(element.style.left || 0);  
element._originalTop = top - parseFloat(element.style.top || 0);  
element._originalWidth = element.style.width;  
element._originalHeight = element.style.height;  
 
element.style.position = 'absolute';  
element.style.top = top + 'px';  
element.style.left = left + 'px';  
element.style.width = width + 'px';  
element.style.height = height + 'px';  
return element;  
},  
 
relativize: function(element) {  
element = $(element);  
if (element.getStyle('position') == 'relative') return;  
// Position.prepare(); // To be done manually by Scripty when it needs it.  
 
element.style.position = 'relative';  
var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);  
var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);  
 
element.style.top = top + 'px';  
element.style.left = left + 'px';  
element.style.height = element._originalHeight;  
element.style.width = element._originalWidth;  
return element;  
},  
 
cumulativeScrollOffset: function(element) {  
var valueT = 0, valueL = 0;  
do {  
valueT += element.scrollTop || 0;  
valueL += element.scrollLeft || 0;  
element = element.parentNode;  
} while (element);  
return Element._returnOffset(valueL, valueT);  
},  
 
getOffsetParent: function(element) {  
if (element.offsetParent) return $(element.offsetParent);  
if (element == document.body) return $(element);  
 
while ((element = element.parentNode) && element != document.body)  
if (Element.getStyle(element, 'position') != 'static')  
return $(element);  
 
return $(document.body);  
},  
 
viewportOffset: function(forElement) {  
var valueT = 0, valueL = 0;  
 
var element = forElement;  
do {  
valueT += element.offsetTop || 0;  
valueL += element.offsetLeft || 0;  
 
// Safari fix  
if (element.offsetParent == document.body &&  
Element.getStyle(element, 'position') == 'absolute') break;  
 
} while (element = element.offsetParent);  
 
element = forElement;  
do {  
if (!Prototype.Browser.Opera || element.tagName == 'BODY') {  
valueT -= element.scrollTop || 0;  
valueL -= element.scrollLeft || 0;  
}  
} while (element = element.parentNode);  
 
return Element._returnOffset(valueL, valueT);  
},  
 
clonePosition: function(element, source) {  
var options = Object.extend({  
setLeft: true,  
setTop: true,  
setWidth: true,  
setHeight: true,  
offsetTop: 0,  
offsetLeft: 0  
}, arguments[2] || { });  
 
// find page position of source  
source = $(source);  
var p = source.viewportOffset();  
 
// find coordinate system to use  
element = $(element);  
var delta = [0, 0];  
var parent = null;  
// delta [0,0] will do fine with position: fixed elements,  
// position:absolute needs offsetParent deltas  
if (Element.getStyle(element, 'position') == 'absolute') {  
parent = element.getOffsetParent();  
delta = parent.viewportOffset();  
}  
 
// correct by body offsets (fixes Safari)  
if (parent == document.body) {  
delta[0] -= document.body.offsetLeft;  
delta[1] -= document.body.offsetTop;  
}  
 
// set position  
if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';  
if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';  
if (options.setWidth) element.style.width = source.offsetWidth + 'px';  
if (options.setHeight) element.style.height = source.offsetHeight + 'px';  
return element;  
}  
};  
 
Element.Methods.identify.counter = 1;  
 
Object.extend(Element.Methods, {  
getElementsBySelector: Element.Methods.select,  
childElements: Element.Methods.immediateDescendants  
});  
 
Element._attributeTranslations = {  
write: {  
names: {  
className: 'class',  
htmlFor: 'for'  
},  
values: { }  
}  
};  
 
if (Prototype.Browser.Opera) {  
Element.Methods.getStyle = Element.Methods.getStyle.wrap(  
function(proceed, element, style) {  
switch (style) {  
case 'left': case 'top': case 'right': case 'bottom':  
if (proceed(element, 'position') === 'static') return null;  
case 'height': case 'width':  
// returns '0px' for hidden elements; we want it to return null  
if (!Element.visible(element)) return null;  
 
// returns the border-box dimensions rather than the content-box  
// dimensions, so we subtract padding and borders from the value  
var dim = parseInt(proceed(element, style), 10);  
 
if (dim !== element['offset' + style.capitalize()])  
return dim + 'px';  
 
var properties;  
if (style === 'height') {  
properties = ['border-top-width', 'padding-top',  
'padding-bottom', 'border-bottom-width'];  
}  
else {  
properties = ['border-left-width', 'padding-left',  
'padding-right', 'border-right-width'];  
}  
return properties.inject(dim, function(memo, property) {  
var val = proceed(element, property);  
return val === null ? memo : memo - parseInt(val, 10);  
}) + 'px';  
default: return proceed(element, style);  
}  
}  
);  
 
Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(  
function(proceed, element, attribute) {  
if (attribute === 'title') return element.title;  
return proceed(element, attribute);  
}  
);  
}  
 
else if (Prototype.Browser.IE) {  
// IE doesn't report offsets correctly for static elements, so we change them  
// to "relative" to get the values, then change them back.  
Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(  
function(proceed, element) {  
element = $(element);  
var position = element.getStyle('position');  
if (position !== 'static') return proceed(element);  
element.setStyle({ position: 'relative' });  
var value = proceed(element);  
element.setStyle({ position: position });  
return value;  
}  
);  
 
$w('positionedOffset viewportOffset').each(function(method) {  
Element.Methods[method] = Element.Methods[method].wrap(  
function(proceed, element) {  
element = $(element);  
var position = element.getStyle('position');  
if (position !== 'static') return proceed(element);  
// Trigger hasLayout on the offset parent so that IE6 reports  
// accurate offsetTop and offsetLeft values for position: fixed.  
var offsetParent = element.getOffsetParent();  
if (offsetParent && offsetParent.getStyle('position') === 'fixed')  
offsetParent.setStyle({ zoom: 1 });  
element.setStyle({ position: 'relative' });  
var value = proceed(element);  
element.setStyle({ position: position });  
return value;  
}  
);  
});  
 
Element.Methods.getStyle = function(element, style) {  
element = $(element);  
style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();  
var value = element.style[style];  
if (!value && element.currentStyle) value = element.currentStyle[style];  
 
if (style == 'opacity') {  
if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))  
if (value[1]) return parseFloat(value[1]) / 100;  
return 1.0;  
}  
 
if (value == 'auto') {  
if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))  
return element['offset' + style.capitalize()] + 'px';  
return null;  
}  
return value;  
};  
 
Element.Methods.setOpacity = function(element, value) {  
function stripAlpha(filter){  
return filter.replace(/alpha\([^\)]*\)/gi,'');  
}  
element = $(element);  
var currentStyle = element.currentStyle;  
if ((currentStyle && !currentStyle.hasLayout) ||  
(!currentStyle && element.style.zoom == 'normal'))  
element.style.zoom = 1;  
 
var filter = element.getStyle('filter'), style = element.style;  
if (value == 1 || value === '') {  
(filter = stripAlpha(filter)) ?  
style.filter = filter : style.removeAttribute('filter');  
return element;  
} else if (value < 0.00001) value = 0;  
style.filter = stripAlpha(filter) +  
'alpha(opacity=' + (value * 100) + ')';  
return element;  
};  
 
Element._attributeTranslations = {  
read: {  
names: {  
'class': 'className',  
'for': 'htmlFor'  
},  
values: {  
_getAttr: function(element, attribute) {  
return element.getAttribute(attribute, 2);  
},  
_getAttrNode: function(element, attribute) {  
var node = element.getAttributeNode(attribute);  
return node ? node.value : "";  
},  
_getEv: function(element, attribute) {  
attribute = element.getAttribute(attribute);  
return attribute ? attribute.toString().slice(23, -2) : null;  
},  
_flag: function(element, attribute) {  
return $(element).hasAttribute(attribute) ? attribute : null;  
},  
style: function(element) {  
return element.style.cssText.toLowerCase();  
},  
title: function(element) {  
return element.title;  
}  
}  
}  
};  
 
Element._attributeTranslations.write = {  
names: Object.extend({  
cellpadding: 'cellPadding',  
cellspacing: 'cellSpacing'  
}, Element._attributeTranslations.read.names),  
values: {  
checked: function(element, value) {  
element.checked = !!value;  
},  
 
style: function(element, value) {  
element.style.cssText = value ? value : '';  
}  
}  
};  
 
Element._attributeTranslations.has = {};  
 
$w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +  
'encType maxLength readOnly longDesc').each(function(attr) {  
Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;  
Element._attributeTranslations.has[attr.toLowerCase()] = attr;  
});  
 
(function(v) {  
Object.extend(v, {  
href: v._getAttr,  
src: v._getAttr,  
type: v._getAttr,  
action: v._getAttrNode,  
disabled: v._flag,  
checked: v._flag,  
readonly: v._flag,  
multiple: v._flag,  
onload: v._getEv,  
onunload: v._getEv,  
onclick: v._getEv,  
ondblclick: v._getEv,  
onmousedown: v._getEv,  
onmouseup: v._getEv,  
onmouseover: v._getEv,  
onmousemove: v._getEv,  
onmouseout: v._getEv,  
onfocus: v._getEv,  
onblur: v._getEv,  
onkeypress: v._getEv,  
onkeydown: v._getEv,  
onkeyup: v._getEv,  
onsubmit: v._getEv,  
onreset: v._getEv,  
onselect: v._getEv,  
onchange: v._getEv  
});  
})(Element._attributeTranslations.read.values);  
}  
 
else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {  
Element.Methods.setOpacity = function(element, value) {  
element = $(element);  
element.style.opacity = (value == 1) ? 0.999999 :  
(value === '') ? '' : (value < 0.00001) ? 0 : value;  
return element;  
};  
}  
 
else if (Prototype.Browser.WebKit) {  
Element.Methods.setOpacity = function(element, value) {  
element = $(element);  
element.style.opacity = (value == 1 || value === '') ? '' :  
(value < 0.00001) ? 0 : value;  
 
if (value == 1)  
if(element.tagName == 'IMG' && element.width) {  
element.width++; element.width--;  
} else try {  
var n = document.createTextNode(' ');  
element.appendChild(n);  
element.removeChild(n);  
} catch (e) { }  
 
return element;  
};  
 
// Safari returns margins on body which is incorrect if the child is absolutely  
// positioned. For performance reasons, redefine Element#cumulativeOffset for  
// KHTML/WebKit only.  
Element.Methods.cumulativeOffset = function(element) {  
var valueT = 0, valueL = 0;  
do {  
valueT += element.offsetTop || 0;  
valueL += element.offsetLeft || 0;  
if (element.offsetParent == document.body)  
if (Element.getStyle(element, 'position') == 'absolute') break;  
 
element = element.offsetParent;  
} while (element);  
 
return Element._returnOffset(valueL, valueT);  
};  
}  
 
if (Prototype.Browser.IE || Prototype.Browser.Opera) {  
// IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements  
Element.Methods.update = function(element, content) {  
element = $(element);  
 
if (content && content.toElement) content = content.toElement();  
if (Object.isElement(content)) return element.update().insert(content);  
 
content = Object.toHTML(content);  
var tagName = element.tagName.toUpperCase();  
 
if (tagName in Element._insertionTranslations.tags) {  
$A(element.childNodes).each(function(node) { element.removeChild(node) });  
Element._getContentFromAnonymousElement(tagName, content.stripScripts())  
.each(function(node) { element.appendChild(node) });  
}  
else element.innerHTML = content.stripScripts();  
 
content.evalScripts.bind(content).defer();  
return element;  
};  
}  
 
if ('outerHTML' in document.createElement('div')) {  
Element.Methods.replace = function(element, content) {  
element = $(element);  
 
if (content && content.toElement) content = content.toElement();  
if (Object.isElement(content)) {  
element.parentNode.replaceChild(content, element);  
return element;  
}  
 
content = Object.toHTML(content);  
var parent = element.parentNode, tagName = parent.tagName.toUpperCase();  
 
if (Element._insertionTranslations.tags[tagName]) {  
var nextSibling = element.next();  
var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());  
parent.removeChild(element);  
if (nextSibling)  
fragments.each(function(node) { parent.insertBefore(node, nextSibling) });  
else  
fragments.each(function(node) { parent.appendChild(node) });  
}  
else element.outerHTML = content.stripScripts();  
 
content.evalScripts.bind(content).defer();  
return element;  
};  
}  
 
Element._returnOffset = function(l, t) {  
var result = [l, t];  
result.left = l;  
result.top = t;  
return result;  
};  
 
Element._getContentFromAnonymousElement = function(tagName, html) {  
var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];  
if (t) {  
div.innerHTML = t[0] + html + t[1];  
t[2].times(function() { div = div.firstChild });  
} else div.innerHTML = html;  
return $A(div.childNodes);  
};  
 
Element._insertionTranslations = {  
before: function(element, node) {  
element.parentNode.insertBefore(node, element);  
},  
top: function(element, node) {  
element.insertBefore(node, element.firstChild);  
},  
bottom: function(element, node) {  
element.appendChild(node);  
},  
after: function(element, node) {  
element.parentNode.insertBefore(node, element.nextSibling);  
},  
tags: {  
TABLE: ['<table>', '</table>', 1],  
TBODY: ['<table><tbody>', '</tbody></table>', 2],  
TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],  
TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],  
SELECT: ['<select>', '</select>', 1]  
}  
};  
 
(function() {  
Object.extend(this.tags, {  
THEAD: this.tags.TBODY,  
TFOOT: this.tags.TBODY,  
TH: this.tags.TD  
});  
}).call(Element._insertionTranslations);  
 
Element.Methods.Simulated = {  
hasAttribute: function(element, attribute) {  
attribute = Element._attributeTranslations.has[attribute] || attribute;  
var node = $(element).getAttributeNode(attribute);  
return node && node.specified;  
}  
};  
 
Element.Methods.ByTag = { };  
 
Object.extend(Element, Element.Methods);  
 
if (!Prototype.BrowserFeatures.ElementExtensions &&  
document.createElement('div').__proto__) {  
window.HTMLElement = { };  
window.HTMLElement.prototype = document.createElement('div').__proto__;  
Prototype.BrowserFeatures.ElementExtensions = true;  
}  
 
Element.extend = (function() {  
if (Prototype.BrowserFeatures.SpecificElementExtensions)  
return Prototype.K;  
 
var Methods = { }, ByTag = Element.Methods.ByTag;  
 
var extend = Object.extend(function(element) {  
if (!element || element._extendedByPrototype ||  
element.nodeType != 1 || element == window) return element;  
 
var methods = Object.clone(Methods),  
tagName = element.tagName, property, value;  
 
// extend methods for specific tags  
if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);  
 
for (property in methods) {  
value = methods[property];  
if (Object.isFunction(value) && !(property in element))  
element[property] = value.methodize();  
}  
 
element._extendedByPrototype = Prototype.emptyFunction;  
return element;  
 
}, {  
refresh: function() {  
// extend methods for all tags (Safari doesn't need this)  
if (!Prototype.BrowserFeatures.ElementExtensions) {  
Object.extend(Methods, Element.Methods);  
Object.extend(Methods, Element.Methods.Simulated);  
}  
}  
});  
 
extend.refresh();  
return extend;  
})();  
 
Element.hasAttribute = function(element, attribute) {  
if (element.hasAttribute) return element.hasAttribute(attribute);  
return Element.Methods.Simulated.hasAttribute(element, attribute);  
};  
 
Element.addMethods = function(methods) {  
var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;  
 
if (!methods) {  
Object.extend(Form, Form.Methods);  
Object.extend(Form.Element, Form.Element.Methods);  
Object.extend(Element.Methods.ByTag, {  
"FORM": Object.clone(Form.Methods),  
"INPUT": Object.clone(Form.Element.Methods),  
"SELECT": Object.clone(Form.Element.Methods),  
"TEXTAREA": Object.clone(Form.Element.Methods)  
});  
}  
 
if (arguments.length == 2) {  
var tagName = methods;  
methods = arguments[1];  
}  
 
if (!tagName) Object.extend(Element.Methods, methods || { });  
else {  
if (Object.isArray(tagName)) tagName.each(extend);  
else extend(tagName);  
}  
 
function extend(tagName) {  
tagName = tagName.toUpperCase();  
if (!Element.Methods.ByTag[tagName])  
Element.Methods.ByTag[tagName] = { };  
Object.extend(Element.Methods.ByTag[tagName], methods);  
}  
 
function copy(methods, destination, onlyIfAbsent) {  
onlyIfAbsent = onlyIfAbsent || false;  
for (var property in methods) {  
var value = methods[property];  
if (!Object.isFunction(value)) continue;  
if (!onlyIfAbsent || !(property in destination))  
destination[property] = value.methodize();  
}  
}  
 
function findDOMClass(tagName) {  
var klass;  
var trans = {  
"OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",  
"FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",  
"DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",  
"H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",  
"INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":  
"TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":  
"TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":  
"TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":  
"FrameSet", "IFRAME": "IFrame"  
};  
if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';  
if (window[klass]) return window[klass];  
klass = 'HTML' + tagName + 'Element';  
if (window[klass]) return window[klass];  
klass = 'HTML' + tagName.capitalize() + 'Element';  
if (window[klass]) return window[klass];  
 
window[klass] = { };  
window[klass].prototype = document.createElement(tagName).__proto__;  
return window[klass];  
}  
 
if (F.ElementExtensions) {  
copy(Element.Methods, HTMLElement.prototype);  
copy(Element.Methods.Simulated, HTMLElement.prototype, true);  
}  
 
if (F.SpecificElementExtensions) {  
for (var tag in Element.Methods.ByTag) {  
var klass = findDOMClass(tag);  
if (Object.isUndefined(klass)) continue;  
copy(T[tag], klass.prototype);  
}  
}  
 
Object.extend(Element, Element.Methods);  
delete Element.ByTag;  
 
if (Element.extend.refresh) Element.extend.refresh();  
Element.cache = { };  
};  
 
document.viewport = {  
getDimensions: function() {  
var dimensions = { };  
var B = Prototype.Browser;  
$w('width height').each(function(d) {  
var D = d.capitalize();  
dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :  
(B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];  
});  
return dimensions;  
},  
 
getWidth: function() {  
return this.getDimensions().width;  
},  
 
getHeight: function() {  
return this.getDimensions().height;  
},  
 
getScrollOffsets: function() {  
return Element._returnOffset(  
window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,  
window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);  
}  
};  
/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,  
* part of YUI-Ext version 0.40, distributed under the terms of an MIT-style  
* license. Please see http://www.yui-ext.com/ for more information. */  
 
var Selector = Class.create({  
initialize: function(expression) {  
this.expression = expression.strip();  
this.compileMatcher();  
},  
 
shouldUseXPath: function() {  
if (!Prototype.BrowserFeatures.XPath) return false;  
 
var e = this.expression;  
 
// Safari 3 chokes on :*-of-type and :empty  
if (Prototype.Browser.WebKit &&  
(e.include("-of-type") || e.include(":empty")))  
return false;  
 
// XPath can't do namespaced attributes, nor can it read  
// the "checked" property from DOM nodes  
if ((/(\[[\w-]*?:|:checked)/).test(this.expression))  
return false;  
 
return true;  
},  
 
compileMatcher: function() {  
if (this.shouldUseXPath())  
return this.compileXPathMatcher();  
 
var e = this.expression, ps = Selector.patterns, h = Selector.handlers,  
c = Selector.criteria, le, p, m;  
 
if (Selector._cache[e]) {  
this.matcher = Selector._cache[e];  
return;  
}  
 
this.matcher = ["this.matcher = function(root) {",  
"var r = root, h = Selector.handlers, c = false, n;"];  
 
while (e && le != e && (/\S/).test(e)) {  
le = e;  
for (var i in ps) {  
p = ps[i];  
if (m = e.match(p)) {  
this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :  
new Template(c[i]).evaluate(m));  
e = e.replace(m[0], '');  
break;  
}  
}  
}  
 
this.matcher.push("return h.unique(n);\n}");  
eval(this.matcher.join('\n'));  
Selector._cache[this.expression] = this.matcher;  
},  
 
compileXPathMatcher: function() {  
var e = this.expression, ps = Selector.patterns,  
x = Selector.xpath, le, m;  
 
if (Selector._cache[e]) {  
this.xpath = Selector._cache[e]; return;  
}  
 
this.matcher = ['.//*'];  
while (e && le != e && (/\S/).test(e)) {  
le = e;  
for (var i in ps) {  
if (m = e.match(ps[i])) {  
this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :  
new Template(x[i]).evaluate(m));  
e = e.replace(m[0], '');  
break;  
}  
}  
}  
 
this.xpath = this.matcher.join('');  
Selector._cache[this.expression] = this.xpath;  
},  
 
findElements: function(root) {  
root = root || document;  
if (this.xpath) return document._getElementsByXPath(this.xpath, root);  
return this.matcher(root);  
},  
 
match: function(element) {  
this.tokens = [];  
 
var e = this.expression, ps = Selector.patterns, as = Selector.assertions;  
var le, p, m;  
 
while (e && le !== e && (/\S/).test(e)) {  
le = e;  
for (var i in ps) {  
p = ps[i];  
if (m = e.match(p)) {  
// use the Selector.assertions methods unless the selector  
// is too complex.  
if (as[i]) {  
this.tokens.push([i, Object.clone(m)]);  
e = e.replace(m[0], '');  
} else {  
// reluctantly do a document-wide search  
// and look for a match in the array  
return this.findElements(document).include(element);  
}  
}  
}  
}  
 
var match = true, name, matches;  
for (var i = 0, token; token = this.tokens[i]; i++) {  
name = token[0], matches = token[1];  
if (!Selector.assertions[name](element, matches)) {  
match = false; break;  
}  
}  
 
return match;  
},  
 
toString: function() {  
return this.expression;  
},  
 
inspect: function() {  
return "#<Selector:" + this.expression.inspect() + ">";  
}  
});  
 
Object.extend(Selector, {  
_cache: { },  
 
xpath: {  
descendant: "//*",  
child: "/*",  
adjacent: "/following-sibling::*[1]",  
laterSibling: '/following-sibling::*',  
tagName: function(m) {  
if (m[1] == '*') return '';  
return "[local-name()='" + m[1].toLowerCase() +  
"' or local-name()='" + m[1].toUpperCase() + "']";  
},  
className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",  
id: "[@id='#{1}']",  
attrPresence: function(m) {  
m[1] = m[1].toLowerCase();  
return new Template("[@#{1}]").evaluate(m);  
},  
attr: function(m) {  
m[1] = m[1].toLowerCase();  
m[3] = m[5] || m[6];  
return new Template(Selector.xpath.operators[m[2]]).evaluate(m);  
},  
pseudo: function(m) {  
var h = Selector.xpath.pseudos[m[1]];  
if (!h) return '';  
if (Object.isFunction(h)) return h(m);  
return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);  
},  
operators: {  
'=': "[@#{1}='#{3}']",  
'!=': "[@#{1}!='#{3}']",  
'^=': "[starts-with(@#{1}, '#{3}')]",  
'$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",  
'*=': "[contains(@#{1}, '#{3}')]",  
'~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",  
'|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"  
},  
pseudos: {  
'first-child': '[not(preceding-sibling::*)]',  
'last-child': '[not(following-sibling::*)]',  
'only-child': '[not(preceding-sibling::* or following-sibling::*)]',  
'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]",  
'checked': "[@checked]",  
'disabled': "[@disabled]",  
'enabled': "[not(@disabled)]",  
'not': function(m) {  
var e = m[6], p = Selector.patterns,  
x = Selector.xpath, le, v;  
 
var exclusion = [];  
while (e && le != e && (/\S/).test(e)) {  
le = e;  
for (var i in p) {  
if (m = e.match(p[i])) {  
v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);  
exclusion.push("(" + v.substring(1, v.length - 1) + ")");  
e = e.replace(m[0], '');  
break;  
}  
}  
}  
return "[not(" + exclusion.join(" and ") + ")]";  
},  
'nth-child': function(m) {  
return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);  
},  
'nth-last-child': function(m) {  
return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);  
},  
'nth-of-type': function(m) {  
return Selector.xpath.pseudos.nth("position() ", m);  
},  
'nth-last-of-type': function(m) {  
return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);  
},  
'first-of-type': function(m) {  
m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);  
},  
'last-of-type': function(m) {  
m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);  
},  
'only-of-type': function(m) {  
var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);  
},  
nth: function(fragment, m) {  
var mm, formula = m[6], predicate;  
if (formula == 'even') formula = '2n+0';  
if (formula == 'odd') formula = '2n+1';  
if (mm = formula.match(/^(\d+)$/)) // digit only  
return '[' + fragment + "= " + mm[1] + ']';  
if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b  
if (mm[1] == "-") mm[1] = -1;  
var a = mm[1] ? Number(mm[1]) : 1;  
var b = mm[2] ? Number(mm[2]) : 0;  
predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +  
"((#{fragment} - #{b}) div #{a} >= 0)]";  
return new Template(predicate).evaluate({  
fragment: fragment, a: a, b: b });  
}  
}  
}  
},  
 
criteria: {  
tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',  
className: 'n = h.className(n, r, "#{1}", c); c = false;',  
id: 'n = h.id(n, r, "#{1}", c); c = false;',  
attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',  
attr: function(m) {  
m[3] = (m[5] || m[6]);  
return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);  
},  
pseudo: function(m) {  
if (m[6]) m[6] = m[6].replace(/"/g, '\\"');  
return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);  
},  
descendant: 'c = "descendant";',  
child: 'c = "child";',  
adjacent: 'c = "adjacent";',  
laterSibling: 'c = "laterSibling";'  
},  
 
patterns: {  
// combinators must be listed first  
// (and descendant needs to be last combinator)  
laterSibling: /^\s*~\s*/,  
child: /^\s*>\s*/,  
adjacent: /^\s*\+\s*/,  
descendant: /^\s/,  
 
// selectors follow  
tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,  
id: /^#([\w\-\*]+)(\b|$)/,  
className: /^\.([\w\-\*]+)(\b|$)/,  
pseudo:  
/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,  
attrPresence: /^\[([\w]+)\]/,  
attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/  
},  
 
// for Selector.match and Element#match  
assertions: {  
tagName: function(element, matches) {  
return matches[1].toUpperCase() == element.tagName.toUpperCase();  
},  
 
className: function(element, matches) {  
return Element.hasClassName(element, matches[1]);  
},  
 
id: function(element, matches) {  
return element.id === matches[1];  
},  
 
attrPresence: function(element, matches) {  
return Element.hasAttribute(element, matches[1]);  
},  
 
attr: function(element, matches) {  
var nodeValue = Element.readAttribute(element, matches[1]);  
return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);  
}  
},  
 
handlers: {  
// UTILITY FUNCTIONS  
// joins two collections  
concat: function(a, b) {  
for (var i = 0, node; node = b[i]; i++)  
a.push(node);  
return a;  
},  
 
// marks an array of nodes for counting  
mark: function(nodes) {  
var _true = Prototype.emptyFunction;  
for (var i = 0, node; node = nodes[i]; i++)  
node._countedByPrototype = _true;  
return nodes;  
},  
 
unmark: function(nodes) {  
for (var i = 0, node; node = nodes[i]; i++)  
node._countedByPrototype = undefined;  
return nodes;  
},  
 
// mark each child node with its position (for nth calls)  
// "ofType" flag indicates whether we're indexing for nth-of-type  
// rather than nth-child  
index: function(parentNode, reverse, ofType) {  
parentNode._countedByPrototype = Prototype.emptyFunction;  
if (reverse) {  
for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {  
var node = nodes[i];  
if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;  
}  
} else {  
for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)  
if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;  
}  
},  
 
// filters out duplicates and extends all nodes  
unique: function(nodes) {  
if (nodes.length == 0) return nodes;  
var results = [], n;  
for (var i = 0, l = nodes.length; i < l; i++)  
if (!(n = nodes[i])._countedByPrototype) {  
n._countedByPrototype = Prototype.emptyFunction;  
results.push(Element.extend(n));  
}  
return Selector.handlers.unmark(results);  
},  
 
// COMBINATOR FUNCTIONS  
descendant: function(nodes) {  
var h = Selector.handlers;  
for (var i = 0, results = [], node; node = nodes[i]; i++)  
h.concat(results, node.getElementsByTagName('*'));  
return results;  
},  
 
child: function(nodes) {  
var h = Selector.handlers;  
for (var i = 0, results = [], node; node = nodes[i]; i++) {  
for (var j = 0, child; child = node.childNodes[j]; j++)  
if (child.nodeType == 1 && child.tagName != '!') results.push(child);  
}  
return results;  
},  
 
adjacent: function(nodes) {  
for (var i = 0, results = [], node; node = nodes[i]; i++) {  
var next = this.nextElementSibling(node);  
if (next) results.push(next);  
}  
return results;  
},  
 
laterSibling: function(nodes) {  
var h = Selector.handlers;  
for (var i = 0, results = [], node; node = nodes[i]; i++)  
h.concat(results, Element.nextSiblings(node));  
return results;  
},  
 
nextElementSibling: function(node) {  
while (node = node.nextSibling)  
if (node.nodeType == 1) return node;  
return null;  
},  
 
previousElementSibling: function(node) {  
while (node = node.previousSibling)  
if (node.nodeType == 1) return node;  
return null;  
},  
 
// TOKEN FUNCTIONS  
tagName: function(nodes, root, tagName, combinator) {  
var uTagName = tagName.toUpperCase();  
var results = [], h = Selector.handlers;  
if (nodes) {  
if (combinator) {  
// fastlane for ordinary descendant combinators  
if (combinator == "descendant") {  
for (var i = 0, node; node = nodes[i]; i++)  
h.concat(results, node.getElementsByTagName(tagName));  
return results;  
} else nodes = this[combinator](nodes);  
if (tagName == "*") return nodes;  
}  
for (var i = 0, node; node = nodes[i]; i++)  
if (node.tagName.toUpperCase() === uTagName) results.push(node);  
return results;  
} else return root.getElementsByTagName(tagName);  
},  
 
id: function(nodes, root, id, combinator) {  
var targetNode = $(id), h = Selector.handlers;  
if (!targetNode) return [];  
if (!nodes && root == document) return [targetNode];  
if (nodes) {  
if (combinator) {  
if (combinator == 'child') {  
for (var i = 0, node; node = nodes[i]; i++)  
if (targetNode.parentNode == node) return [targetNode];  
} else if (combinator == 'descendant') {  
for (var i = 0, node; node = nodes[i]; i++)  
if (Element.descendantOf(targetNode, node)) return [targetNode];  
} else if (combinator == 'adjacent') {  
for (var i = 0, node; node = nodes[i]; i++)  
if (Selector.handlers.previousElementSibling(targetNode) == node)  
return [targetNode];  
} else nodes = h[combinator](nodes);  
}  
for (var i = 0, node; node = nodes[i]; i++)  
if (node == targetNode) return [targetNode];  
return [];  
}  
return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];  
},  
 
className: function(nodes, root, className, combinator) {  
if (nodes && combinator) nodes = this[combinator](nodes);  
return Selector.handlers.byClassName(nodes, root, className);  
},  
 
byClassName: function(nodes, root, className) {  
if (!nodes) nodes = Selector.handlers.descendant([root]);  
var needle = ' ' + className + ' ';  
for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {  
nodeClassName = node.className;  
if (nodeClassName.length == 0) continue;  
if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))  
results.push(node);  
}  
return results;  
},  
 
attrPresence: function(nodes, root, attr, combinator) {  
if (!nodes) nodes = root.getElementsByTagName("*");  
if (nodes && combinator) nodes = this[combinator](nodes);  
var results = [];  
for (var i = 0, node; node = nodes[i]; i++)  
if (Element.hasAttribute(node, attr)) results.push(node);  
return results;  
},  
 
attr: function(nodes, root, attr, value, operator, combinator) {  
if (!nodes) nodes = root.getElementsByTagName("*");  
if (nodes && combinator) nodes = this[combinator](nodes);  
var handler = Selector.operators[operator], results = [];  
for (var i = 0, node; node = nodes[i]; i++) {  
var nodeValue = Element.readAttribute(node, attr);  
if (nodeValue === null) continue;  
if (handler(nodeValue, value)) results.push(node);  
}  
return results;  
},  
 
pseudo: function(nodes, name, value, root, combinator) {  
if (nodes && combinator) nodes = this[combinator](nodes);  
if (!nodes) nodes = root.getElementsByTagName("*");  
return Selector.pseudos[name](nodes, value, root);  
}  
},  
 
pseudos: {  
'first-child': function(nodes, value, root) {  
for (var i = 0, results = [], node; node = nodes[i]; i++) {  
if (Selector.handlers.previousElementSibling(node)) continue;  
results.push(node);  
}  
return results;  
},  
'last-child': function(nodes, value, root) {  
for (var i = 0, results = [], node; node = nodes[i]; i++) {  
if (Selector.handlers.nextElementSibling(node)) continue;  
results.push(node);  
}  
return results;  
},  
'only-child': function(nodes, value, root) {  
var h = Selector.handlers;  
for (var i = 0, results = [], node; node = nodes[i]; i++)  
if (!h.previousElementSibling(node) && !h.nextElementSibling(node))  
results.push(node);  
return results;  
},  
'nth-child': function(nodes, formula, root) {  
return Selector.pseudos.nth(nodes, formula, root);  
},  
'nth-last-child': function(nodes, formula, root) {  
return Selector.pseudos.nth(nodes, formula, root, true);  
},  
'nth-of-type': function(nodes, formula, root) {  
return Selector.pseudos.nth(nodes, formula, root, false, true);  
},  
'nth-last-of-type': function(nodes, formula, root) {  
return Selector.pseudos.nth(nodes, formula, root, true, true);  
},  
'first-of-type': function(nodes, formula, root) {  
return Selector.pseudos.nth(nodes, "1", root, false, true);  
},  
'last-of-type': function(nodes, formula, root) {  
return Selector.pseudos.nth(nodes, "1", root, true, true);  
},  
'only-of-type': function(nodes, formula, root) {  
var p = Selector.pseudos;  
return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);  
},  
 
// handles the an+b logic  
getIndices: function(a, b, total) {  
if (a == 0) return b > 0 ? [b] : [];  
return $R(1, total).inject([], function(memo, i) {  
if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);  
return memo;  
});  
},  
 
// handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type  
nth: function(nodes, formula, root, reverse, ofType) {  
if (nodes.length == 0) return [];  
if (formula == 'even') formula = '2n+0';  
if (formula == 'odd') formula = '2n+1';  
var h = Selector.handlers, results = [], indexed = [], m;  
h.mark(nodes);  
for (var i = 0, node; node = nodes[i]; i++) {  
if (!node.parentNode._countedByPrototype) {  
h.index(node.parentNode, reverse, ofType);  
indexed.push(node.parentNode);  
}  
}  
if (formula.match(/^\d+$/)) { // just a number  
formula = Number(formula);  
for (var i = 0, node; node = nodes[i]; i++)  
if (node.nodeIndex == formula) results.push(node);  
} else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b  
if (m[1] == "-") m[1] = -1;  
var a = m[1] ? Number(m[1]) : 1;  
var b = m[2] ? Number(m[2]) : 0;  
var indices = Selector.pseudos.getIndices(a, b, nodes.length);  
for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {  
for (var j = 0; j < l; j++)  
if (node.nodeIndex == indices[j]) results.push(node);  
}  
}  
h.unmark(nodes);  
h.unmark(indexed);  
return results;  
},  
 
'empty': function(nodes, value, root) {  
for (var i = 0, results = [], node; node = nodes[i]; i++) {  
// IE treats comments as element nodes  
if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue;  
results.push(node);  
}  
return results;  
},  
 
'not': function(nodes, selector, root) {  
var h = Selector.handlers, selectorType, m;  
var exclusions = new Selector(selector).findElements(root);  
h.mark(exclusions);  
for (var i = 0, results = [], node; node = nodes[i]; i++)  
if (!node._countedByPrototype) results.push(node);  
h.unmark(exclusions);  
return results;  
},  
 
'enabled': function(nodes, value, root) {  
for (var i = 0, results = [], node; node = nodes[i]; i++)  
if (!node.disabled) results.push(node);  
return results;  
},  
 
'disabled': function(nodes, value, root) {  
for (var i = 0, results = [], node; node = nodes[i]; i++)  
if (node.disabled) results.push(node);  
return results;  
},  
 
'checked': function(nodes, value, root) {  
for (var i = 0, results = [], node; node = nodes[i]; i++)  
if (node.checked) results.push(node);  
return results;  
}  
},  
 
operators: {  
'=': function(nv, v) { return nv == v; },  
'!=': function(nv, v) { return nv != v; },  
'^=': function(nv, v) { return nv.startsWith(v); },  
'$=': function(nv, v) { return nv.endsWith(v); },  
'*=': function(nv, v) { return nv.include(v); },  
'~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },  
'|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }  
},  
 
split: function(expression) {  
var expressions = [];  
expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {  
expressions.push(m[1].strip());  
});  
return expressions;  
},  
 
matchElements: function(elements, expression) {  
var matches = $$(expression), h = Selector.handlers;  
h.mark(matches);  
for (var i = 0, results = [], element; element = elements[i]; i++)  
if (element._countedByPrototype) results.push(element);  
h.unmark(matches);  
return results;  
},  
 
findElement: function(elements, expression, index) {  
if (Object.isNumber(expression)) {  
index = expression; expression = false;  
}  
return Selector.matchElements(elements, expression || '*')[index || 0];  
},  
 
findChildElements: function(element, expressions) {  
expressions = Selector.split(expressions.join(','));  
var results = [], h = Selector.handlers;  
for (var i = 0, l = expressions.length, selector; i < l; i++) {  
selector = new Selector(expressions[i].strip());  
h.concat(results, selector.findElements(element));  
}  
return (l > 1) ? h.unique(results) : results;  
}  
});  
 
if (Prototype.Browser.IE) {  
Object.extend(Selector.handlers, {  
// IE returns comment nodes on getElementsByTagName("*").  
// Filter them out.  
concat: function(a, b) {  
for (var i = 0, node; node = b[i]; i++)  
if (node.tagName !== "!") a.push(node);  
return a;  
},  
 
// IE improperly serializes _countedByPrototype in (inner|outer)HTML.  
unmark: function(nodes) {  
for (var i = 0, node; node = nodes[i]; i++)  
node.removeAttribute('_countedByPrototype');  
return nodes;  
}  
});  
}  
 
function $$() {  
return Selector.findChildElements(document, $A(arguments));  
}  
var Form = {  
reset: function(form) {  
$(form).reset();  
return form;  
},  
 
serializeElements: function(elements, options) {  
if (typeof options != 'object') options = { hash: !!options };  
else if (Object.isUndefined(options.hash)) options.hash = true;  
var key, value, submitted = false, submit = options.submit;  
 
var data = elements.inject({ }, function(result, element) {  
if (!element.disabled && element.name) {  
key = element.name; value = $(element).getValue();  
if (value != null && (element.type != 'submit' || (!submitted &&  
submit !== false && (!submit || key == submit) && (submitted = true)))) {  
if (key in result) {  
// a key is already present; construct an array of values  
if (!Object.isArray(result[key])) result[key] = [result[key]];  
result[key].push(value);  
}  
else result[key] = value;  
}  
}  
return result;  
});  
 
return options.hash ? data : Object.toQueryString(data);  
}  
};  
 
Form.Methods = {  
serialize: function(form, options) {  
return Form.serializeElements(Form.getElements(form), options);  
},  
 
getElements: function(form) {  
return $A($(form).getElementsByTagName('*')).inject([],  
function(elements, child) {  
if (Form.Element.Serializers[child.tagName.toLowerCase()])  
elements.push(Element.extend(child));  
return elements;  
}  
);  
},  
 
getInputs: function(form, typeName, name) {  
form = $(form);  
var inputs = form.getElementsByTagName('input');  
 
if (!typeName && !name) return $A(inputs).map(Element.extend);  
 
for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {  
var input = inputs[i];  
if ((typeName && input.type != typeName) || (name && input.name != name))  
continue;  
matchingInputs.push(Element.extend(input));  
}  
 
return matchingInputs;  
},  
 
disable: function(form) {  
form = $(form);  
Form.getElements(form).invoke('disable');  
return form;  
},  
 
enable: function(form) {  
form = $(form);  
Form.getElements(form).invoke('enable');  
return form;  
},  
 
findFirstElement: function(form) {  
var elements = $(form).getElements().findAll(function(element) {  
return 'hidden' != element.type && !element.disabled;  
});  
var firstByIndex = elements.findAll(function(element) {  
return element.hasAttribute('tabIndex') && element.tabIndex >= 0;  
}).sortBy(function(element) { return element.tabIndex }).first();  
 
return firstByIndex ? firstByIndex : elements.find(function(element) {  
return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());  
});  
},  
 
focusFirstElement: function(form) {  
form = $(form);  
form.findFirstElement().activate();  
return form;  
},  
 
request: function(form, options) {  
form = $(form), options = Object.clone(options || { });  
 
var params = options.parameters, action = form.readAttribute('action') || '';  
if (action.blank()) action = window.location.href;  
options.parameters = form.serialize(true);  
 
if (params) {  
if (Object.isString(params)) params = params.toQueryParams();  
Object.extend(options.parameters, params);  
}  
 
if (form.hasAttribute('method') && !options.method)  
options.method = form.method;  
 
return new Ajax.Request(action, options);  
}  
};  
 
/*--------------------------------------------------------------------------*/  
 
Form.Element = {  
focus: function(element) {  
$(element).focus();  
return element;  
},  
 
select: function(element) {  
$(element).select();  
return element;  
}  
};  
 
Form.Element.Methods = {  
serialize: function(element) {  
element = $(element);  
if (!element.disabled && element.name) {  
var value = element.getValue();  
if (value != undefined) {  
var pair = { };  
pair[element.name] = value;  
return Object.toQueryString(pair);  
}  
}  
return '';  
},  
 
getValue: function(element) {  
element = $(element);  
var method = element.tagName.toLowerCase();  
return Form.Element.Serializers[method](element);  
},  
 
setValue: function(element, value) {  
element = $(element);  
var method = element.tagName.toLowerCase();  
Form.Element.Serializers[method](element, value);  
return element;  
},  
 
clear: function(element) {  
$(element).value = '';  
return element;  
},  
 
present: function(element) {  
return $(element).value != '';  
},  
 
activate: function(element) {  
element = $(element);  
try {  
element.focus();  
if (element.select && (element.tagName.toLowerCase() != 'input' ||  
!['button', 'reset', 'submit'].include(element.type)))  
element.select();  
} catch (e) { }  
return element;  
},  
 
disable: function(element) {  
element = $(element);  
element.blur();  
element.disabled = true;  
return element;  
},  
 
enable: function(element) {  
element = $(element);  
element.disabled = false;  
return element;  
}  
};  
 
/*--------------------------------------------------------------------------*/  
 
var Field = Form.Element;  
var $F = Form.Element.Methods.getValue;  
 
/*--------------------------------------------------------------------------*/  
 
Form.Element.Serializers = {  
input: function(element, value) {  
switch (element.type.toLowerCase()) {  
case 'checkbox':  
case 'radio':  
return Form.Element.Serializers.inputSelector(element, value);  
default:  
return Form.Element.Serializers.textarea(element, value);  
}  
},  
 
inputSelector: function(element, value) {  
if (Object.isUndefined(value)) return element.checked ? element.value : null;  
else element.checked = !!value;  
},  
 
textarea: function(element, value) {  
if (Object.isUndefined(value)) return element.value;  
else element.value = value;  
},  
 
select: function(element, index) {  
if (Object.isUndefined(index))  
return this[element.type == 'select-one' ?  
'selectOne' : 'selectMany'](element);  
else {  
var opt, value, single = !Object.isArray(index);  
for (var i = 0, length = element.length; i < length; i++) {  
opt = element.options[i];  
value = this.optionValue(opt);  
if (single) {  
if (value == index) {  
opt.selected = true;  
return;  
}  
}  
else opt.selected = index.include(value);  
}  
}  
},  
 
selectOne: function(element) {  
var index = element.selectedIndex;  
return index >= 0 ? this.optionValue(element.options[index]) : null;  
},  
 
selectMany: function(element) {  
var values, length = element.length;  
if (!length) return null;  
 
for (var i = 0, values = []; i < length; i++) {  
var opt = element.options[i];  
if (opt.selected) values.push(this.optionValue(opt));  
}  
return values;  
},  
 
optionValue: function(opt) {  
// extend element because hasAttribute may not be native  
return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;  
}  
};  
 
/*--------------------------------------------------------------------------*/  
 
Abstract.TimedObserver = Class.create(PeriodicalExecuter, {  
initialize: function($super, element, frequency, callback) {  
$super(callback, frequency);  
this.element = $(element);  
this.lastValue = this.getValue();  
},  
 
execute: function() {  
var value = this.getValue();  
if (Object.isString(this.lastValue) && Object.isString(value) ?  
this.lastValue != value : String(this.lastValue) != String(value)) {  
this.callback(this.element, value);  
this.lastValue = value;  
}  
}  
});  
 
Form.Element.Observer = Class.create(Abstract.TimedObserver, {  
getValue: function() {  
return Form.Element.getValue(this.element);  
}  
});  
 
Form.Observer = Class.create(Abstract.TimedObserver, {  
getValue: function() {  
return Form.serialize(this.element);  
}  
});  
 
/*--------------------------------------------------------------------------*/  
 
Abstract.EventObserver = Class.create({  
initialize: function(element, callback) {  
this.element = $(element);  
this.callback = callback;  
 
this.lastValue = this.getValue();  
if (this.element.tagName.toLowerCase() == 'form')  
this.registerFormCallbacks();  
else  
this.registerCallback(this.element);  
},  
 
onElementEvent: function() {  
var value = this.getValue();  
if (this.lastValue != value) {  
this.callback(this.element, value);  
this.lastValue = value;  
}  
},  
 
registerFormCallbacks: function() {  
Form.getElements(this.element).each(this.registerCallback, this);  
},  
 
registerCallback: function(element) {  
if (element.type) {  
switch (element.type.toLowerCase()) {  
case 'checkbox':  
case 'radio':  
Event.observe(element, 'click', this.onElementEvent.bind(this));  
break;  
default:  
Event.observe(element, 'change', this.onElementEvent.bind(this));  
break;  
}  
}  
}  
});  
 
Form.Element.EventObserver = Class.create(Abstract.EventObserver, {  
getValue: function() {  
return Form.Element.getValue(this.element);  
}  
});  
 
Form.EventObserver = Class.create(Abstract.EventObserver, {  
getValue: function() {  
return Form.serialize(this.element);  
}  
});  
if (!window.Event) var Event = { };  
 
Object.extend(Event, {  
KEY_BACKSPACE: 8,  
KEY_TAB: 9,  
KEY_RETURN: 13,  
KEY_ESC: 27,  
KEY_LEFT: 37,  
KEY_UP: 38,  
KEY_RIGHT: 39,  
KEY_DOWN: 40,  
KEY_DELETE: 46,  
KEY_HOME: 36,  
KEY_END: 35,  
KEY_PAGEUP: 33,  
KEY_PAGEDOWN: 34,  
KEY_INSERT: 45,  
 
cache: { },  
 
relatedTarget: function(event) {  
var element;  
switch(event.type) {  
case 'mouseover': element = event.fromElement; break;  
case 'mouseout': element = event.toElement; break;  
default: return null;  
}  
return Element.extend(element);  
}  
});  
 
Event.Methods = (function() {  
var isButton;  
 
if (Prototype.Browser.IE) {  
var buttonMap = { 0: 1, 1: 4, 2: 2 };  
isButton = function(event, code) {  
return event.button == buttonMap[code];  
};  
 
} else if (Prototype.Browser.WebKit) {  
isButton = function(event, code) {  
switch (code) {  
case 0: return event.which == 1 && !event.metaKey;  
case 1: return event.which == 1 && event.metaKey;  
default: return false;  
}  
};  
 
} else {  
isButton = function(event, code) {  
return event.which ? (event.which === code + 1) : (event.button === code);  
};  
}  
 
return {  
isLeftClick: function(event) { return isButton(event, 0) },  
isMiddleClick: function(event) { return isButton(event, 1) },  
isRightClick: function(event) { return isButton(event, 2) },  
 
element: function(event) {  
var node = Event.extend(event).target;  
return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node);  
},  
 
findElement: function(event, expression) {  
var element = Event.element(event);  
if (!expression) return element;  
var elements = [element].concat(element.ancestors());  
return Selector.findElement(elements, expression, 0);  
},  
 
pointer: function(event) {  
return {  
x: event.pageX || (event.clientX +  
(document.documentElement.scrollLeft || document.body.scrollLeft)),  
y: event.pageY || (event.clientY +  
(document.documentElement.scrollTop || document.body.scrollTop))  
};  
},  
 
pointerX: function(event) { return Event.pointer(event).x },  
pointerY: function(event) { return Event.pointer(event).y },  
 
stop: function(event) {  
Event.extend(event);  
event.preventDefault();  
event.stopPropagation();  
event.stopped = true;  
}  
};  
})();  
 
Event.extend = (function() {  
var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {  
m[name] = Event.Methods[name].methodize();  
return m;  
});  
 
if (Prototype.Browser.IE) {  
Object.extend(methods, {  
stopPropagation: function() { this.cancelBubble = true },  
preventDefault: function() { this.returnValue = false },  
inspect: function() { return "[object Event]" }  
});  
 
return function(event) {  
if (!event) return false;  
if (event._extendedByPrototype) return event;  
 
event._extendedByPrototype = Prototype.emptyFunction;  
var pointer = Event.pointer(event);  
Object.extend(event, {  
target: event.srcElement,  
relatedTarget: Event.relatedTarget(event),  
pageX: pointer.x,  
pageY: pointer.y  
});  
return Object.extend(event, methods);  
};  
 
} else {  
Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__;  
Object.extend(Event.prototype, methods);  
return Prototype.K;  
}  
})();  
 
Object.extend(Event, (function() {  
var cache = Event.cache;  
 
function getEventID(element) {  
if (element._prototypeEventID) return element._prototypeEventID[0];  
arguments.callee.id = arguments.callee.id || 1;  
return element._prototypeEventID = [++arguments.callee.id];  
}  
 
function getDOMEventName(eventName) {  
if (eventName && eventName.include(':')) return "dataavailable";  
return eventName;  
}  
 
function getCacheForID(id) {  
return cache[id] = cache[id] || { };  
}  
 
function getWrappersForEventName(id, eventName) {  
var c = getCacheForID(id);  
return c[eventName] = c[eventName] || [];  
}  
 
function createWrapper(element, eventName, handler) {  
var id = getEventID(element);  
var c = getWrappersForEventName(id, eventName);  
if (c.pluck("handler").include(handler)) return false;  
 
var wrapper = function(event) {  
if (!Event || !Event.extend ||  
(event.eventName && event.eventName != eventName))  
return false;  
 
Event.extend(event);  
handler.call(element, event);  
};  
 
wrapper.handler = handler;  
c.push(wrapper);  
return wrapper;  
}  
 
function findWrapper(id, eventName, handler) {  
var c = getWrappersForEventName(id, eventName);  
return c.find(function(wrapper) { return wrapper.handler == handler });  
}  
 
function destroyWrapper(id, eventName, handler) {  
var c = getCacheForID(id);  
if (!c[eventName]) return false;  
c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));  
}  
 
function destroyCache() {  
for (var id in cache)  
for (var eventName in cache[id])  
cache[id][eventName] = null;  
}  
 
if (window.attachEvent) {  
window.attachEvent("onunload", destroyCache);  
}  
 
return {  
observe: function(element, eventName, handler) {  
element = $(element);  
var name = getDOMEventName(eventName);  
 
var wrapper = createWrapper(element, eventName, handler);  
if (!wrapper) return element;  
 
if (element.addEventListener) {  
element.addEventListener(name, wrapper, false);  
} else {  
element.attachEvent("on" + name, wrapper);  
}  
 
return element;  
},  
 
stopObserving: function(element, eventName, handler) {  
element = $(element);  
var id = getEventID(element), name = getDOMEventName(eventName);  
 
if (!handler && eventName) {  
getWrappersForEventName(id, eventName).each(function(wrapper) {  
element.stopObserving(eventName, wrapper.handler);  
});  
return element;  
 
} else if (!eventName) {  
Object.keys(getCacheForID(id)).each(function(eventName) {  
element.stopObserving(eventName);  
});  
return element;  
}  
 
var wrapper = findWrapper(id, eventName, handler);  
if (!wrapper) return element;  
 
if (element.removeEventListener) {  
element.removeEventListener(name, wrapper, false);  
} else {  
element.detachEvent("on" + name, wrapper);  
}  
 
destroyWrapper(id, eventName, handler);  
 
return element;  
},  
 
fire: function(element, eventName, memo) {  
element = $(element);  
if (element == document && document.createEvent && !element.dispatchEvent)  
element = document.documentElement;  
 
var event;  
if (document.createEvent) {  
event = document.createEvent("HTMLEvents");  
event.initEvent("dataavailable", true, true);  
} else {  
event = document.createEventObject();  
event.eventType = "ondataavailable";  
}  
 
event.eventName = eventName;  
event.memo = memo || { };  
 
if (document.createEvent) {  
element.dispatchEvent(event);  
} else {  
element.fireEvent(event.eventType, event);  
}  
 
return Event.extend(event);  
}  
};  
})());  
 
Object.extend(Event, Event.Methods);  
 
Element.addMethods({  
fire: Event.fire,  
observe: Event.observe,  
stopObserving: Event.stopObserving  
});  
 
Object.extend(document, {  
fire: Element.Methods.fire.methodize(),  
observe: Element.Methods.observe.methodize(),  
stopObserving: Element.Methods.stopObserving.methodize(),  
loaded: false  
});  
 
(function() {  
/* Support for the DOMContentLoaded event is based on work by Dan Webb,  
Matthias Miller, Dean Edwards and John Resig. */  
 
var timer;  
 
function fireContentLoadedEvent() {  
if (document.loaded) return;  
if (timer) window.clearInterval(timer);  
document.fire("dom:loaded");  
document.loaded = true;  
}  
 
if (document.addEventListener) {  
if (Prototype.Browser.WebKit) {  
timer = window.setInterval(function() {  
if (/loaded|complete/.test(document.readyState))  
fireContentLoadedEvent();  
}, 0);  
 
Event.observe(window, "load", fireContentLoadedEvent);  
 
} else {  
document.addEventListener("DOMContentLoaded",  
fireContentLoadedEvent, false);  
}  
 
} else {  
document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");  
$("__onDOMContentLoaded").onreadystatechange = function() {  
if (this.readyState == "complete") {  
this.onreadystatechange = null;  
fireContentLoadedEvent();  
}  
};  
}  
})();  
/*------------------------------- DEPRECATED -------------------------------*/  
 
Hash.toQueryString = Object.toQueryString;  
 
var Toggle = { display: Element.toggle };  
 
Element.Methods.childOf = Element.Methods.descendantOf;  
 
var Insertion = {  
Before: function(element, content) {  
return Element.insert(element, {before:content});  
},  
 
Top: function(element, content) {  
return Element.insert(element, {top:content});  
},  
 
Bottom: function(element, content) {  
return Element.insert(element, {bottom:content});  
},  
 
After: function(element, content) {  
return Element.insert(element, {after:content});  
}  
};  
 
var $continue = new Error('"throw $continue" is deprecated, use "return" instead');  
 
// This should be moved to script.aculo.us; notice the deprecated methods  
// further below, that map to the newer Element methods.  
var Position = {  
// set to true if needed, warning: firefox performance problems  
// NOT neeeded for page scrolling, only if draggable contained in  
// scrollable elements  
includeScrollOffsets: false,  
 
// must be called before calling withinIncludingScrolloffset, every time the  
// page is scrolled  
prepare: function() {  
this.deltaX = window.pageXOffset  
|| document.documentElement.scrollLeft  
|| document.body.scrollLeft  
|| 0;  
this.deltaY = window.pageYOffset  
|| document.documentElement.scrollTop  
|| document.body.scrollTop  
|| 0;  
},  
 
// caches x/y coordinate pair to use with overlap  
within: function(element, x, y) {  
if (this.includeScrollOffsets)  
return this.withinIncludingScrolloffsets(element, x, y);  
this.xcomp = x;  
this.ycomp = y;  
this.offset = Element.cumulativeOffset(element);  
 
return (y >= this.offset[1] &&  
y < this.offset[1] + element.offsetHeight &&  
x >= this.offset[0] &&  
x < this.offset[0] + element.offsetWidth);  
},  
 
withinIncludingScrolloffsets: function(element, x, y) {  
var offsetcache = Element.cumulativeScrollOffset(element);  
 
this.xcomp = x + offsetcache[0] - this.deltaX;  
this.ycomp = y + offsetcache[1] - this.deltaY;  
this.offset = Element.cumulativeOffset(element);  
 
return (this.ycomp >= this.offset[1] &&  
this.ycomp < this.offset[1] + element.offsetHeight &&  
this.xcomp >= this.offset[0] &&  
this.xcomp < this.offset[0] + element.offsetWidth);  
},  
 
// within must be called directly before  
overlap: function(mode, element) {  
if (!mode) return 0;  
if (mode == 'vertical')  
return ((this.offset[1] + element.offsetHeight) - this.ycomp) /  
element.offsetHeight;  
if (mode == 'horizontal')  
return ((this.offset[0] + element.offsetWidth) - this.xcomp) /  
element.offsetWidth;  
},  
 
// Deprecation layer -- use newer Element methods now (1.5.2).  
 
cumulativeOffset: Element.Methods.cumulativeOffset,  
 
positionedOffset: Element.Methods.positionedOffset,  
 
absolutize: function(element) {  
Position.prepare();  
return Element.absolutize(element);  
},  
 
relativize: function(element) {  
Position.prepare();  
return Element.relativize(element);  
},  
 
realOffset: Element.Methods.cumulativeScrollOffset,  
 
offsetParent: Element.Methods.getOffsetParent,  
 
page: Element.Methods.viewportOffset,  
 
clone: function(source, target, options) {  
options = options || { };  
return Element.clonePosition(target, source, options);  
}  
};  
 
/*--------------------------------------------------------------------------*/  
 
if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){  
function iter(name) {  
return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";  
}  
 
instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?  
function(element, className) {  
className = className.toString().strip();  
var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);  
return cond ? document._getElementsByXPath('.//*' + cond, element) : [];  
} : function(element, className) {  
className = className.toString().strip();  
var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);  
if (!classNames && !className) return elements;  
 
var nodes = $(element).getElementsByTagName('*');  
className = ' ' + className + ' ';  
 
for (var i = 0, child, cn; child = nodes[i]; i++) {  
if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||  
(classNames && classNames.all(function(name) {  
return !name.toString().blank() && cn.include(' ' + name + ' ');  
}))))  
elements.push(Element.extend(child));  
}  
return elements;  
};  
 
return function(className, parentElement) {  
return $(parentElement || document.body).getElementsByClassName(className);  
};  
}(Element.Methods);  
 
/*--------------------------------------------------------------------------*/  
 
Element.ClassNames = Class.create();  
Element.ClassNames.prototype = {  
initialize: function(element) {  
this.element = $(element);  
},  
 
_each: function(iterator) {  
this.element.className.split(/\s+/).select(function(name) {  
return name.length > 0;  
})._each(iterator);  
},  
 
set: function(className) {  
this.element.className = className;  
},  
 
add: function(classNameToAdd) {  
if (this.include(classNameToAdd)) return;  
this.set($A(this).concat(classNameToAdd).join(' '));  
},  
 
remove: function(classNameToRemove) {  
if (!this.include(classNameToRemove)) return;  
this.set($A(this).without(classNameToRemove).join(' '));  
},  
 
toString: function() {  
return $A(this).join(' ');  
}  
};  
 
Object.extend(Element.ClassNames.prototype, Enumerable);  
 
/*--------------------------------------------------------------------------*/  
 
Element.addMethods();  
directory:b/js/flotr2 (new)
 
file:a/js/jquery-1.6.1.min.js (deleted)
/*!  
* 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("<!doctype><html><body></body></html>");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<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bF.test(a)?d(a,e):b_(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bU,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bQ),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bD(a,b,c){var d=b==="width"?bx:by,e=b==="width"?a.offsetWidth:a.offsetHeight;if(c==="border")return e;f.each(d,function(){c||(e-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?e+=parseFloat(f.css(a,"margin"+this))||0:e-=parseFloat(f.css(a,"border"+this+"Width"))||0});return e}function bn(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bm(a){f.nodeName(a,"input")?bl(a):a.getElementsByTagName&&f.grep(a.getElementsByTagName("input"),bl)}function bl(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bk(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bj(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bi(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bh(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function X(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(S.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=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;i<s.length;i++)g=s[i],g.origType.replace(y,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)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(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)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(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:E?function(a){return a==null?"":E.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?C.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(F)return F.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=D.call(arguments,2),g=function(){return a.apply(c,f.concat(D.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){G["[object "+b+"]"]=b.toLowerCase()}),x=e.uaMatch(w),x.browser&&(e.browser[x.browser]=!0,e.browser.version=x.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?z=function(){c.removeEventListener("DOMContentLoaded",z,!1),e.ready()}:c.attachEvent&&(z=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",z),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g](h)}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?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<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",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="<div style='width:4px;'></div>",j.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",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<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u=/\:/,v,w;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.addClass(a.call(this,b,c.attr("class")||""))});if(a&&typeof a=="string"){var b=(a||"").split(o);for(var c=0,d=this.length;c<d;c++){var e=this[c];if(e.nodeType===1)if(!e.className)e.className=a;else{var g=" "+e.className+" ",h=e.className;for(var i=0,j=b.length;i<j;i++)g.indexOf(" "+b[i]+" ")<0&&(h+=" "+b[i]);e.className=f.trim(h)}}}return this},removeClass:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.removeClass(a.call(this,b,c.attr("class")))});if(a&&typeof a=="string"||a===b){var c=(a||"").split(o);for(var d=0,e=this.length;d<e;d++){var g=this[d];if(g.nodeType===1&&g.className)if(a){var h=(" "+g.className+" ").replace(n," ");for(var i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){var d=f(this);d.toggleClass(a.call(this,c,d.attr("class"),b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(n," ").indexOf(b)>-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<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=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<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=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<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,O(a.origType,a.selector),f.extend({},a,{handler:N,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,O(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?F:E):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=F;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=F;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=F,this.stopPropagation()},isDefaultPrevented:E,isPropagationStopped:E,isImmediatePropagationStopped:E};var G=function(a){var b=a.relatedTarget;a.type=a.data;try{if(b&&b!==c&&!b.parentNode)return;while(b&&b!==this)b=b.parentNode;b!==this&&f.event.handle.apply(this,arguments)}catch(d){}},H=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?H:G,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?H:G)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&f(b).closest("form").length&&L("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&L("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var I,J=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-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;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var M={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||E,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=y.exec(h),k="",j&&(k=j[0],h=h.replace(y,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,M[h]?(a.push(M[h]+k),h=h+k):h=(M[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+O(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+O(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?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;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){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<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\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;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=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 b<c[3]-0},gt:function(a,b,c){return b>c[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<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=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<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",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 href='#'></a>",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="<p class='TEST'></p>";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="<div class='test e'></div><div class='test'></div>";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;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var P=/Until$/,Q=/^(?:parents|prevUntil|prevAll)/,R=/,/,S=/^.[^:#\[\.,]*$/,T=Array.prototype.slice,U=f.expr.match.POS,V={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(X(this,a,!1),"not",a)},filter:function(a){return this.pushStack(X(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0: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<e;d++)i=a[d],j[i]||(j[i]=U.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-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<e;d++){g=this[d];while(g){if(l?l.index(g)>-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=/<tbody/i,bb=/<|&#?\w+;/,bc=/<(?:script|object|embed|option|style)/i,bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_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<div>","</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></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bh(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bn)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i=b&&b[0]?b[0].ownerDocument||b[0]:c;a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!bc.test(a[0])&&(f.support.checkClone||!bd.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?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></$2>");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]==="<table>"&&!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<r;i++)bm(k[i]);else bm(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bo=/alpha\([^)]*\)/i,bp=/opacity=([^)]*)/,bq=/-([a-z])/ig,br=/([A-Z]|^ms)/g,bs=/^-?\d+(?:px)?$/i,bt=/^-?\d/,bu=/^[+\-]=/,bv=/[^+\-\.\de]+/g,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB,bC=function(a,b){return b.toUpperCase()};f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0,widows:!0,orphans:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d;if(h==="number"&&isNaN(d)||d==null)return;h==="string"&&bu.test(d)&&(d=+d.replace(bv,"")+parseFloat(f.css(a,c))),h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bq,bC)}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){a.offsetWidth!==0?e=bD(a,b,d):f.swap(a,bw,function(){e=bD(a,b,d)});if(e<=0){e=bz(a,b,b),e==="0px"&&bB&&(e=bB(a,b,b));if(e!=null)return e===""||e==="auto"?"0px":e}if(e<0||e==null){e=a.style[b];return e===""||e==="auto"?"0px":e}return typeof e=="string"?e:e+"px"}},set:function(a,b){if(!bs.test(b))return b;b=parseFloat(b);if(b>=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\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/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("<div>").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<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cv(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cm.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=cn.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this),f.isFunction(d.old)&&d.old.call(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.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,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function h(a){return d.step(a)}var d=this,e=f.fx,g;this.startTime=cq||cs(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,h.elem=this.elem,h()&&f.timers.push(h)&&!co&&(cr?(co=1,g=function(){co&&(cr(g),e.tick())},cr(g)):co=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cq||cs(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=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<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";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);  
/*!  
* jQuery Mobile v1.0b1  
* http://jquerymobile.com/  
*  
* Copyright 2010, jQuery Project  
* Dual licensed under the MIT or GPL Version 2 licenses.  
* http://jquery.org/license  
*/  
/*!  
* jQuery UI Widget @VERSION  
*  
* 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/Widget  
*/  
(function( $, undefined ) {  
 
// jQuery 1.4+  
if ( $.cleanData ) {  
var _cleanData = $.cleanData;  
$.cleanData = function( elems ) {  
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {  
$( elem ).triggerHandler( "remove" );  
}  
_cleanData( elems );  
};  
} else {  
var _remove = $.fn.remove;  
$.fn.remove = function( selector, keepData ) {  
return this.each(function() {  
if ( !keepData ) {  
if ( !selector || $.filter( selector, [ this ] ).length ) {  
$( "*", this ).add( [ this ] ).each(function() {  
$( this ).triggerHandler( "remove" );  
});  
}  
}  
return _remove.call( $(this), selector, keepData );  
});  
};  
}  
 
$.widget = function( name, base, prototype ) {  
var namespace = name.split( "." )[ 0 ],  
fullName;  
name = name.split( "." )[ 1 ];  
fullName = namespace + "-" + name;  
 
if ( !prototype ) {  
prototype = base;  
base = $.Widget;  
}  
 
// create selector for plugin  
$.expr[ ":" ][ fullName ] = function( elem ) {  
return !!$.data( elem, name );  
};  
 
$[ namespace ] = $[ namespace ] || {};  
$[ namespace ][ name ] = function( options, element ) {  
// allow instantiation without initializing for simple inheritance  
if ( arguments.length ) {  
this._createWidget( options, element );  
}  
};  
 
var basePrototype = new base();  
// we need to make the options hash a property directly on the new instance  
// otherwise we'll modify the options hash on the prototype that we're  
// inheriting from  
// $.each( basePrototype, function( key, val ) {  
// if ( $.isPlainObject(val) ) {  
// basePrototype[ key ] = $.extend( {}, val );  
// }  
// });  
basePrototype.options = $.extend( true, {}, basePrototype.options );  
$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {  
namespace: namespace,  
widgetName: name,  
widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,  
widgetBaseClass: fullName  
}, prototype );  
 
$.widget.bridge( name, $[ namespace ][ name ] );  
};  
 
$.widget.bridge = function( name, object ) {  
$.fn[ name ] = function( options ) {  
var isMethodCall = typeof options === "string",  
args = Array.prototype.slice.call( arguments, 1 ),  
returnValue = this;  
 
// allow multiple hashes to be passed on init  
options = !isMethodCall && args.length ?  
$.extend.apply( null, [ true, options ].concat(args) ) :  
options;  
 
// prevent calls to internal methods  
if ( isMethodCall && options.charAt( 0 ) === "_" ) {  
return returnValue;  
}  
 
if ( isMethodCall ) {  
this.each(function() {  
var instance = $.data( this, name );  
if ( !instance ) {  
throw "cannot call methods on " + name + " prior to initialization; " +  
"attempted to call method '" + options + "'";  
}  
if ( !$.isFunction( instance[options] ) ) {  
throw "no such method '" + options + "' for " + name + " widget instance";  
}  
var methodValue = instance[ options ].apply( instance, args );  
if ( methodValue !== instance && methodValue !== undefined ) {  
returnValue = methodValue;  
return false;  
}  
});  
} else {  
this.each(function() {  
var instance = $.data( this, name );  
if ( instance ) {  
instance.option( options || {} )._init();  
} else {  
$.data( this, name, new object( options, this ) );  
}  
});  
}  
 
return returnValue;  
};  
};  
 
$.Widget = function( options, element ) {  
// allow instantiation without initializing for simple inheritance  
if ( arguments.length ) {  
this._createWidget( options, element );  
}  
};  
 
$.Widget.prototype = {  
widgetName: "widget",  
widgetEventPrefix: "",  
options: {  
disabled: false  
},  
_createWidget: function( options, element ) {  
// $.widget.bridge stores the plugin instance, but we do it anyway  
// so that it's stored even before the _create function runs  
$.data( element, this.widgetName, this );  
this.element = $( element );  
this.options = $.extend( true, {},  
this.options,  
this._getCreateOptions(),  
options );  
 
var self = this;  
this.element.bind( "remove." + this.widgetName, function() {  
self.destroy();  
});  
 
this._create();  
this._trigger( "create" );  
this._init();  
},  
_getCreateOptions: function() {  
var options = {};  
if ( $.metadata ) {  
options = $.metadata.get( element )[ this.widgetName ];  
}  
return options;  
},  
_create: