Merge branch 'master' of github.com:maxious/ACTBus-ui
Conflicts:
include/common-auth.inc.php
lib/openid-php/Auth/OpenID/Consumer.php
lib/openid-php/Auth/OpenID/Server.php
lib/openid-php/Auth/OpenID/TrustRoot.php
lib/openid-php/Auth/Yadis/Manager.php
lib/openid-php/Auth/Yadis/XRDS.php
--- /dev/null
+++ b/.gitignore
@@ -1,1 +1,9 @@
+/labs/tiles/12
+/labs/tiles/13
+/labs/tiles/14
+/labs/tiles/15
+/labs/tiles/16
+/labs/tiles/17
+/labs/tiles/19
+/nbproject/private/
--- a/about.php
+++ b/about.php
@@ -1,35 +1,53 @@
<?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_header("About", "about")
?>
<p>
-Busness Time - An ACT bus timetable webapp<br />
-Based on the maxious-canberra-transit-feed (<a
-href="http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip">download</a>,
-last updated <?php
-echo date("F d Y.", @filemtime('cbrfeed.zip')); ?>)<br />
-Source code for the <a
-href="https://github.com/maxious/ACTBus-data">transit
-feed</a> and <a href="https://github.com/maxious/ACTBus-ui">this
-site</a> available from github.<br />
-Uses jQuery Mobile, PHP, PostgreSQL, OpenTripPlanner, OpenLayers, OpenStreetMap, Cloudmade Geocoder and Tile Service<br />
-<br />
-Feedback encouraged; contact maxious@lambdacomplex.org<br />
+ Busness Time - An ACT bus timetable webapp<br />
+ Based on the maxious-canberra-transit-feed (<a
+ href="http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip">download</a>,
+ last updated <?php echo date("F d Y.", @filemtime('cbrfeed.zip')); ?>)<br />
+ Source code for the <a
+ href="https://github.com/maxious/ACTBus-data">transit
+ feed</a> and <a href="https://github.com/maxious/ACTBus-ui">this
+ site</a> available from github.<br />
+ Uses jQuery Mobile, PHP, PostgreSQL, OpenTripPlanner, OpenLayers, OpenStreetMap, Cloudmade Geocoder and Tile Service<br />
<br />
-Some icons by Joseph Wain / glyphish.com<br />
-Native clients also available for iPhone(<a href="http://itunes.apple.com/au/app/cbrtimetable/id444287349?mt=8">cbrTimetable by Sandor Kolotenko</a>
-, <a href="http://itunes.apple.com/au/app/act-buses/id376634797?mt=8">ACT Buses by David Sullivan</a>)
-and Android (<a href="https://market.android.com/details?id=com.action">MyBus 2.0 by Imagine Team</a>)
-<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();
-?>
+ Feedback encouraged; contact maxious@lambdacomplex.org<br />
+ <br />
+ Some icons by Joseph Wain / glyphish.com<br />
+ Native clients also available for iPhone(<a href="http://itunes.apple.com/au/app/cbrtimetable/id444287349?mt=8">cbrTimetable by Sandor Kolotenko</a>
+ , <a href="http://itunes.apple.com/au/app/act-buses/id376634797?mt=8">ACT Buses by David Sullivan</a>)
+ and Android (<a href="https://market.android.com/details?id=com.action">MyBus 2.0 by Imagine Team</a>)
+ <br />
+ GTFS-realtime API;
+ Alerts and Trip Updates (but only Cancelled or Stop Skipped)
+ Default format binary 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();
+ ?>
--- a/aws/awsStartup.sh
+++ b/aws/awsStartup.sh
@@ -5,38 +5,9 @@
#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
+sh busuiphp.sh
+sh busuidb.sh
+sh busuiotp.sh
-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;\"
-#psql -d transitdata -c "GRANT SELECT,INSERT ON TABLE myway_observations,myway_routes,myway_stops,myway_timingdeltas TO transitdata;"
-#psql -d transitdata -c "GRANT SELECT,INSERT,UPDATE ON TABLE myway_routes,myway_stops TO transitdata;"
-##psql -d transitdata -c "GRANT SELECT ON ALL TABLES IN SCHEMA public 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
--- /dev/null
+++ b/aws/busuidb.sh
@@ -1,1 +1,14 @@
-
+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;"
+#psql -d transitdata -c "GRANT SELECT,INSERT ON TABLE myway_observations,myway_routes,myway_stops,myway_timingdeltas TO transitdata;"
+#psql -d transitdata -c "GRANT SELECT,INSERT,UPDATE ON TABLE myway_routes,myway_stops TO transitdata;"
+##psql -d transitdata -c "GRANT SELECT ON ALL TABLES IN SCHEMA public TO transitdata;"
+php /var/www/updatedb.php
--- /dev/null
+++ b/aws/busuiotp.sh
@@ -1,1 +1,10 @@
+wget http://s3-ap-southeast-1.amazonaws.com/busresources/Graph.obj \
+-O /tmp/Graph.obj
+/etc/init.d/tomcat6 stop
+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
--- /dev/null
+++ b/aws/busuiotp.testing.sh
@@ -1,1 +1,10 @@
+wget http://s3-ap-southeast-1.amazonaws.com/busresources/testing/Graph.obj \
+-O /tmp/Graph.obj
+/etc/init.d/tomcat6 stop
+rm -rfv /usr/share/tomcat6/webapps/opentripplanner*
+wget http://s3-ap-southeast-1.amazonaws.com/busresources/testing/opentripplanner-webapp.war \
+-O /usr/share/tomcat6/webapps/opentripplanner-webapp.war
+wget http://s3-ap-southeast-1.amazonaws.com/busresources/testing/opentripplanner-api-webapp.war \
+-O /usr/share/tomcat6/webapps/opentripplanner-api-webapp.war
+/etc/init.d/tomcat6 restart
--- /dev/null
+++ b/aws/busuiphp.sh
@@ -1,1 +1,17 @@
+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
+
+mkdir /var/www/lib/openid-php/oid_store
+chcon -R -t httpd_sys_content_rw_t /var/www/lib/openid-php/oid_store
+chmod -R 777 /var/www/lib/openid-php/oid_store
+
+wget http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip \
+-O /var/www/cbrfeed.zip
--- /dev/null
+++ b/aws/data-sources.xml
@@ -1,1 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+ <!-- Single graph -->
+ <import resource="classpath:org/opentripplanner/api/application-context.xml" />
+
+ <bean id="graphBundle" class="org.opentripplanner.model.GraphBundle">
+ <property name="path" value="/tmp/" />
+ </bean>
+
+</beans>
+
--- a/css/jquery.mobile-1.0b2.css
+++ /dev/null
@@ -1,1641 +1,1 @@
-/*!
- * jQuery Mobile v1.0b2
- * 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.
-*/
-
-/* A
------------------------------------------------------------------------------------------------------------*/
-
-.ui-bar-a {
- border: 1px solid #2A2A2A;
- background: #111111;
- color: #ffffff;
- font-weight: bold;
- text-shadow: 0 -1px 1px #000000;
- background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#111)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #3c3c3c, #111); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #3c3c3c, #111); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #3c3c3c, #111); /* IE10 */
- background-image: -o-linear-gradient(top, #3c3c3c, #111); /* Opera 11.10+ */
- background-image: linear-gradient(top, #3c3c3c, #111);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#666), to(#222)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #666, #222); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #666, #222); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #666, #222); /* IE10 */
- background-image: -o-linear-gradient(top, #666, #222); /* Opera 11.10+ */
- background-image: linear-gradient(top, #666, #222);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#555), to(#333)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #555, #333); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #555, #333); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #555, #333); /* IE10 */
- background-image: -o-linear-gradient(top, #555, #333); /* Opera 11.10+ */
- background-image: linear-gradient(top, #555, #333);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#666), to(#444)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #666, #444); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #666, #444); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #666, #444); /* IE10 */
- background-image: -o-linear-gradient(top, #666, #444); /* Opera 11.10+ */
- background-image: linear-gradient(top, #666, #444);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#333), to(#5a5a5a)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #333, #5a5a5a); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #333, #5a5a5a); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #333, #5a5a5a); /* IE10 */
- background-image: -o-linear-gradient(top, #333, #5a5a5a); /* Opera 11.10+ */
- background-image: linear-gradient(top, #333, #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: -webkit-gradient(linear, left top, left bottom, from(#81a8ce), to(#5e87b0)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #81a8ce, #5e87b0); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #81a8ce, #5e87b0); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #81a8ce, #5e87b0); /* IE10 */
- background-image: -o-linear-gradient(top, #81a8ce, #5e87b0); /* Opera 11.10+ */
- background-image: linear-gradient(top, #81a8ce, #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: -webkit-gradient(linear, left top, left bottom, from(#e6e6e6), to(#ccc)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #e6e6e6, #ccc); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #e6e6e6, #ccc); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #e6e6e6, #ccc); /* IE10 */
- background-image: -o-linear-gradient(top, #e6e6e6, #ccc); /* Opera 11.10+ */
- background-image: linear-gradient(top, #e6e6e6, #ccc);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#5f9cc5), to(#396b9e)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #5f9cc5, #396b9e); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #5f9cc5, #396b9e); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #5f9cc5, #396b9e); /* IE10 */
- background-image: -o-linear-gradient(top, #5f9cc5, #396b9e); /* Opera 11.10+ */
- background-image: linear-gradient(top, #5f9cc5, #396b9e);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#72b0d4), to(#4b88b6)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #72b0d4, #4b88b6); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #72b0d4, #4b88b6); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #72b0d4, #4b88b6); /* IE10 */
- background-image: -o-linear-gradient(top, #72b0d4, #4b88b6); /* Opera 11.10+ */
- background-image: linear-gradient(top, #72b0d4, #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: -webkit-gradient(linear, left top, left bottom, from(#396b9e), to(#4e89c5)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #396b9e, #4e89c5); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #396b9e, #4e89c5); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #396b9e, #4e89c5); /* IE10 */
- background-image: -o-linear-gradient(top, #396b9e, #4e89c5); /* Opera 11.10+ */
- background-image: linear-gradient(top, #396b9e, #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: -webkit-gradient(linear, left top, left bottom, from(#f0f0f0), to(#e9eaeb)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #f0f0f0, #e9eaeb); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #f0f0f0, #e9eaeb); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #f0f0f0, #e9eaeb); /* IE10 */
- background-image: -o-linear-gradient(top, #f0f0f0, #e9eaeb); /* Opera 11.10+ */
- background-image: linear-gradient(top, #f0f0f0, #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: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#ddd)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #eee, #ddd); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #eee, #ddd); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #eee, #ddd); /* IE10 */
- background-image: -o-linear-gradient(top, #eee, #ddd); /* Opera 11.10+ */
- background-image: linear-gradient(top, #eee, #ddd);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#fdfdfd), to(#eee)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #fdfdfd, #eee); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #fdfdfd, #eee); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #fdfdfd, #eee); /* IE10 */
- background-image: -o-linear-gradient(top, #fdfdfd, #eee); /* Opera 11.10+ */
- background-image: linear-gradient(top, #fdfdfd, #eee);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#ededed), to(#dadada)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #ededed, #dadada); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #ededed, #dadada); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #ededed, #dadada); /* IE10 */
- background-image: -o-linear-gradient(top, #ededed, #dadada); /* Opera 11.10+ */
- background-image: linear-gradient(top, #ededed, #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: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#fdfdfd)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #eee, #fdfdfd); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #eee, #fdfdfd); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #eee, #fdfdfd); /* IE10 */
- background-image: -o-linear-gradient(top, #eee, #fdfdfd); /* Opera 11.10+ */
- background-image: linear-gradient(top, #eee, #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: -webkit-gradient(linear, left top, left bottom, from(#ddd), to(#bbb)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #ddd, #bbb); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #ddd, #bbb); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #ddd, #bbb); /* IE10 */
- background-image: -o-linear-gradient(top, #ddd, #bbb); /* Opera 11.10+ */
- background-image: linear-gradient(top, #ddd, #bbb);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#fdfdfd), to(#eee)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #fdfdfd, #eee); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #fdfdfd, #eee); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #fdfdfd, #eee); /* IE10 */
- background-image: -o-linear-gradient(top, #fdfdfd, #eee); /* Opera 11.10+ */
- background-image: linear-gradient(top, #fdfdfd, #eee);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#fff)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #eee, #fff); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #eee, #fff); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #eee, #fff); /* IE10 */
- background-image: -o-linear-gradient(top, #eee, #fff); /* Opera 11.10+ */
- background-image: linear-gradient(top, #eee, #fff);
-}
-.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: -webkit-gradient(linear, left top, left bottom, from(#fceda7), to(#fadb4e)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #fceda7, #fadb4e); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #fceda7, #fadb4e); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #fceda7, #fadb4e); /* IE10 */
- background-image: -o-linear-gradient(top, #fceda7, #fadb4e); /* Opera 11.10+ */
- background-image: linear-gradient(top, #fceda7, #fadb4e);
-}
-.ui-bar-e,
-.ui-bar-e input,
-.ui-bar-e select,
-.ui-bar-e textarea,
-.ui-bar-e 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: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#faeb9e)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #fff, #faeb9e); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #fff, #faeb9e); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #fff, #faeb9e); /* IE10 */
- background-image: -o-linear-gradient(top, #fff, #faeb9e); /* Opera 11.10+ */
- background-image: linear-gradient(top, #fff, #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: -webkit-gradient(linear, left top, left bottom, from(#fceda7), to(#fadb4e)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #fceda7, #fadb4e); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #fceda7, #fadb4e); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #fceda7, #fadb4e); /* IE10 */
- background-image: -o-linear-gradient(top, #fceda7, #fadb4e); /* Opera 11.10+ */
- background-image: linear-gradient(top, #fceda7, #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: -webkit-gradient(linear, left top, left bottom, from(#fcf0b5), to(#fbe26f)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #fcf0b5, #fbe26f); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #fcf0b5, #fbe26f); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #fcf0b5, #fbe26f); /* IE10 */
- background-image: -o-linear-gradient(top, #fcf0b5, #fbe26f); /* Opera 11.10+ */
- background-image: linear-gradient(top, #fcf0b5, #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: -webkit-gradient(linear, left top, left bottom, from(#fadb4e), to(#fceda7)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #fadb4e, #fceda7); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #fadb4e, #fceda7); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #fadb4e, #fceda7); /* IE10 */
- background-image: -o-linear-gradient(top, #fadb4e, #fceda7); /* Opera 11.10+ */
- background-image: linear-gradient(top, #fadb4e, #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: -webkit-gradient(linear, left top, left bottom, from(#85bae4), to(#5393c5)); /* Saf4+, Chrome */
- background-image: -webkit-linear-gradient(top, #85bae4, #5393c5); /* Chrome 10+, Saf5.1+ */
- background-image: -moz-linear-gradient(top, #85bae4, #5393c5); /* FF3.6 */
- background-image: -ms-linear-gradient(top, #85bae4, #5393c5); /* IE10 */
- background-image: -o-linear-gradient(top, #85bae4, #5393c5); /* Opera 11.10+ */
- background-image: linear-gradient(top, #85bae4, #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-checkbox .ui-icon {
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
- border-radius: 3px;
-}
-.ui-icon-checkbox-off,
-.ui-icon-radio-off {
- background-color: transparent;
-}
-.ui-checkbox-on .ui-icon,
-.ui-radio-on .ui-icon {
- background-color: #4596ce; /* NOTE: this hex should match the active state color. It's repeated here for cascade */
-}
-.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;
- 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.
-*/
-
-/* 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-animation-timing-function: linear;
-}
-@-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; zoom: 1; }
-.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 { 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: block; min-height: 1em; }
-.ui-select .ui-btn-text { text-overflow: ellipsis; overflow: hidden;}
-
-.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 }
-
--- /dev/null
+++ b/css/jquery.mobile-1.0b3.css
@@ -1,1 +1,1700 @@
-
+/*!
+ * jQuery Mobile v1.0b3
+ * 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.
+*/
+
+
+/* A
+-----------------------------------------------------------------------------------------------------------*/
+
+.ui-bar-a {
+ border: 1px solid #2A2A2A;
+ background: #111111;
+ color: #ffffff;
+ font-weight: bold;
+ text-shadow: 0 -1px 1px #000000;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#111)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #3c3c3c, #111); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #3c3c3c, #111); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #3c3c3c, #111); /* IE10 */
+ background-image: -o-linear-gradient(top, #3c3c3c, #111); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #3c3c3c, #111);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#666), to(#222)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #666, #222); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #666, #222); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #666, #222); /* IE10 */
+ background-image: -o-linear-gradient(top, #666, #222); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #666, #222);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#555), to(#333)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #555, #333); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #555, #333); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #555, #333); /* IE10 */
+ background-image: -o-linear-gradient(top, #555, #333); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #555, #333);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#666), to(#444)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #666, #444); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #666, #444); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #666, #444); /* IE10 */
+ background-image: -o-linear-gradient(top, #666, #444); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #666, #444);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#333), to(#5a5a5a)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #333, #5a5a5a); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #333, #5a5a5a); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #333, #5a5a5a); /* IE10 */
+ background-image: -o-linear-gradient(top, #333, #5a5a5a); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #333, #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: -webkit-gradient(linear, left top, left bottom, from(#81a8ce), to(#5e87b0)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #81a8ce, #5e87b0); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #81a8ce, #5e87b0); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #81a8ce, #5e87b0); /* IE10 */
+ background-image: -o-linear-gradient(top, #81a8ce, #5e87b0); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #81a8ce, #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: -webkit-gradient(linear, left top, left bottom, from(#e6e6e6), to(#ccc)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #e6e6e6, #ccc); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #e6e6e6, #ccc); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #e6e6e6, #ccc); /* IE10 */
+ background-image: -o-linear-gradient(top, #e6e6e6, #ccc); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #e6e6e6, #ccc);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#5f9cc5), to(#396b9e)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #5f9cc5, #396b9e); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #5f9cc5, #396b9e); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #5f9cc5, #396b9e); /* IE10 */
+ background-image: -o-linear-gradient(top, #5f9cc5, #396b9e); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #5f9cc5, #396b9e);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#72b0d4), to(#4b88b6)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #72b0d4, #4b88b6); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #72b0d4, #4b88b6); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #72b0d4, #4b88b6); /* IE10 */
+ background-image: -o-linear-gradient(top, #72b0d4, #4b88b6); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #72b0d4, #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: -webkit-gradient(linear, left top, left bottom, from(#396b9e), to(#4e89c5)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #396b9e, #4e89c5); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #396b9e, #4e89c5); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #396b9e, #4e89c5); /* IE10 */
+ background-image: -o-linear-gradient(top, #396b9e, #4e89c5); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #396b9e, #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: -webkit-gradient(linear, left top, left bottom, from(#f0f0f0), to(#e9eaeb)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #f0f0f0, #e9eaeb); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #f0f0f0, #e9eaeb); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #f0f0f0, #e9eaeb); /* IE10 */
+ background-image: -o-linear-gradient(top, #f0f0f0, #e9eaeb); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #f0f0f0, #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: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#ddd)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #eee, #ddd); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #eee, #ddd); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #eee, #ddd); /* IE10 */
+ background-image: -o-linear-gradient(top, #eee, #ddd); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #eee, #ddd);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#fdfdfd), to(#eee)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #fdfdfd, #eee); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #fdfdfd, #eee); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #fdfdfd, #eee); /* IE10 */
+ background-image: -o-linear-gradient(top, #fdfdfd, #eee); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #fdfdfd, #eee);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#ededed), to(#dadada)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #ededed, #dadada); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #ededed, #dadada); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #ededed, #dadada); /* IE10 */
+ background-image: -o-linear-gradient(top, #ededed, #dadada); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #ededed, #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: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#fdfdfd)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #eee, #fdfdfd); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #eee, #fdfdfd); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #eee, #fdfdfd); /* IE10 */
+ background-image: -o-linear-gradient(top, #eee, #fdfdfd); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #eee, #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: -webkit-gradient(linear, left top, left bottom, from(#ddd), to(#bbb)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #ddd, #bbb); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #ddd, #bbb); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #ddd, #bbb); /* IE10 */
+ background-image: -o-linear-gradient(top, #ddd, #bbb); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #ddd, #bbb);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#fdfdfd), to(#eee)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #fdfdfd, #eee); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #fdfdfd, #eee); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #fdfdfd, #eee); /* IE10 */
+ background-image: -o-linear-gradient(top, #fdfdfd, #eee); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #fdfdfd, #eee);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#fff)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #eee, #fff); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #eee, #fff); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #eee, #fff); /* IE10 */
+ background-image: -o-linear-gradient(top, #eee, #fff); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #eee, #fff);
+}
+.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: -webkit-gradient(linear, left top, left bottom, from(#fceda7), to(#fadb4e)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #fceda7, #fadb4e); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #fceda7, #fadb4e); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #fceda7, #fadb4e); /* IE10 */
+ background-image: -o-linear-gradient(top, #fceda7, #fadb4e); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #fceda7, #fadb4e);
+}
+.ui-bar-e,
+.ui-bar-e input,
+.ui-bar-e select,
+.ui-bar-e textarea,
+.ui-bar-e 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: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#faeb9e)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #fff, #faeb9e); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #fff, #faeb9e); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #fff, #faeb9e); /* IE10 */
+ background-image: -o-linear-gradient(top, #fff, #faeb9e); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #fff, #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: -webkit-gradient(linear, left top, left bottom, from(#fceda7), to(#fadb4e)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #fceda7, #fadb4e); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #fceda7, #fadb4e); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #fceda7, #fadb4e); /* IE10 */
+ background-image: -o-linear-gradient(top, #fceda7, #fadb4e); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #fceda7, #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: -webkit-gradient(linear, left top, left bottom, from(#fcf0b5), to(#fbe26f)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #fcf0b5, #fbe26f); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #fcf0b5, #fbe26f); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #fcf0b5, #fbe26f); /* IE10 */
+ background-image: -o-linear-gradient(top, #fcf0b5, #fbe26f); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #fcf0b5, #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: -webkit-gradient(linear, left top, left bottom, from(#fadb4e), to(#fceda7)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #fadb4e, #fceda7); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #fadb4e, #fceda7); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #fadb4e, #fceda7); /* IE10 */
+ background-image: -o-linear-gradient(top, #fadb4e, #fceda7); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #fadb4e, #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: -webkit-gradient(linear, left top, left bottom, from(#85bae4), to(#5393c5)); /* Saf4+, Chrome */
+ background-image: -webkit-linear-gradient(top, #85bae4, #5393c5); /* Chrome 10+, Saf5.1+ */
+ background-image: -moz-linear-gradient(top, #85bae4, #5393c5); /* FF3.6 */
+ background-image: -ms-linear-gradient(top, #85bae4, #5393c5); /* IE10 */
+ background-image: -o-linear-gradient(top, #85bae4, #5393c5); /* Opera 11.10+ */
+ background-image: linear-gradient(top, #85bae4, #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;
+}
+.ui-corner-none {
+ -moz-border-radius: 0;
+ -webkit-border-radius: 0;
+ border-radius: 0;
+}
+
+/* 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-checkbox .ui-icon {
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+}
+.ui-icon-checkbox-off,
+.ui-icon-radio-off {
+ background-color: transparent;
+}
+.ui-icon-checkbox-on,
+.ui-checkbox-on .ui-icon,
+.ui-radio-on .ui-icon {
+ background-color: #4596ce; /* NOTE: this hex should match the active state color. It's repeated here for cascade */
+}
+.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;
+ 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.
+*/
+
+/* 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; }
+
+/* native overflow scrolling */
+.ui-page.ui-mobile-touch-overflow,
+.ui-mobile-touch-overflow.ui-native-fixed .ui-content {
+ overflow: auto;
+ height: 100%;
+ -webkit-overflow-scrolling: touch;
+ -moz-overflow-scrolling: touch;
+ -o-overflow-scrolling: touch;
+ -ms-overflow-scrolling: touch;
+ overflow-scrolling: touch;
+}
+.ui-page.ui-mobile-pre-transition {
+ display: block;
+}
+
+/* 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; }
+
+/* native fixed headers and footers */
+.ui-mobile-touch-overflow.ui-page.ui-native-fixed,
+.ui-mobile-touch-overflow.ui-page.ui-native-fullscreen {
+ overflow: visible;
+}
+.ui-mobile-touch-overflow.ui-native-fixed .ui-header,
+.ui-mobile-touch-overflow.ui-native-fixed .ui-footer {
+ position: fixed;
+ left: 0;
+ right: 0;
+ top: 0;
+ z-index: 200;
+}
+.ui-mobile-touch-overflow.ui-page.ui-native-fixed .ui-footer {
+ top: auto;
+ bottom: 0;
+}
+.ui-mobile-touch-overflow.ui-native-fixed .ui-content {
+ padding-top: 2.5em;
+ padding-bottom: 3em;
+ top: 0;
+ bottom: 0;
+ height: auto;
+ position: absolute;
+}
+.ui-mobile-touch-overflow.ui-native-fullscreen .ui-content {
+ padding-top: 0;
+ padding-bottom: 0;
+}
+.ui-mobile-touch-overflow.ui-native-fullscreen .ui-header,
+.ui-mobile-touch-overflow.ui-native-fullscreen .ui-footer {
+ opacity: .9;
+}
+.ui-native-bars-hidden {
+ display: none;
+}
+
+/* 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-animation-timing-function: linear;
+}
+@-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; zoom: 1; }
+.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 { 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: block; min-height: 1em; }
+.ui-select .ui-btn-text { text-overflow: ellipsis; overflow: hidden;}
+
+.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 15px .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-has-count .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-count { padding-right: 45px; }
+.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-arrow { padding-right: 30px; }
+.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-arrow.ui-li-has-count { padding-right: 75px; }
+.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%; }
+a.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 }
+
--- /dev/null
+++ b/include/common-auth.inc.php
@@ -1,1 +1,33 @@
+<?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();
+ }
+ }
+?>
--- a/include/common-db.inc.php
+++ b/include/common-db.inc.php
@@ -1,20 +1,35 @@
<?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 (php_uname('n') == "actbus-www") {
- $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");
+ $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) {
- die("A database error occurred.\n");
+ die("A database error occurred.\n");
}
-function databaseError($errMsg)
-{
- die($errMsg);
+
+function databaseError($errMsg) {
+ die($errMsg);
}
+
include ('db/route-dao.inc.php');
include ('db/trip-dao.inc.php');
include ('db/stop-dao.inc.php');
--- a/include/common-geo.inc.php
+++ b/include/common-geo.inc.php
@@ -1,153 +1,181 @@
<?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), ',')
$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, $twotone = false)
-{
- global $labsPath;
- $width = 300;
- $height = 300;
- $metersperpixel[9] = 305.492 * $width;
- $metersperpixel[10] = 152.746 * $width;
- $metersperpixel[11] = 76.373 * $width;
- $metersperpixel[12] = 38.187 * $width;
- $metersperpixel[13] = 19.093 * $width;
- $metersperpixel[14] = 9.547 * $width;
- $metersperpixel[15] = 4.773 * $width;
- //$metersperpixel[16] = 2.387 * $width;
- // $metersperpixel[17]=1.193*$width;
- $center = "";
- $markers = "";
- $mapwidthinmeters = 50;
- if (sizeof($mapPoints) < 1) return "map error";
- if (sizeof($mapPoints) === 1) {
- if ($zoom == 0) $zoom = 14;
- $markers.= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage";
- $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}";
- }
- else {
- foreach ($mapPoints as $index => $mapPoint) {
- if ($twotone && $index == 0) {
- $markers.= $mapPoint[0] . "," . $mapPoint[1] . "," . "iconr" . ($index + 1);
- $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}";
- }
- else {
- $markers.= $mapPoint[0] . "," . $mapPoint[1] . "," . $markerImage . ($index + 1);
- }
- if ($index + 1 != sizeof($mapPoints)) $markers.= "|";
- $dist = distance($mapPoints[0][0], $mapPoint[0][1], $mapPoint[0], $mapPoint[1]);
- $mapwidthinmeters = ($dist > $mapwidthinmeters ? $dist : $mapwidthinmeters);
- $totalLat+= $mapPoint[0];
- $totalLon+= $mapPoint[1];
- }
- if ($zoom == 0) {
- $mapwidthinmeters = distance($minlat, $minlon, $minlat, $maxlon);
- foreach (array_reverse($metersperpixel, true) as $zoomLevel => $maxdistance) {
- if ($zoom == 0 && $mapwidthinmeters * 1.5 < ($maxdistance)) $zoom = $zoomLevel;
- }
- }
- $center = $totalLat / sizeof($mapPoints) . "," . $totalLon / sizeof($mapPoints);
- }
- $output = "";
- if ($collapsible) $output.= '<div class="map" data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
- $output.= '<img class="map" src="' . curPageURL() . '/' . $labsPath . '/lib/staticmaplite/staticmap.php?center=' . $center . '&zoom=' . $zoom . '&size=' . $width . 'x' . $height . '&markers=' . $markers . '" width=' . $width . ' height=' . $height . '>';
- if ($collapsible) $output.= '</div>';
- return $output;
+
+function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb", $collapsible = true, $twotone = false) {
+ global $basePath;
+ $width = 300;
+ $height = 300;
+ $metersperpixel[9] = 305.492 * $width;
+ $metersperpixel[10] = 152.746 * $width;
+ $metersperpixel[11] = 76.373 * $width;
+ $metersperpixel[12] = 38.187 * $width;
+ $metersperpixel[13] = 19.093 * $width;
+ $metersperpixel[14] = 9.547 * $width;
+ $metersperpixel[15] = 4.773 * $width;
+ //$metersperpixel[16] = 2.387 * $width;
+ // $metersperpixel[17]=1.193*$width;
+ $center = "";
+ $markers = "";
+ $mapwidthinmeters = 50;
+ if (sizeof($mapPoints) < 1)
+ return "map error";
+ if (sizeof($mapPoints) === 1) {
+ if ($zoom == 0)
+ $zoom = 14;
+ $markers.= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage";
+ $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}";
+ }
+ else {
+ foreach ($mapPoints as $index => $mapPoint) {
+ if ($twotone && $index == 0) {
+ $markers.= $mapPoint[0] . "," . $mapPoint[1] . "," . "iconr" . ($index + 1);
+ $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}";
+ } else {
+ $markers.= $mapPoint[0] . "," . $mapPoint[1] . "," . $markerImage . ($index + 1);
+ }
+ if ($index + 1 != sizeof($mapPoints))
+ $markers.= "|";
+ $dist = distance($mapPoints[0][0], $mapPoint[0][1], $mapPoint[0], $mapPoint[1]);
+ $mapwidthinmeters = ($dist > $mapwidthinmeters ? $dist : $mapwidthinmeters);
+ $totalLat+= $mapPoint[0];
+ $totalLon+= $mapPoint[1];
+ }
+ if ($zoom == 0) {
+ $mapwidthinmeters = distance($minlat, $minlon, $minlat, $maxlon);
+ foreach (array_reverse($metersperpixel, true) as $zoomLevel => $maxdistance) {
+ if ($zoom == 0 && $mapwidthinmeters * 1.5 < ($maxdistance))
+ $zoom = $zoomLevel;
+ }
+ }
+ $center = $totalLat / sizeof($mapPoints) . "," . $totalLon / sizeof($mapPoints);
+ }
+ $output = "";
+ if ($collapsible)
+ $output.= '<div class="map" data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
+ $output.= '<img class="map" src="' . curPageURL() . '/' . $basePath . '/lib/staticmaplite/staticmap.php?center=' . $center . '&zoom=' . $zoom . '&size=' . $width . 'x' . $height . '&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 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)
-{
- // source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5
- $length = strlen($encoded);
- $index = 0;
- $points = array();
- $lat = 0;
- $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 decodePolylineToArray($encoded) {
+ // source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5
+ $length = strlen($encoded);
+ $index = 0;
+ $points = array();
+ $lat = 0;
+ $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 geocode($query, $giveOptions)
-{
- global $cloudmadeAPIkey;
- $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));
- 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 geocode($query, $giveOptions) {
+ global $cloudmadeAPIkey;
+ $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));
+ 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;
+
+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;
}
+
?>
--- a/include/common-net.inc.php
+++ b/include/common-net.inc.php
@@ -1,31 +1,48 @@
<?php
-function getPage($url)
-{
- 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;
+
+/*
+ * 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.
+ */
+
+function getPage($url) {
+ 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()
-{
- $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on");
- $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443")));
- $port = ($port) ? ':' . $_SERVER["SERVER_PORT"] : '';
- $url = ($isHTTPS ? 'https://' : 'http://') . $_SERVER["SERVER_NAME"] . $port . htmlentities(dirname($_SERVER['PHP_SELF']) , ENT_QUOTES);
- return $url;
+
+function curPageURL() {
+ $isHTTPS = (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on");
+ $port = (isset($_SERVER["SERVER_PORT"]) && ((!$isHTTPS && $_SERVER["SERVER_PORT"] != "80") || ($isHTTPS && $_SERVER["SERVER_PORT"] != "443")));
+ $port = ($port) ? ':' . $_SERVER["SERVER_PORT"] : '';
+ $url = ($isHTTPS ? 'https://' : 'http://') . $_SERVER["SERVER_NAME"] . $port . htmlentities(dirname($_SERVER['PHP_SELF']), ENT_QUOTES);
+ return $url;
}
+
?>
--- a/include/common-request.inc.php
+++ b/include/common-request.inc.php
@@ -1,48 +1,64 @@
<?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'])) {
- $firstLetter = filter_var($_REQUEST['firstLetter'], FILTER_SANITIZE_STRING);
+ $firstLetter = filter_var($_REQUEST['firstLetter'], FILTER_SANITIZE_STRING);
}
if (isset($_REQUEST['bysuburbs'])) {
- $bysuburbs = true;
+ $bysuburbs = true;
}
if (isset($_REQUEST['bynumber'])) {
- $bynumber = true;
+ $bynumber = true;
}
if (isset($_REQUEST['allstops'])) {
- $allstops = true;
+ $allstops = true;
}
if (isset($_REQUEST['nearby'])) {
- $nearby = true;
+ $nearby = true;
}
if (isset($_REQUEST['suburb'])) {
- $suburb = $_REQUEST['suburb'];
+ $suburb = $_REQUEST['suburb'];
}
$pageKey = filter_var($_REQUEST['pageKey'], FILTER_SANITIZE_NUMBER_INT);
$lat = filter_var($_REQUEST['lat'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
$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['numberSeries'])) {
- $numberSeries = filter_var($_REQUEST['numberSeries'], FILTER_SANITIZE_NUMBER_INT);
+ $numberSeries = filter_var($_REQUEST['numberSeries'], FILTER_SANITIZE_NUMBER_INT);
}
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['stopcode'])) {
- $stopcode = filter_var($_REQUEST['stopcode'], FILTER_SANITIZE_STRING);
+ $stopcode = filter_var($_REQUEST['stopcode'], FILTER_SANITIZE_STRING);
}
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['tripid'])) {
- $tripid = filter_var($_REQUEST['tripid'], FILTER_SANITIZE_NUMBER_INT);
+ $tripid = filter_var($_REQUEST['tripid'], FILTER_SANITIZE_NUMBER_INT);
}
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);
+ $routeid = filter_var($_REQUEST['routeid'], FILTER_SANITIZE_NUMBER_INT);
}
if (isset($_REQUEST['geolocate'])) {
-$geolocate = filter_var($_REQUEST['geolocate'], FILTER_SANITIZE_URL);
+ $geolocate = filter_var($_REQUEST['geolocate'], FILTER_SANITIZE_URL);
}
?>
--- a/include/common-session.inc.php
+++ b/include/common-session.inc.php
@@ -1,63 +1,77 @@
<?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
session_start();
if (isset($_REQUEST['service_period'])) {
- $_SESSION['service_period'] = filter_var($_REQUEST['service_period'], FILTER_SANITIZE_STRING);
- sessionUpdated();
+ $_SESSION['service_period'] = filter_var($_REQUEST['service_period'], FILTER_SANITIZE_STRING);
+ sessionUpdated();
}
if (isset($_REQUEST['time'])) {
- $_SESSION['time'] = filter_var($_REQUEST['time'], FILTER_SANITIZE_STRING);
- sessionUpdated();
+ $_SESSION['time'] = filter_var($_REQUEST['time'], FILTER_SANITIZE_STRING);
+ sessionUpdated();
}
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();
+ $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();
+
+function sessionUpdated() {
+ $_SESSION['lastUpdated'] = time();
}
+
// timeoutSession
$TIMEOUT_LIMIT = 60 * 5; // 5 minutes
if (isset($_SESSION['lastUpdated']) && $_SESSION['lastUpdated'] + $TIMEOUT_LIMIT < time()) {
- debug("Session timeout " . ($_SESSION['lastUpdated'] + $TIMEOUT_LIMIT) . ">" . time() , "session");
- session_destroy();
- session_start();
+ debug("Session timeout " . ($_SESSION['lastUpdated'] + $TIMEOUT_LIMIT) . ">" . time(), "session");
+ session_destroy();
+ session_start();
}
+
//debug(print_r($_SESSION, true) , "session");
-function current_time()
-{
- return ($_SESSION['time'] ? $_SESSION['time'] : date("H:i:s"));
+function current_time() {
+ return ($_SESSION['time'] ? $_SESSION['time'] : date("H:i:s"));
}
+
?>
--- a/include/common-template.inc.php
+++ b/include/common-template.inc.php
@@ -1,64 +1,80 @@
<?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.
$GA_ACCOUNT = "MO-22173039-1";
$GA_PIXEL = "/lib/ga.php";
-function googleAnalyticsGetImageUrl()
-{
- global $GA_ACCOUNT, $GA_PIXEL;
- //if (stristr($_SERVER['HTTP_USER_AGENT'], 'Googlebot') return "";
- $url = "";
- $url.= $GA_PIXEL . "?";
- $url.= "utmac=" . $GA_ACCOUNT;
- $url.= "&utmn=" . rand(0, 0x7fffffff);
- $referer = $_SERVER["HTTP_REFERER"];
- $query = $_SERVER["QUERY_STRING"];
- $path = $_SERVER["REQUEST_URI"];
- if (empty($referer)) {
- $referer = "-";
- }
- $url.= "&utmr=" . urlencode($referer);
- if (!empty($path)) {
- $url.= "&utmp=" . urlencode($path);
- }
- $url.= "&guid=ON";
- return str_replace("&", "&", $url);
-}
-function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false)
-{
- global $labsPath;
- echo '
+
+function googleAnalyticsGetImageUrl() {
+ global $GA_ACCOUNT, $GA_PIXEL;
+ //if (stristr($_SERVER['HTTP_USER_AGENT'], 'Googlebot') return "";
+ $url = "";
+ $url.= $GA_PIXEL . "?";
+ $url.= "utmac=" . $GA_ACCOUNT;
+ $url.= "&utmn=" . rand(0, 0x7fffffff);
+ $referer = $_SERVER["HTTP_REFERER"];
+ $query = $_SERVER["QUERY_STRING"];
+ $path = $_SERVER["REQUEST_URI"];
+ if (empty($referer)) {
+ $referer = "-";
+ }
+ $url.= "&utmr=" . urlencode($referer);
+ if (!empty($path)) {
+ $url.= "&utmp=" . urlencode($path);
+ }
+ $url.= "&guid=ON";
+ return str_replace("&", "&", $url);
+}
+
+function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false) {
+ global $basePath, $serviceAlertsEnabled;
+ echo '
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>' . $pageTitle . '</title>
+<title>' . $pageTitle . ' - Canberra Bus Timetable</title>
<meta name="google-site-verification" content="-53T5Qn4TB_de1NyfR_ZZkEVdUNcNFSaYKSFkWKx-sY" />
<link rel="dns-prefetch" href="//code.jquery.com">
<link rel="dns-prefetch" href="//ajax.googleapis.com">
- <link rel="stylesheet" href="' . $labsPath . 'css/jquery-ui-1.8.12.custom.css" />';
- if (isDebugServer()) {
- $jqmcss = $labsPath . 'css/jquery.mobile-1.0b2.css';
- $jqjs = $labsPath . 'js/jquery-1.6.2.min.js';
- $jqmjs = $labsPath . 'js/jquery.mobile-1.0b2.js';
- }
- else {
- $jqmcss = "//code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.css";
- $jqjs = "//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js";
- $jqmjs = "//code.jquery.com/mobile/1.0b2/jquery.mobile-1.0b2.min.js";
- }
- echo '<link rel="stylesheet" href="' . $jqmcss . '" />
- <script src="'.$jqjs.'"></script>
+ <link rel="stylesheet" href="' . $basePath . 'css/jquery-ui-1.8.12.custom.css" />';
+ if (isDebugServer()) {
+ $jqmcss = $basePath . 'css/jquery.mobile-1.0b3.css';
+ $jqjs = $basePath . 'js/jquery-1.6.2.min.js';
+ $jqmjs = $basePath . 'js/jquery.mobile-1.0b3.js';
+ } else {
+ $jqmcss = "//code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css";
+ $jqjs = "//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js";
+ $jqmjs = "//code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.js";
+ }
+ echo '<link rel="stylesheet" href="' . $jqmcss . '" />
+ <script src="' . $jqjs . '"></script>
<script>$(document).bind("mobileinit", function(){
$.mobile.ajaxEnabled = false;
});
</script>
- <script src="'.$jqmjs.'"></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 src="' . $labsPath . 'js/jquery.ui.autocomplete.min.js"></script>
+ <script src="' . $jqmjs . '"></script>
+
+<script src="' . $basePath . 'js/jquery.ui.core.min.js"></script>
+<script src="' . $basePath . 'js/jquery.ui.position.min.js"></script>
+<script src="' . $basePath . 'js/jquery.ui.widget.min.js"></script>
+ <script src="' . $basePath . 'js/jquery.ui.autocomplete.min.js"></script>
<script>
$(function() {
$( "#geolocate" ).autocomplete({
@@ -75,8 +91,9 @@
});
});
</script>';
- echo '<style type="text/css">';
- 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,
+ echo '<style type="text/css">';
+ 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-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 {
@@ -84,22 +101,25 @@
box-shadow: none;
-webkit-box-shadow: none;
}';
- echo '</style>';
- echo '<link rel="stylesheet" href="' . $labsPath . 'css/local.css.php" />';
- 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" />
+ echo '</style>';
+ echo '<link rel="stylesheet" href="' . $basePath . 'css/local.css.php" />';
+ 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" />
<link rel="apple-touch-startup-image" href="startup.png" />
<link rel="apple-touch-icon" href="apple-touch-icon.png" />';
- }
- if ($geolocate) {
- echo "<script>
+ }
+ if ($geolocate) {
+ echo "<script>
function success(position) {
$('#error').val('Location now detected. Please wait for data to load.');
$('#geolocate').val(position.coords.latitude+','+position.coords.longitude);
-$.ajax({ url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude });
-location.reload(true);
+$.ajax({ async: false,
+success: function(){
+ location.reload(true);
+ },
+url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude });
}
function error(msg) {
$('#error').val('Error: '+msg);
@@ -120,10 +140,12 @@
$('#here').show();
});
";
- if (!isset($_SESSION['lat']) || $_SESSION['lat'] == "") echo "geolocate();";
- echo "</script> ";
- }
- if (isAnalyticsOn()) echo '
+ if (!isset($_SESSION['lat']) || $_SESSION['lat'] == "")
+ echo "geolocate();";
+ echo "</script> ";
+ }
+ if (isAnalyticsOn())
+ echo '
<script type="text/javascript">' . "
var _gaq = _gaq || [];
@@ -131,40 +153,46 @@
_gaq.push(['_trackPageview']);
_gaq.push(['_trackPageLoadTime']);
</script>";
- echo '</head>
+ echo '</head>
<body>
<div id="skip">
<a href="#maincontent">Skip to content</a>
</div>
';
- if ($opendiv) {
- echo '<div data-role="page">
+ if ($opendiv) {
+ echo '<div data-role="page">
<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>
<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 -->
<a name="maincontent" id="maincontent"></a>
<div data-role="content"> ';
- $overrides = getServiceOverride();
- if ($overrides['service_id']) {
- if ($overrides['service_id'] == "noservice") {
- echo '<div id="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a
+ $overrides = getServiceOverride();
+ if ($overrides['service_id']) {
+ if ($overrides['service_id'] == "noservice") {
+ echo '<div id="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>';
- }
- else {
- 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>';
- }
- }
- }
-}
-function include_footer()
-{
- global $labsPath;
- echo '<div id="footer"><a href="' . $labsPath . 'about.php">About/Contact Us</a> <a href="' . $labsPath . 'feedback.php">Feedback/Bug Report</a> <a href="' . $labsPath . 'privacy.php">Privacy Policy</a>';
- echo '</div>';
- if (isAnalyticsOn()) {
- echo "<script> (function() {
+ } else {
+ 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>';
+ }
+ }
+ if ($GTFSREnabled) {
+ $serviceAlerts = getServiceAlertsAsArray("agency", "0");
+ foreach ($serviceAlerts['entity'] as $entity) {
+ echo "<div id='servicewarning'>" . date("F j, g:i a", strtotime($entity['alert']['active_period'][0]['start'])) . " to " . date("F j, g:i a", strtotime($entity['alert']['active_period'][0]['end'])) . "{$entity['alert']['header_text']['translation'][0]['text']}<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> <a href="' . $basePath . 'feedback.php">Feedback/Bug Report</a> <a href="' . $basePath . 'privacy.php">Privacy Policy</a>';
+ echo '</div>';
+ if (isAnalyticsOn()) {
+ echo "<script> (function() {
var ga = document.createElement('script'); ga.type =
'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ?
@@ -172,25 +200,25 @@
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();</script>";
- $googleAnalyticsImageUrl = googleAnalyticsGetImageUrl();
- echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" /></noscript>';
- }
- echo "\n</div></div></body></html>";
-}
-function placeSettings()
-{
- global $service_periods;
- $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.
+ $googleAnalyticsImageUrl = googleAnalyticsGetImageUrl();
+ echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" /></noscript>';
+ }
+ echo "\n</div></div></body></html>";
+}
+
+function placeSettings() {
+ global $service_periods;
+ $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,
or enter an address/co-ordinates in the box below.';
- }
- echo '</div>';
- echo '<div id="settings" data-role="collapsible" data-collapsed="' . !$geoerror . '">
+ }
+ echo '</div>';
+ echo '<div id="settings" data-role="collapsible" data-collapsed="' . !$geoerror . '">
<h3>Change Location...</h3>
<form action="' . basename($_SERVER['PHP_SELF']) . "?" . $_SERVER['QUERY_STRING'] . '" method="post">
<div class="ui-body">
@@ -203,11 +231,12 @@
</div></form>
</div>';
}
-function trackEvent($category, $action, $label = "", $value = - 1)
-{
- if (isAnalyticsOn()) {
- echo "\n<script> _gaq.push(['_trackEvent', '$category', '$action'" . ($label != "" ? ", '$label'" : "") . ($value != - 1 ? ", $value" : "") . "]);</script>";
- }
-}
+
+function trackEvent($category, $action, $label = "", $value = - 1) {
+ if (isAnalyticsOn()) {
+ echo "\n<script> _gaq.push(['_trackEvent', '$category', '$action'" . ($label != "" ? ", '$label'" : "") . ($value != - 1 ? ", $value" : "") . "]);</script>";
+ }
+}
+
?>
--- a/include/common-transit.inc.php
+++ b/include/common-transit.inc.php
@@ -1,49 +1,278 @@
<?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(
- 'sunday',
- 'saturday',
- 'weekday'
+ 'sunday',
+ 'saturday',
+ 'weekday'
);
-function service_period($date = "")
-{
-
- if (isset($_SESSION['service_period'])) return $_SESSION['service_period'];
- $override = getServiceOverride($date);
- if ($override['service_id']){
- return $override['service_id'];
- }
-
- switch (date('w',($date != "" ? $date : time()))) {
- case 0:
- return 'sunday';
- case 6:
- return 'saturday';
- default:
- return 'weekday';
- }
-}
-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 "";
- }
+function service_period($date = "") {
+
+ if (isset($_SESSION['service_period']))
+ return $_SESSION['service_period'];
+ $override = getServiceOverride($date);
+ if ($override['service_id']) {
+ return $override['service_id'];
+ }
+
+ switch (date('w', ($date != "" ? $date : time()))) {
+ case 0:
+ return 'sunday';
+ case 6:
+ return 'saturday';
+ default:
+ return 'weekday';
+ }
+}
+
+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
+ */
+ $fm = new transit_realtime\FeedMessage();
+ $fh = new transit_realtime\FeedHeader();
+ $fh->setGtfsRealtimeVersion(1);
+ $fh->setTimestamp(time());
+ $fm->setHeader($fh);
+ foreach (getCurrentAlerts() as $alert) {
+ $fe = new transit_realtime\FeedEntity();
+ $fe->setId($alert['id']);
+ $fe->setIsDeleted(false);
+ $alert = new transit_realtime\Alert();
+ $tr = new transit_realtime\TimeRange();
+ $tr->setStart($alert['start']);
+ $tr->setEnd($alert['end']);
+ $alert->addActivePeriod($tr);
+ $informedEntities = getInformedAlerts($alert['id'], $_REQUEST['filter_class'], $_REQUEST['filter_id']);
+ if (sizeof($informedEntities) > 0) {
+ $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);
+ }
+ $alert->setCause(constant("transit_realtime\Alert\Cause::" . $alert['cause']));
+ $alert->setEffect(constant("transit_realtime\Alert\Effect::" . $alert['effect']));
+ $tsUrl = new transit_realtime\TranslatedString();
+ $tUrl = new transit_realtime\TranslatedString\Translation();
+ $tUrl->setText($alert['url']);
+ $tUrl->setLanguage("en");
+ $tsUrl->addTranslation($tUrl);
+ $alert->setUrl($tsUrl);
+ $tsHeaderText = new transit_realtime\TranslatedString();
+ $tHeaderText = new transit_realtime\TranslatedString\Translation();
+ $tHeaderText->setText($alert['header']);
+ $tHeaderText->setLanguage("en");
+ $tsHeaderText->addTranslation($tHeaderText);
+ $alert->setHeaderText($tsHeaderText);
+ $tsDescriptionText = new transit_realtime\TranslatedString();
+ $tDescriptionText = new transit_realtime\TranslatedString\Translation();
+ $tDescriptionText->setText($alert['description']);
+ $tDescriptionText->setLanguage("en");
+ $tsDescriptionText->addTranslation($tDescriptionText);
+ $alert->setDescriptionText($tsDescriptionText);
+ $fe->setAlert($alert);
+ $fm->addEntity($fe);
+ }
+ return $fm;
+ }
+
+ function getServiceAlertsAsArray($filter_class = "", $filter_id = "") {
+ $codec = new DrSlump\Protobuf\Codec\PhpArray();
+ return $codec->encode(getServiceAlerts($filter_class, $filter_id));
+ }
+
+ 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));
+ }
+
}
?>
--- a/include/common.inc.php
+++ b/include/common.inc.php
@@ -1,38 +1,59 @@
<?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');
$debugOkay = Array(
- "session",
- "json",
- "phperror",
- "awsotp",
- //"squallotp",
- //"vanilleotp",
- "database",
- "other"
+ "session",
+ "json",
+ "phperror",
+ "awsotp",
+ //"squallotp",
+ //"vanilleotp",
+ "database",
+ "other"
);
+$GTFSREnabled = true;
$cloudmadeAPIkey = "daa03470bb8740298d4b10e3f03d63e6";
$googleMapsAPIkey = "ABQIAAAA95XYXN0cki3Yj_Sb71CFvBTPaLd08ONybQDjcH_VdYtHHLgZvRTw2INzI_m17_IoOUqH3RNNmlTk1Q";
$otpAPIurl = 'http://localhost:8080/opentripplanner-api-webapp/';
if (isDebug("awsotp") || php_uname('n') == "maxious.xen.prgmr.com") {
- $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") {
- $otpAPIurl = 'http://otp.actbus.dotcloud.com/opentripplanner-api-webapp/';
+ $otpAPIurl = 'http://otp.actbus.dotcloud.com/opentripplanner-api-webapp/';
}
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")) {
- $otpAPIurl = 'http://10.0.1.135:8080/opentripplanner-api-webapp/';
-}
-if (isDebug("phperror")) error_reporting(E_ALL ^ E_NOTICE);
-$labsPath = "";
-if (strstr($_SERVER['PHP_SELF'],"labs")) $labsPath = "../";
-
-function isDebugServer()
-{
- return php_sapi_name() == "cli" || isset($_SERVER['SERVER_NAME']) && ( $_SERVER['SERVER_NAME'] == "10.0.1.154" || $_SERVER['SERVER_NAME'] == "10.1.0.4" || $_SERVER['SERVER_NAME'] ==
-"localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1") ;
+ $otpAPIurl = 'http://10.0.1.135:8080/opentripplanner-api-webapp/';
+}
+if (isDebug("phperror"))
+ error_reporting(E_ALL ^ E_NOTICE);
+$basePath = "";
+if (strstr($_SERVER['PHP_SELF'], "labs/")
+ || strstr($_SERVER['PHP_SELF'], "myway/")
+ || strstr($_SERVER['PHP_SELF'], "servicealerts/"))
+ $basePath = "../";
+
+function isDebugServer() {
+ return php_sapi_name() == "cli" || isset($_SERVER['SERVER_NAME']) && ( $_SERVER['SERVER_NAME'] == "azusa" || $_SERVER['SERVER_NAME'] == "vanille"
+ || $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1");
}
include_once ("common-geo.inc.php");
@@ -42,149 +63,157 @@
include_once ("common-request.inc.php");
include_once ("common-session.inc.php");
+include_once ("common-auth.inc.php");
include_once ("common-template.inc.php");
-
-function isAnalyticsOn()
-{
- return !isDebugServer();
-}
-function isDebug($debugReason = "other")
-{
- global $debugOkay;
- return in_array($debugReason, $debugOkay, false) && isDebugServer();
-}
-function debug($msg, $debugReason = "other")
-{
- if (isDebug($debugReason)) echo "\n<!-- " . date(DATE_RFC822) . "\n $msg -->\n";
-}
-function isJQueryMobileDevice()
-{
- // 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'];
- 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'];
- $fastDevices = Array(
- "Mozilla/5.0 (X11;",
- "Mozilla/5.0 (Windows;",
- "Mozilla/5.0 (iP",
- "Mozilla/5.0 (Linux; U; Android",
- "Mozilla/4.0 (compatible; MSIE"
- );
- $slowDevices = Array(
- "J2ME",
- "MIDP",
- "Opera/",
- "Mozilla/2.0 (compatible;",
- "Mozilla/3.0 (compatible;"
- );
- return true;
-}
-function array_flatten($a, $f = array())
-{
- if (!$a || !is_array($a)) return '';
- foreach ($a as $k => $v) {
- if (is_array($v)) $f = array_flatten($v, $f);
- else $f[$k] = $v;
- }
- return $f;
-}
-function remove_spaces($string)
-{
- return str_replace(' ', '', $string);
-}
-function object2array($object)
-{
- if (is_object($object)) {
- foreach ($object as $key => $value) {
- $array[$key] = $value;
- }
- }
- else {
- $array = $object;
- }
- return $array;
-}
-function startsWith($haystack, $needle, $case = true)
-{
- if ($case) {
- return (strcmp(substr($haystack, 0, strlen($needle)) , $needle) === 0);
- }
- return (strcasecmp(substr($haystack, 0, strlen($needle)) , $needle) === 0);
-}
-
-function endsWith($haystack, $needle, $case = true)
-{
- if ($case) {
- return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)) , $needle) === 0);
- }
- return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)) , $needle) === 0);
-}
-function bracketsMeanNewLine($input)
-{
- return str_replace(")", "</small>", str_replace("(", "<br><small>", $input));
-}
-function sksort(&$array, $subkey = "id", $sort_ascending = false)
-{
- if (count($array)) $temp_array[key($array) ] = array_shift($array);
- foreach ($array as $key => $val) {
- $offset = 0;
- $found = false;
- 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(
- $key => $val
- ) , array_slice($temp_array, $offset));
- $found = true;
- }
- $offset++;
- }
- if (!$found) $temp_array = array_merge($temp_array, array(
- $key => $val
- ));
- }
- if ($sort_ascending) $array = array_reverse($temp_array);
- else $array = $temp_array;
-}
-function sktimesort(&$array, $subkey = "id", $sort_ascending = false)
-{
- if (count($array)) $temp_array[key($array) ] = array_shift($array);
- foreach ($array as $key => $val) {
- $offset = 0;
- $found = false;
- foreach ($temp_array as $tmp_key => $tmp_val) {
- if (!$found and strtotime($val[$subkey]) > strtotime($tmp_val[$subkey])) {
- $temp_array = array_merge((array)array_slice($temp_array, 0, $offset) , array(
- $key => $val
- ) , array_slice($temp_array, $offset));
- $found = true;
- }
- $offset++;
- }
- if (!$found) $temp_array = array_merge($temp_array, array(
- $key => $val
- ));
- }
- 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 );
-}
+function isAnalyticsOn() {
+ $user_agent = $_SERVER['HTTP_USER_AGENT'];
+ return!isDebugServer() && !preg_match('/cloudkick/i', $user_agent) && !preg_match('/googlebot/i', $user_agent) &&
+ !preg_match('/baidu/i', $user_agent);
+}
+
+function isDebug($debugReason = "other") {
+ global $debugOkay;
+ return in_array($debugReason, $debugOkay, false) && isDebugServer();
+}
+
+function debug($msg, $debugReason = "other") {
+ if (isDebug($debugReason))
+ echo "\n<!-- " . date(DATE_RFC822) . "\n $msg -->\n";
+}
+
+function isJQueryMobileDevice() {
+ // 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'];
+ 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'];
+ $fastDevices = Array(
+ "Mozilla/5.0 (X11;",
+ "Mozilla/5.0 (Windows;",
+ "Mozilla/5.0 (iP",
+ "Mozilla/5.0 (Linux; U; Android",
+ "Mozilla/4.0 (compatible; MSIE"
+ );
+ $slowDevices = Array(
+ "J2ME",
+ "MIDP",
+ "Opera/",
+ "Mozilla/2.0 (compatible;",
+ "Mozilla/3.0 (compatible;"
+ );
+ return true;
+}
+
+function array_flatten($a, $f = array()) {
+ if (!$a || !is_array($a))
+ return '';
+ foreach ($a as $k => $v) {
+ if (is_array($v))
+ $f = array_flatten($v, $f);
+ else
+ $f[$k] = $v;
+ }
+ return $f;
+}
+
+function remove_spaces($string) {
+ return str_replace(' ', '', $string);
+}
+
+function object2array($object) {
+ if (is_object($object)) {
+ foreach ($object as $key => $value) {
+ $array[$key] = $value;
+ }
+ } else {
+ $array = $object;
+ }
+ return $array;
+}
+
+function startsWith($haystack, $needle, $case = true) {
+ if ($case) {
+ return (strcmp(substr($haystack, 0, strlen($needle)), $needle) === 0);
+ }
+ return (strcasecmp(substr($haystack, 0, strlen($needle)), $needle) === 0);
+}
+
+function endsWith($haystack, $needle, $case = true) {
+ if ($case) {
+ return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);
+ }
+ return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)), $needle) === 0);
+}
+
+function bracketsMeanNewLine($input) {
+ return str_replace(")", "</small>", str_replace("(", "<br><small>", $input));
+}
+
+function sksort(&$array, $subkey = "id", $sort_ascending = false) {
+ if (count($array))
+ $temp_array[key($array)] = array_shift($array);
+ foreach ($array as $key => $val) {
+ $offset = 0;
+ $found = false;
+ 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(
+ $key => $val
+ ), array_slice($temp_array, $offset));
+ $found = true;
+ }
+ $offset++;
+ }
+ if (!$found)
+ $temp_array = array_merge($temp_array, array(
+ $key => $val
+ ));
+ }
+ if ($sort_ascending)
+ $array = array_reverse($temp_array);
+ else
+ $array = $temp_array;
+}
+
+function sktimesort(&$array, $subkey = "id", $sort_ascending = false) {
+ if (count($array))
+ $temp_array[key($array)] = array_shift($array);
+ foreach ($array as $key => $val) {
+ $offset = 0;
+ $found = false;
+ foreach ($temp_array as $tmp_key => $tmp_val) {
+ if (!$found and strtotime($val[$subkey]) > strtotime($tmp_val[$subkey])) {
+ $temp_array = array_merge((array) array_slice($temp_array, 0, $offset), array(
+ $key => $val
+ ), array_slice($temp_array, $offset));
+ $found = true;
+ }
+ $offset++;
+ }
+ if (!$found)
+ $temp_array = array_merge($temp_array, array(
+ $key => $val
+ ));
+ }
+ 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);
+}
+
?>
--- a/include/db/route-dao.inc.php
+++ b/include/db/route-dao.inc.php
@@ -1,211 +1,229 @@
<?php
-function getRoute($routeID)
-{
- global $conn;
- $query = "Select * from routes where route_id = :routeID LIMIT 1";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":routeID", $routeID);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetch(PDO::FETCH_ASSOC);
-}
-
-function getRouteByFullName($routeFullName)
-{
- global $conn;
- $query = "Select * from routes where route_short_name||route_long_name = :routeFullName LIMIT 1";
- 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 getRoutesByNumber($routeNumber = "")
-{
- global $conn;
- if ($routeNumber != "") {
- $query = "Select distinct routes.route_id,routes.route_short_name,routes.route_long_name,service_id from routes join trips on trips.route_id =
+
+/*
+ * 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.
+ */
+
+function getRoute($routeID) {
+ global $conn;
+ $query = "Select * from routes where route_id = :routeID LIMIT 1";
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":routeID", $routeID);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetch(PDO :: FETCH_ASSOC);
+}
+
+function getRouteByFullName($routeFullName) {
+ global $conn;
+ $query = "Select * from routes where route_short_name||route_long_name = :routeFullName LIMIT 1";
+ 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 getRoutesByNumber($routeNumber = "") {
+ global $conn;
+ if ($routeNumber != "") {
+ $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 route_short_name = :routeNumber OR route_short_name LIKE :routeNumber2 order by route_short_name;";
- }
- else {
- $query = "SELECT DISTINCT route_short_name from routes order by route_short_name";
- }
- debug($query, "database");
- $query = $conn->prepare($query);
- if ($routeNumber != "") {
- $query->bindParam(":routeNumber", $routeNumber);
- $routeNumber2 = "% ".$routeNumber;
- $query->bindParam(":routeNumber2", $routeNumber2);
- }
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function getRoutesByNumberSeries($routeNumberSeries = "")
-{
- global $conn;
- if (strlen($routeNumberSeries) == 1) {
- return getRoutesByNumber($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 =
+ } else {
+ $query = "SELECT DISTINCT route_short_name from routes order by route_short_name";
+ }
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ if ($routeNumber != "") {
+ $query->bindParam(":routeNumber", $routeNumber);
+ $routeNumber2 = "% " . $routeNumber;
+ $query->bindParam(":routeNumber2", $routeNumber2);
+ }
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getRoutesByNumberSeries($routeNumberSeries = "") {
+ global $conn;
+ if (strlen($routeNumberSeries) == 1) {
+ return getRoutesByNumber($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;";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":seriesMin", $seriesMin);
- $query->bindParam(":seriesMax", $seriesMax);
- $routeNumberSeries = "% ".substr($routeNumberSeries, 0, -1)."%";
- $query->bindParam(":routeNumberSeries", $routeNumberSeries);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function getRouteNextTrip($routeID)
-{
- global $conn;
- $query = "select * from routes join trips on trips.route_id = routes.route_id
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":seriesMin", $seriesMin);
+ $query->bindParam(":seriesMax", $seriesMax);
+ $routeNumberSeries = "% " . substr($routeNumberSeries, 0, -1) . "%";
+ $query->bindParam(":routeNumberSeries", $routeNumberSeries);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getRouteNextTrip($routeID) {
+ 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
arrival_time > :currentTime and routes.route_id = :routeID order by
arrival_time limit 1";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":currentTime", current_time());
- $query->bindParam(":routeID", $routeID);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- $r = $query->fetch(PDO::FETCH_ASSOC);
-
- // past last trip of the day special case
- if (sizeof($r) < 16) {
- $query = "select * from routes join trips on trips.route_id = routes.route_id
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":currentTime", current_time());
+ $query->bindParam(":routeID", $routeID);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ $r = $query->fetch(PDO :: FETCH_ASSOC);
+
+ // past last trip of the day special case
+ if (sizeof($r) < 16) {
+ $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
arrival_time DESC limit 1";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":routeID", $routeID);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
-
- $r = $query->fetch(PDO::FETCH_ASSOC);
- }
- return $r;
-}
-function getTimeInterpolatedRouteAtStop($routeID, $stop_id)
-{
- $nextTrip = getRouteNextTrip($routeID);
- if ($nextTrip['trip_id']) {
- foreach (getTimeInterpolatedTrip($nextTrip['trip_id']) as $tripStop) {
- if ($tripStop['stop_id'] == $stop_id) return $tripStop;
- }
- }
- return Array();
-}
-function getRouteTrips($routeID)
-{
- 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
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":routeID", $routeID);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+
+ $r = $query->fetch(PDO :: FETCH_ASSOC);
+ }
+ return $r;
+}
+
+function getTimeInterpolatedRouteAtStop($routeID, $stop_id) {
+ $nextTrip = getRouteNextTrip($routeID);
+ if ($nextTrip['trip_id']) {
+ foreach (getTimeInterpolatedTrip($nextTrip['trip_id']) as $tripStop) {
+ if ($tripStop['stop_id'] == $stop_id)
+ return $tripStop;
+ }
+ }
+ return Array();
+}
+
+function getRouteTrips($routeID) {
+ 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
join stop_times on stop_times.trip_id = trips.trip_id where routes.route_id = :routeID and stop_sequence = '1' order by
arrival_time ";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":routeID", $routeID);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function getRoutesByDestination($destination = "", $service_period = "")
-{
- global $conn;
- if ($service_period == "") $service_period = service_period();
- if ($destination != "") {
- $query = "SELECT DISTINCT trips.route_id,route_short_name,route_long_name, service_id
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":routeID", $routeID);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getRoutesByDestination($destination = "", $service_period = "") {
+ global $conn;
+ if ($service_period == "")
+ $service_period = service_period();
+ 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 =
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";
- }
- else {
- $query = "SELECT DISTINCT route_long_name
+ } else {
+ $query = "SELECT DISTINCT route_long_name
FROM stop_times join trips on trips.trip_id =
stop_times.trip_id join routes on trips.route_id = routes.route_id
WHERE service_id= :service_period order by route_long_name";
- }
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":service_period", $service_period);
- if ($destination != "") $query->bindParam(":destination", $destination);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function getRoutesBySuburb($suburb, $service_period = "")
-{
- if ($service_period == "") $service_period = service_period();
- global $conn;
- $query = "SELECT DISTINCT service_id,trips.route_id,route_short_name,route_long_name
+ }
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":service_period", $service_period);
+ if ($destination != "")
+ $query->bindParam(":destination", $destination);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getRoutesBySuburb($suburb, $service_period = "") {
+ if ($service_period == "")
+ $service_period = service_period();
+ 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
join routes on trips.route_id = routes.route_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";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":service_period", $service_period);
- $suburb = "%" . $suburb . ";%";
- $query->bindParam(":suburb", $suburb);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function getRoutesNearby($lat, $lng, $limit = "", $distance = 500)
-{
- if ($service_period == "") $service_period = service_period();
- if ($limit != "") $limitSQL = " LIMIT :limit ";
- global $conn;
- $query = "SELECT service_id,trips.route_id,route_short_name,route_long_name,min(stops.stop_id) as stop_id,
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":service_period", $service_period);
+ $suburb = "%" . $suburb . ";%";
+ $query->bindParam(":suburb", $suburb);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getRoutesNearby($lat, $lng, $limit = "", $distance = 500) {
+ if ($service_period == "")
+ $service_period = service_period();
+ if ($limit != "")
+ $limitSQL = " LIMIT :limit ";
+ global $conn;
+ $query = "SELECT service_id,trips.route_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
FROM stop_times
join trips on trips.trip_id = stop_times.trip_id
@@ -215,16 +233,18 @@
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
order by distance $limitSQL";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":service_period", $service_period);
- $query->bindParam(":distance", $distance);
- if ($limit != "") $query->bindParam(":limit", $limit);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":service_period", $service_period);
+ $query->bindParam(":distance", $distance);
+ if ($limit != "")
+ $query->bindParam(":limit", $limit);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
?>
--- a/include/db/servicealert-dao.inc.php
+++ b/include/db/servicealert-dao.inc.php
@@ -1,53 +1,177 @@
<?php
-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
- $query->bindParam(":date", date("Ymd",($date != "" ? $date : time())));
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetch(PDO::FETCH_ASSOC);
+
+/*
+ * 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.
+ */
+
+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
+ $query->bindParam(":date", date("Ymd", ($date != "" ? $date : time())));
+ $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', start) as start, extract('epoch', 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, $start, $end, $header, $description, $url) {
+ global $conn;
+ $query = 'update servicealerts_alerts set start=:start, "end"=:end, header=:header, description=:description, url=:url where id = :servicealert_id';
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":servicealert_id", $alertID);
+ $query->bindParam(":start", $start);
+ $query->bindParam(":end", $end);
+ $query->bindParam(":header", $header);
+ $query->bindParam(":description", $description);
+ $query->bindParam(":url", $url);
+ $query->execute();
+
+ print_r($conn->errorInfo());
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetch(PDO :: FETCH_ASSOC);
+}
+
+function addServiceAlert($start, $end, $header, $description, $url) {
+ global $conn;
+ $query = 'INSERT INTO servicealerts_alerts (start, "end", header, description, url) VALUES (:start, :end, :header, :description, :url) ';
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":start", $start);
+ $query->bindParam(":end", $end);
+ $query->bindParam(":header", $header);
+ $query->bindParam(":description", $description);
+ $query->bindParam(":url", $url);
+ $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 * from servicealerts_alerts";
- //debug($query, "database");
- $query = $conn->prepare($query);
- //if ($stop_sequence != "") $query->bindParam(":stop_sequence", $stop_sequence);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
+ global $conn;
+ $query = "SELECT id,extract('epoch', start) as start, extract('epoch', 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 getInformedAlerts($id,$filter_class,$filter_id) {
-
- global $conn;
- $query = "SELECT * from servicealerts_informed where servicealert_id = :servicealert_id";
-
- if ($filter_class != "" && $filter_id != "") {
- $query .= " AND (informed_class = :informed_class OR informed_class = 'network') AND informed_id = :informed_id";
-
- }
- //debug($query, "database");
- $query = $conn->prepare($query);
- if ($filter_class != "" && $filter_id != "") {
- $query->bindParam(":informed_class", $filter_class);
- $query->bindParam(":informed_id", $filter_id);
- }
- $query->bindParam(":servicealert_id", $id);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
+
+function getFutureAlerts() {
+ global $conn;
+ $query = "SELECT id,extract('epoch', start) as start, extract('epoch', end) as end,cause,effect,header,description,url from servicealerts_alerts where NOW() > start or NOW() < \"end\"";
+ // 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;
+ $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) VALUES(:servicealert_id ,:informed_class, :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;
}
?>
--- a/include/db/stop-dao.inc.php
+++ b/include/db/stop-dao.inc.php
@@ -1,131 +1,171 @@
<?php
-function getStop($stopID)
-{
- global $conn;
- $query = "Select * from stops where stop_id = :stopID LIMIT 1";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":stopID", $stopID);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetch(PDO::FETCH_ASSOC);
-}
-function getStops($timingPointsOnly = false, $firstLetter = "", $startsWith = "")
-{
- global $conn;
- $conditions = Array();
- if ($timingPointsOnly) $conditions[] = "substr(stop_code,1,2) != 'Wj'";
- if ($firstLetter != "") $conditions[] = "substr(stop_name,1,1) = :firstLetter";
- 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.= " order by stop_name;";
- $query = $conn->prepare($query);
- if ($firstLetter != "") $query->bindParam(":firstLetter", $firstLetter);
-
- if ($startsWith != "") {
- $startsWith = $startsWith."%";
- $query->bindParam(":startsWith", $startsWith);
+
+/*
+ * 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.
+ */
+
+function getStop($stopID) {
+ global $conn;
+ $query = "Select * from stops where stop_id = :stopID LIMIT 1";
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":stopID", $stopID);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetch(PDO :: FETCH_ASSOC);
+}
+
+function getStops($timingPointsOnly = false, $firstLetter = "", $startsWith = "") {
+ global $conn;
+ $conditions = Array();
+ if ($timingPointsOnly)
+ $conditions[] = "substr(stop_code,1,2) != 'Wj'";
+ if ($firstLetter != "")
+ $conditions[] = "substr(stop_name,1,1) = :firstLetter";
+ 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) {
- 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
+ }
+ $query .= " order by stop_name;";
+ $query = $conn->prepare($query);
+ if ($firstLetter != "")
+ $query->bindParam(":firstLetter", $firstLetter);
+
+ if ($startsWith != "") {
+ $startsWith = $startsWith . "%";
+ $query->bindParam(":startsWith", $startsWith);
+ }
+ $query->execute();
+ 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)
order by distance $limitSQL;";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":distance", $distance);
- $query->bindParam(":limit", $limit);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function getStopsBySuburb($suburb)
-{
- global $conn;
- $query = "Select * from stops where zone_id LIKE :suburb order by stop_name;";
- debug($query, "database");
- $query = $conn->prepare($query);
- $suburb = "%" . $suburb . ";%";
- $query->bindParam(":suburb", $suburb);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function getStopsByStopCode($stop_code,$startsWith = "")
-{
- global $conn;
- $query = "Select * from stops where (stop_code = :stop_code OR stop_code LIKE :stop_code2)";
- if ($startsWith != "") $query .= " AND stop_name like :startsWith";
-
- debug($query, "database");
- $query = $conn->prepare($query);
-
- $query->bindParam(":stop_code", $stop_code);
- $stop_code2 = $stop_code . "%";
- $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();
- global $conn;
- $query = "SELECT distinct service_id,trips.route_id,route_short_name,route_long_name
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":distance", $distance);
+ $query->bindParam(":limit", $limit);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getStopsByName($name) {
+ global $conn;
+ $query = "Select * from stops where stop_name LIKE :name;";
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $name = "%" . $name . ";%";
+ $query->bindParam(":name", $name);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getStopsBySuburb($suburb) {
+ global $conn;
+ $query = "Select * from stops where zone_id LIKE :suburb order by stop_name;";
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $suburb = "%" . $suburb . ";%";
+ $query->bindParam(":suburb", $suburb);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getStopsByStopCode($stop_code, $startsWith = "") {
+ global $conn;
+ $query = "Select * from stops where (stop_code = :stop_code OR stop_code LIKE :stop_code2)";
+ if ($startsWith != "")
+ $query .= " AND stop_name like :startsWith";
+
+ debug($query, "database");
+ $query = $conn->prepare($query);
+
+ $query->bindParam(":stop_code", $stop_code);
+ $stop_code2 = $stop_code . "%";
+ $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();
+ 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 join routes on trips.route_id = routes.route_id WHERE stop_id = :stopID AND service_id=:service_period";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":service_period", $service_period);
- $query->bindParam(":stopID", $stopID);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function getStopTrips($stopID, $service_period = "", $afterTime = "", $limit = "")
-{
- if ($service_period == "") $service_period = service_period();
- 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,route_short_name,route_long_name, end_times.arrival_time as end_time
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":service_period", $service_period);
+ $query->bindParam(":stopID", $stopID);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getStopTrips($stopID, $service_period = "", $afterTime = "", $limit = "") {
+ if ($service_period == "")
+ $service_period = service_period();
+ 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,route_short_name,route_long_name, end_times.arrival_time as end_time
FROM stop_times
join trips on trips.trip_id =
stop_times.trip_id
@@ -136,9 +176,8 @@
AND service_id=:service_period
AND end_times.arrival_time > :afterTime
ORDER BY end_time $limitSQL";
- }
- 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
+ } 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
FROM stop_times
join trips on trips.trip_id =
stop_times.trip_id
@@ -146,45 +185,52 @@
WHERE stop_times.stop_id = :stopID
AND service_id=:service_period
ORDER BY arrival_time $limitSQL";
- }
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":service_period", $service_period);
- $query->bindParam(":stopID", $stopID);
- if ($limit != "") $query->bindParam(":limit", $limit);
- if ($afterTime != "") $query->bindParam(":afterTime", $afterTime);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function getStopTripsWithTimes($stopID, $time = "", $service_period = "", $time_range = "", $limit = "")
-{
- if ($service_period == "") $service_period = service_period();
- if ($time_range == "") $time_range = (24 * 60 * 60);
- if ($time == "") $time = current_time();
- if ($limit == "") $limit = 10;
- $trips = getStopTrips($stopID, $service_period, $time);
- $timedTrips = Array();
- if ($trips && sizeof($trips) > 0) {
- foreach ($trips as $trip) {
- if ($trip['arrival_time'] != "") {
- if (strtotime($trip['arrival_time']) > strtotime($time) and strtotime($trip['arrival_time']) < (strtotime($time) + $time_range)) {
- $timedTrips[] = $trip;
- }
- }
- else {
- $timedTrip = getTimeInterpolatedTripAtStop($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;
- }
- sktimesort($timedTrips, "arrival_time", true);
+ }
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":service_period", $service_period);
+ $query->bindParam(":stopID", $stopID);
+ if ($limit != "")
+ $query->bindParam(":limit", $limit);
+ if ($afterTime != "")
+ $query->bindParam(":afterTime", $afterTime);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function getStopTripsWithTimes($stopID, $time = "", $service_period = "", $time_range = "", $limit = "") {
+ if ($service_period == "")
+ $service_period = service_period();
+ if ($time_range == "")
+ $time_range = (24 * 60 * 60);
+ if ($time == "")
+ $time = current_time();
+ if ($limit == "")
+ $limit = 10;
+ $trips = getStopTrips($stopID, $service_period, $time);
+ $timedTrips = Array();
+ if ($trips && sizeof($trips) > 0) {
+ foreach ($trips as $trip) {
+ if ($trip['arrival_time'] != "") {
+ if (strtotime($trip['arrival_time']) > strtotime($time) and strtotime($trip['arrival_time']) < (strtotime($time) + $time_range)) {
+ $timedTrips[] = $trip;
+ }
+ } else {
+ $timedTrip = getTimeInterpolatedTripAtStop($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;
+}
+
?>
--- a/include/db/trip-dao.inc.php
+++ b/include/db/trip-dao.inc.php
@@ -1,240 +1,256 @@
<?php
-function getTrip($tripID)
-{
- global $conn;
- $query = "Select * from trips
+
+/*
+ * 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.
+ */
+
+function getTrip($tripID) {
+ global $conn;
+ $query = "Select * from trips
join routes on trips.route_id = routes.route_id
where trip_id = :tripID
LIMIT 1";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":tripID", $tripID);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetch(PDO::FETCH_ASSOC);
-}
-function getTripShape($tripID)
-{
- global $conn;
- $query = "SELECT ST_AsKML(ST_MakeLine(geometry(a.position))) as the_route
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":tripID", $tripID);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetch(PDO :: FETCH_ASSOC);
+}
+
+function getTripShape($tripID) {
+ global $conn;
+ $query = "SELECT ST_AsKML(ST_MakeLine(geometry(a.position))) as the_route
FROM (SELECT position,
stop_sequence, trips.trip_id
FROM stop_times
join trips on trips.trip_id = stop_times.trip_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";
- 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 getTimeInterpolatedTrip($tripID, $range = "")
-{
- global $conn;
- $query = "SELECT stop_times.trip_id,arrival_time,stop_times.stop_id,stop_lat,stop_lon,stop_name,stop_code,
+ 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 getTimeInterpolatedTrip($tripID, $range = "") {
+ global $conn;
+ $query = "SELECT stop_times.trip_id,arrival_time,stop_times.stop_id,stop_lat,stop_lon,stop_name,stop_code,
stop_sequence,service_id,trips.route_id,route_short_name,route_long_name
FROM stop_times
join trips on trips.trip_id = stop_times.trip_id
join routes on trips.route_id = routes.route_id
join stops on stops.stop_id = stop_times.stop_id
WHERE trips.trip_id = :tripID $range ORDER BY stop_sequence";
- debug($query, "database");
- $query = $conn->prepare($query);
- $query->bindParam(":tripID", $tripID);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- $stopTimes = $query->fetchAll();
- $cur_timepoint = Array();
- $next_timepoint = Array();
- $distance_between_timepoints = 0.0;
- $distance_traveled_between_timepoints = 0.0;
- $rv = Array();
- foreach ($stopTimes as $i => $stopTime) {
- if ($stopTime['arrival_time'] != "") {
- // is timepoint
- $cur_timepoint = $stopTime;
- $distance_between_timepoints = 0.0;
- $distance_traveled_between_timepoints = 0.0;
- if ($i + 1 < sizeof($stopTimes)) {
- $k = $i + 1;
- $distance_between_timepoints+= distance($stopTimes[$k - 1]["stop_lat"], $stopTimes[$k - 1]["stop_lon"], $stopTimes[$k]["stop_lat"], $stopTimes[$k]["stop_lon"]);
- while ($stopTimes[$k]["arrival_time"] == "" && $k + 1 < sizeof($stopTimes)) {
- $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,
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":tripID", $tripID);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ $stopTimes = $query->fetchAll();
+ $cur_timepoint = Array();
+ $next_timepoint = Array();
+ $distance_between_timepoints = 0.0;
+ $distance_traveled_between_timepoints = 0.0;
+ $rv = Array();
+ foreach ($stopTimes as $i => $stopTime) {
+ if ($stopTime['arrival_time'] != "") {
+ // is timepoint
+ $cur_timepoint = $stopTime;
+ $distance_between_timepoints = 0.0;
+ $distance_traveled_between_timepoints = 0.0;
+ if ($i + 1 < sizeof($stopTimes)) {
+ $k = $i + 1;
+ $distance_between_timepoints += distance($stopTimes[$k - 1]["stop_lat"], $stopTimes[$k - 1]["stop_lon"], $stopTimes[$k]["stop_lat"], $stopTimes[$k]["stop_lon"]);
+ while ($stopTimes[$k]["arrival_time"] == "" && $k + 1 < sizeof($stopTimes)) {
+ $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,
+ 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
+ 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
AND arrival_time IS NOT NULL
AND stop_sequence = '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['arrival_time'];
-}
-function getTripEndTime($tripID)
-{
- global $conn;
- $query = "SELECT trip_id,max(arrival_time) as arrival_time from stop_times
+ 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 getTripEndTime($tripID) {
+ global $conn;
+ $query = "SELECT trip_id,max(arrival_time) as arrival_time from stop_times
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 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
+ 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 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
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");
- $query = $conn->prepare($query);
- $query->bindParam(":time", $time);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- return $query->fetchAll();
-}
-function viaPoints($tripID, $stop_sequence = "")
-{
- global $conn;
- $query = "SELECT stops.stop_id, stop_name, arrival_time
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ $query->bindParam(":time", $time);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ return $query->fetchAll();
+}
+
+function viaPoints($tripID, $stop_sequence = "", $timing_points_only = true) {
+ global $conn;
+ $query = "SELECT stops.stop_id, stop_name, arrival_time
FROM stop_times join stops on stops.stop_id = stop_times.stop_id
WHERE stop_times.trip_id = :tripID
-" . ($stop_sequence != "" ? " AND stop_sequence > :stop_sequence " : "") . "AND substr(stop_code,1,2) != 'Wj' ORDER BY stop_sequence";
- debug($query, "database");
- $query = $conn->prepare($query);
- if ($stop_sequence != "") $query->bindParam(":stop_sequence", $stop_sequence);
- $query->bindParam(":tripID", $tripID);
- $query->execute();
- if (!$query) {
- databaseError($conn->errorInfo());
- return Array();
- }
- 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 "";
- }
-}
+" . ($stop_sequence != "" ? " AND stop_sequence > :stop_sequence " : "") . ($timing_points_only ? "AND substr(stop_code,1,2) != 'Wj' " : "") . " ORDER BY stop_sequence";
+ debug($query, "database");
+ $query = $conn->prepare($query);
+ if ($stop_sequence != "")
+ $query->bindParam(":stop_sequence", $stop_sequence);
+ $query->bindParam(":tripID", $tripID);
+ $query->execute();
+ if (!$query) {
+ databaseError($conn->errorInfo());
+ return Array();
+ }
+ 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 "";
+ }
+}
+
?>
--- a/index.php
+++ b/index.php
@@ -1,30 +1,46 @@
<?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_header("bus.lambdacomplex.org", "index", false)
?>
<div data-role="page">
- <div data-role="content">
- <div id="jqm-homeheader">
- <h1>busness time</h1><br><small>Canberra Bus Timetables and Trip Planner</small>
- </div>
- <a name="maincontent" id="maincontent"></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">
- <li data-role="list-divider">Timetables - Stops</li>
- <li><a href="stopList.php">Major (Timing Point) Stops</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 class="nearby" href="stopList.php?nearby=yes">Nearby Stops</a></li>
- </ul>
- <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
- <li data-role="list-divider">Timetables - Routes</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?bysuburbs=yes">Routes By Suburb</a></li>
- <li><a class="nearby" href="routeList.php?nearby=yes">Nearby Routes</a></li>
- </ul>
-<?php
-echo ' <a href="labs/index.php" data-role="button" data-icon="beaker">Busness R&D</a>';
-include_footer(true)
-?>
+ <div data-role="content">
+ <div id="jqm-homeheader">
+ <h1>busness time</h1><br><small>Canberra Bus Timetables and Trip Planner</small>
+ </div>
+ <a name="maincontent" id="maincontent"></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">
+ <li data-role="list-divider">Timetables - Stops</li>
+ <li><a href="stopList.php">Major (Timing Point) Stops</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 class="nearby" href="stopList.php?nearby=yes">Nearby Stops</a></li>
+ </ul>
+ <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
+ <li data-role="list-divider">Timetables - Routes</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?bysuburbs=yes">Routes By Suburb</a></li>
+ <li><a class="nearby" href="routeList.php?nearby=yes">Nearby Routes</a></li>
+ </ul>
+ <?php
+ echo ' <a href="labs/index.php" data-role="button" data-icon="beaker">Busness R&D</a>';
+ echo ' <a href="myway/index.php" data-role="button">MyWay Balance and Timeliness Survey Results</a>';
+ include_footer(true)
+ ?>
--- a/js/jquery.mobile-1.0b2.js
+++ /dev/null
@@ -1,6260 +1,1 @@
-/*!
- * jQuery Mobile v1.0b2
- * 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: function() {},
- _init: function() {},
-
- destroy: function() {
- this.element
- .unbind( "." + this.widgetName )
- .removeData( this.widgetName );
- this.widget()
- .unbind( "." + this.widgetName )
- .removeAttr( "aria-disabled" )
- .removeClass(
- this.widgetBaseClass + "-disabled " +
- "ui-state-disabled" );
- },
-
- widget: function() {
- return this.element;
- },
-
- option: function( key, value ) {
- var options = key;
-
- if ( arguments.length === 0 ) {
- // don't return a reference to the internal hash
- return $.extend( {}, this.options );
- }
-
- if (typeof key === "string" ) {
- if ( value === undefined ) {
- return this.options[ key ];
- }
- options = {};
- options[ key ] = value;
- }
-
- this._setOptions( options );
-
- return this;
- },
- _setOptions: function( options ) {
- var self = this;
- $.each( options, function( key, value ) {
- self._setOption( key, value );
- });
-
- return this;
- },
- _setOption: function( key, value ) {
- this.options[ key ] = value;
-
- if ( key === "disabled" ) {
- this.widget()
- [ value ? "addClass" : "removeClass"](
- this.widgetBaseClass + "-disabled" + " " +
- "ui-state-disabled" )
- .attr( "aria-disabled", value );
- }
-
- return this;
- },
-
- enable: function() {
- return this._setOption( "disabled", false );
- },
- disable: function() {
- return this._setOption( "disabled", true );
- },
-
- _trigger: function( type, event, data ) {
- var callback = this.options[ type ];
-
- event = $.Event( event );
- event.type = ( type === this.widgetEventPrefix ?
- type :
- this.widgetEventPrefix + type ).toLowerCase();
- data = data || {};
-
- // copy original event properties over to the new event
- // this would happen if we could call $.event.fix instead of $.Event
- // but we don't have a way to force an event to be fixed multiple times
- if ( event.originalEvent ) {
- for ( var i = $.event.props.length, prop; i; ) {
- prop = $.event.props[ --i ];
- event[ prop ] = event.originalEvent[ prop ];
- }
- }
-
- this.element.trigger( event, data );
-
- return !( $.isFunction(callback) &&
- callback.call( this.element[0], event, data ) === false ||
- event.isDefaultPrevented() );
- }
-};
-
-})( jQuery );
-/*
-* jQuery Mobile Framework : widget factory extentions for mobile
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.widget( "mobile.widget", {
- _getCreateOptions: function() {
-
- var elem = this.element,
- options = {};
-
- $.each( this.options, function( option ) {
-
- var value = elem.jqmData( option.replace( /[A-Z]/g, function( c ) {
- return "-" + c.toLowerCase();
- })
- );
-
- if ( value !== undefined ) {
- options[ option ] = value;
- }
- });
-
- return options;
- }
-});
-
-})( jQuery );
-/*
-* jQuery Mobile Framework : resolution and CSS media query related helpers and behavior
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-(function( $, undefined ) {
-
-var $window = $( window ),
- $html = $( "html" );
-
-/* $.mobile.media method: pass a CSS media type or query and get a bool return
- note: this feature relies on actual media query support for media queries, though types will work most anywhere
- examples:
- $.mobile.media('screen') //>> tests for screen media type
- $.mobile.media('screen and (min-width: 480px)') //>> tests for screen media type with window width > 480px
- $.mobile.media('@media screen and (-webkit-min-device-pixel-ratio: 2)') //>> tests for webkit 2x pixel ratio (iPhone 4)
-*/
-$.mobile.media = (function() {
- // TODO: use window.matchMedia once at least one UA implements it
- var cache = {},
- testDiv = $( "<div id='jquery-mediatest'>" ),
- fakeBody = $( "<body>" ).append( testDiv );
-
- return function( query ) {
- if ( !( query in cache ) ) {
- var styleBlock = document.createElement( "style" ),
- cssrule = "@media " + query + " { #jquery-mediatest { position:absolute; } }";
-
- //must set type for IE!
- styleBlock.type = "text/css";
-
- if ( styleBlock.styleSheet ){
- styleBlock.styleSheet.cssText = cssrule;
- } else {
- styleBlock.appendChild( document.createTextNode(cssrule) );
- }
-
- $html.prepend( fakeBody ).prepend( styleBlock );
- cache[ query ] = testDiv.css( "position" ) === "absolute";
- fakeBody.add( styleBlock ).remove();
- }
- return cache[ query ];
- };
-})();
-
-})(jQuery);/*
-* jQuery Mobile Framework : support tests
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
-*/
-
-(function( $, undefined ) {
-
-var fakeBody = $( "<body>" ).prependTo( "html" ),
- fbCSS = fakeBody[ 0 ].style,
- vendors = [ "webkit", "moz", "o" ],
- webos = "palmGetResource" in window, //only used to rule out scrollTop
- bb = window.blackberry; //only used to rule out box shadow, as it's filled opaque on BB
-
-// thx Modernizr
-function propExists( prop ) {
- var uc_prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ),
- props = ( prop + " " + vendors.join( uc_prop + " " ) + uc_prop ).split( " " );
-
- for ( var v in props ){
- if ( fbCSS[ v ] !== undefined ) {
- return true;
- }
- }
-}
-
-// Test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting )
-function baseTagTest() {
- var fauxBase = location.protocol + "//" + location.host + location.pathname + "ui-dir/",
- base = $( "head base" ),
- fauxEle = null,
- href = "",
- link, rebase;
-
- if ( !base.length ) {
- base = fauxEle = $( "<base>", { "href": fauxBase }).appendTo( "head" );
- } else {
- href = base.attr( "href" );
- }
-
- link = $( "<a href='testurl'></a>" ).prependTo( fakeBody );
- rebase = link[ 0 ].href;
- base[ 0 ].href = href ? href : location.pathname;
-
- if ( fauxEle ) {
- fauxEle.remove();
- }
- return rebase.indexOf( fauxBase ) === 0;
-}
-
-
-// non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683
-// allows for inclusion of IE 6+, including Windows Mobile 7
-$.mobile.browser = {};
-$.mobile.browser.ie = (function() {
- var v = 3,
- div = document.createElement( "div" ),
- a = div.all || [];
-
- while ( div.innerHTML = "<!--[if gt IE " + ( ++v ) + "]><br><![endif]-->", a[ 0 ] );
-
- return v > 4 ? v : !v;
-})();
-
-
-$.extend( $.support, {
- orientation: "orientation" in window,
- touch: "ontouchend" in document,
- cssTransitions: "WebKitTransitionEvent" in window,
- pushState: !!history.pushState,
- mediaquery: $.mobile.media( "only all" ),
- cssPseudoElement: !!propExists( "content" ),
- boxShadow: !!propExists( "boxShadow" ) && !bb,
- scrollTop: ( "pageXOffset" in window || "scrollTop" in document.documentElement || "scrollTop" in fakeBody[ 0 ] ) && !webos,
- dynamicBaseTag: baseTagTest(),
- // TODO: This is a weak test. We may want to beef this up later.
- eventCapture: "addEventListener" in document
-});
-
-fakeBody.remove();
-
-
-// $.mobile.ajaxBlacklist is used to override ajaxEnabled on platforms that have known conflicts with hash history updates (BB5, Symbian)
-// or that generally work better browsing in regular http for full page refreshes (Opera Mini)
-// Note: This detection below is used as a last resort.
-// We recommend only using these detection methods when all other more reliable/forward-looking approaches are not possible
-var nokiaLTE7_3 = (function(){
-
- var ua = window.navigator.userAgent;
-
- //The following is an attempt to match Nokia browsers that are running Symbian/s60, with webkit, version 7.3 or older
- return ua.indexOf( "Nokia" ) > -1 &&
- ( ua.indexOf( "Symbian/3" ) > -1 || ua.indexOf( "Series60/5" ) > -1 ) &&
- ua.indexOf( "AppleWebKit" ) > -1 &&
- ua.match( /(BrowserNG|NokiaBrowser)\/7\.[0-3]/ );
-})();
-
-$.mobile.ajaxBlacklist =
- // BlackBerry browsers, pre-webkit
- window.blackberry && !window.WebKitPoint ||
- // Opera Mini
- window.operamini && Object.prototype.toString.call( window.operamini ) === "[object OperaMini]" ||
- // Symbian webkits pre 7.3
- nokiaLTE7_3;
-
-// Lastly, this workaround is the only way we've found so far to get pre 7.3 Symbian webkit devices
-// to render the stylesheets when they're referenced before this script, as we'd recommend doing.
-// This simply reappends the CSS in place, which for some reason makes it apply
-if ( nokiaLTE7_3 ) {
- $(function() {
- $( "head link[rel=stylesheet]" ).attr( "rel", "alternate stylesheet" ).attr( "rel", "stylesheet" );
- });
-}
-
-// For ruling out shadows via css
-if ( !$.support.boxShadow ) {
- $( "html" ).addClass( "ui-mobile-nosupport-boxshadow" );
-}
-
-})( jQuery );/*
-* jQuery Mobile Framework : "mouse" plugin
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-// This plugin is an experiment for abstracting away the touch and mouse
-// events so that developers don't have to worry about which method of input
-// the device their document is loaded on supports.
-//
-// The idea here is to allow the developer to register listeners for the
-// basic mouse events, such as mousedown, mousemove, mouseup, and click,
-// and the plugin will take care of registering the correct listeners
-// behind the scenes to invoke the listener at the fastest possible time
-// for that device, while still retaining the order of event firing in
-// the traditional mouse environment, should multiple handlers be registered
-// on the same element for different events.
-//
-// The current version exposes the following virtual events to jQuery bind methods:
-// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel"
-
-(function( $, window, document, undefined ) {
-
-var dataPropertyName = "virtualMouseBindings",
- touchTargetPropertyName = "virtualTouchID",
- virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ),
- touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ),
- activeDocHandlers = {},
- resetTimerID = 0,
- startX = 0,
- startY = 0,
- didScroll = false,
- clickBlockList = [],
- blockMouseTriggers = false,
- blockTouchTriggers = false,
- eventCaptureSupported = $.support.eventCapture,
- $document = $( document ),
- nextTouchID = 1,
- lastTouchID = 0;
-
-$.vmouse = {
- moveDistanceThreshold: 10,
- clickDistanceThreshold: 10,
- resetTimerDuration: 1500
-};
-
-function getNativeEvent( event ) {
-
- while ( event && typeof event.originalEvent !== "undefined" ) {
- event = event.originalEvent;
- }
- return event;
-}
-
-function createVirtualEvent( event, eventType ) {
-
- var t = event.type,
- oe, props, ne, prop, ct, touch, i, j;
-
- event = $.Event(event);
- event.type = eventType;
-
- oe = event.originalEvent;
- props = $.event.props;
-
- // copy original event properties over to the new event
- // this would happen if we could call $.event.fix instead of $.Event
- // but we don't have a way to force an event to be fixed multiple times
- if ( oe ) {
- for ( i = props.length, prop; i; ) {
- prop = props[ --i ];
- event[ prop ] = oe[ prop ];
- }
- }
-
- if ( t.search(/^touch/) !== -1 ) {
- ne = getNativeEvent( oe );
- t = ne.touches;
- ct = ne.changedTouches;
- touch = ( t && t.length ) ? t[0] : ( (ct && ct.length) ? ct[ 0 ] : undefined );
-
- if ( touch ) {
- for ( j = 0, len = touchEventProps.length; j < len; j++){
- prop = touchEventProps[ j ];
- event[ prop ] = touch[ prop ];
- }
- }
- }
-
- return event;
-}
-
-function getVirtualBindingFlags( element ) {
-
- var flags = {},
- b, k;
-
- while ( element ) {
-
- b = $.data( element, dataPropertyName );
-
- for ( k in b ) {
- if ( b[ k ] ) {
- flags[ k ] = flags.hasVirtualBinding = true;
- }
- }
- element = element.parentNode;
- }
- return flags;
-}
-
-function getClosestElementWithVirtualBinding( element, eventType ) {
- var b;
- while ( element ) {
-
- b = $.data( element, dataPropertyName );
-
- if ( b && ( !eventType || b[ eventType ] ) ) {
- return element;
- }
- element = element.parentNode;
- }
- return null;
-}
-
-function enableTouchBindings() {
- blockTouchTriggers = false;
-}
-
-function disableTouchBindings() {
- blockTouchTriggers = true;
-}
-
-function enableMouseBindings() {
- lastTouchID = 0;
- clickBlockList.length = 0;
- blockMouseTriggers = false;
-
- // When mouse bindings are enabled, our
- // touch bindings are disabled.
- disableTouchBindings();
-}
-
-function disableMouseBindings() {
- // When mouse bindings are disabled, our
- // touch bindings are enabled.
- enableTouchBindings();
-}
-
-function startResetTimer() {
- clearResetTimer();
- resetTimerID = setTimeout(function(){
- resetTimerID = 0;
- enableMouseBindings();
- }, $.vmouse.resetTimerDuration );
-}
-
-function clearResetTimer() {
- if ( resetTimerID ){
- clearTimeout( resetTimerID );
- resetTimerID = 0;
- }
-}
-
-function triggerVirtualEvent( eventType, event, flags ) {
- var defaultPrevented = false,
- ve;
-
- if ( ( flags && flags[ eventType ] ) ||
- ( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {
-
- ve = createVirtualEvent( event, eventType );
-
- $( event.target).trigger( ve );
-
- defaultPrevented = ve.isDefaultPrevented();
- }
-
- return defaultPrevented;
-}
-
-function mouseEventCallback( event ) {
- var touchID = $.data(event.target, touchTargetPropertyName);
-
- if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ){
- triggerVirtualEvent( "v" + event.type, event );
- }
-}
-
-function handleTouchStart( event ) {
-
- var touches = getNativeEvent( event ).touches,
- target, flags;
-
- if ( touches && touches.length === 1 ) {
-
- target = event.target;
- flags = getVirtualBindingFlags( target );
-
- if ( flags.hasVirtualBinding ) {
-
- lastTouchID = nextTouchID++;
- $.data( target, touchTargetPropertyName, lastTouchID );
-
- clearResetTimer();
-
- disableMouseBindings();
- didScroll = false;
-
- var t = getNativeEvent( event ).touches[ 0 ];
- startX = t.pageX;
- startY = t.pageY;
-
- triggerVirtualEvent( "vmouseover", event, flags );
- triggerVirtualEvent( "vmousedown", event, flags );
- }
- }
-}
-
-function handleScroll( event ) {
- if ( blockTouchTriggers ) {
- return;
- }
-
- if ( !didScroll ) {
- triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) );
- }
-
- didScroll = true;
- startResetTimer();
-}
-
-function handleTouchMove( event ) {
- if ( blockTouchTriggers ) {
- return;
- }
-
- var t = getNativeEvent( event ).touches[ 0 ],
- didCancel = didScroll,
- moveThreshold = $.vmouse.moveDistanceThreshold;
- didScroll = didScroll ||
- ( Math.abs(t.pageX - startX) > moveThreshold ||
- Math.abs(t.pageY - startY) > moveThreshold ),
- flags = getVirtualBindingFlags( event.target );
-
- if ( didScroll && !didCancel ) {
- triggerVirtualEvent( "vmousecancel", event, flags );
- }
-
- triggerVirtualEvent( "vmousemove", event, flags );
- startResetTimer();
-}
-
-function handleTouchEnd( event ) {
- if ( blockTouchTriggers ) {
- return;
- }
-
- disableTouchBindings();
-
- var flags = getVirtualBindingFlags( event.target ),
- t;
- triggerVirtualEvent( "vmouseup", event, flags );
-
- if ( !didScroll ) {
- if ( triggerVirtualEvent( "vclick", event, flags ) ) {
- // The target of the mouse events that follow the touchend
- // event don't necessarily match the target used during the
- // touch. This means we need to rely on coordinates for blocking
- // any click that is generated.
- t = getNativeEvent( event ).changedTouches[ 0 ];
- clickBlockList.push({
- touchID: lastTouchID,
- x: t.clientX,
- y: t.clientY
- });
-
- // Prevent any mouse events that follow from triggering
- // virtual event notifications.
- blockMouseTriggers = true;
- }
- }
- triggerVirtualEvent( "vmouseout", event, flags);
- didScroll = false;
-
- startResetTimer();
-}
-
-function hasVirtualBindings( ele ) {
- var bindings = $.data( ele, dataPropertyName ),
- k;
-
- if ( bindings ) {
- for ( k in bindings ) {
- if ( bindings[ k ] ) {
- return true;
- }
- }
- }
- return false;
-}
-
-function dummyMouseHandler(){}
-
-function getSpecialEventObject( eventType ) {
- var realType = eventType.substr( 1 );
-
- return {
- setup: function( data, namespace ) {
- // If this is the first virtual mouse binding for this element,
- // add a bindings object to its data.
-
- if ( !hasVirtualBindings( this ) ) {
- $.data( this, dataPropertyName, {});
- }
-
- // If setup is called, we know it is the first binding for this
- // eventType, so initialize the count for the eventType to zero.
- var bindings = $.data( this, dataPropertyName );
- bindings[ eventType ] = true;
-
- // If this is the first virtual mouse event for this type,
- // register a global handler on the document.
-
- activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;
-
- if ( activeDocHandlers[ eventType ] === 1 ) {
- $document.bind( realType, mouseEventCallback );
- }
-
- // Some browsers, like Opera Mini, won't dispatch mouse/click events
- // for elements unless they actually have handlers registered on them.
- // To get around this, we register dummy handlers on the elements.
-
- $( this ).bind( realType, dummyMouseHandler );
-
- // For now, if event capture is not supported, we rely on mouse handlers.
- if ( eventCaptureSupported ) {
- // If this is the first virtual mouse binding for the document,
- // register our touchstart handler on the document.
-
- activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1;
-
- if (activeDocHandlers[ "touchstart" ] === 1) {
- $document.bind( "touchstart", handleTouchStart )
- .bind( "touchend", handleTouchEnd )
-
- // On touch platforms, touching the screen and then dragging your finger
- // causes the window content to scroll after some distance threshold is
- // exceeded. On these platforms, a scroll prevents a click event from being
- // dispatched, and on some platforms, even the touchend is suppressed. To
- // mimic the suppression of the click event, we need to watch for a scroll
- // event. Unfortunately, some platforms like iOS don't dispatch scroll
- // events until *AFTER* the user lifts their finger (touchend). This means
- // we need to watch both scroll and touchmove events to figure out whether
- // or not a scroll happenens before the touchend event is fired.
-
- .bind( "touchmove", handleTouchMove )
- .bind( "scroll", handleScroll );
- }
- }
- },
-
- teardown: function( data, namespace ) {
- // If this is the last virtual binding for this eventType,
- // remove its global handler from the document.
-
- --activeDocHandlers[ eventType ];
-
- if ( !activeDocHandlers[ eventType ] ) {
- $document.unbind( realType, mouseEventCallback );
- }
-
- if ( eventCaptureSupported ) {
- // If this is the last virtual mouse binding in existence,
- // remove our document touchstart listener.
-
- --activeDocHandlers[ "touchstart" ];
-
- if ( !activeDocHandlers[ "touchstart" ] ) {
- $document.unbind( "touchstart", handleTouchStart )
- .unbind( "touchmove", handleTouchMove )
- .unbind( "touchend", handleTouchEnd )
- .unbind( "scroll", handleScroll );
- }
- }
-
- var $this = $( this ),
- bindings = $.data( this, dataPropertyName );
-
- // teardown may be called when an element was
- // removed from the DOM. If this is the case,
- // jQuery core may have already stripped the element
- // of any data bindings so we need to check it before
- // using it.
- if ( bindings ) {
- bindings[ eventType ] = false;
- }
-
- // Unregister the dummy event handler.
-
- $this.unbind( realType, dummyMouseHandler );
-
- // If this is the last virtual mouse binding on the
- // element, remove the binding data from the element.
-
- if ( !hasVirtualBindings( this ) ) {
- $this.removeData( dataPropertyName );
- }
- }
- };
-}
-
-// Expose our custom events to the jQuery bind/unbind mechanism.
-
-for ( var i = 0; i < virtualEventNames.length; i++ ){
- $.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );
-}
-
-// Add a capture click handler to block clicks.
-// Note that we require event capture support for this so if the device
-// doesn't support it, we punt for now and rely solely on mouse events.
-if ( eventCaptureSupported ) {
- document.addEventListener( "click", function( e ){
- var cnt = clickBlockList.length,
- target = e.target,
- x, y, ele, i, o, touchID;
-
- if ( cnt ) {
- x = e.clientX;
- y = e.clientY;
- threshold = $.vmouse.clickDistanceThreshold;
-
- // The idea here is to run through the clickBlockList to see if
- // the current click event is in the proximity of one of our
- // vclick events that had preventDefault() called on it. If we find
- // one, then we block the click.
- //
- // Why do we have to rely on proximity?
- //
- // Because the target of the touch event that triggered the vclick
- // can be different from the target of the click event synthesized
- // by the browser. The target of a mouse/click event that is syntehsized
- // from a touch event seems to be implementation specific. For example,
- // some browsers will fire mouse/click events for a link that is near
- // a touch event, even though the target of the touchstart/touchend event
- // says the user touched outside the link. Also, it seems that with most
- // browsers, the target of the mouse/click event is not calculated until the
- // time it is dispatched, so if you replace an element that you touched
- // with another element, the target of the mouse/click will be the new
- // element underneath that point.
- //
- // Aside from proximity, we also check to see if the target and any
- // of its ancestors were the ones that blocked a click. This is necessary
- // because of the strange mouse/click target calculation done in the
- // Android 2.1 browser, where if you click on an element, and there is a
- // mouse/click handler on one of its ancestors, the target will be the
- // innermost child of the touched element, even if that child is no where
- // near the point of touch.
-
- ele = target;
-
- while ( ele ) {
- for ( i = 0; i < cnt; i++ ) {
- o = clickBlockList[ i ];
- touchID = 0;
-
- if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||
- $.data( ele, touchTargetPropertyName ) === o.touchID ) {
- // XXX: We may want to consider removing matches from the block list
- // instead of waiting for the reset timer to fire.
- e.preventDefault();
- e.stopPropagation();
- return;
- }
- }
- ele = ele.parentNode;
- }
- }
- }, true);
-}
-})( jQuery, window, document );
-/*
-* jQuery Mobile Framework : events
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-(function( $, window, undefined ) {
-
-// add new event shortcuts
-$.each( ( "touchstart touchmove touchend orientationchange throttledresize " +
- "tap taphold swipe swipeleft swiperight scrollstart scrollstop" ).split( " " ), function( i, name ) {
-
- $.fn[ name ] = function( fn ) {
- return fn ? this.bind( name, fn ) : this.trigger( name );
- };
-
- $.attrFn[ name ] = true;
-});
-
-var supportTouch = $.support.touch,
- scrollEvent = "touchmove scroll",
- touchStartEvent = supportTouch ? "touchstart" : "mousedown",
- touchStopEvent = supportTouch ? "touchend" : "mouseup",
- touchMoveEvent = supportTouch ? "touchmove" : "mousemove";
-
-function triggerCustomEvent( obj, eventType, event ) {
- var originalType = event.type;
- event.type = eventType;
- $.event.handle.call( obj, event );
- event.type = originalType;
-}
-
-// also handles scrollstop
-$.event.special.scrollstart = {
-
- enabled: true,
-
- setup: function() {
-
- var thisObject = this,
- $this = $( thisObject ),
- scrolling,
- timer;
-
- function trigger( event, state ) {
- scrolling = state;
- triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event );
- }
-
- // iPhone triggers scroll after a small delay; use touchmove instead
- $this.bind( scrollEvent, function( event ) {
-
- if ( !$.event.special.scrollstart.enabled ) {
- return;
- }
-
- if ( !scrolling ) {
- trigger( event, true );
- }
-
- clearTimeout( timer );
- timer = setTimeout(function() {
- trigger( event, false );
- }, 50 );
- });
- }
-};
-
-// also handles taphold
-$.event.special.tap = {
- setup: function() {
- var thisObject = this,
- $this = $( thisObject );
-
- $this.bind( "vmousedown", function( event ) {
-
- if ( event.which && event.which !== 1 ) {
- return false;
- }
-
- var touching = true,
- origTarget = event.target,
- origEvent = event.originalEvent,
- timer;
-
- function clearTapHandlers() {
- touching = false;
- clearTimeout(timer);
-
- $this.unbind( "vclick", clickHandler )
- .unbind( "vmousecancel", clearTapHandlers );
- }
-
- function clickHandler(event) {
- clearTapHandlers();
-
- // ONLY trigger a 'tap' event if the start target is
- // the same as the stop target.
- if ( origTarget == event.target ) {
- triggerCustomEvent( thisObject, "tap", event );
- }
- }
-
- $this.bind( "vmousecancel", clearTapHandlers )
- .bind( "vclick", clickHandler );
-
- timer = setTimeout(function() {
- if ( touching ) {
- triggerCustomEvent( thisObject, "taphold", event );
- }
- }, 750 );
- });
- }
-};
-
-// also handles swipeleft, swiperight
-$.event.special.swipe = {
- scrollSupressionThreshold: 10, // More than this horizontal displacement, and we will suppress scrolling.
-
- durationThreshold: 1000, // More time than this, and it isn't a swipe.
-
- horizontalDistanceThreshold: 30, // Swipe horizontal displacement must be more than this.
-
- verticalDistanceThreshold: 75, // Swipe vertical displacement must be less than this.
-
- setup: function() {
- var thisObject = this,
- $this = $( thisObject );
-
- $this.bind( touchStartEvent, function( event ) {
- var data = event.originalEvent.touches ?
- event.originalEvent.touches[ 0 ] : event,
- start = {
- time: ( new Date() ).getTime(),
- coords: [ data.pageX, data.pageY ],
- origin: $( event.target )
- },
- stop;
-
- function moveHandler( event ) {
-
- if ( !start ) {
- return;
- }
-
- var data = event.originalEvent.touches ?
- event.originalEvent.touches[ 0 ] : event;
-
- stop = {
- time: ( new Date() ).getTime(),
- coords: [ data.pageX, data.pageY ]
- };
-
- // prevent scrolling
- if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {
- event.preventDefault();
- }
- }
-
- $this.bind( touchMoveEvent, moveHandler )
- .one( touchStopEvent, function( event ) {
- $this.unbind( touchMoveEvent, moveHandler );
-
- if ( start && stop ) {
- if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
- Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&
- Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {
-
- start.origin.trigger( "swipe" )
- .trigger( start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight" );
- }
- }
- start = stop = undefined;
- });
- });
- }
-};
-
-(function( $, window ) {
- // "Cowboy" Ben Alman
-
- var win = $( window ),
- special_event,
- get_orientation,
- last_orientation;
-
- $.event.special.orientationchange = special_event = {
- setup: function() {
- // If the event is supported natively, return false so that jQuery
- // will bind to the event using DOM methods.
- if ( $.support.orientation ) {
- return false;
- }
-
- // Get the current orientation to avoid initial double-triggering.
- last_orientation = get_orientation();
-
- // Because the orientationchange event doesn't exist, simulate the
- // event by testing window dimensions on resize.
- win.bind( "throttledresize", handler );
- },
- teardown: function(){
- // If the event is not supported natively, return false so that
- // jQuery will unbind the event using DOM methods.
- if ( $.support.orientation ) {
- return false;
- }
-
- // Because the orientationchange event doesn't exist, unbind the
- // resize event handler.
- win.unbind( "throttledresize", handler );
- },
- add: function( handleObj ) {
- // Save a reference to the bound event handler.
- var old_handler = handleObj.handler;
-
- handleObj.handler = function( event ) {
- // Modify event object, adding the .orientation property.
- event.orientation = get_orientation();
-
- // Call the originally-bound event handler and return its result.
- return old_handler.apply( this, arguments );
- };
- }
- };
-
- // If the event is not supported natively, this handler will be bound to
- // the window resize event to simulate the orientationchange event.
- function handler() {
- // Get the current orientation.
- var orientation = get_orientation();
-
- if ( orientation !== last_orientation ) {
- // The orientation has changed, so trigger the orientationchange event.
- last_orientation = orientation;
- win.trigger( "orientationchange" );
- }
- };
-
- // Get the current page orientation. This method is exposed publicly, should it
- // be needed, as jQuery.event.special.orientationchange.orientation()
- $.event.special.orientationchange.orientation = get_orientation = function() {
- var elem = document.documentElement;
- return elem && elem.clientWidth / elem.clientHeight < 1.1 ? "portrait" : "landscape";
- };
-
-})( jQuery, window );
-
-
-// throttled resize event
-(function() {
-
- $.event.special.throttledresize = {
- setup: function() {
- $( this ).bind( "resize", handler );
- },
- teardown: function(){
- $( this ).unbind( "resize", handler );
- }
- };
-
- var throttle = 250,
- handler = function() {
- curr = ( new Date() ).getTime();
- diff = curr - lastCall;
-
- if ( diff >= throttle ) {
-
- lastCall = curr;
- $( this ).trigger( "throttledresize" );
-
- } else {
-
- if ( heldCall ) {
- clearTimeout( heldCall );
- }
-
- // Promise a held call will still execute
- heldCall = setTimeout( handler, throttle - diff );
- }
- },
- lastCall = 0,
- heldCall,
- curr,
- diff;
-})();
-
-
-$.each({
- scrollstop: "scrollstart",
- taphold: "tap",
- swipeleft: "swipe",
- swiperight: "swipe"
-}, function( event, sourceEvent ) {
-
- $.event.special[ event ] = {
- setup: function() {
- $( this ).bind( sourceEvent, $.noop );
- }
- };
-});
-
-})( jQuery, this );
-/*!
- * jQuery hashchange event - v1.3 - 7/21/2010
- * http://benalman.com/projects/jquery-hashchange-plugin/
- *
- * Copyright (c) 2010 "Cowboy" Ben Alman
- * Dual licensed under the MIT and GPL licenses.
- * http://benalman.com/about/license/
- */
-
-// Script: jQuery hashchange event
-//
-// *Version: 1.3, Last updated: 7/21/2010*
-//
-// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/
-// GitHub - http://github.com/cowboy/jquery-hashchange/
-// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js
-// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)
-//
-// About: License
-//
-// Copyright (c) 2010 "Cowboy" Ben Alman,
-// Dual licensed under the MIT and GPL licenses.
-// http://benalman.com/about/license/
-//
-// About: Examples
-//
-// These working examples, complete with fully commented code, illustrate a few
-// ways in which this plugin can be used.
-//
-// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/
-// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/
-//
-// About: Support and Testing
-//
-// Information about what version or versions of jQuery this plugin has been
-// tested with, what browsers it has been tested in, and where the unit tests
-// reside (so you can test it yourself).
-//
-// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2
-// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,
-// Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.
-// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/
-//
-// About: Known issues
-//
-// While this jQuery hashchange event implementation is quite stable and
-// robust, there are a few unfortunate browser bugs surrounding expected
-// hashchange event-based behaviors, independent of any JavaScript
-// window.onhashchange abstraction. See the following examples for more
-// information:
-//
-// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/
-// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/
-// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/
-// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/
-//
-// Also note that should a browser natively support the window.onhashchange
-// event, but not report that it does, the fallback polling loop will be used.
-//
-// About: Release History
-//
-// 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more
-// "removable" for mobile-only development. Added IE6/7 document.title
-// support. Attempted to make Iframe as hidden as possible by using
-// techniques from http://www.paciellogroup.com/blog/?p=604. Added
-// support for the "shortcut" format $(window).hashchange( fn ) and
-// $(window).hashchange() like jQuery provides for built-in events.
-// Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and
-// lowered its default value to 50. Added <jQuery.fn.hashchange.domain>
-// and <jQuery.fn.hashchange.src> properties plus document-domain.html
-// file to address access denied issues when setting document.domain in
-// IE6/7.
-// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin
-// from a page on another domain would cause an error in Safari 4. Also,
-// IE6/7 Iframe is now inserted after the body (this actually works),
-// which prevents the page from scrolling when the event is first bound.
-// Event can also now be bound before DOM ready, but it won't be usable
-// before then in IE6/7.
-// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug
-// where browser version is incorrectly reported as 8.0, despite
-// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.
-// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special
-// window.onhashchange functionality into a separate plugin for users
-// who want just the basic event & back button support, without all the
-// extra awesomeness that BBQ provides. This plugin will be included as
-// part of jQuery BBQ, but also be available separately.
-
-(function($,window,undefined){
- '$:nomunge'; // Used by YUI compressor.
-
- // Reused string.
- var str_hashchange = 'hashchange',
-
- // Method / object references.
- doc = document,
- fake_onhashchange,
- special = $.event.special,
-
- // Does the browser support window.onhashchange? Note that IE8 running in
- // IE7 compatibility mode reports true for 'onhashchange' in window, even
- // though the event isn't supported, so also test document.documentMode.
- doc_mode = doc.documentMode,
- supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );
-
- // Get location.hash (or what you'd expect location.hash to be) sans any
- // leading #. Thanks for making this necessary, Firefox!
- function get_fragment( url ) {
- url = url || location.href;
- return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );
- };
-
- // Method: jQuery.fn.hashchange
- //
- // Bind a handler to the window.onhashchange event or trigger all bound
- // window.onhashchange event handlers. This behavior is consistent with
- // jQuery's built-in event handlers.
- //
- // Usage:
- //
- // > jQuery(window).hashchange( [ handler ] );
- //
- // Arguments:
- //
- // handler - (Function) Optional handler to be bound to the hashchange
- // event. This is a "shortcut" for the more verbose form:
- // jQuery(window).bind( 'hashchange', handler ). If handler is omitted,
- // all bound window.onhashchange event handlers will be triggered. This
- // is a shortcut for the more verbose
- // jQuery(window).trigger( 'hashchange' ). These forms are described in
- // the <hashchange event> section.
- //
- // Returns:
- //
- // (jQuery) The initial jQuery collection of elements.
-
- // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and
- // $(elem).hashchange() for triggering, like jQuery does for built-in events.
- $.fn[ str_hashchange ] = function( fn ) {
- return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );
- };
-
- // Property: jQuery.fn.hashchange.delay
- //
- // The numeric interval (in milliseconds) at which the <hashchange event>
- // polling loop executes. Defaults to 50.
-
- // Property: jQuery.fn.hashchange.domain
- //
- // If you're setting document.domain in your JavaScript, and you want hash
- // history to work in IE6/7, not only must this property be set, but you must
- // also set document.domain BEFORE jQuery is loaded into the page. This
- // property is only applicable if you are supporting IE6/7 (or IE8 operating
- // in "IE7 compatibility" mode).
- //
- // In addition, the <jQuery.fn.hashchange.src> property must be set to the
- // path of the included "document-domain.html" file, which can be renamed or
- // modified if necessary (note that the document.domain specified must be the
- // same in both your main JavaScript as well as in this file).
- //
- // Usage:
- //
- // jQuery.fn.hashchange.domain = document.domain;
-
- // Property: jQuery.fn.hashchange.src
- //
- // If, for some reason, you need to specify an Iframe src file (for example,
- // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can
- // do so using this property. Note that when using this property, history
- // won't be recorded in IE6/7 until the Iframe src file loads. This property
- // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7
- // compatibility" mode).
- //
- // Usage:
- //
- // jQuery.fn.hashchange.src = 'path/to/file.html';
-
- $.fn[ str_hashchange ].delay = 50;
- /*
- $.fn[ str_hashchange ].domain = null;
- $.fn[ str_hashchange ].src = null;
- */
-
- // Event: hashchange event
- //
- // Fired when location.hash changes. In browsers that support it, the native
- // HTML5 window.onhashchange event is used, otherwise a polling loop is
- // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to
- // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7
- // compatibility" mode), a hidden Iframe is created to allow the back button
- // and hash-based history to work.
- //
- // Usage as described in <jQuery.fn.hashchange>:
- //
- // > // Bind an event handler.
- // > jQuery(window).hashchange( function(e) {
- // > var hash = location.hash;
- // > ...
- // > });
- // >
- // > // Manually trigger the event handler.
- // > jQuery(window).hashchange();
- //
- // A more verbose usage that allows for event namespacing:
- //
- // > // Bind an event handler.
- // > jQuery(window).bind( 'hashchange', function(e) {
- // > var hash = location.hash;
- // > ...
- // > });
- // >
- // > // Manually trigger the event handler.
- // > jQuery(window).trigger( 'hashchange' );
- //
- // Additional Notes:
- //
- // * The polling loop and Iframe are not created until at least one handler
- // is actually bound to the 'hashchange' event.
- // * If you need the bound handler(s) to execute immediately, in cases where
- // a location.hash exists on page load, via bookmark or page refresh for
- // example, use jQuery(window).hashchange() or the more verbose
- // jQuery(window).trigger( 'hashchange' ).
- // * The event can be bound before DOM ready, but since it won't be usable
- // before then in IE6/7 (due to the necessary Iframe), recommended usage is
- // to bind it inside a DOM ready handler.
-
- // Override existing $.event.special.hashchange methods (allowing this plugin
- // to be defined after jQuery BBQ in BBQ's source code).
- special[ str_hashchange ] = $.extend( special[ str_hashchange ], {
-
- // Called only when the first 'hashchange' event is bound to window.
- setup: function() {
- // If window.onhashchange is supported natively, there's nothing to do..
- if ( supports_onhashchange ) { return false; }
-
- // Otherwise, we need to create our own. And we don't want to call this
- // until the user binds to the event, just in case they never do, since it
- // will create a polling loop and possibly even a hidden Iframe.
- $( fake_onhashchange.start );
- },
-
- // Called only when the last 'hashchange' event is unbound from window.
- teardown: function() {
- // If window.onhashchange is supported natively, there's nothing to do..
- if ( supports_onhashchange ) { return false; }
-
- // Otherwise, we need to stop ours (if possible).
- $( fake_onhashchange.stop );
- }
-
- });
-
- // fake_onhashchange does all the work of triggering the window.onhashchange
- // event for browsers that don't natively support it, including creating a
- // polling loop to watch for hash changes and in IE 6/7 creating a hidden
- // Iframe to enable back and forward.
- fake_onhashchange = (function(){
- var self = {},
- timeout_id,
-
- // Remember the initial hash so it doesn't get triggered immediately.
- last_hash = get_fragment(),
-
- fn_retval = function(val){ return val; },
- history_set = fn_retval,
- history_get = fn_retval;
-
- // Start the polling loop.
- self.start = function() {
- timeout_id || poll();
- };
-
- // Stop the polling loop.
- self.stop = function() {
- timeout_id && clearTimeout( timeout_id );
- timeout_id = undefined;
- };
-
- // This polling loop checks every $.fn.hashchange.delay milliseconds to see
- // if location.hash has changed, and triggers the 'hashchange' event on
- // window when necessary.
- function poll() {
- var hash = get_fragment(),
- history_hash = history_get( last_hash );
-
- if ( hash !== last_hash ) {
- history_set( last_hash = hash, history_hash );
-
- $(window).trigger( str_hashchange );
-
- } else if ( history_hash !== last_hash ) {
- location.href = location.href.replace( /#.*/, '' ) + history_hash;
- }
-
- timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );
- };
-
- // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
- // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv
- // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
- $.browser.msie && !supports_onhashchange && (function(){
- // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8
- // when running in "IE7 compatibility" mode.
-
- var iframe,
- iframe_src;
-
- // When the event is bound and polling starts in IE 6/7, create a hidden
- // Iframe for history handling.
- self.start = function(){
- if ( !iframe ) {
- iframe_src = $.fn[ str_hashchange ].src;
- iframe_src = iframe_src && iframe_src + get_fragment();
-
- // Create hidden Iframe. Attempt to make Iframe as hidden as possible
- // by using techniques from http://www.paciellogroup.com/blog/?p=604.
- iframe = $('<iframe tabindex="-1" title="empty"/>').hide()
-
- // When Iframe has completely loaded, initialize the history and
- // start polling.
- .one( 'load', function(){
- iframe_src || history_set( get_fragment() );
- poll();
- })
-
- // Load Iframe src if specified, otherwise nothing.
- .attr( 'src', iframe_src || 'javascript:0' )
-
- // Append Iframe after the end of the body to prevent unnecessary
- // initial page scrolling (yes, this works).
- .insertAfter( 'body' )[0].contentWindow;
-
- // Whenever `document.title` changes, update the Iframe's title to
- // prettify the back/next history menu entries. Since IE sometimes
- // errors with "Unspecified error" the very first time this is set
- // (yes, very useful) wrap this with a try/catch block.
- doc.onpropertychange = function(){
- try {
- if ( event.propertyName === 'title' ) {
- iframe.document.title = doc.title;
- }
- } catch(e) {}
- };
-
- }
- };
-
- // Override the "stop" method since an IE6/7 Iframe was created. Even
- // if there are no longer any bound event handlers, the polling loop
- // is still necessary for back/next to work at all!
- self.stop = fn_retval;
-
- // Get history by looking at the hidden Iframe's location.hash.
- history_get = function() {
- return get_fragment( iframe.location.href );
- };
-
- // Set a new history item by opening and then closing the Iframe
- // document, *then* setting its location.hash. If document.domain has
- // been set, update that as well.
- history_set = function( hash, history_hash ) {
- var iframe_doc = iframe.document,
- domain = $.fn[ str_hashchange ].domain;
-
- if ( hash !== history_hash ) {
- // Update Iframe with any initial `document.title` that might be set.
- iframe_doc.title = doc.title;
-
- // Opening the Iframe's document after it has been closed is what
- // actually adds a history entry.
- iframe_doc.open();
-
- // Set document.domain for the Iframe document as well, if necessary.
- domain && iframe_doc.write( '<script>document.domain="' + domain + '"</script>' );
-
- iframe_doc.close();
-
- // Update the Iframe's hash, for great justice.
- iframe.location.hash = hash;
- }
- };
-
- })();
- // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^
- // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- return self;
- })();
-
-})(jQuery,this);
-/*
-* jQuery Mobile Framework : "page" plugin
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.widget( "mobile.page", $.mobile.widget, {
- options: {
- theme: "c",
- domCache: false
- },
-
- _create: function() {
- var $elem = this.element,
- o = this.options;
-
- if ( this._trigger( "beforeCreate" ) === false ) {
- return;
- }
-
- $elem.addClass( "ui-page ui-body-" + o.theme );
- }
-});
-
-})( jQuery );
-/*!
- * jQuery Mobile v@VERSION
- * http://jquerymobile.com/
- *
- * Copyright 2010, jQuery Project
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- */
-
-(function( $, window, undefined ) {
-
- // jQuery.mobile configurable options
- $.extend( $.mobile, {
-
- // Namespace used framework-wide for data-attrs. Default is no namespace
- ns: "",
-
- // Define the url parameter used for referencing widget-generated sub-pages.
- // Translates to to example.html&ui-page=subpageIdentifier
- // hash segment before &ui-page= is used to make Ajax request
- subPageUrlKey: "ui-page",
-
- // Class assigned to page currently in view, and during transitions
- activePageClass: "ui-page-active",
-
- // Class used for "active" button state, from CSS framework
- activeBtnClass: "ui-btn-active",
-
- // Automatically handle clicks and form submissions through Ajax, when same-domain
- ajaxEnabled: true,
-
- // Automatically load and show pages based on location.hash
- hashListeningEnabled: true,
-
- // Set default page transition - 'none' for no transitions
- defaultPageTransition: "slide",
-
- // Minimum scroll distance that will be remembered when returning to a page
- minScrollBack: screen.height / 2,
-
- // Set default dialog transition - 'none' for no transitions
- defaultDialogTransition: "pop",
-
- // Show loading message during Ajax requests
- // if false, message will not appear, but loading classes will still be toggled on html el
- loadingMessage: "loading",
-
- // Error response message - appears when an Ajax page request fails
- pageLoadErrorMessage: "Error Loading Page",
-
- //automatically initialize the DOM when it's ready
- autoInitializePage: true,
-
- // Support conditions that must be met in order to proceed
- // default enhanced qualifications are media query support OR IE 7+
- gradeA: function(){
- return $.support.mediaquery || $.mobile.browser.ie && $.mobile.browser.ie >= 7;
- },
-
- // TODO might be useful upstream in jquery itself ?
- keyCode: {
- ALT: 18,
- BACKSPACE: 8,
- CAPS_LOCK: 20,
- COMMA: 188,
- COMMAND: 91,
- COMMAND_LEFT: 91, // COMMAND
- COMMAND_RIGHT: 93,
- CONTROL: 17,
- DELETE: 46,
- DOWN: 40,
- END: 35,
- ENTER: 13,
- ESCAPE: 27,
- HOME: 36,
- INSERT: 45,
- LEFT: 37,
- MENU: 93, // COMMAND_RIGHT
- NUMPAD_ADD: 107,
- NUMPAD_DECIMAL: 110,
- NUMPAD_DIVIDE: 111,
- NUMPAD_ENTER: 108,
- NUMPAD_MULTIPLY: 106,
- NUMPAD_SUBTRACT: 109,
- PAGE_DOWN: 34,
- PAGE_UP: 33,
- PERIOD: 190,
- RIGHT: 39,
- SHIFT: 16,
- SPACE: 32,
- TAB: 9,
- UP: 38,
- WINDOWS: 91 // COMMAND
- },
-
- // Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value
- silentScroll: function( ypos ) {
- if ( $.type( ypos ) !== "number" ) {
- ypos = $.mobile.defaultHomeScroll;
- }
-
- // prevent scrollstart and scrollstop events
- $.event.special.scrollstart.enabled = false;
-
- setTimeout(function() {
- window.scrollTo( 0, ypos );
- $( document ).trigger( "silentscroll", { x: 0, y: ypos });
- }, 20 );
-
- setTimeout(function() {
- $.event.special.scrollstart.enabled = true;
- }, 150 );
- },
-
- // Take a data attribute property, prepend the namespace
- // and then camel case the attribute string
- nsNormalize: function( prop ) {
- if ( !prop ) {
- return;
- }
-
- return $.camelCase( $.mobile.ns + prop );
- }
- });
-
- // Mobile version of data and removeData and hasData methods
- // ensures all data is set and retrieved using jQuery Mobile's data namespace
- $.fn.jqmData = function( prop, value ) {
- return this.data( prop ? $.mobile.nsNormalize( prop ) : prop, value );
- };
-
- $.jqmData = function( elem, prop, value ) {
- return $.data( elem, $.mobile.nsNormalize( prop ), value );
- };
-
- $.fn.jqmRemoveData = function( prop ) {
- return this.removeData( $.mobile.nsNormalize( prop ) );
- };
-
- $.jqmRemoveData = function( elem, prop ) {
- return $.removeData( elem, $.mobile.nsNormalize( prop ) );
- };
-
- $.jqmHasData = function( elem, prop ) {
- return $.hasData( elem, $.mobile.nsNormalize( prop ) );
- };
-
- // Monkey-patching Sizzle to filter the :jqmData selector
- var oldFind = $.find;
-
- $.find = function( selector, context, ret, extra ) {
- selector = selector.replace(/:jqmData\(([^)]*)\)/g, "[data-" + ( $.mobile.ns || "" ) + "$1]");
-
- return oldFind.call( this, selector, context, ret, extra );
- };
-
- $.extend( $.find, oldFind );
-
- $.find.matches = function( expr, set ) {
- return $.find( expr, null, null, set );
- };
-
- $.find.matchesSelector = function( node, expr ) {
- return $.find( expr, null, null, [ node ] ).length > 0;
- };
-})( jQuery, this );
-/*
-* jQuery Mobile Framework : core utilities for auto ajax navigation, base tag mgmt,
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-( function( $, undefined ) {
-
- //define vars for interal use
- var $window = $( window ),
- $html = $( 'html' ),
- $head = $( 'head' ),
-
- //url path helpers for use in relative url management
- path = {
-
- // This scary looking regular expression parses an absolute URL or its relative
- // variants (protocol, site, document, query, and hash), into the various
- // components (protocol, host, path, query, fragment, etc that make up the
- // URL as well as some other commonly used sub-parts. When used with RegExp.exec()
- // or String.match, it parses the URL into a results array that looks like this:
- //
- // [0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content
- // [1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread
- // [2]: http://jblas:password@mycompany.com:8080/mail/inbox
- // [3]: http://jblas:password@mycompany.com:8080
- // [4]: http:
- // [5]: jblas:password@mycompany.com:8080
- // [6]: jblas:password
- // [7]: jblas
- // [8]: password
- // [9]: mycompany.com:8080
- // [10]: mycompany.com
- // [11]: 8080
- // [12]: /mail/inbox
- // [13]: /mail/
- // [14]: inbox
- // [15]: ?msg=1234&type=unread
- // [16]: #msg-content
- //
- urlParseRE: /^(((([^:\/#\?]+:)?(?:\/\/((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?]+)(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
-
- //Parse a URL into a structure that allows easy access to
- //all of the URL components by name.
- parseUrl: function( url ) {
- // If we're passed an object, we'll assume that it is
- // a parsed url object and just return it back to the caller.
- if ( $.type( url ) === "object" ) {
- return url;
- }
-
- var u = url || "",
- matches = path.urlParseRE.exec( url ),
- results;
- if ( matches ) {
- // Create an object that allows the caller to access the sub-matches
- // by name. Note that IE returns an empty string instead of undefined,
- // like all other browsers do, so we normalize everything so its consistent
- // no matter what browser we're running on.
- results = {
- href: matches[0] || "",
- hrefNoHash: matches[1] || "",
- hrefNoSearch: matches[2] || "",
- domain: matches[3] || "",
- protocol: matches[4] || "",
- authority: matches[5] || "",
- username: matches[7] || "",
- password: matches[8] || "",
- host: matches[9] || "",
- hostname: matches[10] || "",
- port: matches[11] || "",
- pathname: matches[12] || "",
- directory: matches[13] || "",
- filename: matches[14] || "",
- search: matches[15] || "",
- hash: matches[16] || ""
- };
- }
- return results || {};
- },
-
- //Turn relPath into an asbolute path. absPath is
- //an optional absolute path which describes what
- //relPath is relative to.
- makePathAbsolute: function( relPath, absPath ) {
- if ( relPath && relPath.charAt( 0 ) === "/" ) {
- return relPath;
- }
-
- relPath = relPath || "";
- absPath = absPath ? absPath.replace( /^\/|(\/[^\/]*|[^\/]+)$/g, "" ) : "";
-
- var absStack = absPath ? absPath.split( "/" ) : [],
- relStack = relPath.split( "/" );
- for ( var i = 0; i < relStack.length; i++ ) {
- var d = relStack[ i ];
- switch ( d ) {
- case ".":
- break;
- case "..":
- if ( absStack.length ) {
- absStack.pop();
- }
- break;
- default:
- absStack.push( d );
- break;
- }
- }
- return "/" + absStack.join( "/" );
- },
-
- //Returns true if both urls have the same domain.
- isSameDomain: function( absUrl1, absUrl2 ) {
- return path.parseUrl( absUrl1 ).domain === path.parseUrl( absUrl2 ).domain;
- },
-
- //Returns true for any relative variant.
- isRelativeUrl: function( url ) {
- // All relative Url variants have one thing in common, no protocol.
- return path.parseUrl( url ).protocol === "";
- },
-
- //Returns true for an absolute url.
- isAbsoluteUrl: function( url ) {
- return path.parseUrl( url ).protocol !== "";
- },
-
- //Turn the specified realtive URL into an absolute one. This function
- //can handle all relative variants (protocol, site, document, query, fragment).
- makeUrlAbsolute: function( relUrl, absUrl ) {
- if ( !path.isRelativeUrl( relUrl ) ) {
- return relUrl;
- }
-
- var relObj = path.parseUrl( relUrl ),
- absObj = path.parseUrl( absUrl ),
- protocol = relObj.protocol || absObj.protocol,
- authority = relObj.authority || absObj.authority,
- hasPath = relObj.pathname !== "",
- pathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ),
- search = relObj.search || ( !hasPath && absObj.search ) || "",
- hash = relObj.hash;
-
- return protocol + "//" + authority + pathname + search + hash;
- },
-
- //Add search (aka query) params to the specified url.
- addSearchParams: function( url, params ) {
- var u = path.parseUrl( url ),
- p = ( typeof params === "object" ) ? $.param( params ) : params,
- s = u.search || "?";
- return u.hrefNoSearch + s + ( s.charAt( s.length - 1 ) !== "?" ? "&" : "" ) + p + ( u.hash || "" );
- },
-
- convertUrlToDataUrl: function( absUrl ) {
- var u = path.parseUrl( absUrl );
- if ( path.isEmbeddedPage( u ) ) {
- // For embedded pages, remove the dialog hash key as in getFilePath(),
- // otherwise the Data Url won't match the id of the embedded Page.
- return u.hash.split( dialogHashKey )[0].replace( /^#/, "" );
- } else if ( path.isSameDomain( u, documentBase ) ) {
- return u.hrefNoHash.replace( documentBase.domain, "" );
- }
- return absUrl;
- },
-
- //get path from current hash, or from a file path
- get: function( newPath ) {
- if( newPath === undefined ) {
- newPath = location.hash;
- }
- return path.stripHash( newPath ).replace( /[^\/]*\.[^\/*]+$/, '' );
- },
-
- //return the substring of a filepath before the sub-page key, for making a server request
- getFilePath: function( path ) {
- var splitkey = '&' + $.mobile.subPageUrlKey;
- return path && path.split( splitkey )[0].split( dialogHashKey )[0];
- },
-
- //set location hash to path
- set: function( path ) {
- location.hash = path;
- },
-
- //test if a given url (string) is a path
- //NOTE might be exceptionally naive
- isPath: function( url ) {
- return ( /\// ).test( url );
- },
-
- //return a url path with the window's location protocol/hostname/pathname removed
- clean: function( url ) {
- return url.replace( documentBase.domain, "" );
- },
-
- //just return the url without an initial #
- stripHash: function( url ) {
- return url.replace( /^#/, "" );
- },
-
- //remove the preceding hash, any query params, and dialog notations
- cleanHash: function( hash ) {
- return path.stripHash( hash.replace( /\?.*$/, "" ).replace( dialogHashKey, "" ) );
- },
-
- //check whether a url is referencing the same domain, or an external domain or different protocol
- //could be mailto, etc
- isExternal: function( url ) {
- var u = path.parseUrl( url );
- return u.protocol && u.domain !== documentUrl.domain ? true : false;
- },
-
- hasProtocol: function( url ) {
- return ( /^(:?\w+:)/ ).test( url );
- },
-
- isEmbeddedPage: function( url ) {
- var u = path.parseUrl( url );
-
- //if the path is absolute, then we need to compare the url against
- //both the documentUrl and the documentBase. The main reason for this
- //is that links embedded within external documents will refer to the
- //application document, whereas links embedded within the application
- //document will be resolved against the document base.
- if ( u.protocol !== "" ) {
- return ( u.hash && ( u.hrefNoHash === documentUrl.hrefNoHash || ( documentBaseDiffers && u.hrefNoHash === documentBase.hrefNoHash ) ) );
- }
- return (/^#/).test( u.href );
- }
- },
-
- //will be defined when a link is clicked and given an active class
- $activeClickedLink = null,
-
- //urlHistory is purely here to make guesses at whether the back or forward button was clicked
- //and provide an appropriate transition
- urlHistory = {
- // Array of pages that are visited during a single page load.
- // Each has a url and optional transition, title, and pageUrl (which represents the file path, in cases where URL is obscured, such as dialogs)
- stack: [],
-
- //maintain an index number for the active page in the stack
- activeIndex: 0,
-
- //get active
- getActive: function() {
- return urlHistory.stack[ urlHistory.activeIndex ];
- },
-
- getPrev: function() {
- return urlHistory.stack[ urlHistory.activeIndex - 1 ];
- },
-
- getNext: function() {
- return urlHistory.stack[ urlHistory.activeIndex + 1 ];
- },
-
- // addNew is used whenever a new page is added
- addNew: function( url, transition, title, pageUrl ) {
- //if there's forward history, wipe it
- if( urlHistory.getNext() ) {
- urlHistory.clearForward();
- }
-
- urlHistory.stack.push( {url : url, transition: transition, title: title, pageUrl: pageUrl } );
-
- urlHistory.activeIndex = urlHistory.stack.length - 1;
- },
-
- //wipe urls ahead of active index
- clearForward: function() {
- urlHistory.stack = urlHistory.stack.slice( 0, urlHistory.activeIndex + 1 );
- },
-
- directHashChange: function( opts ) {
- var back , forward, newActiveIndex;
-
- // check if url isp in history and if it's ahead or behind current page
- $.each( urlHistory.stack, function( i, historyEntry ) {
-
- //if the url is in the stack, it's a forward or a back
- if( opts.currentUrl === historyEntry.url ) {
- //define back and forward by whether url is older or newer than current page
- back = i < urlHistory.activeIndex;
- forward = !back;
- newActiveIndex = i;
- }
- });
-
- // save new page index, null check to prevent falsey 0 result
- this.activeIndex = newActiveIndex !== undefined ? newActiveIndex : this.activeIndex;
-
- if( back ) {
- opts.isBack();
- } else if( forward ) {
- opts.isForward();
- }
- },
-
- //disable hashchange event listener internally to ignore one change
- //toggled internally when location.hash is updated to match the url of a successful page load
- ignoreNextHashChange: false
- },
-
- //define first selector to receive focus when a page is shown
- focusable = "[tabindex],a,button:visible,select:visible,input",
-
- //queue to hold simultanious page transitions
- pageTransitionQueue = [],
-
- //indicates whether or not page is in process of transitioning
- isPageTransitioning = false,
-
- //nonsense hash change key for dialogs, so they create a history entry
- dialogHashKey = "&ui-state=dialog",
-
- //existing base tag?
- $base = $head.children( "base" ),
-
- //tuck away the original document URL minus any fragment.
- documentUrl = path.parseUrl( location.href ),
-
- //if the document has an embedded base tag, documentBase is set to its
- //initial value. If a base tag does not exist, then we default to the documentUrl.
- documentBase = $base.length ? path.parseUrl( path.makeUrlAbsolute( $base.attr( "href" ), documentUrl.href ) ) : documentUrl,
-
- //cache the comparison once.
- documentBaseDiffers = ( documentUrl.hrefNoHash !== documentBase.hrefNoHash );
-
- //base element management, defined depending on dynamic base tag support
- var base = $.support.dynamicBaseTag ? {
-
- //define base element, for use in routing asset urls that are referenced in Ajax-requested markup
- element: ( $base.length ? $base : $( "<base>", { href: documentBase.hrefNoHash } ).prependTo( $head ) ),
-
- //set the generated BASE element's href attribute to a new page's base path
- set: function( href ) {
- base.element.attr( "href", path.makeUrlAbsolute( href, documentBase ) );
- },
-
- //set the generated BASE element's href attribute to a new page's base path
- reset: function() {
- base.element.attr( "href", documentBase.hrefNoHash );
- }
-
- } : undefined;
-
-/*
- internal utility functions
---------------------------------------*/
-
-
- //direct focus to the page title, or otherwise first focusable element
- function reFocus( page ) {
- var lastClicked = page.jqmData( "lastClicked" );
-
- if( lastClicked && lastClicked.length ) {
- lastClicked.focus();
- }
- else {
- var pageTitle = page.find( ".ui-title:eq(0)" );
-
- if( pageTitle.length ) {
- pageTitle.focus();
- }
- else{
- page.find( focusable ).eq( 0 ).focus();
- }
- }
- }
-
- //remove active classes after page transition or error
- function removeActiveLinkClass( forceRemoval ) {
- if( !!$activeClickedLink && ( !$activeClickedLink.closest( '.ui-page-active' ).length || forceRemoval ) ) {
- $activeClickedLink.removeClass( $.mobile.activeBtnClass );
- }
- $activeClickedLink = null;
- }
-
- function releasePageTransitionLock() {
- isPageTransitioning = false;
- if( pageTransitionQueue.length > 0 ) {
- $.mobile.changePage.apply( null, pageTransitionQueue.pop() );
- }
- }
-
- //function for transitioning between two existing pages
- function transitionPages( toPage, fromPage, transition, reverse ) {
-
- //get current scroll distance
- var currScroll = $.support.scrollTop ? $window.scrollTop() : true,
- toScroll = toPage.data( "lastScroll" ) || $.mobile.defaultHomeScroll,
- screenHeight = getScreenHeight();
-
- //if scrolled down, scroll to top
- if( currScroll ){
- window.scrollTo( 0, $.mobile.defaultHomeScroll );
- }
-
- //if the Y location we're scrolling to is less than 10px, let it go for sake of smoothness
- if( toScroll < $.mobile.minScrollBack ){
- toScroll = 0;
- }
-
- if( fromPage ) {
- //set as data for returning to that spot
- fromPage
- .height( screenHeight + currScroll )
- .jqmData( "lastScroll", currScroll )
- .jqmData( "lastClicked", $activeClickedLink );
-
- //trigger before show/hide events
- fromPage.data( "page" )._trigger( "beforehide", null, { nextPage: toPage } );
- }
- toPage
- .height( screenHeight + toScroll )
- .data( "page" )._trigger( "beforeshow", null, { prevPage: fromPage || $( "" ) } );
-
- //clear page loader
- $.mobile.hidePageLoadingMsg();
-
- //find the transition handler for the specified transition. If there
- //isn't one in our transitionHandlers dictionary, use the default one.
- //call the handler immediately to kick-off the transition.
- var th = $.mobile.transitionHandlers[transition || "none"] || $.mobile.defaultTransitionHandler,
- promise = th( transition, reverse, toPage, fromPage );
-
- promise.done(function() {
- //reset toPage height bac
- toPage.height( "" );
-
- //jump to top or prev scroll, sometimes on iOS the page has not rendered yet.
- if( toScroll ){
- $.mobile.silentScroll( toScroll );
- $( document ).one( "silentscroll", function() { reFocus( toPage ); } );
- }
- else{
- reFocus( toPage );
- }
-
- //trigger show/hide events
- if( fromPage ) {
- fromPage.height("").data( "page" )._trigger( "hide", null, { nextPage: toPage } );
- }
-
- //trigger pageshow, define prevPage as either fromPage or empty jQuery obj
- toPage.data( "page" )._trigger( "show", null, { prevPage: fromPage || $( "" ) } );
- });
-
- return promise;
- }
-
- //simply set the active page's minimum height to screen height, depending on orientation
- function getScreenHeight(){
- var orientation = jQuery.event.special.orientationchange.orientation(),
- port = orientation === "portrait",
- winMin = port ? 480 : 320,
- screenHeight = port ? screen.availHeight : screen.availWidth,
- winHeight = Math.max( winMin, $( window ).height() ),
- pageMin = Math.min( screenHeight, winHeight );
-
- return pageMin;
- }
-
- //simply set the active page's minimum height to screen height, depending on orientation
- function resetActivePageHeight(){
- $( "." + $.mobile.activePageClass ).css( "min-height", getScreenHeight() );
- }
-
- //shared page enhancements
- function enhancePage( $page, role ) {
- // If a role was specified, make sure the data-role attribute
- // on the page element is in sync.
- if( role ) {
- $page.attr( "data-" + $.mobile.ns + "role", role );
- }
-
- //run page plugin
- $page.page();
- }
-
-/* exposed $.mobile methods */
-
- //animation complete callback
- $.fn.animationComplete = function( callback ) {
- if( $.support.cssTransitions ) {
- return $( this ).one( 'webkitAnimationEnd', callback );
- }
- else{
- // defer execution for consistency between webkit/non webkit
- setTimeout( callback, 0 );
- return $( this );
- }
- };
-
- //update location.hash, with or without triggering hashchange event
- //TODO - deprecate this one at 1.0
- $.mobile.updateHash = path.set;
-
- //expose path object on $.mobile
- $.mobile.path = path;
-
- //expose base object on $.mobile
- $.mobile.base = base;
-
- //url stack, useful when plugins need to be aware of previous pages viewed
- //TODO: deprecate this one at 1.0
- $.mobile.urlstack = urlHistory.stack;
-
- //history stack
- $.mobile.urlHistory = urlHistory;
-
- //default non-animation transition handler
- $.mobile.noneTransitionHandler = function( name, reverse, $toPage, $fromPage ) {
- if ( $fromPage ) {
- $fromPage.removeClass( $.mobile.activePageClass );
- }
- $toPage.addClass( $.mobile.activePageClass );
-
- return $.Deferred().resolve( name, reverse, $toPage, $fromPage ).promise();
- };
-
- //default handler for unknown transitions
- $.mobile.defaultTransitionHandler = $.mobile.noneTransitionHandler;
-
- //transition handler dictionary for 3rd party transitions
- $.mobile.transitionHandlers = {
- none: $.mobile.defaultTransitionHandler
- };
-
- //enable cross-domain page support
- $.mobile.allowCrossDomainPages = false;
-
- //return the original document url
- $.mobile.getDocumentUrl = function(asParsedObject) {
- return asParsedObject ? $.extend( {}, documentUrl ) : documentUrl.href;
- };
-
- //return the original document base url
- $.mobile.getDocumentBase = function(asParsedObject) {
- return asParsedObject ? $.extend( {}, documentBase ) : documentBase.href;
- };
-
- // Load a page into the DOM.
- $.mobile.loadPage = function( url, options ) {
- // This function uses deferred notifications to let callers
- // know when the page is done loading, or if an error has occurred.
- var deferred = $.Deferred(),
-
- // The default loadPage options with overrides specified by
- // the caller.
- settings = $.extend( {}, $.mobile.loadPage.defaults, options ),
-
- // The DOM element for the page after it has been loaded.
- page = null,
-
- // If the reloadPage option is true, and the page is already
- // in the DOM, dupCachedPage will be set to the page element
- // so that it can be removed after the new version of the
- // page is loaded off the network.
- dupCachedPage = null,
-
- // determine the current base url
- findBaseWithDefault = function(){
- var closestBase = ( $.mobile.activePage && getClosestBaseUrl( $.mobile.activePage ) );
- return closestBase || documentBase.hrefNoHash;
- },
-
- // The absolute version of the URL passed into the function. This
- // version of the URL may contain dialog/subpage params in it.
- absUrl = path.makeUrlAbsolute( url, findBaseWithDefault() );
-
-
- // If the caller provided data, and we're using "get" request,
- // append the data to the URL.
- if ( settings.data && settings.type === "get" ) {
- absUrl = path.addSearchParams( absUrl, settings.data );
- settings.data = undefined;
- }
-
- // The absolute version of the URL minus any dialog/subpage params.
- // In otherwords the real URL of the page to be loaded.
- var fileUrl = path.getFilePath( absUrl ),
-
- // The version of the Url actually stored in the data-url attribute of
- // the page. For embedded pages, it is just the id of the page. For pages
- // within the same domain as the document base, it is the site relative
- // path. For cross-domain pages (Phone Gap only) the entire absolute Url
- // used to load the page.
- dataUrl = path.convertUrlToDataUrl( absUrl );
-
- // Make sure we have a pageContainer to work with.
- settings.pageContainer = settings.pageContainer || $.mobile.pageContainer;
-
- // Check to see if the page already exists in the DOM.
- page = settings.pageContainer.children( ":jqmData(url='" + dataUrl + "')" );
-
- // Reset base to the default document base.
- if ( base ) {
- base.reset();
- }
-
- // If the page we are interested in is already in the DOM,
- // and the caller did not indicate that we should force a
- // reload of the file, we are done. Otherwise, track the
- // existing page as a duplicated.
- if ( page.length ) {
- if ( !settings.reloadPage ) {
- enhancePage( page, settings.role );
- deferred.resolve( absUrl, options, page );
- return deferred.promise();
- }
- dupCachedPage = page;
- }
-
- if ( settings.showLoadMsg ) {
-
- // This configurable timeout allows cached pages a brief delay to load without showing a message
- var loadMsgDelay = setTimeout(function(){
- $.mobile.showPageLoadingMsg();
- }, settings.loadMsgDelay ),
-
- // Shared logic for clearing timeout and removing message.
- hideMsg = function(){
-
- // Stop message show timer
- clearTimeout( loadMsgDelay );
-
- // Hide loading message
- $.mobile.hidePageLoadingMsg();
- };
- }
-
- if ( !( $.mobile.allowCrossDomainPages || path.isSameDomain( documentUrl, absUrl ) ) ) {
- deferred.reject( absUrl, options );
- } else {
- // Load the new page.
- $.ajax({
- url: fileUrl,
- type: settings.type,
- data: settings.data,
- dataType: "html",
- success: function( html ) {
- //pre-parse html to check for a data-url,
- //use it as the new fileUrl, base path, etc
- var all = $( "<div></div>" ),
-
- //page title regexp
- newPageTitle = html.match( /<title[^>]*>([^<]*)/ ) && RegExp.$1,
-
- // TODO handle dialogs again
- pageElemRegex = new RegExp( ".*(<[^>]+\\bdata-" + $.mobile.ns + "role=[\"']?page[\"']?[^>]*>).*" ),
- dataUrlRegex = new RegExp( "\\bdata-" + $.mobile.ns + "url=[\"']?([^\"'>]*)[\"']?" );
-
-
- // data-url must be provided for the base tag so resource requests can be directed to the
- // correct url. loading into a temprorary element makes these requests immediately
- if( pageElemRegex.test( html )
- && RegExp.$1
- && dataUrlRegex.test( RegExp.$1 )
- && RegExp.$1 ) {
- url = fileUrl = path.getFilePath( RegExp.$1 );
- }
- else{
-
- }
-
- if ( base ) {
- base.set( fileUrl );
- }
-
- //workaround to allow scripts to execute when included in page divs
- all.get( 0 ).innerHTML = html;
- page = all.find( ":jqmData(role='page'), :jqmData(role='dialog')" ).first();
-
- //if page elem couldn't be found, create one and insert the body element's contents
- if( !page.length ){
- page = $( "<div data-" + $.mobile.ns + "role='page'>" + html.split( /<\/?body[^>]*>/gmi )[1] + "</div>" );
- }
-
- if ( newPageTitle && !page.jqmData( "title" ) ) {
- page.jqmData( "title", newPageTitle );
- }
-
- //rewrite src and href attrs to use a base url
- if( !$.support.dynamicBaseTag ) {
- var newPath = path.get( fileUrl );
- page.find( "[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]" ).each(function() {
- var thisAttr = $( this ).is( '[href]' ) ? 'href' :
- $(this).is('[src]') ? 'src' : 'action',
- thisUrl = $( this ).attr( thisAttr );
-
- // XXX_jblas: We need to fix this so that it removes the document
- // base URL, and then prepends with the new page URL.
- //if full path exists and is same, chop it - helps IE out
- thisUrl = thisUrl.replace( location.protocol + '//' + location.host + location.pathname, '' );
-
- if( !/^(\w+:|#|\/)/.test( thisUrl ) ) {
- $( this ).attr( thisAttr, newPath + thisUrl );
- }
- });
- }
-
- //append to page and enhance
- page
- .attr( "data-" + $.mobile.ns + "url", path.convertUrlToDataUrl( fileUrl ) )
- .appendTo( settings.pageContainer );
-
- // wait for page creation to leverage options defined on widget
- page.one('pagecreate', function(){
-
- // when dom caching is not enabled bind to remove the page on hide
- if( !page.data("page").options.domCache ){
- page.bind( "pagehide.remove", function(){
- $(this).remove();
- });
- }
- });
-
- enhancePage( page, settings.role );
-
- // Enhancing the page may result in new dialogs/sub pages being inserted
- // into the DOM. If the original absUrl refers to a sub-page, that is the
- // real page we are interested in.
- if ( absUrl.indexOf( "&" + $.mobile.subPageUrlKey ) > -1 ) {
- page = settings.pageContainer.children( ":jqmData(url='" + dataUrl + "')" );
- }
-
- //bind pageHide to removePage after it's hidden, if the page options specify to do so
-
- // Remove loading message.
- if ( settings.showLoadMsg ) {
- hideMsg();
- }
-
- deferred.resolve( absUrl, options, page, dupCachedPage );
- },
- error: function() {
- //set base back to current path
- if( base ) {
- base.set( path.get() );
- }
-
- // Remove loading message.
- if ( settings.showLoadMsg ) {
-
- // Remove loading message.
- hideMsg();
-
- //show error message
- $( "<div class='ui-loader ui-overlay-shadow ui-body-e ui-corner-all'><h1>"+ $.mobile.pageLoadErrorMessage +"</h1></div>" )
- .css({ "display": "block", "opacity": 0.96, "top": $window.scrollTop() + 100 })
- .appendTo( settings.pageContainer )
- .delay( 800 )
- .fadeOut( 400, function() {
- $( this ).remove();
- });
- }
-
- deferred.reject( absUrl, options );
- }
- });
- }
-
- return deferred.promise();
- };
-
- $.mobile.loadPage.defaults = {
- type: "get",
- data: undefined,
- reloadPage: false,
- role: undefined, // By default we rely on the role defined by the @data-role attribute.
- showLoadMsg: false,
- pageContainer: undefined,
- loadMsgDelay: 50 // This delay allows loads that pull from browser cache to occur without showing the loading message.
- };
-
- // Show a specific page in the page container.
- $.mobile.changePage = function( toPage, options ) {
- // XXX: REMOVE_BEFORE_SHIPPING_1.0
- // This is temporary code that makes changePage() compatible with previous alpha versions.
- if ( typeof options !== "object" ) {
- var opts = null;
-
- // Map old-style call signature for form submit to the new options object format.
- if ( typeof toPage === "object" && toPage.url && toPage.type ) {
- opts = {
- type: toPage.type,
- data: toPage.data,
- forcePageLoad: true
- };
- toPage = toPage.url;
- }
-
- // The arguments passed into the function need to be re-mapped
- // to the new options object format.
- var len = arguments.length;
- if ( len > 1 ) {
- var argNames = [ "transition", "reverse", "changeHash", "fromHashChange" ], i;
- for ( i = 1; i < len; i++ ) {
- var a = arguments[ i ];
- if ( typeof a !== "undefined" ) {
- opts = opts || {};
- opts[ argNames[ i - 1 ] ] = a;
- }
- }
- }
-
- // If an options object was created, then we know changePage() was called
- // with an old signature.
- if ( opts ) {
- return $.mobile.changePage( toPage, opts );
- }
- }
- // XXX: REMOVE_BEFORE_SHIPPING_1.0
-
- // If we are in the midst of a transition, queue the current request.
- // We'll call changePage() once we're done with the current transition to
- // service the request.
- if( isPageTransitioning ) {
- pageTransitionQueue.unshift( arguments );
- return;
- }
-
- // Set the isPageTransitioning flag to prevent any requests from
- // entering this method while we are in the midst of loading a page
- // or transitioning.
-
- isPageTransitioning = true;
-
- var settings = $.extend( {}, $.mobile.changePage.defaults, options );
-
- // Make sure we have a pageContainer to work with.
- settings.pageContainer = settings.pageContainer || $.mobile.pageContainer;
-
- // If the caller passed us a url, call loadPage()
- // to make sure it is loaded into the DOM. We'll listen
- // to the promise object it returns so we know when
- // it is done loading or if an error ocurred.
- if ( typeof toPage == "string" ) {
- $.mobile.loadPage( toPage, settings )
- .done(function( url, options, newPage, dupCachedPage ) {
- isPageTransitioning = false;
- options.duplicateCachedPage = dupCachedPage;
- $.mobile.changePage( newPage, options );
- })
- .fail(function( url, options ) {
- // XXX_jblas: Fire off changepagefailed notificaiton.
- isPageTransitioning = false;
-
- //clear out the active button state
- removeActiveLinkClass( true );
-
- //release transition lock so navigation is free again
- releasePageTransitionLock();
- settings.pageContainer.trigger("changepagefailed");
- });
- return;
- }
-
- // The caller passed us a real page DOM element. Update our
- // internal state and then trigger a transition to the page.
- var mpc = settings.pageContainer,
- fromPage = $.mobile.activePage,
- url = toPage.jqmData( "url" ),
- // The pageUrl var is usually the same as url, except when url is obscured as a dialog url. pageUrl always contains the file path
- pageUrl = url,
- fileUrl = path.getFilePath( url ),
- active = urlHistory.getActive(),
- activeIsInitialPage = urlHistory.activeIndex === 0,
- historyDir = 0,
- pageTitle = document.title,
- isDialog = settings.role === "dialog" || toPage.jqmData( "role" ) === "dialog";
-
- // Let listeners know we're about to change the current page.
- mpc.trigger( "beforechangepage" );
-
- // If we are trying to transition to the same page that we are currently on ignore the request.
- // an illegal same page request is defined by the current page being the same as the url, as long as there's history
- // and toPage is not an array or object (those are allowed to be "same")
- //
- // XXX_jblas: We need to remove this at some point when we allow for transitions
- // to the same page.
- if( fromPage && fromPage[0] === toPage[0] ) {
- isPageTransitioning = false;
- mpc.trigger( "changepage" );
- return;
- }
-
- // We need to make sure the page we are given has already been enhanced.
- enhancePage( toPage, settings.role );
-
- // If the changePage request was sent from a hashChange event, check to see if the
- // page is already within the urlHistory stack. If so, we'll assume the user hit
- // the forward/back button and will try to match the transition accordingly.
- if( settings.fromHashChange ) {
- urlHistory.directHashChange({
- currentUrl: url,
- isBack: function() { historyDir = -1; },
- isForward: function() { historyDir = 1; }
- });
- }
-
- // Kill the keyboard.
- // XXX_jblas: We need to stop crawling the entire document to kill focus. Instead,
- // we should be tracking focus with a live() handler so we already have
- // the element in hand at this point.
- // Wrap this in a try/catch block since IE9 throw "Unspecified error" if document.activeElement
- // is undefined when we are in an IFrame.
- try {
- $( document.activeElement || "" ).add( "input:focus, textarea:focus, select:focus" ).blur();
- } catch(e) {}
-
- // If we're displaying the page as a dialog, we don't want the url
- // for the dialog content to be used in the hash. Instead, we want
- // to append the dialogHashKey to the url of the current page.
- if ( isDialog && active ) {
- url = active.url + dialogHashKey;
- }
-
- // Set the location hash.
- if( settings.changeHash !== false && url ) {
- //disable hash listening temporarily
- urlHistory.ignoreNextHashChange = true;
- //update hash and history
- path.set( url );
- }
-
- //if title element wasn't found, try the page div data attr too
- var newPageTitle = toPage.jqmData( "title" ) || toPage.children(":jqmData(role='header')").find(".ui-title" ).text();
- if( !!newPageTitle && pageTitle == document.title ) {
- pageTitle = newPageTitle;
- }
-
- //add page to history stack if it's not back or forward
- if( !historyDir ) {
- urlHistory.addNew( url, settings.transition, pageTitle, pageUrl );
- }
-
- //set page title
- document.title = urlHistory.getActive().title;
-
- //set "toPage" as activePage
- $.mobile.activePage = toPage;
-
- // Make sure we have a transition defined.
- settings.transition = settings.transition
- || ( ( historyDir && !activeIsInitialPage ) ? active.transition : undefined )
- || ( isDialog ? $.mobile.defaultDialogTransition : $.mobile.defaultPageTransition );
-
- // If we're navigating back in the URL history, set reverse accordingly.
- settings.reverse = settings.reverse || historyDir < 0;
-
- transitionPages( toPage, fromPage, settings.transition, settings.reverse )
- .done(function() {
- removeActiveLinkClass();
-
- //if there's a duplicateCachedPage, remove it from the DOM now that it's hidden
- if ( settings.duplicateCachedPage ) {
- settings.duplicateCachedPage.remove();
- }
-
- //remove initial build class (only present on first pageshow)
- $html.removeClass( "ui-mobile-rendering" );
-
- releasePageTransitionLock();
-
- // Let listeners know we're all done changing the current page.
- mpc.trigger( "changepage" );
- });
- };
-
- $.mobile.changePage.defaults = {
- transition: undefined,
- reverse: false,
- changeHash: true,
- fromHashChange: false,
- role: undefined, // By default we rely on the role defined by the @data-role attribute.
- duplicateCachedPage: undefined,
- pageContainer: undefined,
- showLoadMsg: true //loading message shows by default when pages are being fetched during changePage
- };
-
-/* Event Bindings - hashchange, submit, and click */
- function findClosestLink( ele )
- {
- while ( ele ) {
- if ( ele.nodeName.toLowerCase() == "a" ) {
- break;
- }
- ele = ele.parentNode;
- }
- return ele;
- }
-
- // The base URL for any given element depends on the page it resides in.
- function getClosestBaseUrl( ele )
- {
- // Find the closest page and extract out its url.
- var url = $( ele ).closest( ".ui-page" ).jqmData( "url" ),
- base = documentBase.hrefNoHash;
-
- if ( !url || !path.isPath( url ) ) {
- url = base;
- }
-
- return path.makeUrlAbsolute( url, base);
- }
-
-
- //The following event bindings should be bound after mobileinit has been triggered
- //the following function is called in the init file
- $.mobile._registerInternalEvents = function(){
-
- //bind to form submit events, handle with Ajax
- $( "form" ).live('submit', function( event ) {
- var $this = $( this );
- if( !$.mobile.ajaxEnabled ||
- $this.is( ":jqmData(ajax='false')" ) ) {
- return;
- }
-
- var type = $this.attr( "method" ),
- target = $this.attr( "target" ),
- url = $this.attr( "action" );
-
- // If no action is specified, browsers default to using the
- // URL of the document containing the form. Since we dynamically
- // pull in pages from external documents, the form should submit
- // to the URL for the source document of the page containing
- // the form.
- if ( !url ) {
- // Get the @data-url for the page containing the form.
- url = getClosestBaseUrl( $this );
- if ( url === documentBase.hrefNoHash ) {
- // The url we got back matches the document base,
- // which means the page must be an internal/embedded page,
- // so default to using the actual document url as a browser
- // would.
- url = documentUrl.hrefNoSearch;
- }
- }
-
- url = path.makeUrlAbsolute( url, getClosestBaseUrl($this) );
-
- //external submits use regular HTTP
- if( path.isExternal( url ) || target ) {
- return;
- }
-
- $.mobile.changePage(
- url,
- {
- type: type && type.length && type.toLowerCase() || "get",
- data: $this.serialize(),
- transition: $this.jqmData( "transition" ),
- direction: $this.jqmData( "direction" ),
- reloadPage: true
- }
- );
- event.preventDefault();
- });
-
- //add active state on vclick
- $( document ).bind( "vclick", function( event ) {
- var link = findClosestLink( event.target );
- if ( link ) {
- if ( path.parseUrl( link.getAttribute( "href" ) || "#" ).hash !== "#" ) {
- $( link ).closest( ".ui-btn" ).not( ".ui-disabled" ).addClass( $.mobile.activeBtnClass );
- $( "." + $.mobile.activePageClass + " .ui-btn" ).not( link ).blur();
- }
- }
- });
-
- // click routing - direct to HTTP or Ajax, accordingly
- $( document ).bind( "click", function( event ) {
- var link = findClosestLink( event.target );
- if ( !link ) {
- return;
- }
-
- var $link = $( link ),
- //remove active link class if external (then it won't be there if you come back)
- httpCleanup = function(){
- window.setTimeout( function() { removeActiveLinkClass( true ); }, 200 );
- };
-
- //if there's a data-rel=back attr, go back in history
- if( $link.is( ":jqmData(rel='back')" ) ) {
- window.history.back();
- return false;
- }
-
- //if ajax is disabled, exit early
- if( !$.mobile.ajaxEnabled ){
- httpCleanup();
- //use default click handling
- return;
- }
-
- var baseUrl = getClosestBaseUrl( $link ),
-
- //get href, if defined, otherwise default to empty hash
- href = path.makeUrlAbsolute( $link.attr( "href" ) || "#", baseUrl );
-
- // XXX_jblas: Ideally links to application pages should be specified as
- // an url to the application document with a hash that is either
- // the site relative path or id to the page. But some of the
- // internal code that dynamically generates sub-pages for nested
- // lists and select dialogs, just write a hash in the link they
- // create. This means the actual URL path is based on whatever
- // the current value of the base tag is at the time this code
- // is called. For now we are just assuming that any url with a
- // hash in it is an application page reference.
- if ( href.search( "#" ) != -1 ) {
- href = href.replace( /[^#]*#/, "" );
- if ( !href ) {
- //link was an empty hash meant purely
- //for interaction, so we ignore it.
- event.preventDefault();
- return;
- } else if ( path.isPath( href ) ) {
- //we have apath so make it the href we want to load.
- href = path.makeUrlAbsolute( href, baseUrl );
- } else {
- //we have a simple id so use the documentUrl as its base.
- href = path.makeUrlAbsolute( "#" + href, documentUrl.hrefNoHash );
- }
- }
-
- // Should we handle this link, or let the browser deal with it?
- var useDefaultUrlHandling = $link.is( "[rel='external']" ) || $link.is( ":jqmData(ajax='false')" ) || $link.is( "[target]" ),
-
- // Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR
- // requests if the document doing the request was loaded via the file:// protocol.
- // This is usually to allow the application to "phone home" and fetch app specific
- // data. We normally let the browser handle external/cross-domain urls, but if the
- // allowCrossDomainPages option is true, we will allow cross-domain http/https
- // requests to go through our page loading logic.
- isCrossDomainPageLoad = ( $.mobile.allowCrossDomainPages && documentUrl.protocol === "file:" && href.search( /^https?:/ ) != -1 ),
-
- //check for protocol or rel and its not an embedded page
- //TODO overlap in logic from isExternal, rel=external check should be
- // moved into more comprehensive isExternalLink
- isExternal = useDefaultUrlHandling || ( path.isExternal( href ) && !isCrossDomainPageLoad );
-
- $activeClickedLink = $link.closest( ".ui-btn" );
-
- if( isExternal ) {
- httpCleanup();
- //use default click handling
- return;
- }
-
- //use ajax
- var transition = $link.jqmData( "transition" ),
- direction = $link.jqmData( "direction" ),
- reverse = ( direction && direction === "reverse" ) ||
- // deprecated - remove by 1.0
- $link.jqmData( "back" ),
-
- //this may need to be more specific as we use data-rel more
- role = $link.attr( "data-" + $.mobile.ns + "rel" ) || undefined;
-
- $.mobile.changePage( href, { transition: transition, reverse: reverse, role: role } );
- event.preventDefault();
- });
-
- //prefetch pages when anchors with data-prefetch are encountered
- $( ".ui-page" ).live( "pageshow.prefetch", function(){
- var urls = [];
- $( this ).find( "a:jqmData(prefetch)" ).each(function(){
- var url = $( this ).attr( "href" );
- if ( url && $.inArray( url, urls ) === -1 ) {
- urls.push( url );
- $.mobile.loadPage( url );
- }
- });
- } );
-
- //hashchange event handler
- $window.bind( "hashchange", function( e, triggered ) {
- //find first page via hash
- var to = path.stripHash( location.hash ),
- //transition is false if it's the first page, undefined otherwise (and may be overridden by default)
- transition = $.mobile.urlHistory.stack.length === 0 ? "none" : undefined;
-
- //if listening is disabled (either globally or temporarily), or it's a dialog hash
- if( !$.mobile.hashListeningEnabled || urlHistory.ignoreNextHashChange ) {
- urlHistory.ignoreNextHashChange = false;
- return;
- }
-
- // special case for dialogs
- if( urlHistory.stack.length > 1 &&
- to.indexOf( dialogHashKey ) > -1 ) {
-
- // If current active page is not a dialog skip the dialog and continue
- // in the same direction
- if(!$.mobile.activePage.is( ".ui-dialog" )) {
- //determine if we're heading forward or backward and continue accordingly past
- //the current dialog
- urlHistory.directHashChange({
- currentUrl: to,
- isBack: function() { window.history.back(); },
- isForward: function() { window.history.forward(); }
- });
-
- // prevent changepage
- return;
- } else {
- var setTo = function() { to = $.mobile.urlHistory.getActive().pageUrl; };
- // if the current active page is a dialog and we're navigating
- // to a dialog use the dialog objected saved in the stack
- urlHistory.directHashChange({ currentUrl: to, isBack: setTo, isForward: setTo });
- }
- }
-
- //if to is defined, load it
- if ( to ) {
- to = ( typeof to === "string" && !path.isPath( to ) ) ? ( '#' + to ) : to;
- $.mobile.changePage( to, { transition: transition, changeHash: false, fromHashChange: true } );
- }
- //there's no hash, go to the first page in the dom
- else {
- $.mobile.changePage( $.mobile.firstPage, { transition: transition, changeHash: false, fromHashChange: true } );
- }
- });
-
- //set page min-heights to be device specific
- $( document ).bind( "pageshow", resetActivePageHeight );
- $( window ).bind( "throttledresize", resetActivePageHeight );
-
- };//_registerInternalEvents callback
-
-})( jQuery );
-/*!
- * jQuery Mobile v@VERSION
- * http://jquerymobile.com/
- *
- * Copyright 2010, jQuery Project
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- */
-
-(function( $, window, undefined ) {
-
-function css3TransitionHandler( name, reverse, $to, $from ) {
-
- var deferred = new $.Deferred(),
- reverseClass = reverse ? " reverse" : "",
- viewportClass = "ui-mobile-viewport-transitioning viewport-" + name,
- doneFunc = function() {
-
- $to.add( $from ).removeClass( "out in reverse " + name );
-
- if ( $from ) {
- $from.removeClass( $.mobile.activePageClass );
- }
-
- $to.parent().removeClass( viewportClass );
-
- deferred.resolve( name, reverse, $to, $from );
- };
-
- $to.animationComplete( doneFunc );
-
- $to.parent().addClass( viewportClass );
-
- if ( $from ) {
- $from.addClass( name + " out" + reverseClass );
- }
- $to.addClass( $.mobile.activePageClass + " " + name + " in" + reverseClass );
-
- return deferred.promise();
-}
-
-// Make our transition handler public.
-$.mobile.css3TransitionHandler = css3TransitionHandler;
-
-// If the default transition handler is the 'none' handler, replace it with our handler.
-if ( $.mobile.defaultTransitionHandler === $.mobile.noneTransitionHandler ) {
- $.mobile.defaultTransitionHandler = css3TransitionHandler;
-}
-
-})( jQuery, this );
-/*
-* jQuery Mobile Framework : "degradeInputs" plugin - degrades inputs to another type after custom enhancements are made.
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.mobile.page.prototype.options.degradeInputs = {
- color: false,
- date: false,
- datetime: false,
- "datetime-local": false,
- email: false,
- month: false,
- number: false,
- range: "number",
- search: true,
- tel: false,
- time: false,
- url: false,
- week: false
-};
-
-$.mobile.page.prototype.options.keepNative = ":jqmData(role='none'), :jqmData(role='nojs')";
-
-
-//auto self-init widgets
-$( document ).bind( "pagecreate enhance", function( e ){
-
- var page = $( e.target ).data( "page" ),
- o = page.options;
-
- // degrade inputs to avoid poorly implemented native functionality
- $( e.target ).find( "input" ).not( o.keepNative ).each(function() {
- var $this = $( this ),
- type = this.getAttribute( "type" ),
- optType = o.degradeInputs[ type ] || "text";
-
- if ( o.degradeInputs[ type ] ) {
- $this.replaceWith(
- $( "<div>" ).html( $this.clone() ).html()
- .replace( /\s+type=["']?\w+['"]?/, " type=\"" + optType + "\" data-" + $.mobile.ns + "type=\"" + type + "\" " )
- );
- }
- });
-
-});
-
-})( jQuery );/*
-* jQuery Mobile Framework : "dialog" plugin.
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
-*/
-
-(function( $, window, undefined ) {
-
-$.widget( "mobile.dialog", $.mobile.widget, {
- options: {
- closeBtnText : "Close",
- theme : "a",
- initSelector : ":jqmData(role='dialog')"
- },
- _create: function() {
- var $el = this.element,
- pageTheme = $el.attr( "class" ).match( /ui-body-[a-z]/ );
-
- if( pageTheme.length ){
- $el.removeClass( pageTheme[ 0 ] );
- }
-
- $el.addClass( "ui-body-" + this.options.theme );
-
- // Class the markup for dialog styling
- // Set aria role
- $el.attr( "role", "dialog" )
- .addClass( "ui-dialog" )
- .find( ":jqmData(role='header')" )
- .addClass( "ui-corner-top ui-overlay-shadow" )
- .prepend( "<a href='#' data-" + $.mobile.ns + "icon='delete' data-" + $.mobile.ns + "rel='back' data-" + $.mobile.ns + "iconpos='notext'>"+ this.options.closeBtnText + "</a>" )
- .end()
- .find( ":jqmData(role='content'),:jqmData(role='footer')" )
- .last()
- .addClass( "ui-corner-bottom ui-overlay-shadow" );
-
- /* bind events
- - clicks and submits should use the closing transition that the dialog opened with
- unless a data-transition is specified on the link/form
- - if the click was on the close button, or the link has a data-rel="back" it'll go back in history naturally
- */
- $el.bind( "vclick submit", function( event ) {
- var $target = $( event.target ).closest( event.type === "vclick" ? "a" : "form" ),
- active;
-
- if ( $target.length && !$target.jqmData( "transition" ) ) {
-
- active = $.mobile.urlHistory.getActive() || {};
-
- $target.attr( "data-" + $.mobile.ns + "transition", ( active.transition || $.mobile.defaultDialogTransition ) )
- .attr( "data-" + $.mobile.ns + "direction", "reverse" );
- }
- })
- .bind( "pagehide", function() {
- $( this ).find( "." + $.mobile.activeBtnClass ).removeClass( $.mobile.activeBtnClass );
- });
- },
-
- // Close method goes back in history
- close: function() {
- window.history.back();
- }
-});
-
-//auto self-init widgets
-$( $.mobile.dialog.prototype.options.initSelector ).live( "pagecreate", function(){
- $( this ).dialog();
-});
-
-})( jQuery, this );
-/*
-* jQuery Mobile Framework : This plugin handles theming and layout of headers, footers, and content areas
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.mobile.page.prototype.options.backBtnText = "Back";
-$.mobile.page.prototype.options.addBackBtn = false;
-$.mobile.page.prototype.options.backBtnTheme = null;
-$.mobile.page.prototype.options.headerTheme = "a";
-$.mobile.page.prototype.options.footerTheme = "a";
-$.mobile.page.prototype.options.contentTheme = null;
-
-$( ":jqmData(role='page'), :jqmData(role='dialog')" ).live( "pagecreate", function( e ) {
-
- var $page = $( this ),
- o = $page.data( "page" ).options,
- pageTheme = o.theme;
-
- $( ":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')", this ).each(function() {
- var $this = $( this ),
- role = $this.jqmData( "role" ),
- theme = $this.jqmData( "theme" ),
- $headeranchors,
- leftbtn,
- rightbtn,
- backBtn;
-
- $this.addClass( "ui-" + role );
-
- //apply theming and markup modifications to page,header,content,footer
- if ( role === "header" || role === "footer" ) {
-
- var thisTheme = theme || ( role === "header" ? o.headerTheme : o.footerTheme ) || pageTheme;
-
- //add theme class
- $this.addClass( "ui-bar-" + thisTheme );
-
- // Add ARIA role
- $this.attr( "role", role === "header" ? "banner" : "contentinfo" );
-
- // Right,left buttons
- $headeranchors = $this.children( "a" );
- leftbtn = $headeranchors.hasClass( "ui-btn-left" );
- rightbtn = $headeranchors.hasClass( "ui-btn-right" );
-
- if ( !leftbtn ) {
- leftbtn = $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
- }
-
- if ( !rightbtn ) {
- rightbtn = $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
- }
-
- // Auto-add back btn on pages beyond first view
- if ( o.addBackBtn && role === "header" &&
- $( ".ui-page" ).length > 1 &&
- $this.jqmData( "url" ) !== $.mobile.path.stripHash( location.hash ) &&
- !leftbtn ) {
-
- backBtn = $( "<a href='#' class='ui-btn-left' data-"+ $.mobile.ns +"rel='back' data-"+ $.mobile.ns +"icon='arrow-l'>"+ o.backBtnText +"</a>" ).prependTo( $this );
-
- // If theme is provided, override default inheritance
- backBtn.attr( "data-"+ $.mobile.ns +"theme", o.backBtnTheme || thisTheme );
- }
-
- // Page title
- $this.children( "h1, h2, h3, h4, h5, h6" )
- .addClass( "ui-title" )
- // Regardless of h element number in src, it becomes h1 for the enhanced page
- .attr({
- "tabindex": "0",
- "role": "heading",
- "aria-level": "1"
- });
-
- } else if ( role === "content" ) {
-
- $this.addClass( "ui-body-" + ( theme || pageTheme || o.contentTheme ) );
-
- // Add ARIA role
- $this.attr( "role", "main" );
-
- }
- });
-});
-
-})( jQuery );/*
-* jQuery Mobile Framework : "collapsible" plugin
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-(function( $, undefined ) {
-
-$.widget( "mobile.collapsible", $.mobile.widget, {
- options: {
- expandCueText: " click to expand contents",
- collapseCueText: " click to collapse contents",
- collapsed: false,
- heading: ">:header,>legend",
- theme: null,
- iconTheme: "d",
- initSelector: ":jqmData(role='collapsible')"
- },
- _create: function() {
-
- var $el = this.element,
- o = this.options,
- collapsibleContain = $el.addClass( "ui-collapsible-contain" ),
- collapsibleHeading = $el.find( o.heading ).eq( 0 ),
- collapsibleContent = collapsibleContain.wrapInner( "<div class='ui-collapsible-content'></div>" ).find( ".ui-collapsible-content" ),
- collapsibleParent = $el.closest( ":jqmData(role='collapsible-set')" ).addClass( "ui-collapsible-set" );
-
- // Replace collapsibleHeading if it's a legend
- if ( collapsibleHeading.is( "legend" ) ) {
- collapsibleHeading = $( "<div role='heading'>"+ collapsibleHeading.html() +"</div>" ).insertBefore( collapsibleHeading );
- collapsibleHeading.next().remove();
- }
-
- collapsibleHeading
- //drop heading in before content
- .insertBefore( collapsibleContent )
- //modify markup & attributes
- .addClass( "ui-collapsible-heading" )
- .append( "<span class='ui-collapsible-heading-status'></span>" )
- .wrapInner( "<a href='#' class='ui-collapsible-heading-toggle'></a>" )
- .find( "a:eq(0)" )
- .buttonMarkup({
- shadow: !collapsibleParent.length,
- corners: false,
- iconPos: "left",
- icon: "plus",
- theme: o.theme
- })
- .find( ".ui-icon" )
- .removeAttr( "class" )
- .buttonMarkup({
- shadow: true,
- corners: true,
- iconPos: "notext",
- icon: "plus",
- theme: o.iconTheme
- });
-
- if ( !collapsibleParent.length ) {
- collapsibleHeading
- .find( "a:eq(0)" )
- .addClass( "ui-corner-all" )
- .find( ".ui-btn-inner" )
- .addClass( "ui-corner-all" );
- } else {
- if ( collapsibleContain.jqmData( "collapsible-last" ) ) {
- collapsibleHeading
- .find( "a:eq(0), .ui-btn-inner" )
- .addClass( "ui-corner-bottom" );
- }
- }
-
- //events
- collapsibleContain
- .bind( "collapse", function( event ) {
- if ( ! event.isDefaultPrevented() &&
- $( event.target ).closest( ".ui-collapsible-contain" ).is( collapsibleContain ) ) {
-
- event.preventDefault();
-
- collapsibleHeading
- .addClass( "ui-collapsible-heading-collapsed" )
- .find( ".ui-collapsible-heading-status" )
- .text( o.expandCueText )
- .end()
- .find( ".ui-icon" )
- .removeClass( "ui-icon-minus" )
- .addClass( "ui-icon-plus" );
-
- collapsibleContent.addClass( "ui-collapsible-content-collapsed" ).attr( "aria-hidden", true );
-
- if ( collapsibleContain.jqmData( "collapsible-last" ) ) {
- collapsibleHeading
- .find( "a:eq(0), .ui-btn-inner" )
- .addClass( "ui-corner-bottom" );
- }
- }
- })
- .bind( "expand", function( event ) {
- if ( !event.isDefaultPrevented() ) {
-
- event.preventDefault();
-
- collapsibleHeading
- .removeClass( "ui-collapsible-heading-collapsed" )
- .find( ".ui-collapsible-heading-status" ).text( o.collapseCueText );
-
- collapsibleHeading.find( ".ui-icon" ).removeClass( "ui-icon-plus" ).addClass( "ui-icon-minus" );
-
- collapsibleContent.removeClass( "ui-collapsible-content-collapsed" ).attr( "aria-hidden", false );
-
- if ( collapsibleContain.jqmData( "collapsible-last" ) ) {
-
- collapsibleHeading
- .find( "a:eq(0), .ui-btn-inner" )
- .removeClass( "ui-corner-bottom" );
- }
- }
- })
- .trigger( o.collapsed ? "collapse" : "expand" );
-
- // Close others in a set
- if ( collapsibleParent.length && !collapsibleParent.jqmData( "collapsiblebound" ) ) {
-
- collapsibleParent
- .jqmData( "collapsiblebound", true )
- .bind( "expand", function( event ) {
-
- $( event.target )
- .closest( ".ui-collapsible-contain" )
- .siblings( ".ui-collapsible-contain" )
- .trigger( "collapse" );
-
- });
-
- var set = collapsibleParent.children( ":jqmData(role='collapsible')" );
-
- set.first()
- .find( "a:eq(0)" )
- .addClass( "ui-corner-top" )
- .find( ".ui-btn-inner" )
- .addClass( "ui-corner-top" );
-
- set.last().jqmData( "collapsible-last", true );
- }
-
- collapsibleHeading
- .bind( "vclick", function( event ) {
-
- var type = collapsibleHeading.is( ".ui-collapsible-heading-collapsed" ) ?
- "expand" : "collapse";
-
- collapsibleContain.trigger( type );
-
- event.preventDefault();
- });
- }
-});
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
- $( $.mobile.collapsible.prototype.options.initSelector, e.target ).collapsible();
-});
-
-})( jQuery );
-/*
-* jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.fn.fieldcontain = function( options ) {
- return this.addClass( "ui-field-contain ui-body ui-br" );
-};
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
- $( ":jqmData(role='fieldcontain')", e.target ).fieldcontain();
-});
-
-})( jQuery );/*
-* jQuery Mobile Framework : plugin for creating CSS grids
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.fn.grid = function( options ) {
- return this.each(function() {
-
- var $this = $( this ),
- o = $.extend({
- grid: null
- },options),
- $kids = $this.children(),
- gridCols = {solo:1, a:2, b:3, c:4, d:5},
- grid = o.grid,
- iterator;
-
- if ( !grid ) {
- if ( $kids.length <= 5 ) {
- for ( var letter in gridCols ) {
- if ( gridCols[ letter ] === $kids.length ) {
- grid = letter;
- }
- }
- } else {
- grid = "a";
- }
- }
- iterator = gridCols[grid];
-
- $this.addClass( "ui-grid-" + grid );
-
- $kids.filter( ":nth-child(" + iterator + "n+1)" ).addClass( "ui-block-a" );
-
- if ( iterator > 1 ) {
- $kids.filter( ":nth-child(" + iterator + "n+2)" ).addClass( "ui-block-b" );
- }
- if ( iterator > 2 ) {
- $kids.filter( ":nth-child(3n+3)" ).addClass( "ui-block-c" );
- }
- if ( iterator > 3 ) {
- $kids.filter( ":nth-child(4n+4)" ).addClass( "ui-block-d" );
- }
- if ( iterator > 4 ) {
- $kids.filter( ":nth-child(5n+5)" ).addClass( "ui-block-e" );
- }
- });
-};
-})( jQuery );/*
-* jQuery Mobile Framework : "navbar" plugin
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.widget( "mobile.navbar", $.mobile.widget, {
- options: {
- iconpos: "top",
- grid: null,
- initSelector: ":jqmData(role='navbar')"
- },
-
- _create: function(){
-
- var $navbar = this.element,
- $navbtns = $navbar.find( "a" ),
- iconpos = $navbtns.filter( ":jqmData(icon)" ).length ?
- this.options.iconpos : undefined;
-
- $navbar.addClass( "ui-navbar" )
- .attr( "role","navigation" )
- .find( "ul" )
- .grid({ grid: this.options.grid });
-
- if ( !iconpos ) {
- $navbar.addClass( "ui-navbar-noicons" );
- }
-
- $navbtns.buttonMarkup({
- corners: false,
- shadow: false,
- iconpos: iconpos
- });
-
- $navbar.delegate( "a", "vclick", function( event ) {
- $navbtns.not( ".ui-state-persist" ).removeClass( $.mobile.activeBtnClass );
- $( this ).addClass( $.mobile.activeBtnClass );
- });
- }
-});
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
- $( $.mobile.navbar.prototype.options.initSelector, e.target ).navbar();
-});
-
-})( jQuery );
-/*
-* jQuery Mobile Framework : "listview" plugin
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-//Keeps track of the number of lists per page UID
-//This allows support for multiple nested list in the same page
-//https://github.com/jquery/jquery-mobile/issues/1617
-var listCountPerPage = {};
-
-$.widget( "mobile.listview", $.mobile.widget, {
- options: {
- theme: "c",
- countTheme: "c",
- headerTheme: "b",
- dividerTheme: "b",
- splitIcon: "arrow-r",
- splitTheme: "b",
- inset: false,
- initSelector: ":jqmData(role='listview')"
- },
-
- _create: function() {
- var t = this;
-
- // create listview markup
- t.element.addClass(function( i, orig ) {
- return orig + " ui-listview " + ( t.options.inset ? " ui-listview-inset ui-corner-all ui-shadow " : "" );
- });
-
- t.refresh();
- },
-
- _itemApply: function( $list, item ) {
- // TODO class has to be defined in markup
- item.find( ".ui-li-count" )
- .addClass( "ui-btn-up-" + ( $list.jqmData( "counttheme" ) || this.options.countTheme ) + " ui-btn-corner-all" ).end()
- .find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" ).end()
- .find( "p, dl" ).addClass( "ui-li-desc" ).end()
- .find( ">img:eq(0), .ui-link-inherit>img:eq(0)" ).addClass( "ui-li-thumb" ).each(function() {
- item.addClass( $(this).is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
- }).end()
- .find( ".ui-li-aside" ).each(function() {
- var $this = $(this);
- $this.prependTo( $this.parent() ); //shift aside to front for css float
- });
- },
-
- _removeCorners: function( li, which ) {
- var top = "ui-corner-top ui-corner-tr ui-corner-tl",
- bot = "ui-corner-bottom ui-corner-br ui-corner-bl";
-
- li = li.add( li.find( ".ui-btn-inner, .ui-li-link-alt, .ui-li-thumb" ) );
-
- if ( which === "top" ) {
- li.removeClass( top );
- } else if ( which === "bottom" ) {
- li.removeClass( bot );
- } else {
- li.removeClass( top + " " + bot );
- }
- },
-
- refresh: function( create ) {
- this.parentPage = this.element.closest( ".ui-page" );
- this._createSubPages();
-
- var o = this.options,
- $list = this.element,
- self = this,
- dividertheme = $list.jqmData( "dividertheme" ) || o.dividerTheme,
- listsplittheme = $list.jqmData( "splittheme" ),
- listspliticon = $list.jqmData( "spliticon" ),
- li = $list.children( "li" ),
- counter = $.support.cssPseudoElement || !$.nodeName( $list[ 0 ], "ol" ) ? 0 : 1,
- item, itemClass, itemTheme,
- a, last, splittheme, countParent, icon;
-
- if ( counter ) {
- $list.find( ".ui-li-dec" ).remove();
- }
-
- for ( var pos = 0, numli = li.length; pos < numli; pos++ ) {
- item = li.eq( pos );
- itemClass = "ui-li";
-
- // If we're creating the element, we update it regardless
- if ( create || !item.hasClass( "ui-li" ) ) {
- itemTheme = item.jqmData("theme") || o.theme;
- a = item.children( "a" );
-
- if ( a.length ) {
- icon = item.jqmData("icon");
-
- item.buttonMarkup({
- wrapperEls: "div",
- shadow: false,
- corners: false,
- iconpos: "right",
- icon: a.length > 1 || icon === false ? false : icon || "arrow-r",
- theme: itemTheme
- });
-
- a.first().addClass( "ui-link-inherit" );
-
- if ( a.length > 1 ) {
- itemClass += " ui-li-has-alt";
-
- last = a.last();
- splittheme = listsplittheme || last.jqmData( "theme" ) || o.splitTheme;
-
- last.appendTo(item)
- .attr( "title", last.text() )
- .addClass( "ui-li-link-alt" )
- .empty()
- .buttonMarkup({
- shadow: false,
- corners: false,
- theme: itemTheme,
- icon: false,
- iconpos: false
- })
- .find( ".ui-btn-inner" )
- .append(
- $( "<span />" ).buttonMarkup({
- shadow: true,
- corners: true,
- theme: splittheme,
- iconpos: "notext",
- icon: listspliticon || last.jqmData( "icon" ) || o.splitIcon
- })
- );
- }
- } else if ( item.jqmData( "role" ) === "list-divider" ) {
-
- itemClass += " ui-li-divider ui-btn ui-bar-" + dividertheme;
- item.attr( "role", "heading" );
-
- //reset counter when a divider heading is encountered
- if ( counter ) {
- counter = 1;
- }
-
- } else {
- itemClass += " ui-li-static ui-body-" + itemTheme;
- }
- }
-
- if ( o.inset ) {
- if ( pos === 0 ) {
- itemClass += " ui-corner-top";
-
- item.add( item.find( ".ui-btn-inner" ) )
- .find( ".ui-li-link-alt" )
- .addClass( "ui-corner-tr" )
- .end()
- .find( ".ui-li-thumb" )
- .addClass( "ui-corner-tl" );
-
- if ( item.next().next().length ) {
- self._removeCorners( item.next() );
- }
- }
-
- if ( pos === li.length - 1 ) {
- itemClass += " ui-corner-bottom";
-
- item.add( item.find( ".ui-btn-inner" ) )
- .find( ".ui-li-link-alt" )
- .addClass( "ui-corner-br" )
- .end()
- .find( ".ui-li-thumb" )
- .addClass( "ui-corner-bl" );
-
- if ( item.prev().prev().length ) {
- self._removeCorners( item.prev() );
- } else if ( item.prev().length ) {
- self._removeCorners( item.prev(), "bottom" );
- }
- }
- }
-
- if ( counter && itemClass.indexOf( "ui-li-divider" ) < 0 ) {
- countParent = item.is( ".ui-li-static:first" ) ? item : item.find( ".ui-link-inherit" );
-
- countParent.addClass( "ui-li-jsnumbering" )
- .prepend( "<span class='ui-li-dec'>" + (counter++) + ". </span>" );
- }
-
- item.add( item.children( ".ui-btn-inner" ) ).addClass( itemClass );
-
- if ( !create ) {
- self._itemApply( $list, item );
- }
- }
- },
-
- //create a string for ID/subpage url creation
- _idStringEscape: function( str ) {
- return str.replace(/[^a-zA-Z0-9]/g, '-');
- },
-
- _createSubPages: function() {
- var parentList = this.element,
- parentPage = parentList.closest( ".ui-page" ),
- parentUrl = parentPage.jqmData( "url" ),
- parentId = parentUrl || parentPage[ 0 ][ $.expando ],
- parentListId = parentList.attr( "id" ),
- o = this.options,
- dns = "data-" + $.mobile.ns,
- self = this,
- persistentFooterID = parentPage.find( ":jqmData(role='footer')" ).jqmData( "id" ),
- hasSubPages;
-
- if ( typeof listCountPerPage[ parentId ] === "undefined" ) {
- listCountPerPage[ parentId ] = -1;
- }
-
- parentListId = parentListId || ++listCountPerPage[ parentId ];
-
- $( parentList.find( "li>ul, li>ol" ).toArray().reverse() ).each(function( i ) {
- var self = this,
- list = $( this ),
- listId = list.attr( "id" ) || parentListId + "-" + i,
- parent = list.parent(),
- nodeEls = $( list.prevAll().toArray().reverse() ),
- nodeEls = nodeEls.length ? nodeEls : $( "<span>" + $.trim(parent.contents()[ 0 ].nodeValue) + "</span>" ),
- title = nodeEls.first().text(),//url limits to first 30 chars of text
- id = ( parentUrl || "" ) + "&" + $.mobile.subPageUrlKey + "=" + listId,
- theme = list.jqmData( "theme" ) || o.theme,
- countTheme = list.jqmData( "counttheme" ) || parentList.jqmData( "counttheme" ) || o.countTheme,
- newPage, anchor;
-
- //define hasSubPages for use in later removal
- hasSubPages = true;
-
- newPage = list.detach()
- .wrap( "<div " + dns + "role='page' " + dns + "url='" + id + "' " + dns + "theme='" + theme + "' " + dns + "count-theme='" + countTheme + "'><div " + dns + "role='content'></div></div>" )
- .parent()
- .before( "<div " + dns + "role='header' " + dns + "theme='" + o.headerTheme + "'><div class='ui-title'>" + title + "</div></div>" )
- .after( persistentFooterID ? $( "<div " + dns + "role='footer' " + dns + "id='"+ persistentFooterID +"'>") : "" )
- .parent()
- .appendTo( $.mobile.pageContainer );
-
- newPage.page();
-
- anchor = parent.find('a:first');
-
- if ( !anchor.length ) {
- anchor = $( "<a/>" ).html( nodeEls || title ).prependTo( parent.empty() );
- }
-
- anchor.attr( "href", "#" + id );
-
- }).listview();
-
- //on pagehide, remove any nested pages along with the parent page, as long as they aren't active
- if( hasSubPages && parentPage.data("page").options.domCache === false ){
- var newRemove = function( e, ui ){
- var nextPage = ui.nextPage, npURL;
-
- if( ui.nextPage ){
- npURL = nextPage.jqmData( "url" );
- if( npURL.indexOf( parentUrl + "&" + $.mobile.subPageUrlKey ) !== 0 ){
- self.childPages().remove();
- parentPage.remove();
- }
- }
- };
-
- // unbind the original page remove and replace with our specialized version
- parentPage
- .unbind( "pagehide.remove" )
- .bind( "pagehide.remove", newRemove);
- }
- },
-
- // TODO sort out a better way to track sub pages of the listview this is brittle
- childPages: function(){
- var parentUrl = this.parentPage.jqmData( "url" );
-
- return $( ":jqmData(url^='"+ parentUrl + "&" + $.mobile.subPageUrlKey +"')");
- }
-});
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
- $( $.mobile.listview.prototype.options.initSelector, e.target ).listview();
-});
-
-})( jQuery );
-/*
-* jQuery Mobile Framework : "listview" filter extension
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.mobile.listview.prototype.options.filter = false;
-$.mobile.listview.prototype.options.filterPlaceholder = "Filter items...";
-$.mobile.listview.prototype.options.filterTheme = "c";
-
-$( ":jqmData(role='listview')" ).live( "listviewcreate", function() {
-
- var list = $( this ),
- listview = list.data( "listview" );
-
- if ( !listview.options.filter ) {
- return;
- }
-
- var wrapper = $( "<form>", {
- "class": "ui-listview-filter ui-bar-" + listview.options.filterTheme,
- "role": "search"
- }),
- search = $( "<input>", {
- placeholder: listview.options.filterPlaceholder
- })
- .attr( "data-" + $.mobile.ns + "type", "search" )
- .jqmData( "lastval", "" )
- .bind( "keyup change", function() {
-
- var $this = $(this),
- val = this.value.toLowerCase(),
- listItems = null,
- lastval = $this.jqmData( "lastval" ) + "",
- childItems = false,
- itemtext = "",
- item;
-
- // Change val as lastval for next execution
- $this.jqmData( "lastval" , val );
-
- change = val.replace( new RegExp( "^" + lastval ) , "" );
-
- if ( val.length < lastval.length || change.length != ( val.length - lastval.length ) ) {
-
- // Removed chars or pasted something totaly different, check all items
- listItems = list.children();
- } else {
-
- // Only chars added, not removed, only use visible subset
- listItems = list.children( ":not(.ui-screen-hidden)" );
- }
-
- if ( val ) {
-
- // This handles hiding regular rows without the text we search for
- // and any list dividers without regular rows shown under it
-
- for ( var i = listItems.length - 1; i >= 0; i-- ) {
- item = $( listItems[ i ] );
- itemtext = item.jqmData( "filtertext" ) || item.text();
-
- if ( item.is( "li:jqmData(role=list-divider)" ) ) {
-
- item.toggleClass( "ui-filter-hidequeue" , !childItems );
-
- // New bucket!
- childItems = false;
-
- } else if ( itemtext.toLowerCase().indexOf( val ) === -1 ) {
-
- //mark to be hidden
- item.toggleClass( "ui-filter-hidequeue" , true );
- } else {
-
- // There"s a shown item in the bucket
- childItems = true;
- }
- }
-
- // Show items, not marked to be hidden
- listItems
- .filter( ":not(.ui-filter-hidequeue)" )
- .toggleClass( "ui-screen-hidden", false );
-
- // Hide items, marked to be hidden
- listItems
- .filter( ".ui-filter-hidequeue" )
- .toggleClass( "ui-screen-hidden", true )
- .toggleClass( "ui-filter-hidequeue", false );
-
- } else {
-
- //filtervalue is empty => show all
- listItems.toggleClass( "ui-screen-hidden", false );
- }
- })
- .appendTo( wrapper )
- .textinput();
-
- if ( $( this ).jqmData( "inset" ) ) {
- wrapper.addClass( "ui-listview-filter-inset" );
- }
-
- wrapper.bind( "submit", function() {
- return false;
- })
- .insertBefore( list );
-});
-
-})( jQuery );/*
-* jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$( document ).bind( "pagecreate create", function( e ){
- $( ":jqmData(role='nojs')", e.target ).addClass( "ui-nojs" );
-
-});
-
-})( jQuery );/*
-* jQuery Mobile Framework : "checkboxradio" plugin
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.widget( "mobile.checkboxradio", $.mobile.widget, {
- options: {
- theme: null,
- initSelector: "input[type='checkbox'],input[type='radio']"
- },
- _create: function() {
- var self = this,
- input = this.element,
- // NOTE: Windows Phone could not find the label through a selector
- // filter works though.
- label = input.closest( "form,fieldset,:jqmData(role='page')" ).find( "label" ).filter( "[for='" + input[ 0 ].id + "']"),
- inputtype = input.attr( "type" ),
- checkedState = inputtype + "-on",
- uncheckedState = inputtype + "-off",
- icon = input.parents( ":jqmData(type='horizontal')" ).length ? undefined : uncheckedState,
- activeBtn = icon ? "" : " " + $.mobile.activeBtnClass,
- checkedClass = "ui-" + checkedState + activeBtn,
- uncheckedClass = "ui-" + uncheckedState,
- checkedicon = "ui-icon-" + checkedState,
- uncheckedicon = "ui-icon-" + uncheckedState;
-
- if ( inputtype !== "checkbox" && inputtype !== "radio" ) {
- return;
- }
-
- // Expose for other methods
- $.extend( this, {
- label: label,
- inputtype: inputtype,
- checkedClass: checkedClass,
- uncheckedClass: uncheckedClass,
- checkedicon: checkedicon,
- uncheckedicon: uncheckedicon
- });
-
- // If there's no selected theme...
- if( !this.options.theme ) {
- this.options.theme = this.element.jqmData( "theme" );
- }
-
- label.buttonMarkup({
- theme: this.options.theme,
- icon: icon,
- shadow: false
- });
-
- // Wrap the input + label in a div
- input.add( label )
- .wrapAll( "<div class='ui-" + inputtype + "'></div>" );
-
- label.bind({
- vmouseover: function() {
- if ( $( this ).parent().is( ".ui-disabled" ) ) {
- return false;
- }
- },
-
- vclick: function( event ) {
- if ( input.is( ":disabled" ) ) {
- event.preventDefault();
- return;
- }
-
- self._cacheVals();
-
- input.prop( "checked", inputtype === "radio" && true || !input.prop( "checked" ) );
-
- // Input set for common radio buttons will contain all the radio
- // buttons, but will not for checkboxes. clearing the checked status
- // of other radios ensures the active button state is applied properly
- self._getInputSet().not( input ).prop( "checked", false );
-
- self._updateAll();
- return false;
- }
-
- });
-
- input
- .bind({
- vmousedown: function() {
- this._cacheVals();
- },
-
- vclick: function() {
-
- var $this = $(this);
-
- // Adds checked attribute to checked input when keyboard is used
- if ( $this.is( ":checked" ) ) {
-
- $this.prop( "checked", true);
- self._getInputSet().not($this).prop( "checked", false );
- } else {
-
- $this.prop( "checked", false );
- }
-
- self._updateAll();
- },
-
- focus: function() {
- label.addClass( "ui-focus" );
- },
-
- blur: function() {
- label.removeClass( "ui-focus" );
- }
- });
-
- this.refresh();
- },
-
- _cacheVals: function() {
- this._getInputSet().each(function() {
- var $this = $(this);
-
- $this.jqmData( "cacheVal", $this.is( ":checked" ) );
- });
- },
-
- //returns either a set of radios with the same name attribute, or a single checkbox
- _getInputSet: function(){
- if(this.inputtype == "checkbox") {
- return this.element;
- }
- return this.element.closest( "form,fieldset,:jqmData(role='page')" )
- .find( "input[name='"+ this.element.attr( "name" ) +"'][type='"+ this.inputtype +"']" );
- },
-
- _updateAll: function() {
- var self = this;
-
- this._getInputSet().each(function() {
- var $this = $(this);
-
- if ( $this.is( ":checked" ) || self.inputtype === "checkbox" ) {
- $this.trigger( "change" );
- }
- })
- .checkboxradio( "refresh" );
- },
-
- refresh: function() {
- var input = this.element,
- label = this.label,
- icon = label.find( ".ui-icon" );
-
- // input[0].checked expando doesn't always report the proper value
- // for checked='checked'
- if ( $( input[ 0 ] ).prop( "checked" ) ) {
-
- label.addClass( this.checkedClass ).removeClass( this.uncheckedClass );
- icon.addClass( this.checkedicon ).removeClass( this.uncheckedicon );
-
- } else {
-
- label.removeClass( this.checkedClass ).addClass( this.uncheckedClass );
- icon.removeClass( this.checkedicon ).addClass( this.uncheckedicon );
- }
-
- if ( input.is( ":disabled" ) ) {
- this.disable();
- } else {
- this.enable();
- }
- },
-
- disable: function() {
- this.element.prop( "disabled", true ).parent().addClass( "ui-disabled" );
- },
-
- enable: function() {
- this.element.prop( "disabled", false ).parent().removeClass( "ui-disabled" );
- }
-});
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
- $( $.mobile.checkboxradio.prototype.options.initSelector, e.target )
- .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
- .checkboxradio();
-});
-
-})( jQuery );
-/*
-* jQuery Mobile Framework : "button" plugin - links that proxy to native input/buttons
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.widget( "mobile.button", $.mobile.widget, {
- options: {
- theme: null,
- icon: null,
- iconpos: null,
- inline: null,
- corners: true,
- shadow: true,
- iconshadow: true,
- initSelector: "button, [type='button'], [type='submit'], [type='reset'], [type='image']"
- },
- _create: function() {
- var $el = this.element,
- o = this.options,
- type;
-
- // Add ARIA role
- this.button = $( "<div></div>" )
- .text( $el.text() || $el.val() )
- .buttonMarkup({
- theme: o.theme,
- icon: o.icon,
- iconpos: o.iconpos,
- inline: o.inline,
- corners: o.corners,
- shadow: o.shadow,
- iconshadow: o.iconshadow
- })
- .insertBefore( $el )
- .append( $el.addClass( "ui-btn-hidden" ) );
-
- // Add hidden input during submit
- type = $el.attr( "type" );
-
- if ( type !== "button" && type !== "reset" ) {
-
- $el.bind( "vclick", function() {
-
- var $buttonPlaceholder = $( "<input>", {
- type: "hidden",
- name: $el.attr( "name" ),
- value: $el.attr( "value" )
- })
- .insertBefore( $el );
-
- // Bind to doc to remove after submit handling
- $( document ).submit(function(){
- $buttonPlaceholder.remove();
- });
- });
- }
-
- this.refresh();
- },
-
- enable: function() {
- this.element.attr( "disabled", false );
- this.button.removeClass( "ui-disabled" ).attr( "aria-disabled", false );
- return this._setOption( "disabled", false );
- },
-
- disable: function() {
- this.element.attr( "disabled", true );
- this.button.addClass( "ui-disabled" ).attr( "aria-disabled", true );
- return this._setOption( "disabled", true );
- },
-
- refresh: function() {
- if ( this.element.attr( "disabled" ) ) {
- this.disable();
- } else {
- this.enable();
- }
- }
-});
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
- $( $.mobile.button.prototype.options.initSelector, e.target )
- .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
- .button();
-});
-
-})( jQuery );/*
-* jQuery Mobile Framework : "slider" plugin
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-( function( $, undefined ) {
-
-$.widget( "mobile.slider", $.mobile.widget, {
- options: {
- theme: null,
- trackTheme: null,
- disabled: false,
- initSelector: "input[type='range'], :jqmData(type='range'), :jqmData(role='slider')"
- },
-
- _create: function() {
-
- // TODO: Each of these should have comments explain what they're for
- var self = this,
-
- control = this.element,
-
- parentTheme = control.parents( "[class*='ui-bar-'],[class*='ui-body-']" ).eq( 0 ),
-
- parentTheme = parentTheme.length ? parentTheme.attr( "class" ).match( /ui-(bar|body)-([a-z])/ )[ 2 ] : "c",
-
- theme = this.options.theme ? this.options.theme : parentTheme,
-
- trackTheme = this.options.trackTheme ? this.options.trackTheme : parentTheme,
-
- cType = control[ 0 ].nodeName.toLowerCase(),
-
- selectClass = ( cType == "select" ) ? "ui-slider-switch" : "",
-
- controlID = control.attr( "id" ),
-
- labelID = controlID + "-label",
-
- label = $( "[for='"+ controlID +"']" ).attr( "id", labelID ),
-
- val = function() {
- return cType == "input" ? parseFloat( control.val() ) : control[0].selectedIndex;
- },
-
- min = cType == "input" ? parseFloat( control.attr( "min" ) ) : 0,
-
- max = cType == "input" ? parseFloat( control.attr( "max" ) ) : control.find( "option" ).length-1,
-
- step = window.parseFloat( control.attr( "step" ) || 1 ),
-
- slider = $( "<div class='ui-slider " + selectClass + " ui-btn-down-" + trackTheme +
- " ui-btn-corner-all' role='application'></div>" ),
-
- handle = $( "<a href='#' class='ui-slider-handle'></a>" )
- .appendTo( slider )
- .buttonMarkup({ corners: true, theme: theme, shadow: true })
- .attr({
- "role": "slider",
- "aria-valuemin": min,
- "aria-valuemax": max,
- "aria-valuenow": val(),
- "aria-valuetext": val(),
- "title": val(),
- "aria-labelledby": labelID
- }),
- options;
-
- $.extend( this, {
- slider: slider,
- handle: handle,
- dragging: false,
- beforeStart: null
- });
-
- if ( cType == "select" ) {
-
- slider.wrapInner( "<div class='ui-slider-inneroffset'></div>" );
-
- options = control.find( "option" );
-
- control.find( "option" ).each(function( i ) {
-
- var side = !i ? "b":"a",
- corners = !i ? "right" :"left",
- theme = !i ? " ui-btn-down-" + trackTheme :" ui-btn-active";
-
- $( "<div class='ui-slider-labelbg ui-slider-labelbg-" + side + theme + " ui-btn-corner-" + corners + "'></div>" )
- .prependTo( slider );
-
- $( "<span class='ui-slider-label ui-slider-label-" + side + theme + " ui-btn-corner-" + corners + "' role='img'>" + $( this ).text() + "</span>" )
- .prependTo( handle );
- });
-
- }
-
- label.addClass( "ui-slider" );
-
- // monitor the input for updated values
- control.addClass( cType === "input" ? "ui-slider-input" : "ui-slider-switch" )
- .change( function() {
- self.refresh( val(), true );
- })
- .keyup( function() { // necessary?
- self.refresh( val(), true, true );
- })
- .blur( function() {
- self.refresh( val(), true );
- });
-
- // prevent screen drag when slider activated
- $( document ).bind( "vmousemove", function( event ) {
- if ( self.dragging ) {
- self.refresh( event );
- return false;
- }
- });
-
- slider.bind( "vmousedown", function( event ) {
- self.dragging = true;
-
- if ( cType === "select" ) {
- self.beforeStart = control[0].selectedIndex;
- }
- self.refresh( event );
- return false;
- });
-
- slider.add( document )
- .bind( "vmouseup", function() {
- if ( self.dragging ) {
-
- self.dragging = false;
-
- if ( cType === "select" ) {
-
- if ( self.beforeStart === control[ 0 ].selectedIndex ) {
- //tap occurred, but value didn't change. flip it!
- self.refresh( !self.beforeStart ? 1 : 0 );
- }
- var curval = val();
- var snapped = Math.round( curval / ( max - min ) * 100 );
- handle
- .addClass( "ui-slider-handle-snapping" )
- .css( "left", snapped + "%" )
- .animationComplete( function() {
- handle.removeClass( "ui-slider-handle-snapping" );
- });
- }
- return false;
- }
- });
-
- slider.insertAfter( control );
-
- // NOTE force focus on handle
- this.handle
- .bind( "vmousedown", function() {
- $( this ).focus();
- })
- .bind( "vclick", false );
-
- this.handle
- .bind( "keydown", function( event ) {
- var index = val();
-
- if ( self.options.disabled ) {
- return;
- }
-
- // In all cases prevent the default and mark the handle as active
- switch ( event.keyCode ) {
- case $.mobile.keyCode.HOME:
- case $.mobile.keyCode.END:
- case $.mobile.keyCode.PAGE_UP:
- case $.mobile.keyCode.PAGE_DOWN:
- case $.mobile.keyCode.UP:
- case $.mobile.keyCode.RIGHT:
- case $.mobile.keyCode.DOWN:
- case $.mobile.keyCode.LEFT:
- event.preventDefault();
-
- if ( !self._keySliding ) {
- self._keySliding = true;
- $( this ).addClass( "ui-state-active" );
- }
- break;
- }
-
- // move the slider according to the keypress
- switch ( event.keyCode ) {
- case $.mobile.keyCode.HOME:
- self.refresh( min );
- break;
- case $.mobile.keyCode.END:
- self.refresh( max );
- break;
- case $.mobile.keyCode.PAGE_UP:
- case $.mobile.keyCode.UP:
- case $.mobile.keyCode.RIGHT:
- self.refresh( index + step );
- break;
- case $.mobile.keyCode.PAGE_DOWN:
- case $.mobile.keyCode.DOWN:
- case $.mobile.keyCode.LEFT:
- self.refresh( index - step );
- break;
- }
- }) // remove active mark
- .keyup( function( event ) {
- if ( self._keySliding ) {
- self._keySliding = false;
- $( this ).removeClass( "ui-state-active" );
- }
- });
-
- this.refresh(undefined, undefined, true);
- },
-
- refresh: function( val, isfromControl, preventInputUpdate ) {
- if ( this.options.disabled ) { return; }
-
- var control = this.element, percent,
- cType = control[0].nodeName.toLowerCase(),
- min = cType === "input" ? parseFloat( control.attr( "min" ) ) : 0,
- max = cType === "input" ? parseFloat( control.attr( "max" ) ) : control.find( "option" ).length - 1;
-
- if ( typeof val === "object" ) {
- var data = val,
- // a slight tolerance helped get to the ends of the slider
- tol = 8;
- if ( !this.dragging ||
- data.pageX < this.slider.offset().left - tol ||
- data.pageX > this.slider.offset().left + this.slider.width() + tol ) {
- return;
- }
- percent = Math.round( ( ( data.pageX - this.slider.offset().left ) / this.slider.width() ) * 100 );
- } else {
- if ( val == null ) {
- val = cType === "input" ? parseFloat( control.val() ) : control[0].selectedIndex;
- }
- percent = ( parseFloat( val ) - min ) / ( max - min ) * 100;
- }
-
- if ( isNaN( percent ) ) {
- return;
- }
-
- if ( percent < 0 ) {
- percent = 0;
- }
-
- if ( percent > 100 ) {
- percent = 100;
- }
-
- var newval = Math.round( ( percent / 100 ) * ( max - min ) ) + min;
-
- if ( newval < min ) {
- newval = min;
- }
-
- if ( newval > max ) {
- newval = max;
- }
-
- // Flip the stack of the bg colors
- if ( percent > 60 && cType === "select" ) {
- // TODO: Dead path?
- }
- this.handle.css( "left", percent + "%" );
- this.handle.attr( {
- "aria-valuenow": cType === "input" ? newval : control.find( "option" ).eq( newval ).attr( "value" ),
- "aria-valuetext": cType === "input" ? newval : control.find( "option" ).eq( newval ).text(),
- title: newval
- });
-
- // add/remove classes for flip toggle switch
- if ( cType === "select" ) {
- if ( newval === 0 ) {
- this.slider.addClass( "ui-slider-switch-a" )
- .removeClass( "ui-slider-switch-b" );
- } else {
- this.slider.addClass( "ui-slider-switch-b" )
- .removeClass( "ui-slider-switch-a" );
- }
- }
-
- if ( !preventInputUpdate ) {
- // update control"s value
- if ( cType === "input" ) {
- control.val( newval );
- } else {
- control[ 0 ].selectedIndex = newval;
- }
- if ( !isfromControl ) {
- control.trigger( "change" );
- }
- }
- },
-
- enable: function() {
- this.element.attr( "disabled", false );
- this.slider.removeClass( "ui-disabled" ).attr( "aria-disabled", false );
- return this._setOption( "disabled", false );
- },
-
- disable: function() {
- this.element.attr( "disabled", true );
- this.slider.addClass( "ui-disabled" ).attr( "aria-disabled", true );
- return this._setOption( "disabled", true );
- }
-
-});
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
-
- $( $.mobile.slider.prototype.options.initSelector, e.target )
- .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
- .slider();
-
-});
-
-})( jQuery );/*
-* jQuery Mobile Framework : "textinput" plugin for text inputs, textareas
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.widget( "mobile.textinput", $.mobile.widget, {
- options: {
- theme: null,
- initSelector: "input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea"
- },
-
- _create: function() {
-
- var input = this.element,
- o = this.options,
- theme = o.theme,
- themedParent, themeclass, themeLetter, focusedEl, clearbtn;
-
- if ( !theme ) {
- themedParent = this.element.closest( "[class*='ui-bar-'],[class*='ui-body-']" );
- themeLetter = themedParent.length && /ui-(bar|body)-([a-z])/.exec( themedParent.attr( "class" ) );
- theme = themeLetter && themeLetter[2] || "c";
- }
-
- themeclass = " ui-body-" + theme;
-
- $( "label[for='" + input.attr( "id" ) + "']" ).addClass( "ui-input-text" );
-
- input.addClass("ui-input-text ui-body-"+ o.theme );
-
- focusedEl = input;
-
- // XXX: Temporary workaround for issue 785. Turn off autocorrect and
- // autocomplete since the popup they use can't be dismissed by
- // the user. Note that we test for the presence of the feature
- // by looking for the autocorrect property on the input element.
- if ( typeof input[0].autocorrect !== "undefined" ) {
- // Set the attribute instead of the property just in case there
- // is code that attempts to make modifications via HTML.
- input[0].setAttribute( "autocorrect", "off" );
- input[0].setAttribute( "autocomplete", "off" );
- }
-
-
- //"search" input widget
- if ( input.is( "[type='search'],:jqmData(type='search')" ) ) {
-
- focusedEl = input.wrap( "<div class='ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield" + themeclass + "'></div>" ).parent();
- clearbtn = $( "<a href='#' class='ui-input-clear' title='clear text'>clear text</a>" )
- .tap(function( event ) {
- input.val( "" ).focus();
- input.trigger( "change" );
- clearbtn.addClass( "ui-input-clear-hidden" );
- event.preventDefault();
- })
- .appendTo( focusedEl )
- .buttonMarkup({
- icon: "delete",
- iconpos: "notext",
- corners: true,
- shadow: true
- });
-
- function toggleClear() {
- if ( !input.val() ) {
- clearbtn.addClass( "ui-input-clear-hidden" );
- } else {
- clearbtn.removeClass( "ui-input-clear-hidden" );
- }
- }
-
- toggleClear();
-
- input.keyup( toggleClear )
- .focus( toggleClear );
-
- } else {
- input.addClass( "ui-corner-all ui-shadow-inset" + themeclass );
- }
-
- input.focus(function() {
- focusedEl.addClass( "ui-focus" );
- })
- .blur(function(){
- focusedEl.removeClass( "ui-focus" );
- });
-
- // Autogrow
- if ( input.is( "textarea" ) ) {
- var extraLineHeight = 15,
- keyupTimeoutBuffer = 100,
- keyup = function() {
- var scrollHeight = input[ 0 ].scrollHeight,
- clientHeight = input[ 0 ].clientHeight;
-
- if ( clientHeight < scrollHeight ) {
- input.css({
- height: (scrollHeight + extraLineHeight)
- });
- }
- },
- keyupTimeout;
-
- input.keyup(function() {
- clearTimeout( keyupTimeout );
- keyupTimeout = setTimeout( keyup, keyupTimeoutBuffer );
- });
- }
- },
-
- disable: function(){
- ( this.element.attr( "disabled", true ).is( "[type='search'],:jqmData(type='search')" ) ?
- this.element.parent() : this.element ).addClass( "ui-disabled" );
- },
-
- enable: function(){
- ( this.element.attr( "disabled", false).is( "[type='search'],:jqmData(type='search')" ) ?
- this.element.parent() : this.element ).removeClass( "ui-disabled" );
- }
-});
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
-
- $( $.mobile.textinput.prototype.options.initSelector, e.target )
- .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
- .textinput();
-
-});
-
-})( jQuery );
-/*
-* jQuery Mobile Framework : "selectmenu" plugin
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$.widget( "mobile.selectmenu", $.mobile.widget, {
- options: {
- theme: null,
- disabled: false,
- icon: "arrow-d",
- iconpos: "right",
- inline: null,
- corners: true,
- shadow: true,
- iconshadow: true,
- menuPageTheme: "b",
- overlayTheme: "a",
- hidePlaceholderMenuItems: true,
- closeText: "Close",
- nativeMenu: true,
- initSelector: "select:not(:jqmData(role='slider'))"
- },
- _create: function() {
-
- var self = this,
-
- o = this.options,
-
- select = this.element
- .wrap( "<div class='ui-select'>" ),
-
- selectID = select.attr( "id" ),
-
- label = $( "label[for='"+ selectID +"']" ).addClass( "ui-select" ),
-
- // IE throws an exception at options.item() function when
- // there is no selected item
- // select first in this case
- selectedIndex = select[ 0 ].selectedIndex == -1 ? 0 : select[ 0 ].selectedIndex,
-
- button = ( self.options.nativeMenu ? $( "<div/>" ) : $( "<a>", {
- "href": "#",
- "role": "button",
- "id": buttonId,
- "aria-haspopup": "true",
- "aria-owns": menuId
- }) )
- .text( $( select[ 0 ].options.item( selectedIndex ) ).text() )
- .insertBefore( select )
- .buttonMarkup({
- theme: o.theme,
- icon: o.icon,
- iconpos: o.iconpos,
- inline: o.inline,
- corners: o.corners,
- shadow: o.shadow,
- iconshadow: o.iconshadow
- }),
-
- // Multi select or not
- isMultiple = self.isMultiple = select[ 0 ].multiple;
-
- // Opera does not properly support opacity on select elements
- // In Mini, it hides the element, but not its text
- // On the desktop,it seems to do the opposite
- // for these reasons, using the nativeMenu option results in a full native select in Opera
- if ( o.nativeMenu && window.opera && window.opera.version ) {
- select.addClass( "ui-select-nativeonly" );
- }
-
- //vars for non-native menus
- if ( !o.nativeMenu ) {
- var options = select.find("option"),
-
- buttonId = selectID + "-button",
-
- menuId = selectID + "-menu",
-
- thisPage = select.closest( ".ui-page" ),
-
- //button theme
- theme = /ui-btn-up-([a-z])/.exec( button.attr( "class" ) )[1],
-
- menuPage = $( "<div data-" + $.mobile.ns + "role='dialog' data-" +$.mobile.ns + "theme='"+ o.menuPageTheme +"'>" +
- "<div data-" + $.mobile.ns + "role='header'>" +
- "<div class='ui-title'>" + label.text() + "</div>"+
- "</div>"+
- "<div data-" + $.mobile.ns + "role='content'></div>"+
- "</div>" )
- .appendTo( $.mobile.pageContainer )
- .page(),
-
- menuPageContent = menuPage.find( ".ui-content" ),
-
- menuPageClose = menuPage.find( ".ui-header a" ),
-
- screen = $( "<div>", {"class": "ui-selectmenu-screen ui-screen-hidden"})
- .appendTo( thisPage ),
-
- listbox = $("<div>", { "class": "ui-selectmenu ui-selectmenu-hidden ui-overlay-shadow ui-corner-all ui-body-" + o.overlayTheme + " " + $.mobile.defaultDialogTransition })
- .insertAfter(screen),
-
- list = $( "<ul>", {
- "class": "ui-selectmenu-list",
- "id": menuId,
- "role": "listbox",
- "aria-labelledby": buttonId
- })
- .attr( "data-" + $.mobile.ns + "theme", theme )
- .appendTo( listbox ),
-
- header = $( "<div>", {
- "class": "ui-header ui-bar-" + theme
- })
- .prependTo( listbox ),
-
- headerTitle = $( "<h1>", {
- "class": "ui-title"
- })
- .appendTo( header ),
-
- headerClose = $( "<a>", {
- "text": o.closeText,
- "href": "#",
- "class": "ui-btn-left"
- })
- .attr( "data-" + $.mobile.ns + "iconpos", "notext" )
- .attr( "data-" + $.mobile.ns + "icon", "delete" )
- .appendTo( header )
- .buttonMarkup(),
-
- menuType;
- } // End non native vars
-
- // Add counter for multi selects
- if ( isMultiple ) {
- self.buttonCount = $( "<span>" )
- .addClass( "ui-li-count ui-btn-up-c ui-btn-corner-all" )
- .hide()
- .appendTo( button );
- }
-
- // Disable if specified
- if ( o.disabled ) {
- this.disable();
- }
-
- // Events on native select
- select.change(function() {
- self.refresh();
- });
-
- // Expose to other methods
- $.extend( self, {
- select: select,
- optionElems: options,
- selectID: selectID,
- label: label,
- buttonId: buttonId,
- menuId: menuId,
- thisPage: thisPage,
- button: button,
- menuPage: menuPage,
- menuPageContent: menuPageContent,
- screen: screen,
- listbox: listbox,
- list: list,
- menuType: menuType,
- header: header,
- headerClose: headerClose,
- headerTitle: headerTitle,
- placeholder: ""
- });
-
- // Support for using the native select menu with a custom button
- if ( o.nativeMenu ) {
-
- select.appendTo( button )
- .bind( "vmousedown", function() {
- // Add active class to button
- button.addClass( $.mobile.activeBtnClass );
- })
- .bind( "focus vmouseover", function() {
- button.trigger( "vmouseover" );
- })
- .bind( "vmousemove", function() {
- // Remove active class on scroll/touchmove
- button.removeClass( $.mobile.activeBtnClass );
- })
- .bind( "change blur vmouseout", function() {
-
- button.trigger( "vmouseout" )
- .removeClass( $.mobile.activeBtnClass );
- });
-
-
- } else {
-
- // Create list from select, update state
- self.refresh();
-
- select.attr( "tabindex", "-1" )
- .focus(function() {
- $(this).blur();
- button.focus();
- });
-
- // Button events
- button.bind( "vclick keydown" , function( event ) {
- if ( event.type == "vclick" ||
- event.keyCode && ( event.keyCode === $.mobile.keyCode.ENTER ||
- event.keyCode === $.mobile.keyCode.SPACE ) ) {
-
- self.open();
- event.preventDefault();
- }
- });
-
- // Events for list items
- list.attr( "role", "listbox" )
- .delegate( ".ui-li>a", "focusin", function() {
- $( this ).attr( "tabindex", "0" );
- })
- .delegate( ".ui-li>a", "focusout", function() {
- $( this ).attr( "tabindex", "-1" );
- })
- .delegate( "li:not(.ui-disabled, .ui-li-divider)", "vclick", function( event ) {
-
- var $this = $( this ),
- // index of option tag to be selected
- oldIndex = select[ 0 ].selectedIndex,
- newIndex = $this.jqmData( "option-index" ),
- option = self.optionElems[ newIndex ];
-
- // toggle selected status on the tag for multi selects
- option.selected = isMultiple ? !option.selected : true;
-
- // toggle checkbox class for multiple selects
- if ( isMultiple ) {
- $this.find( ".ui-icon" )
- .toggleClass( "ui-icon-checkbox-on", option.selected )
- .toggleClass( "ui-icon-checkbox-off", !option.selected );
- }
-
- // trigger change if value changed
- if ( isMultiple || oldIndex !== newIndex ) {
- select.trigger( "change" );
- }
-
- //hide custom select for single selects only
- if ( !isMultiple ) {
- self.close();
- }
-
- event.preventDefault();
- })
- //keyboard events for menu items
- .keydown(function( event ) {
- var target = $( event.target ),
- li = target.closest( "li" ),
- prev, next;
-
- // switch logic based on which key was pressed
- switch ( event.keyCode ) {
- // up or left arrow keys
- case 38:
- prev = li.prev();
-
- // if there's a previous option, focus it
- if ( prev.length ) {
- target
- .blur()
- .attr( "tabindex", "-1" );
-
- prev.find( "a" ).first().focus();
- }
-
- return false;
- break;
-
- // down or right arrow keys
- case 40:
- next = li.next();
-
- // if there's a next option, focus it
- if ( next.length ) {
- target
- .blur()
- .attr( "tabindex", "-1" );
-
- next.find( "a" ).first().focus();
- }
-
- return false;
- break;
-
- // If enter or space is pressed, trigger click
- case 13:
- case 32:
- target.trigger( "vclick" );
-
- return false;
- break;
- }
- });
-
- // button refocus ensures proper height calculation
- // by removing the inline style and ensuring page inclusion
- self.menuPage.bind( "pagehide", function(){
- self.list.appendTo( self.listbox );
- self._focusButton();
- });
-
- // Events on "screen" overlay
- screen.bind( "vclick", function( event ) {
- self.close();
- });
-
- // Close button on small overlays
- self.headerClose.click(function() {
- if ( self.menuType == "overlay" ) {
- self.close();
- return false;
- }
- });
- }
- },
-
- _buildList: function() {
- var self = this,
- o = this.options,
- placeholder = this.placeholder,
- optgroups = [],
- lis = [],
- dataIcon = self.isMultiple ? "checkbox-off" : "false";
-
- self.list.empty().filter( ".ui-listview" ).listview( "destroy" );
-
- // Populate menu with options from select element
- self.select.find( "option" ).each(function( i ) {
- var $this = $( this ),
- $parent = $this.parent(),
- text = $this.text(),
- anchor = "<a href='#'>"+ text +"</a>",
- classes = [],
- extraAttrs = [];
-
- // Are we inside an optgroup?
- if ( $parent.is( "optgroup" ) ) {
- var optLabel = $parent.attr( "label" );
-
- // has this optgroup already been built yet?
- if ( $.inArray( optLabel, optgroups ) === -1 ) {
- lis.push( "<li data-" + $.mobile.ns + "role='list-divider'>"+ optLabel +"</li>" );
- optgroups.push( optLabel );
- }
- }
-
- // Find placeholder text
- // TODO: Are you sure you want to use getAttribute? ^RW
- if ( !this.getAttribute( "value" ) || text.length == 0 || $this.jqmData( "placeholder" ) ) {
- if ( o.hidePlaceholderMenuItems ) {
- classes.push( "ui-selectmenu-placeholder" );
- }
- placeholder = self.placeholder = text;
- }
-
- // support disabled option tags
- if ( this.disabled ) {
- classes.push( "ui-disabled" );
- extraAttrs.push( "aria-disabled='true'" );
- }
-
- lis.push( "<li data-" + $.mobile.ns + "option-index='" + i + "' data-" + $.mobile.ns + "icon='"+ dataIcon +"' class='"+ classes.join(" ") + "' " + extraAttrs.join(" ") +">"+ anchor +"</li>" )
- });
-
- self.list.html( lis.join(" ") );
-
- self.list.find( "li" )
- .attr({ "role": "option", "tabindex": "-1" })
- .first().attr( "tabindex", "0" );
-
- // Hide header close link for single selects
- if ( !this.isMultiple ) {
- this.headerClose.hide();
- }
-
- // Hide header if it's not a multiselect and there's no placeholder
- if ( !this.isMultiple && !placeholder.length ) {
- this.header.hide();
- } else {
- this.headerTitle.text( this.placeholder );
- }
-
- // Now populated, create listview
- self.list.listview();
- },
-
- refresh: function( forceRebuild ) {
- var self = this,
- select = this.element,
- isMultiple = this.isMultiple,
- options = this.optionElems = select.find( "option" ),
- selected = options.filter( ":selected" ),
-
- // return an array of all selected index's
- indicies = selected.map(function() {
- return options.index( this );
- }).get();
-
- if ( !self.options.nativeMenu &&
- ( forceRebuild || select[0].options.length != self.list.find( "li" ).length ) ) {
-
- self._buildList();
- }
-
- self.button.find( ".ui-btn-text" )
- .text(function() {
-
- if ( !isMultiple ) {
- return selected.text();
- }
-
- return selected.length ? selected.map(function() {
- return $( this ).text();
- }).get().join( ", " ) : self.placeholder;
- });
-
- // multiple count inside button
- if ( isMultiple ) {
- self.buttonCount[ selected.length > 1 ? "show" : "hide" ]().text( selected.length );
- }
-
- if ( !self.options.nativeMenu ) {
-
- self.list.find( "li:not(.ui-li-divider)" )
- .removeClass( $.mobile.activeBtnClass )
- .attr( "aria-selected", false )
- .each(function( i ) {
-
- if ( $.inArray( i, indicies ) > -1 ) {
- var item = $( this ).addClass( $.mobile.activeBtnClass );
-
- // Aria selected attr
- item.find( "a" ).attr( "aria-selected", true );
-
- // Multiple selects: add the "on" checkbox state to the icon
- if ( isMultiple ) {
- item.find( ".ui-icon" ).removeClass( "ui-icon-checkbox-off" ).addClass( "ui-icon-checkbox-on" );
- }
- }
- });
- }
- },
-
- open: function() {
- if ( this.options.disabled || this.options.nativeMenu ) {
- return;
- }
-
- var self = this,
- menuHeight = self.list.parent().outerHeight(),
- menuWidth = self.list.parent().outerWidth(),
- scrollTop = $( window ).scrollTop(),
- btnOffset = self.button.offset().top,
- screenHeight = window.innerHeight,
- screenWidth = window.innerWidth;
-
- //add active class to button
- self.button.addClass( $.mobile.activeBtnClass );
-
- //remove after delay
- setTimeout(function() {
- self.button.removeClass( $.mobile.activeBtnClass );
- }, 300);
-
- function focusMenuItem() {
- self.list.find( ".ui-btn-active" ).focus();
- }
-
- if ( menuHeight > screenHeight - 80 || !$.support.scrollTop ) {
- // prevent the parent page from being removed from the DOM,
- // otherwise the results of selecting a list item in the dialog
- // fall into a black hole
- self.thisPage.unbind( "pagehide.remove" );
-
- //for webos (set lastscroll using button offset)
- if ( scrollTop == 0 && btnOffset > screenHeight ) {
- self.thisPage.one( "pagehide", function() {
- $( this ).jqmData( "lastScroll", btnOffset );
- });
- }
-
- self.menuPage.one( "pageshow", function() {
- // silentScroll() is called whenever a page is shown to restore
- // any previous scroll position the page may have had. We need to
- // wait for the "silentscroll" event before setting focus to avoid
- // the browser"s "feature" which offsets rendering to make sure
- // whatever has focus is in view.
- $( window ).one( "silentscroll", function() {
- focusMenuItem();
- });
-
- self.isOpen = true;
- });
-
- self.menuType = "page";
- self.menuPageContent.append( self.list );
- $.mobile.changePage( self.menuPage, {
- transition: $.mobile.defaultDialogTransition
- });
- } else {
-
- self.menuType = "overlay";
-
- self.screen.height( $(document).height() )
- .removeClass( "ui-screen-hidden" );
-
- // Try and center the overlay over the button
- var roomtop = btnOffset - scrollTop,
- roombot = scrollTop + screenHeight - btnOffset,
- halfheight = menuHeight / 2,
- maxwidth = parseFloat( self.list.parent().css( "max-width" ) ),
- newtop, newleft;
-
- if ( roomtop > menuHeight / 2 && roombot > menuHeight / 2 ) {
- newtop = btnOffset + ( self.button.outerHeight() / 2 ) - halfheight;
- } else {
- // 30px tolerance off the edges
- newtop = roomtop > roombot ? scrollTop + screenHeight - menuHeight - 30 : scrollTop + 30;
- }
-
- // If the menuwidth is smaller than the screen center is
- if ( menuWidth < maxwidth ) {
- newleft = ( screenWidth - menuWidth ) / 2;
- } else {
-
- //otherwise insure a >= 30px offset from the left
- newleft = self.button.offset().left + self.button.outerWidth() / 2 - menuWidth / 2;
-
- // 30px tolerance off the edges
- if ( newleft < 30 ) {
- newleft = 30;
- } else if ( ( newleft + menuWidth ) > screenWidth ) {
- newleft = screenWidth - menuWidth - 30;
- }
- }
-
- self.listbox.append( self.list )
- .removeClass( "ui-selectmenu-hidden" )
- .css({
- top: newtop,
- left: newleft
- })
- .addClass( "in" );
-
- focusMenuItem();
-
- // duplicate with value set in page show for dialog sized selects
- self.isOpen = true;
- }
- },
-
- _focusButton : function(){
- var self = this;
- setTimeout(function() {
- self.button.focus();
- }, 40);
- },
-
- close: function() {
- if ( this.options.disabled || !this.isOpen || this.options.nativeMenu ) {
- return;
- }
-
- var self = this;
-
- if ( self.menuType == "page" ) {
- // rebind the page remove that was unbound in the open function
- // to allow for the parent page removal from actions other than the use
- // of a dialog sized custom select
- self.thisPage.bind( "pagehide.remove", function(){
- $(this).remove();
- });
-
- // doesn't solve the possible issue with calling change page
- // where the objects don't define data urls which prevents dialog key
- // stripping - changePage has incoming refactor
- window.history.back();
- } else{
- self.screen.addClass( "ui-screen-hidden" );
- self.listbox.addClass( "ui-selectmenu-hidden" ).removeAttr( "style" ).removeClass( "in" );
- self.list.appendTo( self.listbox );
- self._focusButton();
- }
-
- // allow the dialog to be closed again
- this.isOpen = false;
- },
-
- disable: function() {
- this.element.attr( "disabled", true );
- this.button.addClass( "ui-disabled" ).attr( "aria-disabled", true );
- return this._setOption( "disabled", true );
- },
-
- enable: function() {
- this.element.attr( "disabled", false );
- this.button.removeClass( "ui-disabled" ).attr( "aria-disabled", false );
- return this._setOption( "disabled", false );
- }
-});
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
- $( $.mobile.selectmenu.prototype.options.initSelector, e.target )
- .not( ":jqmData(role='none'), :jqmData(role='nojs')" )
- .selectmenu();
-});
-
-})( jQuery );
-
-/*
-* jQuery Mobile Framework : plugin for making button-like links
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-( function( $, undefined ) {
-
-$.fn.buttonMarkup = function( options ) {
- return this.each( function() {
- var el = $( this ),
- o = $.extend( {}, $.fn.buttonMarkup.defaults, el.jqmData(), options ),
-
- // Classes Defined
- innerClass = "ui-btn-inner",
- buttonClass, iconClass,
- themedParent, wrap;
-
- if ( attachEvents ) {
- attachEvents();
- }
-
- // if not, try to find closest theme container
- if ( !o.theme ) {
- themedParent = el.closest( "[class*='ui-bar-'],[class*='ui-body-']" );
- o.theme = themedParent.length ?
- /ui-(bar|body)-([a-z])/.exec( themedParent.attr( "class" ) )[2] :
- "c";
- }
-
- buttonClass = "ui-btn ui-btn-up-" + o.theme;
-
- if ( o.inline ) {
- buttonClass += " ui-btn-inline";
- }
-
- if ( o.icon ) {
- o.icon = "ui-icon-" + o.icon;
- o.iconpos = o.iconpos || "left";
-
- iconClass = "ui-icon " + o.icon;
-
- if ( o.iconshadow ) {
- iconClass += " ui-icon-shadow";
- }
- }
-
- if ( o.iconpos ) {
- buttonClass += " ui-btn-icon-" + o.iconpos;
-
- if ( o.iconpos == "notext" && !el.attr( "title" ) ) {
- el.attr( "title", el.text() );
- }
- }
-
- if ( o.corners ) {
- buttonClass += " ui-btn-corner-all";
- innerClass += " ui-btn-corner-all";
- }
-
- if ( o.shadow ) {
- buttonClass += " ui-shadow";
- }
-
- el.attr( "data-" + $.mobile.ns + "theme", o.theme )
- .addClass( buttonClass );
-
- wrap = ( "<D class='" + innerClass + "'><D class='ui-btn-text'></D>" +
- ( o.icon ? "<span class='" + iconClass + "'></span>" : "" ) +
- "</D>" ).replace( /D/g, o.wrapperEls );
-
- el.wrapInner( wrap );
- });
-};
-
-$.fn.buttonMarkup.defaults = {
- corners: true,
- shadow: true,
- iconshadow: true,
- wrapperEls: "span"
-};
-
-function closestEnabledButton( element ) {
- while ( element ) {
- var $ele = $( element );
- if ( $ele.hasClass( "ui-btn" ) && !$ele.hasClass( "ui-disabled" ) ) {
- break;
- }
- element = element.parentNode;
- }
- return element;
-}
-
-var attachEvents = function() {
- $( document ).bind( {
- "vmousedown": function( event ) {
- var btn = closestEnabledButton( event.target ),
- $btn, theme;
-
- if ( btn ) {
- $btn = $( btn );
- theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
- $btn.removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-down-" + theme );
- }
- },
- "vmousecancel vmouseup": function( event ) {
- var btn = closestEnabledButton( event.target ),
- $btn, theme;
-
- if ( btn ) {
- $btn = $( btn );
- theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
- $btn.removeClass( "ui-btn-down-" + theme ).addClass( "ui-btn-up-" + theme );
- }
- },
- "vmouseover focus": function( event ) {
- var btn = closestEnabledButton( event.target ),
- $btn, theme;
-
- if ( btn ) {
- $btn = $( btn );
- theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
- $btn.removeClass( "ui-btn-up-" + theme ).addClass( "ui-btn-hover-" + theme );
- }
- },
- "vmouseout blur": function( event ) {
- var btn = closestEnabledButton( event.target ),
- $btn, theme;
-
- if ( btn ) {
- $btn = $( btn );
- theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
- $btn.removeClass( "ui-btn-hover-" + theme ).addClass( "ui-btn-up-" + theme );
- }
- }
- });
-
- attachEvents = null;
-};
-
-//links in bars, or those with data-role become buttons
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
-
- $( ":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a, .ui-bar > :jqmData(role='controlgroup') > a", e.target )
- .not( ".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')" )
- .buttonMarkup();
-});
-
-})( jQuery );
-/*
-* jQuery Mobile Framework: "controlgroup" plugin - corner-rounding for groups of buttons, checks, radios, etc
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-(function( $, undefined ) {
-
-$.fn.controlgroup = function( options ) {
-
- return this.each(function() {
-
- var $el = $( this ),
- o = $.extend({
- direction: $el.jqmData( "type" ) || "vertical",
- shadow: false,
- excludeInvisible: true
- }, options ),
- groupheading = $el.find( ">legend" ),
- flCorners = o.direction == "horizontal" ? [ "ui-corner-left", "ui-corner-right" ] : [ "ui-corner-top", "ui-corner-bottom" ],
- type = $el.find( "input:eq(0)" ).attr( "type" );
-
- // Replace legend with more stylable replacement div
- if ( groupheading.length ) {
- $el.wrapInner( "<div class='ui-controlgroup-controls'></div>" );
- $( "<div role='heading' class='ui-controlgroup-label'>" + groupheading.html() + "</div>" ).insertBefore( $el.children(0) );
- groupheading.remove();
- }
-
- $el.addClass( "ui-corner-all ui-controlgroup ui-controlgroup-" + o.direction );
-
- // TODO: This should be moved out to the closure
- // otherwise it is redefined each time controlgroup() is called
- function flipClasses( els ) {
- els.removeClass( "ui-btn-corner-all ui-shadow" )
- .eq( 0 ).addClass( flCorners[ 0 ] )
- .end()
- .filter( ":last" ).addClass( flCorners[ 1 ] ).addClass( "ui-controlgroup-last" );
- }
-
- flipClasses( $el.find( ".ui-btn" + ( o.excludeInvisible ? ":visible" : "" ) ) );
- flipClasses( $el.find( ".ui-btn-inner" ) );
-
- if ( o.shadow ) {
- $el.addClass( "ui-shadow" );
- }
- });
-};
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( e ){
- $( ":jqmData(role='controlgroup')", e.target ).controlgroup({ excludeInvisible: false });
-});
-
-})(jQuery);/*
-* jQuery Mobile Framework : "fieldcontain" plugin - simple class additions to make form row separators
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-$( document ).bind( "pagecreate create", function( e ){
-
- //links within content areas
- $( e.target )
- .find( "a" )
- .not( ".ui-btn, .ui-link-inherit, :jqmData(role='none'), :jqmData(role='nojs')" )
- .addClass( "ui-link" );
-
-});
-
-})( jQuery );/*
-* jQuery Mobile Framework : "fixHeaderFooter" plugin - on-demand positioning for headers,footers
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-
-(function( $, undefined ) {
-
-var slideDownClass = "ui-header-fixed ui-fixed-inline fade",
- slideUpClass = "ui-footer-fixed ui-fixed-inline fade",
-
- slideDownSelector = ".ui-header:jqmData(position='fixed')",
- slideUpSelector = ".ui-footer:jqmData(position='fixed')";
-
-$.fn.fixHeaderFooter = function( options ) {
-
- if ( !$.support.scrollTop ) {
- return this;
- }
-
- return this.each(function() {
- var $this = $( this );
-
- if ( $this.jqmData( "fullscreen" ) ) {
- $this.addClass( "ui-page-fullscreen" );
- }
-
- // Should be slidedown
- $this.find( slideDownSelector ).addClass( slideDownClass );
-
- // Should be slideup
- $this.find( slideUpSelector ).addClass( slideUpClass );
- });
-};
-
-// single controller for all showing,hiding,toggling
-$.mobile.fixedToolbars = (function() {
-
- if ( !$.support.scrollTop ) {
- return;
- }
-
- var stickyFooter, delayTimer,
- currentstate = "inline",
- autoHideMode = false,
- showDelay = 100,
- ignoreTargets = "a,input,textarea,select,button,label,.ui-header-fixed,.ui-footer-fixed",
- toolbarSelector = ".ui-header-fixed:first, .ui-footer-fixed:not(.ui-footer-duplicate):last",
- // for storing quick references to duplicate footers
- supportTouch = $.support.touch,
- touchStartEvent = supportTouch ? "touchstart" : "mousedown",
- touchStopEvent = supportTouch ? "touchend" : "mouseup",
- stateBefore = null,
- scrollTriggered = false,
- touchToggleEnabled = true;
-
- function showEventCallback( event ) {
- // An event that affects the dimensions of the visual viewport has
- // been triggered. If the header and/or footer for the current page are in overlay
- // mode, we want to hide them, and then fire off a timer to show them at a later
- // point. Events like a resize can be triggered continuously during a scroll, on
- // some platforms, so the timer is used to delay the actual positioning until the
- // flood of events have subsided.
- //
- // If we are in autoHideMode, we don't do anything because we know the scroll
- // callbacks for the plugin will fire off a show when the scrolling has stopped.
- if ( !autoHideMode && currentstate === "overlay" ) {
- if ( !delayTimer ) {
- $.mobile.fixedToolbars.hide( true );
- }
-
- $.mobile.fixedToolbars.startShowTimer();
- }
- }
-
- $(function() {
- var $document = $( document ),
- $window = $( window );
-
- $document
- .bind( "vmousedown", function( event ) {
- if ( touchToggleEnabled ) {
- stateBefore = currentstate;
- }
- })
- .bind( "vclick", function( event ) {
- if ( touchToggleEnabled ) {
-
- if ( $(event.target).closest( ignoreTargets ).length ) {
- return;
- }
-
- if ( !scrollTriggered ) {
- $.mobile.fixedToolbars.toggle( stateBefore );
- stateBefore = null;
- }
- }
- })
- .bind( "silentscroll", showEventCallback );
-
-
- // The below checks first for a $(document).scrollTop() value, and if zero, binds scroll events to $(window) instead.
- // If the scrollTop value is actually zero, both will return zero anyway.
- //
- // Works with $(document), not $(window) : Opera Mobile (WinMO phone; kinda broken anyway)
- // Works with $(window), not $(document) : IE 7/8
- // Works with either $(window) or $(document) : Chrome, FF 3.6/4, Android 1.6/2.1, iOS
- // Needs work either way : BB5, Opera Mobile (iOS)
-
- ( ( $document.scrollTop() === 0 ) ? $window : $document )
- .bind( "scrollstart", function( event ) {
-
- scrollTriggered = true;
-
- if ( stateBefore === null ) {
- stateBefore = currentstate;
- }
-
- // We only enter autoHideMode if the headers/footers are in
- // an overlay state or the show timer was started. If the
- // show timer is set, clear it so the headers/footers don't
- // show up until after we're done scrolling.
- var isOverlayState = stateBefore == "overlay";
-
- autoHideMode = isOverlayState || !!delayTimer;
-
- if ( autoHideMode ) {
- $.mobile.fixedToolbars.clearShowTimer();
-
- if ( isOverlayState ) {
- $.mobile.fixedToolbars.hide( true );
- }
- }
- })
- .bind( "scrollstop", function( event ) {
-
- if ( $( event.target ).closest( ignoreTargets ).length ) {
- return;
- }
-
- scrollTriggered = false;
-
- if ( autoHideMode ) {
- $.mobile.fixedToolbars.startShowTimer();
- autoHideMode = false;
- }
- stateBefore = null;
- });
-
- $window.bind( "resize", showEventCallback );
- });
-
- // 1. Before page is shown, check for duplicate footer
- // 2. After page is shown, append footer to new page
- $( ".ui-page" )
- .live( "pagebeforeshow", function( event, ui ) {
-
- var page = $( event.target ),
- footer = page.find( ":jqmData(role='footer')" ),
- id = footer.data( "id" ),
- prevPage = ui.prevPage,
- prevFooter = prevPage && prevPage.find( ":jqmData(role='footer')" ),
- prevFooterMatches = prevFooter.length && prevFooter.jqmData( "id" ) === id;
-
- if ( id && prevFooterMatches ) {
- stickyFooter = footer;
- setTop( stickyFooter.removeClass( "fade in out" ).appendTo( $.mobile.pageContainer ) );
- }
- })
- .live( "pageshow", function( event, ui ) {
-
- var $this = $( this );
-
- if ( stickyFooter && stickyFooter.length ) {
-
- setTimeout(function() {
- setTop( stickyFooter.appendTo( $this ).addClass( "fade" ) );
- stickyFooter = null;
- }, 500);
- }
-
- $.mobile.fixedToolbars.show( true, this );
- });
-
- // When a collapsiable is hidden or shown we need to trigger the fixed toolbar to reposition itself (#1635)
- $( ".ui-collapsible-contain" ).live( "collapse expand", showEventCallback );
-
- // element.getBoundingClientRect() is broken in iOS 3.2.1 on the iPad. The
- // coordinates inside of the rect it returns don't have the page scroll position
- // factored out of it like the other platforms do. To get around this,
- // we'll just calculate the top offset the old fashioned way until core has
- // a chance to figure out how to handle this situation.
- //
- // TODO: We'll need to get rid of getOffsetTop() once a fix gets folded into core.
-
- function getOffsetTop( ele ) {
- var top = 0,
- op, body;
-
- if ( ele ) {
- body = document.body;
- op = ele.offsetParent;
- top = ele.offsetTop;
-
- while ( ele && ele != body ) {
- top += ele.scrollTop || 0;
-
- if ( ele == op ) {
- top += op.offsetTop;
- op = ele.offsetParent;
- }
-
- ele = ele.parentNode;
- }
- }
- return top;
- }
-
- function setTop( el ) {
- var fromTop = $(window).scrollTop(),
- thisTop = getOffsetTop( el[ 0 ] ), // el.offset().top returns the wrong value on iPad iOS 3.2.1, call our workaround instead.
- thisCSStop = el.css( "top" ) == "auto" ? 0 : parseFloat(el.css( "top" )),
- screenHeight = window.innerHeight,
- thisHeight = el.outerHeight(),
- useRelative = el.parents( ".ui-page:not(.ui-page-fullscreen)" ).length,
- relval;
-
- if ( el.is( ".ui-header-fixed" ) ) {
-
- relval = fromTop - thisTop + thisCSStop;
-
- if ( relval < thisTop ) {
- relval = 0;
- }
-
- return el.css( "top", useRelative ? relval : fromTop );
- } else {
- // relval = -1 * (thisTop - (fromTop + screenHeight) + thisCSStop + thisHeight);
- // if ( relval > thisTop ) { relval = 0; }
- relval = fromTop + screenHeight - thisHeight - (thisTop - thisCSStop );
-
- return el.css( "top", useRelative ? relval : fromTop + screenHeight - thisHeight );
- }
- }
-
- // Exposed methods
- return {
-
- show: function( immediately, page ) {
-
- $.mobile.fixedToolbars.clearShowTimer();
-
- currentstate = "overlay";
-
- var $ap = page ? $( page ) :
- ( $.mobile.activePage ? $.mobile.activePage :
- $( ".ui-page-active" ) );
-
- return $ap.children( toolbarSelector ).each(function() {
-
- var el = $( this ),
- fromTop = $( window ).scrollTop(),
- // el.offset().top returns the wrong value on iPad iOS 3.2.1, call our workaround instead.
- thisTop = getOffsetTop( el[ 0 ] ),
- screenHeight = window.innerHeight,
- thisHeight = el.outerHeight(),
- alreadyVisible = ( el.is( ".ui-header-fixed" ) && fromTop <= thisTop + thisHeight ) ||
- ( el.is( ".ui-footer-fixed" ) && thisTop <= fromTop + screenHeight );
-
- // Add state class
- el.addClass( "ui-fixed-overlay" ).removeClass( "ui-fixed-inline" );
-
- if ( !alreadyVisible && !immediately ) {
- el.animationComplete(function() {
- el.removeClass( "in" );
- }).addClass( "in" );
- }
- setTop(el);
- });
- },
-
- hide: function( immediately ) {
-
- currentstate = "inline";
-
- var $ap = $.mobile.activePage ? $.mobile.activePage :
- $( ".ui-page-active" );
-
- return $ap.children( toolbarSelector ).each(function() {
-
- var el = $(this),
- thisCSStop = el.css( "top" ),
- classes;
-
- thisCSStop = thisCSStop == "auto" ? 0 :
- parseFloat(thisCSStop);
-
- // Add state class
- el.addClass( "ui-fixed-inline" ).removeClass( "ui-fixed-overlay" );
-
- if ( thisCSStop < 0 || ( el.is( ".ui-header-fixed" ) && thisCSStop !== 0 ) ) {
-
- if ( immediately ) {
- el.css( "top", 0);
- } else {
-
- if ( el.css( "top" ) !== "auto" && parseFloat( el.css( "top" ) ) !== 0 ) {
-
- classes = "out reverse";
-
- el.animationComplete(function() {
- el.removeClass( classes ).css( "top", 0 );
- }).addClass( classes );
- }
- }
- }
- });
- },
-
- startShowTimer: function() {
-
- $.mobile.fixedToolbars.clearShowTimer();
-
- var args = [].slice.call( arguments );
-
- delayTimer = setTimeout(function() {
- delayTimer = undefined;
- $.mobile.fixedToolbars.show.apply( null, args );
- }, showDelay);
- },
-
- clearShowTimer: function() {
- if ( delayTimer ) {
- clearTimeout( delayTimer );
- }
- delayTimer = undefined;
- },
-
- toggle: function( from ) {
- if ( from ) {
- currentstate = from;
- }
- return ( currentstate === "overlay" ) ? $.mobile.fixedToolbars.hide() :
- $.mobile.fixedToolbars.show();
- },
-
- setTouchToggleEnabled: function( enabled ) {
- touchToggleEnabled = enabled;
- }
- };
-})();
-
-// TODO - Deprecated namepace on $. Remove in a later release
-$.fixedToolbars = $.mobile.fixedToolbars;
-
-//auto self-init widgets
-$( document ).bind( "pagecreate create", function( event ) {
-
- if ( $( ":jqmData(position='fixed')", event.target ).length ) {
-
- $( event.target ).each(function() {
-
- if ( !$.support.scrollTop ) {
- return this;
- }
-
- var $this = $( this );
-
- if ( $this.jqmData( "fullscreen" ) ) {
- $this.addClass( "ui-page-fullscreen" );
- }
-
- // Should be slidedown
- $this.find( slideDownSelector ).addClass( slideDownClass );
-
- // Should be slideup
- $this.find( slideUpSelector ).addClass( slideUpClass );
-
- })
-
- }
-});
-
-})( jQuery );
-/*
-* jQuery Mobile Framework : resolution and CSS media query related helpers and behavior
-* Copyright (c) jQuery Project
-* Dual licensed under the MIT or GPL Version 2 licenses.
-* http://jquery.org/license
-*/
-(function( $, undefined ) {
-
-var $window = $( window ),
- $html = $( "html" ),
-
- //media-query-like width breakpoints, which are translated to classes on the html element
- resolutionBreakpoints = [ 320, 480, 768, 1024 ];
-
-/*
- private function for adding/removing breakpoint classes to HTML element for faux media-query support
- It does not require media query support, instead using JS to detect screen width > cross-browser support
- This function is called on orientationchange, resize, and mobileinit, and is bound via the 'htmlclass' event namespace
-*/
-function detectResolutionBreakpoints() {
- var currWidth = $window.width(),
- minPrefix = "min-width-",
- maxPrefix = "max-width-",
- minBreakpoints = [],
- maxBreakpoints = [],
- unit = "px",
- breakpointClasses;
-
- $html.removeClass( minPrefix + resolutionBreakpoints.join(unit + " " + minPrefix) + unit + " " +
- maxPrefix + resolutionBreakpoints.join( unit + " " + maxPrefix) + unit );
-
- $.each( resolutionBreakpoints, function( i, breakPoint ) {
- if( currWidth >= breakPoint ) {
- minBreakpoints.push( minPrefix + breakPoint + unit );
- }
- if( currWidth <= breakPoint ) {
- maxBreakpoints.push( maxPrefix + breakPoint + unit );
- }
- });
-
- if ( minBreakpoints.length ) {
- breakpointClasses = minBreakpoints.join(" ");
- }
- if ( maxBreakpoints.length ) {
- breakpointClasses += " " + maxBreakpoints.join(" ");
- }
-
- $html.addClass( breakpointClasses );
-};
-
-/* $.mobile.addResolutionBreakpoints method:
- pass either a number or an array of numbers and they'll be added to the min/max breakpoint classes
- Examples:
- $.mobile.addResolutionBreakpoints( 500 );
- $.mobile.addResolutionBreakpoints( [500, 1200] );
-*/
-$.mobile.addResolutionBreakpoints = function( newbps ) {
- if( $.type( newbps ) === "array" ){
- resolutionBreakpoints = resolutionBreakpoints.concat( newbps );
- } else {
- resolutionBreakpoints.push( newbps );
- }
-
- resolutionBreakpoints.sort(function( a, b ) {
- return a - b;
- });
-
- detectResolutionBreakpoints();
-};
-
-/* on mobileinit, add classes to HTML element
- and set handlers to update those on orientationchange and resize
-*/
-$( document ).bind( "mobileinit.htmlclass", function() {
- // bind to orientationchange and resize
- // to add classes to HTML element for min/max breakpoints and orientation
-
- var ev = $.support.orientation;
-
- $window.bind( "orientationchange.htmlclass throttledResize.htmlclass", function( event ) {
-
- // add orientation class to HTML element on flip/resize.
- if ( event.orientation ) {
- $html.removeClass( "portrait landscape" ).addClass( event.orientation );
- }
-
- // add classes to HTML element for min/max breakpoints
- detectResolutionBreakpoints();
- });
-});
-
-/* Manually trigger an orientationchange event when the dom ready event fires.
- This will ensure that any viewport meta tag that may have been injected
- has taken effect already, allowing us to properly calculate the width of the
- document.
-*/
-$(function() {
- //trigger event manually
- $window.trigger( "orientationchange.htmlclass" );
-});
-
-})(jQuery);/*!
- * jQuery Mobile v@VERSION
- * http://jquerymobile.com/
- *
- * Copyright 2010, jQuery Project
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- */
-
-(function( $, window, undefined ) {
- var $html = $( "html" ),
- $head = $( "head" ),
- $window = $( window );
-
- //trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
- $( window.document ).trigger( "mobileinit" );
-
- //support conditions
- //if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
- //otherwise, proceed with the enhancements
- if ( !$.mobile.gradeA() ) {
- return;
- }
-
- // override ajaxEnabled on platforms that have known conflicts with hash history updates
- // or generally work better browsing in regular http for full page refreshes (BB5, Opera Mini)
- if( $.mobile.ajaxBlacklist ){
- $.mobile.ajaxEnabled = false;
- }
-
- //add mobile, initial load "rendering" classes to docEl
- $html.addClass( "ui-mobile ui-mobile-rendering" );
-
- //loading div which appears during Ajax requests
- //will not appear if $.mobile.loadingMessage is false
- var $loader = $( "<div class='ui-loader ui-body-a ui-corner-all'><span class='ui-icon ui-icon-loading spin'></span><h1></h1></div>" );
-
- $.extend($.mobile, {
- // turn on/off page loading message.
- showPageLoadingMsg: function() {
- if( $.mobile.loadingMessage ){
- var activeBtn = $( "." + $.mobile.activeBtnClass ).first();
-
- $loader
- .find( "h1" )
- .text( $.mobile.loadingMessage )
- .end()
- .appendTo( $.mobile.pageContainer )
- //position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top
- .css( {
- top: $.support.scrollTop && $(window).scrollTop() + $(window).height() / 2 ||
- activeBtn.length && activeBtn.offset().top || 100
- } );
- }
-
- $html.addClass( "ui-loading" );
- },
-
- hidePageLoadingMsg: function() {
- $html.removeClass( "ui-loading" );
- },
-
- // XXX: deprecate for 1.0
- pageLoading: function ( done ) {
- if ( done ) {
- $.mobile.hidePageLoadingMsg();
- } else {
- $.mobile.showPageLoadingMsg();
- }
- },
-
- // find and enhance the pages in the dom and transition to the first page.
- initializePage: function(){
- //find present pages
- var $pages = $( ":jqmData(role='page')" );
-
- //if no pages are found, create one with body's inner html
- if( !$pages.length ){
- $pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role='page'></div>" ).children( 0 );
- }
-
- //add dialogs, set data-url attrs
- $pages.add( ":jqmData(role='dialog')" ).each(function(){
- var $this = $(this);
-
- // unless the data url is already set set it to the id
- if( !$this.jqmData('url') ){
- $this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) );
- }
- });
-
- //define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
- $.mobile.firstPage = $pages.first();
-
- //define page container
- $.mobile.pageContainer = $pages.first().parent().addClass( "ui-mobile-viewport" );
-
- //cue page loading message
- $.mobile.showPageLoadingMsg();
-
- // if hashchange listening is disabled or there's no hash deeplink, change to the first page in the DOM
- if( !$.mobile.hashListeningEnabled || !$.mobile.path.stripHash( location.hash ) ){
- $.mobile.changePage( $.mobile.firstPage, { transition: "none", reverse: true, changeHash: false, fromHashChange: true } );
- }
- // otherwise, trigger a hashchange to load a deeplink
- else {
- $window.trigger( "hashchange", [ true ] );
- }
- }
- });
-
- //initialize events now, after mobileinit has occurred
- $.mobile._registerInternalEvents();
-
- //check which scrollTop value should be used by scrolling to 1 immediately at domready
- //then check what the scroll top is. Android will report 0... others 1
- //note that this initial scroll won't hide the address bar. It's just for the check.
- $(function(){
- window.scrollTo( 0, 1 );
-
- //if defaultHomeScroll hasn't been set yet, see if scrollTop is 1
- //it should be 1 in most browsers, but android treats 1 as 0 (for hiding addr bar)
- //so if it's 1, use 0 from now on
- $.mobile.defaultHomeScroll = ( !$.support.scrollTop || $(window).scrollTop() === 1 ) ? 0 : 1;
-
- //dom-ready inits
- if( $.mobile.autoInitializePage ){
- $( $.mobile.initializePage );
- }
-
- //window load event
- //hide iOS browser chrome on load
- $window.load( $.mobile.silentScroll );
- });
-})( jQuery, this );
-
--- /dev/null
+++ b/js/jquery.mobile-1.0b3.js
@@ -1,1 +1,6658 @@
-
+/*!
+ * jQuery Mobile v1.0b3
+ * 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: function() {},
+ _init: function() {},
+
+ destroy: function() {
+ this.element
+ .unbind( "." + this.widgetName )
+ .removeData( this.widgetName );
+ this.widget()
+ .unbind( "." + this.widgetName )
+ .removeAttr( "aria-disabled" )
+ .removeClass(
+ this.widgetBaseClass + "-disabled " +
+ "ui-state-disabled" );
+ },
+
+ widget: function() {
+ return this.element;
+ },
+
+ option: function( key, value ) {
+ var options = key;
+
+ if ( arguments.length === 0 ) {
+ // don't return a reference to the internal hash
+ return $.extend( {}, this.options );
+ }
+
+ if (typeof key === "string" ) {
+ if ( value === undefined ) {
+ return this.options[ key ];
+ }
+ options = {};
+ options[ key ] = value;
+ }
+
+ this._setOptions( options );
+
+ return this;
+ },
+ _setOptions: function( options ) {
+ var self = this;
+ $.each( options, function( key, value ) {
+ self._setOption( key, value );
+ });
+
+ return this;
+ },
+ _setOption: function( key, value ) {
+ this.options[ key ] = value;
+
+ if ( key === "disabled" ) {
+ this.widget()
+ [ value ? "addClass" : "removeClass"](
+ this.widgetBaseClass + "-disabled" + " " +
+ "ui-state-disabled" )
+ .attr( "aria-disabled", value );
+ }
+
+ return this;
+ },
+
+ enable: function() {
+ return this._setOption( "disabled", false );
+ },
+ disable: function() {
+ return this._setOption( "disabled", true );
+ },
+
+ _trigger: function( type, event, data ) {
+ var callback = this.options[ type ];
+
+ event = $.Event( event );
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+ data = data || {};
+
+ // copy original event properties over to the new event
+ // this would happen if we could call $.event.fix instead of $.Event
+ // but we don't have a way to force an event to be fixed multiple times
+ if ( event.originalEvent ) {
+ for ( var i = $.event.props.length, prop; i; ) {
+ prop = $.event.props[ --i ];
+ event[ prop ] = event.originalEvent[ prop ];
+ }
+ }
+
+ this.element.trigger( event, data );
+
+ return !( $.isFunction(callback) &&
+ callback.call( this.element[0], event, data ) === false ||
+ event.isDefaultPrevented() );
+ }
+};
+
+})( jQuery );
+/*
+* jQuery Mobile Framework : widget factory extentions for mobile
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+
+(function( $, undefined ) {
+
+$.widget( "mobile.widget", {
+ _getCreateOptions: function() {
+
+ var elem = this.element,
+ options = {};
+
+ $.each( this.options, function( option ) {
+
+ var value = elem.jqmData( option.replace( /[A-Z]/g, function( c ) {
+ return "-" + c.toLowerCase();
+ })
+ );
+
+ if ( value !== undefined ) {
+ options[ option ] = value;
+ }
+ });
+
+ return options;
+ }
+});
+
+})( jQuery );
+/*
+* jQuery Mobile Framework : resolution and CSS media query related helpers and behavior
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+(function( $, undefined ) {
+
+var $window = $( window ),
+ $html = $( "html" );
+
+/* $.mobile.media method: pass a CSS media type or query and get a bool return
+ note: this feature relies on actual media query support for media queries, though types will work most anywhere
+ examples:
+ $.mobile.media('screen') //>> tests for screen media type
+ $.mobile.media('screen and (min-width: 480px)') //>> tests for screen media type with window width > 480px
+ $.mobile.media('@media screen and (-webkit-min-device-pixel-ratio: 2)') //>> tests for webkit 2x pixel ratio (iPhone 4)
+*/
+$.mobile.media = (function() {
+ // TODO: use window.matchMedia once at least one UA implements it
+ var cache = {},
+ testDiv = $( "<div id='jquery-mediatest'>" ),
+ fakeBody = $( "<body>" ).append( testDiv );
+
+ return function( query ) {
+ if ( !( query in cache ) ) {
+ var styleBlock = document.createElement( "style" ),
+ cssrule = "@media " + query + " { #jquery-mediatest { position:absolute; } }";
+
+ //must set type for IE!
+ styleBlock.type = "text/css";
+
+ if ( styleBlock.styleSheet ){
+ styleBlock.styleSheet.cssText = cssrule;
+ } else {
+ styleBlock.appendChild( document.createTextNode(cssrule) );
+ }
+
+ $html.prepend( fakeBody ).prepend( styleBlock );
+ cache[ query ] = testDiv.css( "position" ) === "absolute";
+ fakeBody.add( styleBlock ).remove();
+ }
+ return cache[ query ];
+ };
+})();
+
+})(jQuery);/*
+* jQuery Mobile Framework : support tests
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
+*/
+
+(function( $, undefined ) {
+
+var fakeBody = $( "<body>" ).prependTo( "html" ),
+ fbCSS = fakeBody[ 0 ].style,
+ vendors = [ "Webkit", "Moz", "O" ],
+ webos = "palmGetResource" in window, //only used to rule out scrollTop
+ bb = window.blackberry; //only used to rule out box shadow, as it's filled opaque on BB
+
+// thx Modernizr
+function propExists( prop ) {
+ var uc_prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ),
+ props = ( prop + " " + vendors.join( uc_prop + " " ) + uc_prop ).split( " " );
+
+ for ( var v in props ){
+ if ( fbCSS[ props[ v ] ] !== undefined ) {
+ return true;
+ }
+ }
+}
+
+// Test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting )
+function baseTagTest() {
+ var fauxBase = location.protocol + "//" + location.host + location.pathname + "ui-dir/",
+ base = $( "head base" ),
+ fauxEle = null,
+ href = "",
+ link, rebase;
+
+ if ( !base.length ) {
+ base = fauxEle = $( "<base>", { "href": fauxBase }).appendTo( "head" );
+ } else {
+ href = base.attr( "href" );
+ }
+
+ link = $( "<a href='testurl'></a>" ).prependTo( fakeBody );
+ rebase = link[ 0 ].href;
+ base[ 0 ].href = href ? href : location.pathname;
+
+ if ( fauxEle ) {
+ fauxEle.remove();
+ }
+ return rebase.indexOf( fauxBase ) === 0;
+}
+
+
+// non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683
+// allows for inclusion of IE 6+, including Windows Mobile 7
+$.mobile.browser = {};
+$.mobile.browser.ie = (function() {
+ var v = 3,
+ div = document.createElement( "div" ),
+ a = div.all || [];
+
+ while ( div.innerHTML = "<!--[if gt IE " + ( ++v ) + "]><br><![endif]-->", a[ 0 ] );
+
+ return v > 4 ? v : !v;
+})();
+
+
+$.extend( $.support, {
+ orientation: "orientation" in window,
+ touch: "ontouchend" in document,
+ cssTransitions: "WebKitTransitionEvent" in window,
+ pushState: "pushState" in history && "replaceState" in history,
+ mediaquery: $.mobile.media( "only all" ),
+ cssPseudoElement: !!propExists( "content" ),
+ touchOverflow: !!propExists( "overflowScrolling" ),
+ boxShadow: !!propExists( "boxShadow" ) && !bb,
+ scrollTop: ( "pageXOffset" in window || "scrollTop" in document.documentElement || "scrollTop" in fakeBody[ 0 ] ) && !webos,
+ dynamicBaseTag: baseTagTest(),
+ // TODO: This is a weak test. We may want to beef this up later.
+ eventCapture: "addEventListener" in document
+});
+
+fakeBody.remove();
+
+
+// $.mobile.ajaxBlacklist is used to override ajaxEnabled on platforms that have known conflicts with hash history updates (BB5, Symbian)
+// or that generally work better browsing in regular http for full page refreshes (Opera Mini)
+// Note: This detection below is used as a last resort.
+// We recommend only using these detection methods when all other more reliable/forward-looking approaches are not possible
+var nokiaLTE7_3 = (function(){
+
+ var ua = window.navigator.userAgent;
+
+ //The following is an attempt to match Nokia browsers that are running Symbian/s60, with webkit, version 7.3 or older
+ return ua.indexOf( "Nokia" ) > -1 &&
+ ( ua.indexOf( "Symbian/3" ) > -1 || ua.indexOf( "Series60/5" ) > -1 ) &&
+ ua.indexOf( "AppleWebKit" ) > -1 &&
+ ua.match( /(BrowserNG|NokiaBrowser)\/7\.[0-3]/ );
+})();
+
+$.mobile.ajaxBlacklist =
+ // BlackBerry browsers, pre-webkit
+ window.blackberry && !window.WebKitPoint ||
+ // Opera Mini
+ window.operamini && Object.prototype.toString.call( window.operamini ) === "[object OperaMini]" ||
+ // Symbian webkits pre 7.3
+ nokiaLTE7_3;
+
+// Lastly, this workaround is the only way we've found so far to get pre 7.3 Symbian webkit devices
+// to render the stylesheets when they're referenced before this script, as we'd recommend doing.
+// This simply reappends the CSS in place, which for some reason makes it apply
+if ( nokiaLTE7_3 ) {
+ $(function() {
+ $( "head link[rel=stylesheet]" ).attr( "rel", "alternate stylesheet" ).attr( "rel", "stylesheet" );
+ });
+}
+
+// For ruling out shadows via css
+if ( !$.support.boxShadow ) {
+ $( "html" ).addClass( "ui-mobile-nosupport-boxshadow" );
+}
+
+})( jQuery );/*
+* jQuery Mobile Framework : "mouse" plugin
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+
+// This plugin is an experiment for abstracting away the touch and mouse
+// events so that developers don't have to worry about which method of input
+// the device their document is loaded on supports.
+//
+// The idea here is to allow the developer to register listeners for the
+// basic mouse events, such as mousedown, mousemove, mouseup, and click,
+// and the plugin will take care of registering the correct listeners
+// behind the scenes to invoke the listener at the fastest possible time
+// for that device, while still retaining the order of event firing in
+// the traditional mouse environment, should multiple handlers be registered
+// on the same element for different events.
+//
+// The current version exposes the following virtual events to jQuery bind methods:
+// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel"
+
+(function( $, window, document, undefined ) {
+
+var dataPropertyName = "virtualMouseBindings",
+ touchTargetPropertyName = "virtualTouchID",
+ virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ),
+ touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ),
+ activeDocHandlers = {},
+ resetTimerID = 0,
+ startX = 0,
+ startY = 0,
+ didScroll = false,
+ clickBlockList = [],
+ blockMouseTriggers = false,
+ blockTouchTriggers = false,
+ eventCaptureSupported = $.support.eventCapture,
+ $document = $( document ),
+ nextTouchID = 1,
+ lastTouchID = 0;
+
+$.vmouse = {
+ moveDistanceThreshold: 10,
+ clickDistanceThreshold: 10,
+ resetTimerDuration: 1500
+};
+
+function getNativeEvent( event ) {
+
+ while ( event && typeof event.originalEvent !== "undefined" ) {
+ event = event.originalEvent;
+ }
+ return event;
+}
+
+function createVirtualEvent( event, eventType ) {
+
+ var t = event.type,
+ oe, props, ne, prop, ct, touch, i, j;
+
+ event = $.Event(event);
+ event.type = eventType;
+
+ oe = event.originalEvent;
+ props = $.event.props;
+
+ // copy original event properties over to the new event
+ // this would happen if we could call $.event.fix instead of $.Event
+ // but we don't have a way to force an event to be fixed multiple times
+ if ( oe ) {
+ for ( i = props.length, prop; i; ) {
+ prop = props[ --i ];
+ event[ prop ] = oe[ prop ];
+ }
+ }
+
+ if ( t.search(/^touch/) !== -1 ) {
+ ne = getNativeEvent( oe );
+ t = ne.touches;
+ ct = ne.changedTouches;
+ touch = ( t && t.length ) ? t[0] : ( (ct && ct.length) ? ct[ 0 ] : undefined );
+
+ if ( touch ) {
+ for ( j = 0, len = touchEventProps.length; j < len; j++){
+ prop = touchEventProps[ j ];
+ event[ prop ] = touch[ prop ];
+ }
+ }
+ }
+
+ return event;
+}
+
+function getVirtualBindingFlags( element ) {
+
+ var flags = {},
+ b, k;
+
+ while ( element ) {
+
+ b = $.data( element, dataPropertyName );
+
+ for ( k in b ) {
+ if ( b[ k ] ) {
+ flags[ k ] = flags.hasVirtualBinding = true;
+ }
+ }
+ element = element.parentNode;
+ }
+ return flags;
+}
+
+function getClosestElementWithVirtualBinding( element, eventType ) {
+ var b;
+ while ( element ) {
+
+ b = $.data( element, dataPropertyName );
+
+ if ( b && ( !eventType || b[ eventType ] ) ) {
+ return element;
+ }
+ element = element.parentNode;
+ }
+ return null;
+}
+
+function enableTouchBindings() {
+ blockTouchTriggers = false;
+}
+
+function disableTouchBindings() {
+ blockTouchTriggers = true;
+}
+
+function enableMouseBindings() {
+ lastTouchID = 0;
+ clickBlockList.length = 0;
+ blockMouseTriggers = false;
+
+ // When mouse bindings are enabled, our
+ // touch bindings are disabled.
+ disableTouchBindings();
+}
+
+function disableMouseBindings() {
+ // When mouse bindings are disabled, our
+ // touch bindings are enabled.
+ enableTouchBindings();
+}
+
+function startResetTimer() {
+ clearResetTimer();
+ resetTimerID = setTimeout(function(){
+ resetTimerID = 0;
+ enableMouseBindings();
+ }, $.vmouse.resetTimerDuration );
+}
+
+function clearResetTimer() {
+ if ( resetTimerID ){
+ clearTimeout( resetTimerID );
+ resetTimerID = 0;
+ }
+}
+
+function triggerVirtualEvent( eventType, event, flags ) {
+ var ve;
+
+ if ( ( flags && flags[ eventType ] ) ||
+ ( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {
+
+ ve = createVirtualEvent( event, eventType );
+
+ $( event.target).trigger( ve );
+ }
+
+ return ve;
+}
+
+function mouseEventCallback( event ) {
+ var touchID = $.data(event.target, touchTargetPropertyName);
+
+ if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ){
+ var ve = triggerVirtualEvent( "v" + event.type, event );
+ if ( ve ) {
+ if ( ve.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ if ( ve.isPropagationStopped() ) {
+ event.stopPropagation();
+ }
+ if ( ve.isImmediatePropagationStopped() ) {
+ event.stopImmediatePropagation();
+ }
+ }
+ }
+}
+
+function handleTouchStart( event ) {
+
+ var touches = getNativeEvent( event ).touches,
+ target, flags;
+
+ if ( touches && touches.length === 1 ) {
+
+ target = event.target;
+ flags = getVirtualBindingFlags( target );
+
+ if ( flags.hasVirtualBinding ) {
+
+ lastTouchID = nextTouchID++;
+ $.data( target, touchTargetPropertyName, lastTouchID );
+
+ clearResetTimer();
+
+ disableMouseBindings();
+ didScroll = false;
+
+ var t = getNativeEvent( event ).touches[ 0 ];
+ startX = t.pageX;
+ startY = t.pageY;
+
+ triggerVirtualEvent( "vmouseover", event, flags );
+ triggerVirtualEvent( "vmousedown", event, flags );
+ }
+ }
+}
+
+function handleScroll( event ) {
+ if ( blockTouchTriggers ) {
+ return;
+ }
+
+ if ( !didScroll ) {
+ triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) );
+ }
+
+ didScroll = true;
+ startResetTimer();
+}
+
+function handleTouchMove( event ) {
+ if ( blockTouchTriggers ) {
+ return;
+ }
+
+ var t = getNativeEvent( event ).touches[ 0 ],
+ didCancel = didScroll,
+ moveThreshold = $.vmouse.moveDistanceThreshold;
+ didScroll = didScroll ||
+ ( Math.abs(t.pageX - startX) > moveThreshold ||
+ Math.abs(t.pageY - startY) > moveThreshold ),
+ flags = getVirtualBindingFlags( event.target );
+
+ if ( didScroll && !didCancel ) {
+ triggerVirtualEvent( "vmousecancel", event, flags );
+ }
+
+ triggerVirtualEvent( "vmousemove", event, flags );
+ startResetTimer();
+}
+
+function handleTouchEnd( event ) {
+ if ( blockTouchTriggers ) {
+ return;
+ }
+
+ disableTouchBindings();
+
+ var flags = getVirtualBindingFlags( event.target ),
+ t;
+ triggerVirtualEvent( "vmouseup", event, flags );
+
+ if ( !didScroll ) {
+ var ve = triggerVirtualEvent( "vclick", event, flags );
+ if ( ve && ve.isDefaultPrevented() ) {
+ // The target of the mouse events that follow the touchend
+ // event don't necessarily match the target used during the
+ // touch. This means we need to rely on coordinates for blocking
+ // any click that is generated.
+ t = getNativeEvent( event ).changedTouches[ 0 ];
+ clickBlockList.push({
+ touchID: lastTouchID,
+ x: t.clientX,
+ y: t.clientY
+ });
+
+ // Prevent any mouse events that follow from triggering
+ // virtual event notifications.
+ blockMouseTriggers = true;
+ }
+ }
+ triggerVirtualEvent( "vmouseout", event, flags);
+ didScroll = false;
+
+ startResetTimer();
+}
+
+function hasVirtualBindings( ele ) {
+ var bindings = $.data( ele, dataPropertyName ),
+ k;
+
+ if ( bindings ) {
+ for ( k in bindings ) {
+ if ( bindings[ k ] ) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+function dummyMouseHandler(){}
+
+function getSpecialEventObject( eventType ) {
+ var realType = eventType.substr( 1 );
+
+ return {
+ setup: function( data, namespace ) {
+ // If this is the first virtual mouse binding for this element,
+ // add a bindings object to its data.
+
+ if ( !hasVirtualBindings( this ) ) {
+ $.data( this, dataPropertyName, {});
+ }
+
+ // If setup is called, we know it is the first binding for this
+ // eventType, so initialize the count for the eventType to zero.
+ var bindings = $.data( this, dataPropertyName );
+ bindings[ eventType ] = true;
+
+ // If this is the first virtual mouse event for this type,
+ // register a global handler on the document.
+
+ activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;
+
+ if ( activeDocHandlers[ eventType ] === 1 ) {
+ $document.bind( realType, mouseEventCallback );
+ }
+
+ // Some browsers, like Opera Mini, won't dispatch mouse/click events
+ // for elements unless they actually have handlers registered on them.
+ // To get around this, we register dummy handlers on the elements.
+
+ $( this ).bind( realType, dummyMouseHandler );
+
+ // For now, if event capture is not supported, we rely on mouse handlers.
+ if ( eventCaptureSupported ) {
+ // If this is the first virtual mouse binding for the document,
+ // register our touchstart handler on the document.
+
+ activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1;
+
+ if (activeDocHandlers[ "touchstart" ] === 1) {
+ $document.bind( "touchstart", handleTouchStart )
+ .bind( "touchend", handleTouchEnd )
+
+ // On touch platforms, touching the screen and then dragging your finger
+ // causes the window content to scroll after some distance threshold is
+ // exceeded. On these platforms, a scroll prevents a click event from being
+ // dispatched, and on some platforms, even the touchend is suppressed. To
+ // mimic the suppression of the click event, we need to watch for a scroll
+ // event. Unfortunately, some platforms like iOS don't dispatch scroll
+ // events until *AFTER* the user lifts their finger (touchend). This means
+ // we need to watch both scroll and touchmove events to figure out whether
+ // or not a scroll happenens before the touchend event is fired.
+
+ .bind( "touchmove", handleTouchMove )
+ .bind( "scroll", handleScroll );
+ }
+ }
+ },
+
+ teardown: function( data, namespace ) {
+ // If this is the last virtual binding for this eventType,
+ // remove its global handler from the document.
+
+ --activeDocHandlers[ eventType ];
+
+ if ( !activeDocHandlers[ eventType ] ) {
+ $document.unbind( realType, mouseEventCallback );
+ }
+
+ if ( eventCaptureSupported ) {
+ // If this is the last virtual mouse binding in existence,
+ // remove our document touchstart listener.
+
+ --activeDocHandlers[ "touchstart" ];
+
+ if ( !activeDocHandlers[ "touchstart" ] ) {
+ $document.unbind( "touchstart", handleTouchStart )
+ .unbind( "touchmove", handleTouchMove )
+ .unbind( "touchend", handleTouchEnd )
+ .unbind( "scroll", handleScroll );
+ }
+ }
+
+ var $this = $( this ),
+ bindings = $.data( this, dataPropertyName );
+
+ // teardown may be called when an element was
+ // removed from the DOM. If this is the case,
+ // jQuery core may have already stripped the element
+ // of any data bindings so we need to check it before
+ // using it.
+ if ( bindings ) {
+ bindings[ eventType ] = false;
+ }
+
+ // Unregister the dummy event handler.
+
+ $this.unbind( realType, dummyMouseHandler );
+
+ // If this is the last virtual mouse binding on the
+ // element, remove the binding data from the element.
+
+ if ( !hasVirtualBindings( this ) ) {
+ $this.removeData( dataPropertyName );
+ }
+ }
+ };
+}
+
+// Expose our custom events to the jQuery bind/unbind mechanism.
+
+for ( var i = 0; i < virtualEventNames.length; i++ ){
+ $.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );
+}
+
+// Add a capture click handler to block clicks.
+// Note that we require event capture support for this so if the device
+// doesn't support it, we punt for now and rely solely on mouse events.
+if ( eventCaptureSupported ) {
+ document.addEventListener( "click", function( e ){
+ var cnt = clickBlockList.length,
+ target = e.target,
+ x, y, ele, i, o, touchID;
+
+ if ( cnt ) {
+ x = e.clientX;
+ y = e.clientY;
+ threshold = $.vmouse.clickDistanceThreshold;
+
+ // The idea here is to run through the clickBlockList to see if
+ // the current click event is in the proximity of one of our
+ // vclick events that had preventDefault() called on it. If we find
+ // one, then we block the click.
+ //
+ // Why do we have to rely on proximity?
+ //
+ // Because the target of the touch event that triggered the vclick
+ // can be different from the target of the click event synthesized
+ // by the browser. The target of a mouse/click event that is syntehsized
+ // from a touch event seems to be implementation specific. For example,
+ // some browsers will fire mouse/click events for a link that is near
+ // a touch event, even though the target of the touchstart/touchend event
+ // says the user touched outside the link. Also, it seems that with most
+ // browsers, the target of the mouse/click event is not calculated until the
+ // time it is dispatched, so if you replace an element that you touched
+ // with another element, the target of the mouse/click will be the new
+ // element underneath that point.
+ //
+ // Aside from proximity, we also check to see if the target and any
+ // of its ancestors were the ones that blocked a click. This is necessary
+ // because of the strange mouse/click target calculation done in the
+ // Android 2.1 browser, where if you click on an element, and there is a
+ // mouse/click handler on one of its ancestors, the target will be the
+ // innermost child of the touched element, even if that child is no where
+ // near the point of touch.
+
+ ele = target;
+
+ while ( ele ) {
+ for ( i = 0; i < cnt; i++ ) {
+ o = clickBlockList[ i ];
+ touchID = 0;
+
+ if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||
+ $.data( ele, touchTargetPropertyName ) === o.touchID ) {
+ // XXX: We may want to consider removing matches from the block list
+ // instead of waiting for the reset timer to fire.
+ e.preventDefault();
+ e.stopPropagation();
+ return;
+ }
+ }
+ ele = ele.parentNode;
+ }
+ }
+ }, true);
+}
+})( jQuery, window, document );
+/*
+* jQuery Mobile Framework : events
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+(function( $, window, undefined ) {
+
+// add new event shortcuts
+$.each( ( "touchstart touchmove touchend orientationchange throttledresize " +
+ "tap taphold swipe swipeleft swiperight scrollstart scrollstop" ).split( " " ), function( i, name ) {
+
+ $.fn[ name ] = function( fn ) {
+ return fn ? this.bind( name, fn ) : this.trigger( name );
+ };
+
+ $.attrFn[ name ] = true;
+});
+
+var supportTouch = $.support.touch,
+ scrollEvent = "touchmove scroll",
+ touchStartEvent = supportTouch ? "touchstart" : "mousedown",
+ touchStopEvent = supportTouch ? "touchend" : "mouseup",
+ touchMoveEvent = supportTouch ? "touchmove" : "mousemove";
+
+function triggerCustomEvent( obj, eventType, event ) {
+ var originalType = event.type;
+ event.type = eventType;
+ $.event.handle.call( obj, event );
+ event.type = originalType;
+}
+
+// also handles scrollstop
+$.event.special.scrollstart = {
+
+ enabled: true,
+
+ setup: function() {
+
+ var thisObject = this,
+ $this = $( thisObject ),
+ scrolling,
+ timer;
+
+ function trigger( event, state ) {
+ scrolling = state;
+ triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event );
+ }
+
+ // iPhone triggers scroll after a small delay; use touchmove instead
+ $this.bind( scrollEvent, function( event ) {
+
+ if ( !$.event.special.scrollstart.enabled ) {
+ return;
+ }
+
+ if ( !scrolling ) {
+ trigger( event, true );
+ }
+
+ clearTimeout( timer );
+ timer = setTimeout(function() {
+ trigger( event, false );
+ }, 50 );
+ });
+ }
+};
+
+// also handles taphold
+$.event.special.tap = {
+ setup: function() {
+ var thisObject = this,
+ $this = $( thisObject );
+
+ $this.bind( "vmousedown", function( event ) {
+
+ if ( event.which && event.which !== 1 ) {
+ return false;
+ }
+
+ var origTarget = event.target,
+ origEvent = event.originalEvent,
+ timer;
+
+ function clearTapTimer() {
+ clearTimeout( timer );
+ }
+
+ function clearTapHandlers() {
+ clearTapTimer();
+
+ $this.unbind( "vclick", clickHandler )
+ .unbind( "vmouseup", clearTapTimer )
+ .unbind( "vmousecancel", clearTapHandlers );
+ }
+
+ function clickHandler(event) {
+ clearTapHandlers();
+
+ // ONLY trigger a 'tap' event if the start target is
+ // the same as the stop target.
+ if ( origTarget == event.target ) {
+ triggerCustomEvent( thisObject, "tap", event );
+ }
+ }
+
+ $this.bind( "vmousecancel", clearTapHandlers )
+ .bind( "vmouseup", clearTapTimer )
+ .bind( "vclick", clickHandler );
+
+ timer = setTimeout(function() {
+ triggerCustomEvent( thisObject, "taphold", $.Event( "taphold" ) );
+ }, 750 );
+ });
+ }
+};
+
+// also handles swipeleft, swiperight
+$.event.special.swipe = {
+ scrollSupressionThreshold: 10, // More than this horizontal displacement, and we will suppress scrolling.
+
+ durationThreshold: 1000, // More time than this, and it isn't a swipe.
+
+ horizontalDistanceThreshold: 30, // Swipe horizontal displacement must be more than this.
+
+ verticalDistanceThreshold: 75, // Swipe vertical displacement must be less than this.
+
+ setup: function() {
+ var thisObject = this,
+ $this = $( thisObject );
+
+ $this.bind( touchStartEvent, function( event ) {
+ var data = event.originalEvent.touches ?
+ event.originalEvent.touches[ 0 ] : event,
+ start = {
+ time: ( new Date() ).getTime(),
+ coords: [ data.pageX, data.pageY ],
+ origin: $( event.target )
+ },
+ stop;
+
+ function moveHandler( event ) {
+
+ if ( !start ) {
+ return;
+ }
+
+ var data = event.originalEvent.touches ?
+ event.originalEvent.touches[ 0 ] : event;
+
+ stop = {
+ time: ( new Date() ).getTime(),
+ coords: [ data.pageX, data.pageY ]
+ };
+
+ // prevent scrolling
+ if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {
+ event.preventDefault();
+ }
+ }
+
+ $this.bind( touchMoveEvent, moveHandler )
+ .one( touchStopEvent, function( event ) {
+ $this.unbind( touchMoveEvent, moveHandler );
+
+ if ( start && stop ) {
+ if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
+ Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&
+ Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {
+
+ start.origin.trigger( "swipe" )
+ .trigger( start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight" );
+ }
+ }
+ start = stop = undefined;
+ });
+ });
+ }
+};
+
+(function( $, window ) {
+ // "Cowboy" Ben Alman
+
+ var win = $( window ),
+ special_event,
+ get_orientation,
+ last_orientation;
+
+ $.event.special.orientationchange = special_event = {
+ setup: function() {
+ // If the event is supported natively, return false so that jQuery
+ // will bind to the event using DOM methods.
+ if ( $.support.orientation ) {
+ return false;
+ }
+
+ // Get the current orientation to avoid initial double-triggering.
+ last_orientation = get_orientation();
+
+ // Because the orientationchange event doesn't exist, simulate the
+ // event by testing window dimensions on resize.
+ win.bind( "throttledresize", handler );
+ },
+ teardown: function(){
+ // If the event is not supported natively, return false so that
+ // jQuery will unbind the event using DOM methods.
+ if ( $.support.orientation ) {
+ return false;
+ }
+
+ // Because the orientationchange event doesn't exist, unbind the
+ // resize event handler.
+ win.unbind( "throttledresize", handler );
+ },
+ add: function( handleObj ) {
+ // Save a reference to the bound event handler.
+ var old_handler = handleObj.handler;
+
+ handleObj.handler = function( event ) {
+ // Modify event object, adding the .orientation property.
+ event.orientation = get_orientation();
+
+ // Call the originally-bound event handler and return its result.
+ return old_handler.apply( this, arguments );
+ };
+ }
+ };
+
+ // If the event is not supported natively, this handler will be bound to
+ // the window resize event to simulate the orientationchange event.
+ function handler() {
+ // Get the current orientation.
+ var orientation = get_orientation();
+
+ if ( orientation !== last_orientation ) {
+ // The orientation has changed, so trigger the orientationchange event.
+ last_orientation = orientation;
+ win.trigger( "orientationchange" );
+ }
+ };
+
+ // Get the current page orientation. This method is exposed publicly, should it
+ // be needed, as jQuery.event.special.orientationchange.orientation()
+ $.event.special.orientationchange.orientation = get_orientation = function() {
+ var elem = document.documentElement;
+ return elem && elem.clientWidth / elem.clientHeight < 1.1 ? "portrait" : "landscape";
+ };
+
+})( jQuery, window );
+
+
+// throttled resize event
+(function() {
+
+ $.event.special.throttledresize = {
+ setup: function() {
+ $( this ).bind( "resize", handler );
+ },
+ teardown: function(){
+ $( this ).unbind( "resize", handler );
+ }
+ };
+
+ var throttle = 250,
+ handler = function() {
+ curr = ( new Date() ).getTime();
+ diff = curr - lastCall;
+
+ if ( diff >= throttle ) {
+
+ lastCall = curr;
+ $( this ).trigger( "throttledresize" );
+
+ } else {
+
+ if ( heldCall ) {
+ clearTimeout( heldCall );
+ }
+
+ // Promise a held call will still execute
+ heldCall = setTimeout( handler, throttle - diff );
+ }
+ },
+ lastCall = 0,
+ heldCall,
+ curr,
+ diff;
+})();
+
+
+$.each({
+ scrollstop: "scrollstart",
+ taphold: "tap",
+ swipeleft: "swipe",
+ swiperight: "swipe"
+}, function( event, sourceEvent ) {
+
+ $.event.special[ event ] = {
+ setup: function() {
+ $( this ).bind( sourceEvent, $.noop );
+ }
+ };
+});
+
+})( jQuery, this );
+/*!
+ * jQuery hashchange event - v1.3 - 7/21/2010
+ * http://benalman.com/projects/jquery-hashchange-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+
+// Script: jQuery hashchange event
+//
+// *Version: 1.3, Last updated: 7/21/2010*
+//
+// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/
+// GitHub - http://github.com/cowboy/jquery-hashchange/
+// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js
+// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)
+//
+// About: License
+//
+// Copyright (c) 2010 "Cowboy" Ben Alman,
+// Dual licensed under the MIT and GPL licenses.
+// http://benalman.com/about/license/
+//
+// About: Examples
+//
+// These working examples, complete with fully commented code, illustrate a few
+// ways in which this plugin can be used.
+//
+// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/
+// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/
+//
+// About: Support and Testing
+//
+// Information about what version or versions of jQuery this plugin has been
+// tested with, what browsers it has been tested in, and where the unit tests
+// reside (so you can test it yourself).
+//
+// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2
+// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,
+// Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.
+// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/
+//
+// About: Known issues
+//
+// While this jQuery hashchange event implementation is quite stable and
+// robust, there are a few unfortunate browser bugs surrounding expected
+// hashchange event-based behaviors, independent of any JavaScript
+// window.onhashchange abstraction. See the following examples for more
+// information:
+//
+// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/
+// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/
+// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/
+// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/
+//
+// Also note that should a browser natively support the window.onhashchange
+// event, but not report that it does, the fallback polling loop will be used.
+//
+// About: Release History
+//
+// 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more
+// "removable" for mobile-only development. Added IE6/7 document.title
+// support. Attempted to make Iframe as hidden as possible by using
+// techniques from http://www.paciellogroup.com/blog/?p=604. Added
+// support for the "shortcut" format $(window).hashchange( fn ) and
+// $(window).hashchange() like jQuery provides for built-in events.
+// Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and
+// lowered its default value to 50. Added <jQuery.fn.hashchange.domain>
+// and <jQuery.fn.hashchange.src> properties plus document-domain.html
+// file to address access denied issues when setting document.domain in
+// IE6/7.
+// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin
+// from a page on another domain would cause an error in Safari 4. Also,
+// IE6/7 Iframe is now inserted after the body (this actually works),
+// which prevents the page from scrolling when the event is first bound.
+// Event can also now be bound before DOM ready, but it won't be usable
+// before then in IE6/7.
+// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug
+// where browser version is incorrectly reported as 8.0, despite
+// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.
+// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special
+// window.onhashchange functionality into a separate plugin for users
+// who want just the basic event & back button support, without all the
+// extra awesomeness that BBQ provides. This plugin will be included as
+// part of jQuery BBQ, but also be available separately.
+
+(function($,window,undefined){
+ '$:nomunge'; // Used by YUI compressor.
+
+ // Reused string.
+ var str_hashchange = 'hashchange',
+
+ // Method / object references.
+ doc = document,
+ fake_onhashchange,
+ special = $.event.special,
+
+ // Does the browser support window.onhashchange? Note that IE8 running in
+ // IE7 compatibility mode reports true for 'onhashchange' in window, even
+ // though the event isn't supported, so also test document.documentMode.
+ doc_mode = doc.documentMode,
+ supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );
+
+ // Get location.hash (or what you'd expect location.hash to be) sans any
+ // leading #. Thanks for making this necessary, Firefox!
+ function get_fragment( url ) {
+ url = url || location.href;
+ return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );
+ };
+
+ // Method: jQuery.fn.hashchange
+ //
+ // Bind a handler to the window.onhashchange event or trigger all bound
+ // window.onhashchange event handlers. This behavior is consistent with
+ // jQuery's built-in event handlers.
+ //
+ // Usage:
+ //
+ // > jQuery(window).hashchange( [ handler ] );
+ //
+ // Arguments:
+ //
+ // handler - (Function) Optional handler to be bound to the hashchange
+ // event. This is a "shortcut" for the more verbose form:
+ // jQuery(window).bind( 'hashchange', handler ). If handler is omitted,
+ // all bound window.onhashchange event handlers will be triggered. This
+ // is a shortcut for the more verbose
+ // jQuery(window).trigger( 'hashchange' ). These forms are described in
+ // the <hashchange event> section.
+ //
+ // Returns:
+ //
+ // (jQuery) The initial jQuery collection of elements.
+
+ // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and
+ // $(elem).hashchange() for triggering, like jQuery does for built-in events.
+ $.fn[ str_hashchange ] = function( fn ) {
+ return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );
+ };
+
+ // Property: jQuery.fn.hashchange.delay
+ //
+ // The numeric interval (in milliseconds) at which the <hashchange event>
+ // polling loop executes. Defaults to 50.
+
+ // Property: jQuery.fn.hashchange.domain
+ //
+ // If you're setting document.domain in your JavaScript, and you want hash
+ // history to work in IE6/7, not only must this property be set, but you must
+ // also set document.domain BEFORE jQuery is loaded into the page. This
+ // property is only applicable if you are supporting IE6/7 (or IE8 operating
+ // in "IE7 compatibility" mode).
+ //
+ // In addition, the <jQuery.fn.hashchange.src> property must be set to the
+ // path of the included "document-domain.html" file, which can be renamed or
+ // modified if necessary (note that the document.domain specified must be the
+ // same in both your main JavaScript as well as in this file).
+ //
+ // Usage:
+ //
+ // jQuery.fn.hashchange.domain = document.domain;
+
+ // Property: jQuery.fn.hashchange.src
+ //
+ // If, for some reason, you need to specify an Iframe src file (for example,
+ // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can
+ // do so using this property. Note that when using this property, history
+ // won't be recorded in IE6/7 until the Iframe src file loads. This property
+ // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7
+ // compatibility" mode).
+ //
+ // Usage:
+ //
+ // jQuery.fn.hashchange.src = 'path/to/file.html';
+
+ $.fn[ str_hashchange ].delay = 50;
+ /*
+ $.fn[ str_hashchange ].domain = null;
+ $.fn[ str_hashchange ].src = null;
+ */
+
+ // Event: hashchange event
+ //
+ // Fired when location.hash changes. In browsers that support it, the native
+ // HTML5 window.onhashchange event is used, otherwise a polling loop is
+ // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to
+ // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7
+ // compatibility" mode), a hidden Iframe is created to allow the back button
+ // and hash-based history to work.
+ //
+ // Usage as described in <jQuery.fn.hashchange>:
+ //
+ // > // Bind an event handler.
+ // > jQuery(window).hashchange( function(e) {
+ // > var hash = location.hash;
+ // > ...
+ // > });
+ // >
+ // > // Manually trigger the event handler.
+ // > jQuery(window).hashchange();
+ //
+ // A more verbose usage that allows for event namespacing:
+ //
+ // > // Bind an event handler.
+ // > jQuery(window).bind( 'hashchange', function(e) {
+ // > var hash = location.hash;
+ // > ...
+ // > });
+ // >
+ // > // Manually trigger the event handler.
+ // > jQuery(window).trigger( 'hashchange' );
+ //
+ // Additional Notes:
+ //
+ // * The polling loop and Iframe are not created until at least one handler
+ // is actually bound to the 'hashchange' event.
+ // * If you need the bound handler(s) to execute immediately, in cases where
+ // a location.hash exists on page load, via bookmark or page refresh for
+ // example, use jQuery(window).hashchange() or the more verbose
+ // jQuery(window).trigger( 'hashchange' ).
+ // * The event can be bound before DOM ready, but since it won't be usable
+ // before then in IE6/7 (due to the necessary Iframe), recommended usage is
+ // to bind it inside a DOM ready handler.
+
+ // Override existing $.event.special.hashchange methods (allowing this plugin
+ // to be defined after jQuery BBQ in BBQ's source code).
+ special[ str_hashchange ] = $.extend( special[ str_hashchange ], {
+
+ // Called only when the first 'hashchange' event is bound to window.
+ setup: function() {
+ // If window.onhashchange is supported natively, there's nothing to do..
+ if ( supports_onhashchange ) { return false; }
+
+ // Otherwise, we need to create our own. And we don't want to call this
+ // until the user binds to the event, just in case they never do, since it
+ // will create a polling loop and possibly even a hidden Iframe.
+ $( fake_onhashchange.start );
+ },
+
+ // Called only when the last 'hashchange' event is unbound from window.
+ teardown: function() {
+ // If window.onhashchange is supported natively, there's nothing to do..
+ if ( supports_onhashchange ) { return false; }
+
+ // Otherwise, we need to stop ours (if possible).
+ $( fake_onhashchange.stop );
+ }
+
+ });
+
+ // fake_onhashchange does all the work of triggering the window.onhashchange
+ // event for browsers that don't natively support it, including creating a
+ // polling loop to watch for hash changes and in IE 6/7 creating a hidden
+ // Iframe to enable back and forward.
+ fake_onhashchange = (function(){
+ var self = {},
+ timeout_id,
+
+ // Remember the initial hash so it doesn't get triggered immediately.
+ last_hash = get_fragment(),
+
+ fn_retval = function(val){ return val; },
+ history_set = fn_retval,
+ history_get = fn_retval;
+
+ // Start the polling loop.
+ self.start = function() {
+ timeout_id || poll();
+ };
+
+ // Stop the polling loop.
+ self.stop = function() {
+ timeout_id && clearTimeout( timeout_id );
+ timeout_id = undefined;
+ };
+
+ // This polling loop checks every $.fn.hashchange.delay milliseconds to see
+ // if location.hash has changed, and triggers the 'hashchange' event on
+ // window when necessary.
+ function poll() {
+ var hash = get_fragment(),
+ history_hash = history_get( last_hash );
+
+ if ( hash !== last_hash ) {
+ history_set( last_hash = hash, history_hash );
+
+ $(window).trigger( str_hashchange );
+
+ } else if ( history_hash !== last_hash ) {
+ location.href = location.href.replace( /#.*/, '' ) + history_hash;
+ }
+
+ timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );
+ };
+
+ // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+ // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv
+ // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+ $.browser.msie && !supports_onhashchange && (function(){
+ // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8
+ // when running in "IE7 compatibility" mode.
+
+ var iframe,
+ iframe_src;
+
+ // When the event is bound and polling starts in IE 6/7, create a hidden
+ // Iframe for history handling.
+ self.start = function(){
+ if ( !iframe ) {
+ iframe_src = $.fn[ str_hashchange ].src;
+ iframe_src = iframe_src && iframe_src + get_fragment();
+
+ // Create hidden Iframe. Attempt to make Iframe as hidden as possible
+ // by using techniques from http://www.paciellogroup.com/blog/?p=604.
+ iframe = $('<iframe tabindex="-1" title="empty"/>').hide()
+
+ // When Iframe has completely loaded, initialize the history and
+ // start polling.
+ .one( 'load', function(){
+ iframe_src || history_set( get_fragment() );
+ poll();
+ })
+
+ // Load Iframe src if specified, otherwise nothing.
+ .attr( 'src', iframe_src || 'javascript:0' )
+
+ // Append Iframe after the end of the body to prevent unnecessary
+ // initial page scrolling (yes, this works).
+ .insertAfter( 'body' )[0].contentWindow;
+
+ // Whenever `document.title` changes, update the Iframe's title to
+ // prettify the back/next history menu entries. Since IE sometimes
+ // errors with "Unspecified error" the very first time this is set
+ // (yes, very useful) wrap this with a try/catch block.
+ doc.onpropertychange = function(){
+ try {
+ if ( event.propertyName === 'title' ) {
+ iframe.document.title = doc.title;
+ }
+ } catch(e) {}
+ };
+
+ }
+ };
+
+ // Override the "stop" method since an IE6/7 Iframe was created. Even
+ // if there are no longer any bound event handlers, the polling loop
+ // is still necessary for back/next to work at all!
+ self.stop = fn_retval;
+
+ // Get history by looking at the hidden Iframe's location.hash.
+ history_get = function() {
+ return get_fragment( iframe.location.href );
+ };
+
+ // Set a new history item by opening and then closing the Iframe
+ // document, *then* setting its location.hash. If document.domain has
+ // been set, update that as well.
+ history_set = function( hash, history_hash ) {
+ var iframe_doc = iframe.document,
+ domain = $.fn[ str_hashchange ].domain;
+
+ if ( hash !== history_hash ) {
+ // Update Iframe with any initial `document.title` that might be set.
+ iframe_doc.title = doc.title;
+
+ // Opening the Iframe's document after it has been closed is what
+ // actually adds a history entry.
+ iframe_doc.open();
+
+ // Set document.domain for the Iframe document as well, if necessary.
+ domain && iframe_doc.write( '<script>document.domain="' + domain + '"</script>' );
+
+ iframe_doc.close();
+
+ // Update the Iframe's hash, for great justice.
+ iframe.location.hash = hash;
+ }
+ };
+
+ })();
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ return self;
+ })();
+
+})(jQuery,this);
+/*
+* jQuery Mobile Framework : "page" plugin
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+
+(function( $, undefined ) {
+
+$.widget( "mobile.page", $.mobile.widget, {
+ options: {
+ theme: "c",
+ domCache: false
+ },
+
+ _create: function() {
+
+ this._trigger( "beforecreate" );
+
+ this.element
+ .attr( "tabindex", "0" )
+ .addClass( "ui-page ui-body-" + this.options.theme );
+ }
+});
+
+})( jQuery );
+/*!
+ * jQuery Mobile v@VERSION
+ * http://jquerymobile.com/
+ *
+ * Copyright 2010, jQuery Project
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ */
+
+(function( $, window, undefined ) {
+
+ // jQuery.mobile configurable options
+ $.extend( $.mobile, {
+
+ // Namespace used framework-wide for data-attrs. Default is no namespace
+ ns: "",
+
+ // Define the url parameter used for referencing widget-generated sub-pages.
+ // Translates to to example.html&ui-page=subpageIdentifier
+ // hash segment before &ui-page= is used to make Ajax request
+ subPageUrlKey: "ui-page",
+
+ // Class assigned to page currently in view, and during transitions
+ activePageClass: "ui-page-active",
+
+ // Class used for "active" button state, from CSS framework
+ activeBtnClass: "ui-btn-active",
+
+ // Automatically handle clicks and form submissions through Ajax, when same-domain
+ ajaxEnabled: true,
+
+ // Automatically load and show pages based on location.hash
+ hashListeningEnabled: true,
+
+ // Set default page transition - 'none' for no transitions
+ defaultPageTransition: "slide",
+
+ // Minimum scroll distance that will be remembered when returning to a page
+ minScrollBack: 250,
+
+ // Set default dialog transition - 'none' for no transitions
+ defaultDialogTransition: "pop",
+
+ // Show loading message during Ajax requests
+ // if false, message will not appear, but loading classes will still be toggled on html el
+ loadingMessage: "loading",
+
+ // Error response message - appears when an Ajax page request fails
+ pageLoadErrorMessage: "Error Loading Page",
+
+ //automatically initialize the DOM when it's ready
+ autoInitializePage: true,
+
+ pushStateEnabled: true,
+
+ // Support conditions that must be met in order to proceed
+ // default enhanced qualifications are media query support OR IE 7+
+ gradeA: function(){
+ return $.support.mediaquery || $.mobile.browser.ie && $.mobile.browser.ie >= 7;
+ },
+
+ // TODO might be useful upstream in jquery itself ?
+ keyCode: {
+ ALT: 18,
+ BACKSPACE: 8,
+ CAPS_LOCK: 20,
+ COMMA: 188,
+ COMMAND: 91,
+ COMMAND_LEFT: 91, // COMMAND
+ COMMAND_RIGHT: 93,
+ CONTROL: 17,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ INSERT: 45,
+ LEFT: 37,
+ MENU: 93, // COMMAND_RIGHT
+ NUMPAD_ADD: 107,
+ NUMPAD_DECIMAL: 110,
+ NUMPAD_DIVIDE: 111,
+ NUMPAD_ENTER: 108,
+ NUMPAD_MULTIPLY: 106,
+ NUMPAD_SUBTRACT: 109,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SHIFT: 16,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38,
+ WINDOWS: 91 // COMMAND
+ },
+
+ // Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value
+ silentScroll: function( ypos ) {
+ if ( $.type( ypos ) !== "number" ) {
+ ypos = $.mobile.defaultHomeScroll;
+ }
+
+ // prevent scrollstart and scrollstop events
+ $.event.special.scrollstart.enabled = false;
+
+ setTimeout(function() {
+ window.scrollTo( 0, ypos );
+ $( document ).trigger( "silentscroll", { x: 0, y: ypos });
+ }, 20 );
+
+ setTimeout(function() {
+ $.event.special.scrollstart.enabled = true;
+ }, 150 );
+ },
+
+ // Take a data attribute property, prepend the namespace
+ // and then camel case the attribute string
+ nsNormalize: function( prop ) {
+ if ( !prop ) {
+ return;
+ }
+
+ return $.camelCase( $.mobile.ns + prop );
+ }
+ });
+
+ // Mobile version of data and removeData and hasData methods
+ // ensures all data is set and retrieved using jQuery Mobile's data namespace
+ $.fn.jqmData = function( prop, value ) {
+ return this.data( prop ? $.mobile.nsNormalize( prop ) : prop, value );
+ };
+
+ $.jqmData = function( elem, prop, value ) {
+ return $.data( elem, $.mobile.nsNormalize( prop ), value );
+ };
+
+ $.fn.jqmRemoveData = function( prop ) {
+ return this.removeData( $.mobile.nsNormalize( prop ) );
+ };
+
+ $.jqmRemoveData = function( elem, prop ) {
+ return $.removeData( elem, $.mobile.nsNormalize( prop ) );
+ };
+
+ $.jqmHasData = function( elem, prop ) {
+ return $.hasData( elem, $.mobile.nsNormalize( prop ) );
+ };
+
+ // Monkey-patching Sizzle to filter the :jqmData selector
+ var oldFind = $.find;
+
+ $.find = function( selector, context, ret, extra ) {
+ selector = selector.replace(/:jqmData\(([^)]*)\)/g, "[data-" + ( $.mobile.ns || "" ) + "$1]");
+
+ return oldFind.call( this, selector, context, ret, extra );
+ };
+
+ $.extend( $.find, oldFind );
+
+ $.find.matches = function( expr, set ) {
+ return $.find( expr, null, null, set );
+ };
+
+ $.find.matchesSelector = function( node, expr ) {
+ return $.find( expr, null, null, [ node ] ).length > 0;
+ };
+})( jQuery, this );
+
+/*
+* jQuery Mobile Framework : core utilities for auto ajax navigation, base tag mgmt,
+* Copyright (c) jQuery Project
+* Dual licensed under the MIT or GPL Version 2 licenses.
+* http://jquery.org/license
+*/
+( function( $, undefined ) {
+
+ //define vars for interal use
+ var $window = $( window ),
+ $html = $( 'html' ),
+ $head = $( 'head' ),
+
+ //url path helpers for use in relative url management
+ path = {
+
+ // This scary looking regular expression parses an absolute URL or its relative
+ // variants (protocol, site, document, query, and hash), into the various
+ // components (protocol, host, path, query, fragment, etc that make up the
+ // URL as well as some other commonly used sub-parts. When used with RegExp.exec()
+ // or String.match, it parses the URL into a results array that looks like this:
+ //
+ // [0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content
+ // [1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread
+ // [2]: http://jblas:password@mycompany.com:8080/mail/inbox
+ // [3]: http://jblas:password@mycompany.com:8080
+ // [4]: http:
+ // [5]: jblas:password@mycompany.com:8080
+ // [6]: jblas:password
+ // [7]: jblas
+ // [8]: password
+ // [9]: mycompany.com:8080
+ // [10]: mycompany.com
+ // [11]: 8080
+ // [12]: /mail/inbox
+ // [13]: /mail/
+ // [14]: inbox
+ // [15]: ?msg=1234&type=unread
+ // [16]: #msg-content
+ //
+ urlParseRE: /^(((([^:\/#\?]+:)?(?:\/\/((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
+
+ //Parse a URL into a structure that allows easy access to
+ //all of the URL components by name.
+ parseUrl: function( url ) {
+ // If we're passed an object, we'll assume that it is
+ // a parsed url object and just return it back to the caller.
+ if ( $.type( url ) === "object" ) {
+ return url;
+ }
+
+ var u = url || "",
+ matches = path.urlParseRE.exec( url ),
+ results;
+ if ( matches ) {
+ // Create an object that allows the caller to access the sub-matches
+ // by name. Note that IE returns an empty string instead of undefined,
+ // like all other browsers do, so we normalize everything so its consistent
+ // no matter what browser we're running on.
+ results = {
+ href: matches[0] || "",
+ hrefNoHash: matches[1] || "",
+ hrefNoSearch: matches[2] || "",
+ domain: matches[3] || "",
+ protocol: matches[4] || "",
+ authority: matches[5] || "",
+ username: matches[7] || "",
+ password: matches[8] || "",
+ host: matches[9] || "",
+ hostname: matches[10] || "",
+ port: matches[11] || "",
+ pathname: matches[12] || "",
+ directory: matches[13] || "",
+ filename: matches[14] || "",
+ search: matches[15] || "",
+ hash: matches[16] || ""
+ };
+ }
+ return results || {};
+ },
+
+ //Turn relPath into an asbolute path. absPath is
+ //an optional absolute path which describes what
+ //relPath is relative to.
+ makePathAbsolute: function( relPath, absPath ) {
+ if ( relPath && relPath.charAt( 0 ) === "/" ) {
+ return relPath;
+ }
+
+ relPath = relPath || "";
+ absPath = absPath ? absPath.replace( /^\/|(\/[^\/]*|[^\/]+)$/g, "" ) : "";
+
+ var absStack = absPath ? absPath.split( "/" ) : [],
+ relStack = relPath.split( "/" );
+ for ( var i = 0; i < relStack.length; i++ ) {
+ var d = relStack[ i ];
+ switch ( d ) {
+ case ".":
+ break;
+ case "..":
+ if ( absStack.length ) {
+ absStack.pop();
+ }
+ break;
+ default:
+ absStack.push( d );
+ break;
+ }
+ }
+ return "/" + absStack.join( "/" );
+ },
+
+ //Returns true if both urls have the same domain.
+ isSameDomain: function( absUrl1, absUrl2 ) {
+ return path.parseUrl( absUrl1 ).domain === path.parseUrl( absUrl2 ).domain;
+ },
+
+ //Returns true for any relative variant.
+ isRelativeUrl: function( url ) {
+ // All relative Url variants have one thing in common, no protocol.
+ return path.parseUrl( url ).protocol === "";
+ },
+
+ //Returns true for an absolute url.
+ isAbsoluteUrl: function( url ) {
+ return path.parseUrl( url ).protocol !== "";
+ },
+
+ //Turn the specified realtive URL into an absolute one. This function
+ //can handle all relative variants (protocol, site, document, query, fragment).
+ makeUrlAbsolute: function( relUrl, absUrl ) {
+ if ( !path.isRelativeUrl( relUrl ) ) {
+ return relUrl;
+ }
+
+ var relObj = path.parseUrl( relUrl ),
+ absObj = path.parseUrl( absUrl ),
+ protocol = relObj.protocol || absObj.protocol,
+ authority = relObj.authority || absObj.authority,
+ hasPath = relObj.pathname !== "",
+ pathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ),
+ search = relObj.search || ( !hasPath && absObj.search ) || "",
+ hash = relObj.hash;
+
+ return protocol + "//" + authority + pathname + search + hash;
+ },
+
+ //Add search (aka query) params to the specified url.
+ addSearchParams: function( url, params ) {
+ var u = path.parseUrl( url ),
+ p = ( typeof params === "object" ) ? $.param( params ) : params,
+ s = u.search || "?";
+ return u.hrefNoSearch + s + ( s.charAt( s.length - 1 ) !== "?" ? "&" : "" ) + p + ( u.hash || "" );
+ },
+
+ convertUrlToDataUrl: function( absUrl ) {
+ var u = path.parseUrl( absUrl );
+ if ( path.isEmbeddedPage( u ) ) {
+ // For embedded pages, remove the dialog hash key as in getFilePath(),
+ // otherwise the Data Url won't match the id of the embedded Page.
+ return u.hash.split( dialogHashKey )[0].replace( /^#/, "" );
+ } else if ( path.isSameDomain( u, documentBase ) ) {
+ return u.hrefNoHash.replace( documentBase.domain, "" );
+ }
+ return absUrl;
+ },
+
+ //get path from current hash, or from a file path
+ get: function( newPath ) {
+ if( newPath === undefined ) {
+ newPath = location.hash;
+ }
+ return path.stripHash( newPath ).replace( /[^\/]*\.[^\/*]+$/, '' );
+ },
+
+ //return the substring of a filepath before the sub-page key, for making a server request
+ getFilePath: function( path ) {
+ var splitkey = '&' + $.mobile.subPageUrlKey;
+ return path && path.split( splitkey )[0].split( dialogHashKey )[0];
+ },
+
+ //set location hash to path
+ set: function( path ) {
+ location.hash = path;
+ },
+
+ //test if a given url (string) is a path
+ //NOTE might be exceptionally naive
+ isPath: function( url ) {
+ return ( /\// ).test( url );
+ },
+
+ //return a url path with the window's location protocol/hostname/pathname removed
+ clean: function( url ) {
+ return url.replace( documentBase.domain, "" );
+ },
+
+ //just return the url without an initial #
+ stripHash: function( url ) {
+ return url.replace( /^#/, "" );
+ },
+
+ //remove the preceding hash, any query params, and dialog notations
+ cleanHash: function( hash ) {
+ return path.stripHash( hash.replace( /\?.*$/, "" ).replace( dialogHashKey, "" ) );
+ },
+
+ //check whether a url is referencing the same domain, or an external domain or different protocol
+ //could be mailto, etc
+ isExternal: function( url ) {
+ var u = path.parseUrl( url );
+ return u.protocol && u.domain !== documentUrl.domain ? true : false;
+ },
+
+ hasProtocol: function( url ) {
+ return ( /^(:?\w+:)/ ).test( url );
+ },
+
+ //check if the specified url refers to the first page in the main application document.
+ isFirstPageUrl: function( url ) {
+ // We only deal with absolute paths.
+ var u = path.parseUrl( path.makeUrlAbsolute( url, documentBase ) ),
+
+ // Does the url have the same path as the document?
+ samePath = u.hrefNoHash === documentUrl.hrefNoHash || ( documentBaseDiffers && u.hrefNoHash === documentBase.hrefNoHash ),
+
+ // Get the first page element.
+ fp = $.mobile.firstPage,
+
+ // Get the id of the first page element if it has one.
+ fpId = fp && fp[0] ? fp[0].id : undefined;
+
+ // The url refers to the first page if the path matches the document and
+ // it either has no hash value, or the hash is exactly equal to the id of the
+ // first page element.
+ return samePath && ( !u.hash || u.hash === "#" || ( fpId && u.hash.replace( /^#/, "" ) === fpId ) );
+ },
+
+ isEmbeddedPage: function( url ) {
+ var u = path.parseUrl( url );
+
+ //if the path is absolute, then we need to compare the url against
+ //both the documentUrl and the documentBase. The main reason for this
+ //is that links embedded within external documents will refer to the
+ //application document, whereas links embedded within the application
+ //document will be resolved against the document base.
+ if ( u.protocol !== "" ) {
+ return ( u.hash && ( u.hrefNoHash === documentUrl.hrefNoHash || ( documentBaseDiffers && u.hrefNoHash === documentBase.hrefNoHash ) ) );
+ }
+ return (/^#/).test( u.href );
+ }
+ },
+
+ //will be defined when a link is clicked and given an active class
+ $activeClickedLink = null,
+
+ //urlHistory is purely here to make guesses at whether the back or forward button was clicked
+ //and provide an appropriate transition
+ urlHistory = {
+ // Array of pages that are visited during a single page load.
+ // Each has a url and optional transition, title, and pageUrl (which represents the file path, in cases where URL is obscured, such as dialogs)
+ stack: [],
+
+ //maintain an index number for the active page in the stack
+ activeIndex: 0,
+
+ //get active
+ getActive: function() {
+ return urlHistory.stack[ urlHistory.activeIndex ];
+ },
+
+ getPrev: function() {
+ return urlHistory.stack[ urlHistory.activeIndex - 1 ];
+ },
+
+ getNext: function() {
+ return urlHistory.stack[ urlHistory.activeIndex + 1 ];
+ },
+
+ // addNew is used whenever a new page is added
+ addNew: function( url, transition, title, pageUrl, role ) {
+ //if there's forward history, wipe it
+ if( urlHistory.getNext() ) {
+ urlHistory.clearForward();
+ }
+
+ urlHistory.stack.push( {url : url, transition: transition, title: title, pageUrl: pageUrl, role: role } );
+
+ urlHistory.activeIndex = urlHistory.stack.length - 1;
+ },
+
+ //wipe urls ahead of active index
+ clearForward: function() {
+ urlHistory.stack = urlHistory.stack.slice( 0, urlHistory.activeIndex + 1 );
+ },
+
+ directHashChange: function( opts ) {
+ var back , forward, newActiveIndex, prev = this.getActive();
+
+ // check if url isp in history and if it's ahead or behind current page
+ $.each( urlHistory.stack, function( i, historyEntry ) {
+
+ //if the url is in the stack, it's a forward or a back
+ if( opts.currentUrl === historyEntry.url ) {
+ //define back and forward by whether url is older or newer than current page
+ back = i < urlHistory.activeIndex;
+ forward = !back;
+ newActiveIndex = i;
+ }
+ });
+
+ // save new page index, null check to prevent falsey 0 result
+ this.activeIndex = newActiveIndex !== undefined ? newActiveIndex : this.activeIndex;
+
+ if( back ) {
+ ( opts.either || opts.isBack )( true );
+ } else if( forward ) {
+ ( opts.either || opts.isForward )( false );
+ }
+ },
+
+ //disable hashchange event listener internally to ignore one change
+ //toggled internally when location.hash is updated to match the url of a successful page load
+ ignoreNextHashChange: false
+ },
+
+ //define first selector to receive focus when a page is shown
+ focusable = "[tabindex],a,button:visible,select:visible,input",
+
+ //queue to hold simultanious page transitions
+ pageTransitionQueue = [],
+
+ //indicates whether or not page is in process of transitioning
+ isPageTransitioning = false,
+
+ //nonsense hash change key for dialogs, so they create a history entry
+ dialogHashKey = "&ui-state=dialog",
+
+ //existing base tag?
+ $base = $head.children( "base" ),
+
+ //tuck away the original document URL minus any fragment.
+ documentUrl = path.parseUrl( location.href ),
+
+ //if the document has an embedded base tag, documentBase is set to its
+ //initial value. If a base tag does not exist, then we default to the documentUrl.
+ documentBase = $base.length ? path.parseUrl( path.makeUrlAbsolute( $base.attr( "href" ), documentUrl.href ) ) : documentUrl,
+
+ //cache the comparison once.
+ documentBaseDiffers = ( documentUrl.hrefNoHash !== documentBase.hrefNoHash );
+
+ //base element management, defined depending on dynamic base tag support
+ var base = $.support.dynamicBaseTag ? {
+
+ //define base element, for use in routing asset urls that are referenced in Ajax-requested markup
+ element: ( $base.length ? $base : $( "<base>", { href: documentBase.hrefNoHash } ).prependTo( $head ) ),
+
+ //set the generated BASE element's href attribute to a new page's base path
+ set: function( href ) {
+ base.element.attr( "href", path.makeUrlAbsolute( href, documentBase ) );
+ },
+
+ //set the generated BASE element's href attribute to a new page's base path
+ reset: function() {
+ base.element.attr( "href", documentBase.hrefNoHash );
+ }
+
+ } : undefined;
+
+/*
+ internal utility functions
+--------------------------------------*/
+
+
+ //direct focus to the page title, or otherwise first focusable element
+ function reFocus( page ) {
+ var pageTitle = page.find( ".ui-title:eq(0)" );
+
+ if( pageTitle.length ) {
+ pageTitle.focus();
+ }
+ else{
+ page.focus();
+ }
+ }
+
+ //remove active classes after page transition or error
+ function removeActiveLinkClass( forceRemoval ) {
+ if( !!$activeClickedLink && ( !$activeClickedLink.closest( '.ui-page-active' ).length || forceRemoval ) ) {
+ $activeClickedLink.removeClass( $.mobile.activeBtnClass );
+ }
+ $activeClickedLink = null;
+ }
+
+ function releasePageTransitionLock() {
+ isPageTransitioning = false;
+ if( pageTransitionQueue.length > 0 ) {
+ $.mobile.changePage.apply( null, pageTransitionQueue.pop() );
+ }
+ }
+
+ // Save the last scroll distance per page, before it is hidden
+ var getLastScroll = (function( lastScrollEnabled ){
+ return function(){
+ if( !lastScrollEnabled ){
+ lastScrollEnabled = true;
+ return;
+ }
+
+ lastScrollEnabled = false;
+
+ var active = $.mobile.urlHistory.getActive(),
+ activePage = $( ".ui-page-active" ),
+ scrollElem = $( window ),
+ touchOverflow = $.support.touchOverflow && $.mobile.touchOverflowEnabled;
+
+ if( touchOverflow ){
+ scrollElem = activePage.is( ".ui-native-fixed" ) ? activePage.find( ".ui-content" ) : activePage;
+ }
+
+ if( active ){
+ var lastScroll = scrollElem.scrollTop();
+
+ // Set active page's lastScroll prop.
+ // If the Y location we're scrolling to is less than minScrollBack, let it go.
+ active.lastScroll = lastScroll < $.mobile.minScrollBack ? $.mobile.defaultHomeScroll : lastScroll;
+ }
+ };
+ })( true );
+
+ // to get last scroll, we need to get scrolltop before the page change
+ // using beforechangepage or popstate/hashchange (whichever comes first)
+ $( document ).bind( "beforechangepage", getLastScroll );
+ $( window ).bind( $.support.pushState ? "popstate" : "hashchange", getLastScroll );
+
+ // Make the iOS clock quick-scroll work again if we're using native overflow scrolling
+ /*
+ if( $.support.touchOverflow ){
+ if( $.mobile.touchOverflowEnabled ){
+ $( window ).bind( "scrollstop", function(){
+ if( $( this ).scrollTop() === 0 ){
+ $.mobile.activePage.scrollTop( 0 );
+ }
+ });
+ }
+ }
+ */
+
+ //function for transitioning between two existing pages
+ function transitionPages( toPage, fromPage, transition, reverse ) {
+
+ //get current scroll distance
+ var active = $.mobile.urlHistory.getActive(),
+ touchOverflow = $.support.touchOverflow && $.mobile.touchOverflowEnabled,
+ toScroll = active.lastScroll || ( touchOverflow ? 0 : $.mobile.defaultHomeScroll ),
+ screenHeight = getScreenHeight();
+
+ // Scroll to top, hide addr bar
+ window.scrollTo( 0, $.mobile.defaultHomeScroll );
+
+ if( fromPage ) {
+ //trigger before show/hide events
+ fromPage.data( "page" )._trigger( "beforehide", null, { nextPage: toPage } );
+ }
+
+ if( !touchOverflow){
+ toPage.height( screenHeight + toScroll );
+ }
+
+ toPage.data( "page" )._trigger( "beforeshow", null, { prevPage: fromPage || $( "" ) } );
+
+ //clear page loader
+ $.mobile.hidePageLoadingMsg();
+
+ if( touchOverflow && toScroll ){
+
+ toPage.addClass( "ui-mobile-pre-transition" );
+ // Send focus to page as it is now display: block
+ reFocus( toPage );
+
+ //set page's scrollTop to remembered distance
+ if( toPage.is( ".ui-native-fixed" ) ){
+ toPage.find( ".ui-content" ).scrollTop( toScroll );
+ }
+ else{
+ toPage.scrollTop( toScroll );
+ }
+ }
+
+ //find the transition handler for the specified transition. If there
+ //isn't one in our transitionHandlers dictionary, use the default one.
+ //call the handler immediately to kick-off the transition.
+ var th = $.mobile.transitionHandlers[transition || "none"] || $.mobile.defaultTransitionHandler,
+ promise = th( transition, reverse, toPage, fromPage );
+
+ promise.done(function() {
+ //reset toPage height back
+ if( !touchOverflow ){
+ toPage.height( "" );
+ // Send focus to the newly shown page
+ reFocus( toPage );
+ }
+
+ // Jump to top or prev scroll, sometimes on iOS the page has not rendered yet.
+ if( !touchOverflow ){
+ $.mobile.silentScroll( toScroll );
+ }
+
+ //trigger show/hide events
+ if( fromPage ) {
+ if( !touchOverflow ){
+ fromPage.height( "" );
+ }
+
+ fromPage.data( "page" )._trigger( "hide", null, { nextPage: toPage } );
+ }
+
+ //trigger pageshow, define prevPage as either fromPage or empty jQuery obj
+ toPage.data( "page" )._trigger( "show", null, { prevPage: fromPage || $( "" ) } );
+ });
+
+ return promise;
+ }
+
+ //simply set the active page's minimum height to screen height, depending on orientation
+ function getScreenHeight(){
+ var orientation = jQuery.event.special.orientationchange.orientation(),
+ port = orientation === "portrait",
+ winMin = port ? 480 : 320,
+ screenHeight = port ? screen.availHeight : screen.availWidth,
+ winHeight = Math.max( winMin, $( window ).height() ),
+ pageMin = Math.min( screenHeight, winHeight );
+
+ return pageMin;
+ }
+
+ $.mobile.getScreenHeight = getScreenHeight;
+
+ //simply set the active page's minimum height to screen height, depending on orientation
+ function resetActivePageHeight(){
+ $( "." + $.mobile.activePageClass ).css( "min-height", getScreenHeight() );
+ }
+
+ //shared page enhancements
+ function enhancePage( $page, role ) {
+ // If a role was specified, make sure the data-role attribute
+ // on the page element is in sync.
+ if( role ) {
+ $page.attr( "data-" + $.mobile.ns + "role", role );
+ }
+
+ //run page plugin
+ $page.page();
+ }
+
+/* exposed $.mobile methods */
+
+ //animation complete callback
+ $.fn.animationComplete = function( callback ) {
+ if( $.support.cssTransitions ) {
+ return $( this ).one( 'webkitAnimationEnd', callback );
+ }
+ else{
+ // defer execution for consistency between webkit/non webkit
+ setTimeout( callback, 0 );
+ return $( this );
+ }
+ };
+
+ //update location.hash, with or without triggering hashchange event
+ //TODO - deprecate this one at 1.0
+ $.mobile.updateHash = path.set;
+
+ //expose path object on $.mobile
+ $.mobile.path = path;
+
+ //expose base object on $.mobile
+ $.mobile.base = base;
+
+ //url stack, useful when plugins need to be aware of previous pages viewed
+ //TODO: deprecate this one at 1.0
+ $.mobile.urlstack = urlHistory.stack;
+
+ //history stack
+ $.mobile.urlHistory = urlHistory;
+
+ $.mobile.dialogHashKey = dialogHashKey;
+
+ //default non-animation transition handler
+ $.mobile.noneTransitionHandler = function( name, reverse, $toPage, $fromPage ) {
+ if ( $fromPage ) {
+ $fromPage.removeClass( $.mobile.activePageClass );
+ }
+ $toPage.addClass( $.mobile.activePageClass );
+
+ return $.Deferred().resolve( name, reverse, $toPage, $fromPage ).promise();
+ };
+
+ //default handler for unknown transitions
+ $.mobile.defaultTransitionHandler = $.mobile.noneTransitionHandler;
+
+ //transition handler dictionary for 3rd party transitions
+ $.mobile.transitionHandlers = {
+ none: $.mobile.defaultTransitionHandler
+ };
+
+ //enable cross-domain page support
+ $.mobile.allowCrossDomainPages = false;
+
+ //return the original document url
+ $.mobile.getDocumentUrl = function(asParsedObject) {
+ return asParsedObject ? $.extend( {}, documentUrl ) : documentUrl.href;
+ };
+
+ //return the original document base url
+ $.mobile.getDocumentBase = function(asParsedObject) {
+ return asParsedObject ? $.extend( {}, documentBase ) : documentBase.href;
+ };
+
+ // Load a page into the DOM.
+ $.mobile.loadPage = function( url, options ) {
+ // This function uses deferred notifications to let callers
+ // know when the page is done loading, or if an error has occurred.
+ var deferred = $.Deferred(),
+
+ // The default loadPage options with overrides specified by
+ // the caller.
+ settings = $.extend( {}, $.mobile.loadPage.defaults, options ),
+
+ // The DOM element for the page after it has been loaded.
+ page = null,
+
+ // If the reloadPage option is true, and the page is already
+ // in the DOM, dupCachedPage will be set to the page element
+ // so that it can be removed after the new version of the
+ // page is loaded off the network.
+ dupCachedPage = null,
+
+ // determine the current base url
+ findBaseWithDefault = function(){
+ var closestBase = ( $.mobile.activePage && getClosestBaseUrl( $.mobile.activePage ) );
+ return closestBase || documentBase.hrefNoHash;
+ },
+
+ // The absolute version of the URL passed into the function. This
+ // version of the URL may contain dialog/subpage params in it.
+ absUrl = path.makeUrlAbsolute( url, findBaseWithDefault() );
+
+
+ // If the caller provided data, and we're using "get" request,
+ // append the data to the URL.
+ if ( settings.data && settings.type === "get" ) {
+ absUrl = path.addSearchParams( absUrl, settings.data );
+ settings.data = undefined;
+ }
+
+ // The absolute version of the URL minus any dialog/subpage params.
+ // In otherwords the real URL of the page to be loaded.
+ var fileUrl = path.getFilePath( absUrl ),
+
+ // The version of the Url actually stored in the data-url attribute of
+ // the page. For embedded pages, it is just the id of the page. For pages
+ // within the same domain as the document base, it is the site relative
+ // path. For cross-domain pages (Phone Gap only) the entire absolute Url
+ // used to load the page.
+ dataUrl = path.convertUrlToDataUrl( absUrl );
+
+ // Make sure we have a pageContainer to work with.
+ settings.pageContainer = settings.pageContainer || $.mobile.pageContainer;
+
+ // Check to see if the page already exists in the DOM.
+ page = settings.pageContainer.children( ":jqmData(url='" + dataUrl + "')" );
+
+ // If we failed to find a page in the DOM, check the URL to see if it
+ // refers to the first page in the application.
+ if ( page.length === 0 && $.mobile.firstPage && path.isFirstPageUrl( absUrl ) ) {
+ page = $( $.mobile.firstPage );
+ }
+
+ // Reset base to the default document base.
+ if ( base ) {
+ base.reset();
+ }
+
+ // If the page we are interested in is already in the DOM,
+ // and the caller did not indicate that we should force a
+ // reload of the file, we are done. Otherwise, track the
+ // existing page as a duplicated.
+ if ( page.length ) {
+ if ( !settings.reloadPage ) {
+ enhancePage( page, settings.role );
+ deferred.resolve( absUrl, options, page );
+ return deferred.promise();
+ }
+ dupCachedPage = page;
+ }
+
+ if ( settings.showLoadMsg ) {
+
+ // This configurable timeout allows cached pages a brief delay to load without showing a message
+ var loadMsgDelay = setTimeout(function(){
+ $.mobile.showPageLoadingMsg();
+ }, settings.loadMsgDelay ),
+
+ // Shared logic for clearing timeout and removing message.
+ hideMsg = function(){
+
+ // Stop message show timer
+ clearTimeout( loadMsgDelay );
+
+ // Hide loading message
+ $.mobile.hidePageLoadingMsg();
+ };
+ }
+
+ if ( !( $.mobile.allowCrossDomainPages || path.isSameDomain( documentUrl, absUrl ) ) ) {
+ deferred.reject( absUrl, options );
+ } else {
+ // Load the new page.
+ $.ajax({
+ url: fileUrl,
+ type: settings.type,
+ data: settings.data,
+ dataType: "html",
+ success: function( html ) {
+ //pre-parse html to check for a data-url,
+ //use it as the new fileUrl, base path, etc
+ var all = $( "<div></div>" ),
+
+ //page title regexp
+ newPageTitle = html.match( /<title[^>]*>([^<]*)/ ) && RegExp.$1,
+
+ // TODO handle dialogs again
+ pageElemRegex = new RegExp( ".*(<[^>]+\\bdata-" + $.mobile.ns + "role=[\"']?page[\"']?[^>]*>).*" ),
+ dataUrlRegex = new RegExp( "\\bdata-" + $.mobile.ns + "url=[\"']?([^\"'>]*)[\"']?" );
+
+
+ // data-url must be provided for the base tag so resource requests can be directed to the
+ // correct url. loading into a temprorary element makes these requests immediately
+ if( pageElemRegex.test( html )
+ && RegExp.$1
+ && dataUrlRegex.test( RegExp.$1 )
+ && RegExp.$1 ) {
+ url = fileUrl = path.getFilePath( RegExp.$1 );
+ }