From b5f0043312973057fa104b16caff1fd7433e1cdb Mon Sep 17 00:00:00 2001 From: Sean Harvey Date: Thu, 16 Feb 2012 15:07:38 +1300 Subject: [PATCH 01/11] MINOR MobileSiteControllerExtension::onAfterInit(): headers_sent() check for a nicer error when fullSite cookie can't be set --- code/MobileSiteControllerExtension.php | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/code/MobileSiteControllerExtension.php b/code/MobileSiteControllerExtension.php index 110db26..b44699c 100644 --- a/code/MobileSiteControllerExtension.php +++ b/code/MobileSiteControllerExtension.php @@ -38,12 +38,20 @@ public function onAfterInit() { if(is_numeric($fullSite)) { Cookie::set('fullSite', (int)$fullSite); - //use the host of the desktop version of the site to set cross-(sub)domain cookie + // use the host of the desktop version of the site to set cross-(sub)domain cookie if (!empty($config->FullSiteDomain)) { - $parsedURL = parse_url($config->FullSiteDomain); - setcookie('fullSite', $fullSite, time() + self::$cookie_expire_time,null,'.'.$parsedURL['host']); - } else { //otherwise just use a normal cookie with the default domain - setcookie('fullSite', $fullSite, time() + self::$cookie_expire_time); + $parsedURL = parse_url($config->FullSiteDomain); + if(!headers_sent($file, $line)) { + setcookie('fullSite', $fullSite, time() + self::$cookie_expire_time, null, '.' . $parsedURL['host']); + } else { + user_error(sprintf('Cookie \'fullSite\' can\'t be set. Output started at line %s in %s', $line, $file)); + } + } else { // otherwise just use a normal cookie with the default domain + if(!headers_sent($file, $line)) { + setcookie('fullSite', $fullSite, time() + self::$cookie_expire_time); + } else { + user_error(sprintf('Cookie \'fullSite\' can\'t be set. Output started at line %s in %s', $line, $file)); + } } } From 8ade83c3baf2c9b88c31cdd5db6ada656645a965 Mon Sep 17 00:00:00 2001 From: Sean Harvey Date: Wed, 27 Jun 2012 14:56:04 +1200 Subject: [PATCH 02/11] NEW Adding detection for Windows Phone OS to MobileBrowserDetector --- code/MobileBrowserDetector.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/code/MobileBrowserDetector.php b/code/MobileBrowserDetector.php index f0c94df..59cbba9 100644 --- a/code/MobileBrowserDetector.php +++ b/code/MobileBrowserDetector.php @@ -39,6 +39,10 @@ public static function is_windows() { return (preg_match('/(windows ce; ppc;|windows ce; smartphone;|windows ce; iemobile)/i', $_SERVER['HTTP_USER_AGENT'])) ? true : false; } + public static function is_win_phone() { + return (stripos($_SERVER['HTTP_USER_AGENT'], 'Windows Phone OS') !== false) ? true : false; + } + /** * Is the current HTTP_USER_AGENT a known mobile device string? * @see http://mobiforge.com/developing/story/setting-http-headers-advise-transcoding-proxies @@ -66,6 +70,9 @@ public static function is_mobile() { case(self::is_palm()): $isMobile = true; break; + case(self::is_win_phone()): + $isMobile = true; + break; case(self::is_windows()): $isMobile = true; break; @@ -90,4 +97,4 @@ public static function is_mobile() { return $isMobile; } -} \ No newline at end of file +} From 27ccc0c4ac0d8334abafba63936a41e50ad45b68 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 13 Aug 2012 16:01:06 +0200 Subject: [PATCH 03/11] API Allow declaring multiple domains The MobileDomain and FullSiteDomain database columns now accept a comma-separated list of values. This enables developers to serve mobile content under multiple domains, which is for example useful when used along the "subsites" module. It is still recommended to have one canonical URL endpoint for a unique content collection, though. Conflicts: code/MobileSiteConfigExtension.php --- code/MobileSiteConfigExtension.php | 53 ++++++++------------- code/MobileSiteControllerExtension.php | 36 +++++++------- tests/MobileSiteConfigExtensionTest.php | 4 +- tests/MobileSiteControllerExtensionTest.php | 28 ++++++++--- 4 files changed, 59 insertions(+), 62 deletions(-) diff --git a/code/MobileSiteConfigExtension.php b/code/MobileSiteConfigExtension.php index 86df929..a34d213 100644 --- a/code/MobileSiteConfigExtension.php +++ b/code/MobileSiteConfigExtension.php @@ -34,8 +34,10 @@ public static function get_theme_copy_path() { public function extraStatics() { return array( 'db' => array( - 'MobileDomain' => 'Varchar(50)', - 'FullSiteDomain' => 'Varchar(50)', + // Comma-separated list of mobile domains, without protocol + 'MobileDomain' => 'Text', + // Comma-separated list of non-mobile domains, without protocol + 'FullSiteDomain' => 'Text', 'MobileTheme' => 'Varchar(255)', 'MobileSiteType' => 'Enum("Disabled,RedirectToDomain,MobileThemeOnly","Disabled")', ), @@ -47,43 +49,28 @@ public function extraStatics() { ) ); } + /** - * Check whether the protocol was specified for the mobile domain, - * and if it wasn't, then assume http. e.g. "mysite.com" => "http://mysite.com" - * - * @return string + * @return String The first available domain, with the current protocol prefixed, + * suitable for redirections etc. */ - public function getMobileDomain() { - $defaults = $this->owner->stat('defaults'); - - $value = $this->owner->getField('MobileDomain'); - if(!$value) $value = $defaults['MobileDomain']; - - if(strpos($value, '://') === false) { - return 'http://' . $value; - } else { - return $value; - } + public function getMobileDomainNormalized() { + $domains = explode(',', $this->owner->MobileDomain); + $domain = array_shift($domains); + if(!parse_url($domain, PHP_URL_SCHEME)) $domain = Director::protocol() . $domain; + return $domain; } /** - * Check whether the protocol was specified for the full site domain, - * and if it wasn't, then assume http. e.g. "mysite.com" => "http://mysite.com" - * - * @return string + * @return String The first available domain, with the current protocol prefixed, + * suitable for redirections etc. */ - public function getFullSiteDomain() { - $defaults = $this->owner->stat('defaults'); - - $value = $this->owner->getField('FullSiteDomain'); - if(!$value) $value = $defaults['FullSiteDomain']; - - if(strpos($value, '://') === false) { - return 'http://' . $value; - } else { - return $value; - } + public function getFullSiteDomainNormalized() { + $domains = explode(',', $this->owner->FullSiteDomain); + $domain = array_shift($domains); + if(!parse_url($domain, PHP_URL_SCHEME)) $domain = Director::protocol() . $domain; + return $domain; } /** @@ -193,4 +180,4 @@ function rcopy($src, $dst) { } } closedir($dir); -} \ No newline at end of file +} diff --git a/code/MobileSiteControllerExtension.php b/code/MobileSiteControllerExtension.php index b44699c..8a66599 100644 --- a/code/MobileSiteControllerExtension.php +++ b/code/MobileSiteControllerExtension.php @@ -39,19 +39,11 @@ public function onAfterInit() { Cookie::set('fullSite', (int)$fullSite); // use the host of the desktop version of the site to set cross-(sub)domain cookie - if (!empty($config->FullSiteDomain)) { - $parsedURL = parse_url($config->FullSiteDomain); - if(!headers_sent($file, $line)) { - setcookie('fullSite', $fullSite, time() + self::$cookie_expire_time, null, '.' . $parsedURL['host']); - } else { - user_error(sprintf('Cookie \'fullSite\' can\'t be set. Output started at line %s in %s', $line, $file)); - } + $domain = $config->FullSiteDomainNormalized; + if (!empty($domain)) { + Cookie::set('fullSite', $fullSite, time() + self::$cookie_expire_time, null, '.' . parse_url($domain, PHP_URL_HOST)); } else { // otherwise just use a normal cookie with the default domain - if(!headers_sent($file, $line)) { - setcookie('fullSite', $fullSite, time() + self::$cookie_expire_time); - } else { - user_error(sprintf('Cookie \'fullSite\' can\'t be set. Output started at line %s in %s', $line, $file)); - } + Cookie::set('fullSite', $fullSite, time() + self::$cookie_expire_time); } } @@ -61,7 +53,7 @@ public function onAfterInit() { // Full site requested if($fullSiteCookie) { if($this->onMobileDomain() && $config->MobileSiteType == 'RedirectToDomain') { - return $this->owner->redirect($config->FullSiteDomain, 301); + return $this->owner->redirect($config->FullSiteDomainNormalized, 301); } return; @@ -69,7 +61,7 @@ public function onAfterInit() { // Mobile site requested else { if(!$this->onMobileDomain() && $config->MobileSiteType == 'RedirectToDomain') { - return $this->owner->redirect($config->MobileDomain, 301); + return $this->owner->redirect($config->MobileDomainNormalized, 301); } SSViewer::set_theme($config->MobileTheme); @@ -92,7 +84,7 @@ public function onAfterInit() { // If on a mobile device, but not on the mobile domain and has been setup for redirection if(!$this->onMobileDomain() && MobileBrowserDetector::is_mobile() && $config->MobileSiteType == 'RedirectToDomain') { - return $this->owner->redirect($config->MobileDomain, 301); + return $this->owner->redirect($config->MobileDomainNormalized, 301); } } @@ -114,12 +106,16 @@ static public function is_mobile() { */ public function onMobileDomain() { $config = SiteConfig::current_site_config(); - $parts = parse_url($config->MobileDomain); - if(isset($parts['host']) && $parts['host'] == $_SERVER['HTTP_HOST']) { - return true; - } else { - return false; + $domains = explode(',', $config->MobileDomain); + foreach($domains as $domain) { + if(!parse_url($domain, PHP_URL_SCHEME)) $domain = Director::protocol() . $domain; // Normalize URL + $parts = parse_url($domain); + $compare = @$parts['host']; + if(@$parts['port']) $compare .= ':' . $parts['port']; + if($compare && $compare == $_SERVER['HTTP_HOST']) return true; } + + return false; } /** diff --git a/tests/MobileSiteConfigExtensionTest.php b/tests/MobileSiteConfigExtensionTest.php index c905bd8..403f4d4 100644 --- a/tests/MobileSiteConfigExtensionTest.php +++ b/tests/MobileSiteConfigExtensionTest.php @@ -28,13 +28,13 @@ public function testMobileSiteTypesField() { public function testMobileDomainGetterAddsProtocolPrefix() { $config = SiteConfig::current_site_config(); $config->MobileDomain = 'mobile.mysite.com'; - $this->assertEquals('http://mobile.mysite.com', $config->MobileDomain); + $this->assertEquals('http://mobile.mysite.com', $config->MobileDomainNormalized); } public function testFullSiteDomainGetterAddsProtocolPrefix() { $config = SiteConfig::current_site_config(); $config->FullSiteDomain = 'mysite.com'; - $this->assertEquals('http://mysite.com', $config->FullSiteDomain); + $this->assertEquals('http://mysite.com', $config->FullSiteDomainNormalized); } public function tearDown() { diff --git a/tests/MobileSiteControllerExtensionTest.php b/tests/MobileSiteControllerExtensionTest.php index 671ca05..8a36b84 100644 --- a/tests/MobileSiteControllerExtensionTest.php +++ b/tests/MobileSiteControllerExtensionTest.php @@ -69,7 +69,7 @@ public function testRedirectToMobileSite() { $_SERVER['HTTP_USER_AGENT'] = $agent; $response = $this->get($page->URLSegment); $headers = $response->getHeaders(); - $this->assertEquals(302, $response->getStatusCode()); + $this->assertEquals(301, $response->getStatusCode()); $this->assertEquals('http://m.' . $_SERVER['HTTP_HOST'], $headers['Location']); } } @@ -83,7 +83,7 @@ public function testRedirectToMobileFromAcceptSetting() { $_SERVER['HTTP_ACCEPT'] = 'text/vnd.wap.wml'; $response = $this->get($page->URLSegment); $headers = $response->getHeaders(); - $this->assertEquals(302, $response->getStatusCode()); + $this->assertEquals(301, $response->getStatusCode()); $this->assertEquals('http://m.' . $_SERVER['HTTP_HOST'], $headers['Location']); } @@ -96,7 +96,7 @@ public function testRedirectToMobileFromWAPProfile() { $_SERVER['HTTP_X_WAP_PROFILE'] = 1; $response = $this->get($page->URLSegment); $headers = $response->getHeaders(); - $this->assertEquals(302, $response->getStatusCode()); + $this->assertEquals(301, $response->getStatusCode()); $this->assertEquals('http://m.' . $_SERVER['HTTP_HOST'], $headers['Location']); unset($_SERVER['HTTP_X_WAP_PROFILE']); } @@ -120,8 +120,8 @@ public function testRedirectToFullSiteFromMobile() { $_SERVER['HTTP_HOST'] = 'm.' . $_SERVER['HTTP_HOST']; $response = $this->get($page->URLSegment . '?fullSite=1', null, null, array('fullSite' => 1)); $headers = $response->getHeaders(); - $this->assertEquals(302, $response->getStatusCode()); - $this->assertEquals($config->FullSiteDomain, $headers['Location']); + $this->assertEquals(301, $response->getStatusCode()); + $this->assertEquals($config->FullSiteDomainNormalized, $headers['Location']); } public function testRedirectToMobileSiteFromDesktop() { @@ -131,8 +131,8 @@ public function testRedirectToMobileSiteFromDesktop() { $page = $this->objFromFixture('Page', 'page'); $response = $this->get($page->URLSegment . '?fullSite=0', null, null, array('fullSite' => 0)); $headers = $response->getHeaders(); - $this->assertEquals(302, $response->getStatusCode()); - $this->assertEquals($config->MobileDomain, $headers['Location']); + $this->assertEquals(301, $response->getStatusCode()); + $this->assertEquals($config->MobileDomainNormalized, $headers['Location']); } public function testNoMobileRedirectWhenFullSiteSessionSetOnMobile() { @@ -154,6 +154,20 @@ public function testOnMobileSite() { $this->assertTrue($controller->onMobileDomain()); } + public function testOnMobileSiteMultipleDomains() { + $config = SiteConfig::current_site_config(); + $config->FullSiteDomain = 'domain1.com,domain2.com'; + $config->MobileDomain = 'm.domain1.com,m.domain2.com'; + $config->write(); + $_SERVER['HTTP_HOST'] = 'domain1.com'; + $controller = new ContentController(); + $this->assertFalse($controller->onMobileDomain()); + $_SERVER['HTTP_HOST'] = 'm.domain1.com'; + $this->assertTrue($controller->onMobileDomain()); + $_SERVER['HTTP_HOST'] = 'm.domain2.com'; + $this->assertTrue($controller->onMobileDomain()); + } + public function testDirectlyAccessingMobileSiteOnAnyDevice() { $_SERVER['HTTP_USER_AGENT'] = 'anything can be here'; $_SERVER['HTTP_HOST'] = 'm.' . $_SERVER['HTTP_HOST']; From e0ba458b75830e2d95b45a7c398ad253c62aaf79 Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Sat, 15 Sep 2012 18:09:18 +1200 Subject: [PATCH 04/11] FIX: resolve MobileSiteControllerExtension test failing --- code/MobileSiteControllerExtension.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/code/MobileSiteControllerExtension.php b/code/MobileSiteControllerExtension.php index 8a66599..c77a8c8 100644 --- a/code/MobileSiteControllerExtension.php +++ b/code/MobileSiteControllerExtension.php @@ -35,20 +35,24 @@ public function onAfterInit() { // Enforce the site (cookie expires in 30 minutes) $fullSite = $request->getVar('fullSite'); + if(is_numeric($fullSite)) { - Cookie::set('fullSite', (int)$fullSite); + $fullSiteCookie = (int)$fullSite; + Cookie::set('fullSite', $fullSiteCookie); // use the host of the desktop version of the site to set cross-(sub)domain cookie $domain = $config->FullSiteDomainNormalized; + if (!empty($domain)) { Cookie::set('fullSite', $fullSite, time() + self::$cookie_expire_time, null, '.' . parse_url($domain, PHP_URL_HOST)); } else { // otherwise just use a normal cookie with the default domain Cookie::set('fullSite', $fullSite, time() + self::$cookie_expire_time); } } - - // Site is being forced via flag or cookie - $fullSiteCookie = Cookie::get('fullSite'); + else { + $fullSiteCookie = Cookie::get('fullSite'); + } + if(is_numeric($fullSiteCookie)) { // Full site requested if($fullSiteCookie) { From 927f78c2de4e424c8b01ceb1fd231937ba11bc1a Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Thu, 3 Jan 2013 23:17:25 +0100 Subject: [PATCH 05/11] Added composer.json --- composer.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..fc5bbff --- /dev/null +++ b/composer.json @@ -0,0 +1,19 @@ +{ + "name": "silverstripe/mobile", + "description": "The mobile module provides detection for mobile devices, and can serve a different SilverStripe theme to them.The module can either use redirection to a separate mobile domain, or serve mobile optimized content under the same URLs.", + "type": "silverstripe-module", + "keywords": ["silverstripe", "mobile"], + "authors": [ + { + "name": "Sean Harvey", + "email": "sean@silverstripe.com" + }, + { + "name": "Will Rossiter", + "email": "will@fullscreen.io" + } + ], + "require": { + "silverstripe/framework": "~2.3" + } +} \ No newline at end of file From e4d2600b522bb1259a6a8644adce5297e34b341a Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Wed, 6 Mar 2013 14:13:55 +0100 Subject: [PATCH 06/11] is_tablet() detection, make it clearer how unreliable user agent device detection really is --- README.md | 11 +++-- code/MobileBrowserDetector.php | 77 +++++++++++++++++++++++++++-- tests/MobileBrowserDetectorTest.php | 19 +++++++ 3 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 tests/MobileBrowserDetectorTest.php diff --git a/README.md b/README.md index 004fe06..d048381 100755 --- a/README.md +++ b/README.md @@ -8,11 +8,17 @@ The module can either use redirection to a separate mobile domain, or serve mobile optimized content under the same URLs. It includes a default "blackcandymobile" theme to demonstrate the effects. -Note: The W3C recommends a ["One web" approach](http://www.w3.org/TR/mobile-bp/#d0e347) +The codebase relies on server-side device detection based on user agent strings, +which is an [unreliable](http://www.brettjankord.com/2013/01/10/active-development-on-categorizr-has-come-to-an-end/) way to determine if a device is considered to be "mobile". + +The W3C recommends a ["One web" approach](http://www.w3.org/TR/mobile-bp/#d0e347) that uses ["Responsive Design"](http://www.alistapart.com/articles/responsive-web-design/) to adapt content, rather than create isolated mobile experiences under their own domain. Most of the work on mobile optimization will be in client-side techniques -like JavaScript and CSS (e.g. through media queries). +like JavaScript and CSS (e.g. through media queries). + +Responsive design is not covered by this module, and can be achieved with standard +SilverStripe functionality. The module also exposes this state in SilverStripe controllers so custom logic and CSS/JavaScript includes can be adapted to mobile usage. @@ -80,6 +86,5 @@ Google will detect this change by using a different user agent, and index accord * Search form in the default theme * Integrate with subsites module to serve different content for a mobile site - * Integrate with third-party mobile detection, e.g. WURFL or Apache Mobile Filter or browscap (see http://nz.php.net/get_browser) * Device feature detection e.g. "Does this device support SSL?" or "Does this device support XHTML?" for progressive enhancement * Dynamic image insertion and resizing via HTML5 data attributes diff --git a/code/MobileBrowserDetector.php b/code/MobileBrowserDetector.php index 59cbba9..6dc1501 100644 --- a/code/MobileBrowserDetector.php +++ b/code/MobileBrowserDetector.php @@ -1,6 +1,12 @@ assertTrue(MobileBrowserDetector::is_tablet( + 'Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13', + 'XOOM tablet, contains "android" but not "mobile"' + )); + $this->assertFalse(MobileBrowserDetector::is_tablet( + 'Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1', + 'Nexus One, contains "mobile" and "android"' + )); + // This is where this approach falls down ... can't detect MS Surface usage. + // See http://www.brettjankord.com/2013/01/10/active-development-on-categorizr-has-come-to-an-end/ + $this->assertFalse(MobileBrowserDetector::is_tablet( + 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0; Touch)' + )); + } +} \ No newline at end of file From cca20963ba5208a72106ef6e19833b6a6096a410 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Wed, 6 Mar 2013 14:37:20 +0100 Subject: [PATCH 07/11] Allow specifying "tablet" behaviour (more specific is_mobile()) --- README.md | 3 ++ code/MobileBrowserDetector.php | 82 +++++++++++++++++------------ tests/MobileBrowserDetectorTest.php | 26 +++++++++ 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index d048381..b5d9eff 100755 --- a/README.md +++ b/README.md @@ -69,6 +69,9 @@ the one that mobile users of your site will see. Please keep in mind that the mobile domain must point to your site before it will work. +In order to force extended tablet device detection, set `MobileBrowserDetection::$tablet_is_mobile` +either to `TRUE` (forces mobile template) or `FALSE` (forces desktop template). + ### Search Engine Optimization ### The module follows [Google's recommendations](http://googlewebmastercentral.blogspot.com/2011/02/making-websites-mobile-friendly.html) diff --git a/code/MobileBrowserDetector.php b/code/MobileBrowserDetector.php index 6dc1501..a5d416e 100644 --- a/code/MobileBrowserDetector.php +++ b/code/MobileBrowserDetector.php @@ -11,6 +11,13 @@ */ class MobileBrowserDetector { + /** + * @var Boolean Consider tablet devices as "mobile" devices in {@link is_mobile()}. + * Set to FALSE to force non-mobile display if a tablet is detected, + * or to NULL to fall back to the standard mobile detection. + */ + public static $tablet_is_mobile = null; + /** * List of known mobiles, found in the HTTP_USER_AGENT variable * @see MobileBrowserDetector::is_mobile() for how they're used. @@ -66,40 +73,47 @@ public static function is_mobile($agent = null) { if(!$agent) $agent = $_SERVER['HTTP_USER_AGENT']; $accept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : ''; - switch(true) { - case(self::is_iphone()): - $isMobile = true; - break; - case(self::is_android()): - $isMobile = true; - break; - case(self::is_opera_mini()): - $isMobile = true; - break; - case(self::is_blackberry()): - $isMobile = true; - break; - case(self::is_palm()): - $isMobile = true; - break; - case(self::is_win_phone()): - $isMobile = true; - break; - case(self::is_windows()): - $isMobile = true; - break; - case(preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|vodafone|o2|pocket|kindle|mobile|pda|psp|treo)/i', $agent)): - $isMobile = true; - break; - case((strpos($accept, 'text/vnd.wap.wml') !== false) || (strpos($accept, 'application/vnd.wap.xhtml+xml') !== false)): - $isMobile = true; - break; - case(isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])): - $isMobile = true; - break; - case(in_array(strtolower(substr($agent, 0, 4)), self::mobile_index_list())): - $isMobile = true; - break; + $isTablet = self::is_tablet($agent); + if(self::$tablet_is_mobile === TRUE && $isTablet) { + $isMobile = true; + } else if(self::$tablet_is_mobile === FALSE && $isTablet) { + $isMobile = false; + } else { + switch(true) { + case(self::is_iphone()): + $isMobile = true; + break; + case(self::is_android()): + $isMobile = true; + break; + case(self::is_opera_mini()): + $isMobile = true; + break; + case(self::is_blackberry()): + $isMobile = true; + break; + case(self::is_palm()): + $isMobile = true; + break; + case(self::is_win_phone()): + $isMobile = true; + break; + case(self::is_windows()): + $isMobile = true; + break; + case(preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|vodafone|o2|pocket|kindle|mobile|pda|psp|treo)/i', $agent)): + $isMobile = true; + break; + case((strpos($accept, 'text/vnd.wap.wml') !== false) || (strpos($accept, 'application/vnd.wap.xhtml+xml') !== false)): + $isMobile = true; + break; + case(isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])): + $isMobile = true; + break; + case(in_array(strtolower(substr($agent, 0, 4)), self::mobile_index_list())): + $isMobile = true; + break; + } } if(!headers_sent()) { diff --git a/tests/MobileBrowserDetectorTest.php b/tests/MobileBrowserDetectorTest.php index f73fc98..b42acb6 100644 --- a/tests/MobileBrowserDetectorTest.php +++ b/tests/MobileBrowserDetectorTest.php @@ -16,4 +16,30 @@ public function testIsTablet() { 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; ARM; Trident/6.0; Touch)' )); } + + public function testTabletIsMobile() { + $tabletUa = 'Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13'; + $mobileUa = 'Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'; + $desktopUa = 'Mozilla/5.0 (Windows; U; MSIE 9.0; WIndows NT 9.0; en-US))'; + + $orig = MobileBrowserDetector::$tablet_is_mobile; + + MobileBrowserDetector::$tablet_is_mobile = true; + $this->assertTrue(MobileBrowserDetector::is_mobile($tabletUa)); + $this->assertTrue(MobileBrowserDetector::is_mobile($mobileUa)); + $this->assertFalse(MobileBrowserDetector::is_mobile($desktopUa)); + + MobileBrowserDetector::$tablet_is_mobile = false; + $this->assertFalse(MobileBrowserDetector::is_mobile($tabletUa)); + $this->assertTrue(MobileBrowserDetector::is_mobile($mobileUa)); + $this->assertFalse(MobileBrowserDetector::is_mobile($desktopUa)); + + MobileBrowserDetector::$tablet_is_mobile = null; + // Technically this is a bug, but its the standard module check + $this->assertFalse(MobileBrowserDetector::is_mobile($tabletUa)); + $this->assertTrue(MobileBrowserDetector::is_mobile($mobileUa)); + $this->assertFalse(MobileBrowserDetector::is_mobile($desktopUa)); + + MobileBrowserDetector::$tablet_is_mobile = $orig; + } } \ No newline at end of file From 88ea660591fde127e00ed63e3868a8cce3376df2 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Wed, 6 Mar 2013 18:04:56 +0100 Subject: [PATCH 08/11] FIX Infinite redirects on conflicting fullSite cookie domains They were both set for .mydomain.com and m.mydomain.com, which could lead to different values based on which domain, ending up in the redirects infinitely ping-ponging between the two. Regression from e0ba458b --- code/MobileSiteControllerExtension.php | 1 - 1 file changed, 1 deletion(-) diff --git a/code/MobileSiteControllerExtension.php b/code/MobileSiteControllerExtension.php index c77a8c8..a55a114 100644 --- a/code/MobileSiteControllerExtension.php +++ b/code/MobileSiteControllerExtension.php @@ -38,7 +38,6 @@ public function onAfterInit() { if(is_numeric($fullSite)) { $fullSiteCookie = (int)$fullSite; - Cookie::set('fullSite', $fullSiteCookie); // use the host of the desktop version of the site to set cross-(sub)domain cookie $domain = $config->FullSiteDomainNormalized; From 71595fb394366dd213b0c9ae2f1439527877fce9 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Wed, 6 Mar 2013 18:05:23 +0100 Subject: [PATCH 09/11] FIX Set cookie in days rather than seconds Regression caused by moving from setcookie() to Cookie::set() --- code/MobileSiteControllerExtension.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/MobileSiteControllerExtension.php b/code/MobileSiteControllerExtension.php index a55a114..584ba7c 100644 --- a/code/MobileSiteControllerExtension.php +++ b/code/MobileSiteControllerExtension.php @@ -42,10 +42,11 @@ public function onAfterInit() { // use the host of the desktop version of the site to set cross-(sub)domain cookie $domain = $config->FullSiteDomainNormalized; + $expiryDays = (time() + self::$cookie_expire_time) / (60*60*24); if (!empty($domain)) { - Cookie::set('fullSite', $fullSite, time() + self::$cookie_expire_time, null, '.' . parse_url($domain, PHP_URL_HOST)); + Cookie::set('fullSite', $fullSiteCookie, $expiryDays, null, '.' . parse_url($domain, PHP_URL_HOST)); } else { // otherwise just use a normal cookie with the default domain - Cookie::set('fullSite', $fullSite, time() + self::$cookie_expire_time); + Cookie::set('fullSite', $fullSiteCookie, $expiryDays); } } else { From 29fcfcc9ec4f26314588a3955a6bdbb218bf1611 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Wed, 6 Mar 2013 18:20:07 +0100 Subject: [PATCH 10/11] API Moved themes into separate repo Copying themes on dev/build is not really a good idea, and for most purposes you'll want another theme anyway. It also makes tests less fragile in terms of expectations. --- README.md | 24 +-- code/MobileSiteConfigExtension.php | 64 -------- composer.json | 4 + tests/MobileSiteConfigExtensionTest.php | 18 -- tests/MobileSiteTreeExtensionTest.php | 5 - themes/blackcandymobile/css/form.css | 128 --------------- themes/blackcandymobile/css/layout.css | 48 ------ themes/blackcandymobile/css/typography.css | 52 ------ .../blackcandymobile/images/activeTabLeft.png | Bin 2844 -> 0 bytes .../images/activeTabRight.png | Bin 2851 -> 0 bytes themes/blackcandymobile/images/bg.gif | Bin 1409 -> 0 bytes themes/blackcandymobile/images/header.gif | Bin 204 -> 0 bytes .../blackcandymobile/images/headerRounded.gif | Bin 304 -> 0 bytes themes/blackcandymobile/js/iphone.js | 20 --- .../blackcandymobile/js/jquery-1.4.2.min.js | 154 ------------------ .../blackcandymobile/js/jquery.iphone.min.js | 3 - .../templates/Includes/BreadCrumbs.ss | 5 - .../templates/Includes/Footer.ss | 1 - .../templates/Includes/Navigation.ss | 19 --- .../templates/Includes/SideBar.ss | 28 ---- .../blackcandymobile/templates/Layout/Page.ss | 6 - themes/blackcandymobile/templates/Page.ss | 36 ---- .../jquerymobile/templates/Includes/Footer.ss | 6 - .../templates/Includes/Navigation.ss | 13 -- .../Includes/Navigation_manypages.ss | 14 -- themes/jquerymobile/templates/Layout/Page.ss | 19 --- themes/jquerymobile/templates/Page.ss | 31 ---- 27 files changed, 18 insertions(+), 680 deletions(-) delete mode 100644 themes/blackcandymobile/css/form.css delete mode 100755 themes/blackcandymobile/css/layout.css delete mode 100755 themes/blackcandymobile/css/typography.css delete mode 100644 themes/blackcandymobile/images/activeTabLeft.png delete mode 100644 themes/blackcandymobile/images/activeTabRight.png delete mode 100644 themes/blackcandymobile/images/bg.gif delete mode 100644 themes/blackcandymobile/images/header.gif delete mode 100644 themes/blackcandymobile/images/headerRounded.gif delete mode 100644 themes/blackcandymobile/js/iphone.js delete mode 100644 themes/blackcandymobile/js/jquery-1.4.2.min.js delete mode 100644 themes/blackcandymobile/js/jquery.iphone.min.js delete mode 100644 themes/blackcandymobile/templates/Includes/BreadCrumbs.ss delete mode 100644 themes/blackcandymobile/templates/Includes/Footer.ss delete mode 100644 themes/blackcandymobile/templates/Includes/Navigation.ss delete mode 100644 themes/blackcandymobile/templates/Includes/SideBar.ss delete mode 100644 themes/blackcandymobile/templates/Layout/Page.ss delete mode 100644 themes/blackcandymobile/templates/Page.ss delete mode 100644 themes/jquerymobile/templates/Includes/Footer.ss delete mode 100644 themes/jquerymobile/templates/Includes/Navigation.ss delete mode 100644 themes/jquerymobile/templates/Includes/Navigation_manypages.ss delete mode 100644 themes/jquerymobile/templates/Layout/Page.ss delete mode 100644 themes/jquerymobile/templates/Page.ss diff --git a/README.md b/README.md index b5d9eff..095f718 100755 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ The mobile module provides detection for mobile devices, and can serve a different SilverStripe theme to them. The module can either use redirection to a separate mobile domain, or serve mobile optimized content under the same URLs. -It includes a default "blackcandymobile" theme to demonstrate the effects. The codebase relies on server-side device detection based on user agent strings, which is an [unreliable](http://www.brettjankord.com/2013/01/10/active-development-on-categorizr-has-come-to-an-end/) way to determine if a device is considered to be "mobile". @@ -41,17 +40,22 @@ Unpack and copy the mobile folder into your SilverStripe project. Run "dev/build" in your browser, for example: "http://localhost/silverstripe/dev/build?flush=all" -A new theme called "blackcandymobile" will be created in your themes folder after -invoking the database build. This theme is a good starting point which you can modify -to create your own mobile theme. +## Themes -If the themes folder can't be written to by the web server during dev/build, please -manually copy "blackcandymobile" into your themes folder from the mobile folder. +We provide two themes as a starting point which you can modify to create your own mobile theme: -Alternatively, the module contains a "jquerymobile" sample theme -which creates a basic navigation interface through [jQuery Mobile](http://jquerymobile.com). -To use this theme, copy it to `/themes` in the same way, -and set it in your `SiteConfig` as described below. + * ["blackcandymobile"](https://github.com/silverstripe-themes/silverstripe-blackcandymobile): + Modelled to work with the "blackcandy" theme which comes with the SilverStripe 2.x default installation. + * ["jquerymobile"](https://github.com/silverstripe-themes/silverstripe-jquerymobile): + Creates a basic navigation interface through [jQuery Mobile](http://jquerymobile.com) + +Either download the themes from github, or add them via [composer](http://getcomposer.org): + + { + "require": {"silverstripe-themes/blackcandymobile": "*"} + } + +Alternatively, you can start your own mobile theme of course. ## Configuration diff --git a/code/MobileSiteConfigExtension.php b/code/MobileSiteConfigExtension.php index a34d213..6fd6bef 100644 --- a/code/MobileSiteConfigExtension.php +++ b/code/MobileSiteConfigExtension.php @@ -7,27 +7,6 @@ */ class MobileSiteConfigExtension extends DataObjectDecorator { - /** - * The path the default mobile theme should be copied - * to when {@link SiteConfig} is first created in the database. - * - * @see MobileSiteConfigExtension::requireDefaultRecords() - * @var string - */ - protected static $theme_copy_path; - - public static function set_theme_copy_path($path) { - self::$theme_copy_path = $path; - } - - public static function get_theme_copy_path() { - if(!self::$theme_copy_path) { - return '../' . THEMES_DIR . '/blackcandymobile'; - } else { - return self::$theme_copy_path; - } - } - /** * Append Extra Fields onto the {@link SiteConfig} */ @@ -97,49 +76,6 @@ public function getMobileSiteTypes() { return $types; } - /** - * The default theme is "blackcandymobile". If this is still set - * as a field on SiteConfig, then make sure that it's copied - * into the themes directory from the mobile module. - */ - public function augmentDatabase() { - $defaultThemes = array('blackcandymobile', 'jquerymobile'); - $currentTheme = $this->owner->getField('MobileTheme'); - if(!$currentTheme || in_array($currentTheme, $defaultThemes)) { - $this->copyDefaultTheme($currentTheme); - } - } - - /** - * @param String - */ - public static function copyDefaultTheme($theme = null) { - if(!$theme) $theme = 'blackcandymobile'; - $src = '../' . MOBILE_DIR . '/themes/' . $theme; - $dst = self::get_theme_copy_path(); - - if(!file_exists($dst)) { - @mkdir($dst); - if(is_writable($dst)) { - rcopy($src, $dst); - DB::alteration_message( - sprintf('Default mobile theme "%s" has been copied into the themes directory', $theme), - 'created' - ); - } else { - DB::alteration_message( - sprintf( - 'Could not copy default mobile theme "%s" into themes directory (permission denied). - Please manually copy the "%s" directory from the mobile module into the themes directory.', - $theme, - $theme - ), - 'error' - ); - } - } - } - /** * Append extra fields to the new Mobile tab in the cms. */ diff --git a/composer.json b/composer.json index fc5bbff..8a17bed 100644 --- a/composer.json +++ b/composer.json @@ -15,5 +15,9 @@ ], "require": { "silverstripe/framework": "~2.3" + }, + "suggests": { + "silverstripe-themes/blackcandymobile": "*", + "silverstripe-themes/jquerymobile": "*" } } \ No newline at end of file diff --git a/tests/MobileSiteConfigExtensionTest.php b/tests/MobileSiteConfigExtensionTest.php index 403f4d4..c2dc544 100644 --- a/tests/MobileSiteConfigExtensionTest.php +++ b/tests/MobileSiteConfigExtensionTest.php @@ -5,19 +5,6 @@ */ class MobileSiteConfigExtensionTest extends SapphireTest { - public function setUp() { - parent::setUp(); - MobileSiteConfigExtension::set_theme_copy_path(TEMP_FOLDER . '/mobile-test-copy-theme/'); - } - - public function testRequireDefaultRecordsCopiesDefaultThemeWhenDefaultThemeSet() { - $config = SiteConfig::current_site_config(); - $config->MobileTheme = 'blackcandymobile'; - $config->write(); - $config->requireDefaultRecords(); - $this->assertTrue(file_exists(TEMP_FOLDER . '/mobile-test-copy-theme/')); - } - public function testMobileSiteTypesField() { $config = SiteConfig::current_site_config(); $fields = $config->getCMSFields(); @@ -37,9 +24,4 @@ public function testFullSiteDomainGetterAddsProtocolPrefix() { $this->assertEquals('http://mysite.com', $config->FullSiteDomainNormalized); } - public function tearDown() { - parent::tearDown(); - exec('rm -rf ' . TEMP_FOLDER . '/mobile-test-copy-theme/'); - } - } \ No newline at end of file diff --git a/tests/MobileSiteTreeExtensionTest.php b/tests/MobileSiteTreeExtensionTest.php index 75437f1..5f40627 100644 --- a/tests/MobileSiteTreeExtensionTest.php +++ b/tests/MobileSiteTreeExtensionTest.php @@ -16,11 +16,6 @@ class MobileSiteTreeExtensionTest extends FunctionalTest { 'SiteConfig' => array('MobileSiteConfigExtension'), ); - public function setUp() { - parent::setUp(); - MobileSiteConfigExtension::set_theme_copy_path(TEMP_FOLDER . '/mobile-test-copy-theme/'); - } - public function testShowsCanonicalLinkOnMobile() { $page = $this->objFromFixture('Page', 'page'); diff --git a/themes/blackcandymobile/css/form.css b/themes/blackcandymobile/css/form.css deleted file mode 100644 index 9e17713..0000000 --- a/themes/blackcandymobile/css/form.css +++ /dev/null @@ -1,128 +0,0 @@ -/** - * SilverStripe Black Candy Theme - * http://www.silverstripe.com - * - * Form Styling - */ - - -/* FORM ----------------------------------------- */ -form { - border-bottom:1px solid #CCCCCC; - margin:0 0 18px 0; - padding-bottom:18px; -} - -/* FIELDSETS ----------------------------------------- */ -fieldset { - border: 0; -} - -/* ACTION BUTTONS ----------------------------------------- */ -input.action { - padding: 2px; - font-size: 14px ; - font-family: Verdana, Tahoma, Sans-serif; - margin:10px 0 10px 0; -} -input.action:hover, -input.action:focus { - cursor: pointer; -} - -/* FIELD FORMATING ----------------------------------------- */ -form ul { - list-style: none; -} -.middleColumn { - display: block; - /*margin: 15px 10px 10px 0;*/ - /*background: #E9E9E9;*/ - /*padding: 4px;*/ - /*width: 306px;*/ - clear: left; -} - #Sidebar .middleColumn { - margin: 0 0 0 8px; - display: inline; - } - - div.tab .field .middleColumn { - clear: none !important; - margin: 0 !important; - width: auto; - } - - .middleColumn .middleColumn { - margin-left: 0; - margin-right: 0; - padding: 0; - } - - .middleColumn .message { - margin: 0; - } - -/* INPUT BOXS ----------------------------------------- */ - -input.text, textarea, select { - padding: 6px 2px 5px 2px; - border: 1px solid #A7A7A7; - color: #000; - font-size: 14px; - font-weight: bold; - width:99.25%; - margin:0 0 18px 0; -} - -textarea { - font-family: Verdana, Tahoma, sans-serif; - font-size: 12px; -} -input:focus span, textarea:focus span { - border: 3px solid #000; -} - -/* SELECT DROPDOWN ----------------------------------------- */ - -select { - width: auto; -} - -/* LABELS ----------------------------------------- */ -.typography label { - display: block; - font-weight:bold; - margin: 0 0 18px 0; - color: #777; - font-size: 14px; -} - -label.right { - display:inline; -} - -/* CHECKBOXES ----------------------------------------- */ -ul.optionset { - margin: 0; - overflow: hidden; -} - ul.optionset li { - margin: 6px 0; - clear: both; - } - ul.optionset li input { - float: left; - margin: 0 6px; - } - ul.optionset li label { - margin: 0; - } \ No newline at end of file diff --git a/themes/blackcandymobile/css/layout.css b/themes/blackcandymobile/css/layout.css deleted file mode 100755 index 1a48e85..0000000 --- a/themes/blackcandymobile/css/layout.css +++ /dev/null @@ -1,48 +0,0 @@ -/** -* SilverStripe Mobile Theme http://www.silverstripe.com -*/ -/* Misc Styles and defaults --------------------------------------------- */ -* { margin:0; padding:0; } -body { color:#333; font-family:Helvetica, Arial, sans-serif; font-size:62.5%; line-height:18px; } -html { background:#626467 url(../images/bg.gif) repeat; } -table { border-collapse:collapse; border-spacing:0; } -caption, th, td { text-align:left; font-weight:normal; } -img { max-width:320px; } -.clear { clear:both; } -/* CONTAINER */ -#Container { background:#ffffff; padding:0 0 5px 0; width:100%; } -#Layout { padding:10px 15px; } -/* HEADER */ -#Header { background: #58ade1 url(../images/header.gif) repeat-x left center; margin:0 10px; overflow:hidden; } -#Header h1 { color:#fff; padding:10px 0 10px 10px; } -#Header p { color:#fff; clear:left; font-size:12px; font-weight:bold; margin:0 0 0 10px; } -/* NAVIGATION */ -#Navigation { background:#4ea3d7; margin:0 10px; overflow:hidden; padding:10px 0px 0px 0px; --moz-border-radius-bottomleft:10px; -webkit-border-bottom-left-radius:10px; border-bottom-left-radius:10px; --moz-border-radius-bottomright:10px; -webkit-border-bottom-right-radius:10px; border-bottom-right-radius:10px; } -#Navigation ul li { display:block; list-style:none; margin:0; } -#Navigation ul li a { color:#fff; display:block; font-size:14px; font-weight:bold; line-height:36px; padding:0 0 0 9px; text-decoration:none; } -#Navigation ul li.current, -#Navigation ul li.section { border-left:1px solid #CCC; border-right:1px solid #CCC; } -#Navigation ul li.current a, -#Navigation ul.sub li.current a { background:#fff; color:#444; } -#Navigation ul li.section a { background:#fff; color:#999; } -#Navigation ul.sub { background:#ffffff; padding:0; } -#Navigation ul.sub li { border:none; } -#Navigation ul.sub li a { border-top:1px solid #CCC; color:#999; padding-left:18px; } -/* FOOTER */ -#Footer { background:#4EA3D7; clear:both; margin:10px; padding:10px 15px; text-align:center; -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; } -#Footer p { color:#fff; font-size:11px; text-align:center; } -#Footer a { color: #fff; text-decoration:none; } -#Footer a:hover { color:#fff; text-decoration:underline; } -/* PAGE COMMENTS */ -#PageComments_holder { border-top:1px solid #CCCCCC; padding-top:18px; } -#CommentHolder ul { margin:0; padding:0; list-style:none; } -#CommentHolder li { margin:0; padding:0; list-style:none; } -#PageComments li { border-bottom:1px solid #CCCCCC; margin:0 0 18px 0; padding:0 0 18px 0; } -#PageComments .info { font-size:12px; font-style:italic; } -#PageComments .actionLinks { overflow:hidden; } -#PageComments .actionLinks li { border:none; display:block; float:left; margin:0 9px 0 0; padding:0; } -#DeleteComments, #CommentsRSSFeed { margin-bottom:0; padding:0; font-size:12px; } -.typography .spamlink, .typography .deletelink { background:#3E91C4; color:#FFFFFF; font-size:12px; padding:3px 6px; text-align:center; } \ No newline at end of file diff --git a/themes/blackcandymobile/css/typography.css b/themes/blackcandymobile/css/typography.css deleted file mode 100755 index 54ec7ee..0000000 --- a/themes/blackcandymobile/css/typography.css +++ /dev/null @@ -1,52 +0,0 @@ -/** - * SilverStripe Mobile Theme - * http://www.silverstripe.com - * - * This typography file is included in the WYSIWYG editor and the front end. It provides - * a place to add link styles and font styles you would like in the CMS and the Front End. - */ -/* GENERIC STYLES */ -.typography * { font-family:Helvetica, Arial, sans-serif; } -/* PARAGRAPHS */ -.typography p { color: #666; font-weight:bold; font-size: 14px; line-height:18px; margin:0 0 18px 0; } -/* QUOTES */ -.typography blockquote { color:#777; font-size:1.4em; font-style:italic; margin:10px; } -.typography q { border:1px #ccc solid; display:block; font-size:0.8em; margin: 1em 1em; padding:0.5em; } -/* LINKS */ -.typography a { color:#3E91C4; text-decoration:none; } -.typography a:hover { text-decoration:underline; } -/* LINK ICONS - shows type of file */ -.typography a[href$=".pdf"], .typography a[href$=".PDF"], .typography a.pdf { background:url(../images/icons/page_white_acrobat.png) no-repeat left center; padding:2px; padding-left:20px; } -.typography a[href$=".doc"], .typography a[href$=".DOC"], .typography a.doc { background:url(../images/icons/page_word.png) no-repeat left center; padding:2px; padding-left:20px; } -.typography a[href$=".xls"], .typography a[href$=".XLS"], .typography a.xls { background:url(../images/icons/page_excel.png) no-repeat left center; padding:2px; padding-left:20px; } -.typography a[href$=".gz"], .typography a[href$=".GZ"], .typography a[href$=".gzip"], .typography a[href$=".GZIP"], .typography a[href$=".zip"], .typography a[href$=".ZIP"], .typography a.archive { background:url(../images/icons/page_white_zip.png) no-repeat left center; padding:2px; padding-left:20px; } -.typography a[href$=".exe"], .typography a[href$=".EXE"], .typography a.application { background:url(../images/icons/application.png) no-repeat left center; padding:2px; padding-left:20px; } -/* LIST STYLES */ -.typography ul, -.typography ol { margin:0 0 18px 18px; color:#666; } -.typography li { font-size:13px; font-weight:bold; margin:0px 9px; } -.typography li li { } -/* HEADER STYLES */ -.typography h1 { color:#4EA3D7; font-size:27px; font-weight:bold; line-height:1; margin:18px 0 18px 0; } -.typography h2 { color:#222; font-size:24px; font-weight:bold; line-height:1.125; margin:18px 0 18px 0; } -.typography h3 { clear:both; color:#222; font-weight:bold; font-size:18px; line-height:1; margin:9px 0 18px 0; } -.typography h4 { clear:both; color:#222; font-size:16px; font-weight:bold; line-height:1.2857; margin:0 0 9px 0; } -.typography h5 { color:#222; font-size:14px; font-weight:bold; line-height:1.2857; margin:0; } -.typography h6 { color:#555; font-size:14px; font-weight:bold; line-height:1.3846; margin:0; } -/* PRE STYLES */ -.typography pre { display:block; font-family:"Courier New",Courier; font-size:1.2em; margin:2em 5em; padding:0.5em; border:1px #ccc solid; background:#eee; } -/* TABLE STYLING */ -.typography table { border-collapse:collapse; border:1px dotted #CCCCCC; color:#666; font-size:12px; margin:0 0 18px 0; } -.typography tr {} -.typography th { background:#4EA3D7; border:1px dotted #CCCCCC; color:#FFFFFF; font-weight:bold; padding:6px 5px 3px 5px; } -.typography td { border:1px dotted #CCCCCC; font-weight:bold; padding:6px 5px 3px 5px; } -/* WYSIWYG EDITOR ALIGNMENT CLASSES */ -.typography .left { text-align:left; } -.typography .center { text-align:center; } -.typography .right { text-align:right; } -/* IMAGES */ -.typography img { border:none; } -.typography img.right { float:right; margin:0 0 18px 18px; } -.typography img.left { float:left; margin:0 18px 18px 0; } -.typography img.leftAlone { float:left; margin-right:100%; } -.typography img.center { float:none; margin-left:auto; margin-right:auto; display:block; } diff --git a/themes/blackcandymobile/images/activeTabLeft.png b/themes/blackcandymobile/images/activeTabLeft.png deleted file mode 100644 index 31e70bbe2802a64802d2dfb40f411421630b82a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2844 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[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, -Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& -(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, -a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== -"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, -function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a"; -var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, -parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= -false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= -s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, -applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; -else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, -a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== -w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, -cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, -function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); -k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), -C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= -e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& -f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; -if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", -e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, -"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, -d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, -e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); -t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| -g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, -CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, -g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, -text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, -setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= -h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== -"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, -h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& -q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; -if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); -(function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: -function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= -{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== -"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", -d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? -a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== -1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= -c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, -wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, -prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, -this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); -return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, -""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); -return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", -""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= -c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? -c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= -function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= -Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, -"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= -a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= -a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== -"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, -serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), -function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, -global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& -e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? -"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== -false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= -false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", -c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| -d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); -g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== -1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== -"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; -if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== -"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| -c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; -this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= -this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, -e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
"; -a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); -c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, -d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- -f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": -"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in -e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/themes/blackcandymobile/js/jquery.iphone.min.js b/themes/blackcandymobile/js/jquery.iphone.min.js deleted file mode 100644 index a8b4861..0000000 --- a/themes/blackcandymobile/js/jquery.iphone.min.js +++ /dev/null @@ -1,3 +0,0 @@ -jQuery.fn.iPhone={present:(navigator.platform=='iPhone'),version:{safari:(/AppleWebKit\/([^\s]+)/.exec(navigator.userAgent)||[,false])[1],webkit:(/Safari\/(.+)/.exec(navigator.userAgent)||[,false])[1]},orientchange:function(p,l,r){p=p||function(){};l=l||p;r=r||l;window.onorientationchange=function(){switch(window.orientation){case 0:p();break;case 90:l();break;case-90:r();break;};};},hideURLbar:function(f){if(window.innerHeight<(window.outerHeight+20)){$('html').css({'min-height':(window.outerHeight+20)+'px'});} -setTimeout(function(){if(window.pageYOffset<1||f){window.scrollTo(0,1);jQuery.iPhone.hideURLbar();}},0);},disableTextSizeAdjust:function(){jQuery('html').css({'-webkit-text-size-adjust':'none'});},enableTextSizeAdjust:function(){jQuery('html').css({'-webkit-text-size-adjust':'auto'});}};jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i - -<% end_if %> \ No newline at end of file diff --git a/themes/blackcandymobile/templates/Includes/Footer.ss b/themes/blackcandymobile/templates/Includes/Footer.ss deleted file mode 100644 index 823b517..0000000 --- a/themes/blackcandymobile/templates/Includes/Footer.ss +++ /dev/null @@ -1 +0,0 @@ -

© $Now.year | Powered by SilverStripe | Full site

diff --git a/themes/blackcandymobile/templates/Includes/Navigation.ss b/themes/blackcandymobile/templates/Includes/Navigation.ss deleted file mode 100644 index d306ac8..0000000 --- a/themes/blackcandymobile/templates/Includes/Navigation.ss +++ /dev/null @@ -1,19 +0,0 @@ -
    - <% control Menu(1) %> - <% if Children %> -
  • $MenuTitle.XML - <% else %> -
  • $MenuTitle.XML - <% end_if %> - <% if LinkOrSection = section %> - <% if Children %> - - <% end_if %> - <% end_if %> -
  • - <% end_control %> -
\ No newline at end of file diff --git a/themes/blackcandymobile/templates/Includes/SideBar.ss b/themes/blackcandymobile/templates/Includes/SideBar.ss deleted file mode 100644 index 0a61ae6..0000000 --- a/themes/blackcandymobile/templates/Includes/SideBar.ss +++ /dev/null @@ -1,28 +0,0 @@ - - \ No newline at end of file diff --git a/themes/blackcandymobile/templates/Layout/Page.ss b/themes/blackcandymobile/templates/Layout/Page.ss deleted file mode 100644 index a838fe2..0000000 --- a/themes/blackcandymobile/templates/Layout/Page.ss +++ /dev/null @@ -1,6 +0,0 @@ -
-

$Title

- $Content - $Form - $PageComments -
\ No newline at end of file diff --git a/themes/blackcandymobile/templates/Page.ss b/themes/blackcandymobile/templates/Page.ss deleted file mode 100644 index 1c288e7..0000000 --- a/themes/blackcandymobile/templates/Page.ss +++ /dev/null @@ -1,36 +0,0 @@ - - - - <% base_tag %> - <% if MetaTitle %>$MetaTitle<% else %>$Title<% end_if %> » $SiteConfig.Title - $MetaTags(false) - - - <% require themedCSS(layout) %> - <% require themedCSS(typography) %> - <% require themedCSS(form) %> - - - - - -
- - - - -
- $Layout -
- - -
- - \ No newline at end of file diff --git a/themes/jquerymobile/templates/Includes/Footer.ss b/themes/jquerymobile/templates/Includes/Footer.ss deleted file mode 100644 index 5cead38..0000000 --- a/themes/jquerymobile/templates/Includes/Footer.ss +++ /dev/null @@ -1,6 +0,0 @@ -

- - Made with - SilverStripe - -

\ No newline at end of file diff --git a/themes/jquerymobile/templates/Includes/Navigation.ss b/themes/jquerymobile/templates/Includes/Navigation.ss deleted file mode 100644 index 0b87ea5..0000000 --- a/themes/jquerymobile/templates/Includes/Navigation.ss +++ /dev/null @@ -1,13 +0,0 @@ -
- -
\ No newline at end of file diff --git a/themes/jquerymobile/templates/Includes/Navigation_manypages.ss b/themes/jquerymobile/templates/Includes/Navigation_manypages.ss deleted file mode 100644 index f3767b6..0000000 --- a/themes/jquerymobile/templates/Includes/Navigation_manypages.ss +++ /dev/null @@ -1,14 +0,0 @@ -<%-- Alternate template rendering nav with more pages as a list rather than a navigation bar --%> -
- -
\ No newline at end of file diff --git a/themes/jquerymobile/templates/Layout/Page.ss b/themes/jquerymobile/templates/Layout/Page.ss deleted file mode 100644 index 42c4555..0000000 --- a/themes/jquerymobile/templates/Layout/Page.ss +++ /dev/null @@ -1,19 +0,0 @@ -<% if Level(2) %> - -<% end_if %> - -
- $Content -
- -<% if Menu(2) %> - -<% end_if %> \ No newline at end of file diff --git a/themes/jquerymobile/templates/Page.ss b/themes/jquerymobile/templates/Page.ss deleted file mode 100644 index 90a67cd..0000000 --- a/themes/jquerymobile/templates/Page.ss +++ /dev/null @@ -1,31 +0,0 @@ - - - - <% base_tag %> - $Title - $MetaTags(false) - - <%-- Caution: Any Requirements calls in init() methods of custom page types won't work due to jQuery Mobile loading pages via Ajax, place them all in Page_Controller --%> - - - - - -
-
- - Home - -

$SiteConfig.Title

- <%-- See Navigation_manypages.ss for handling more than half a dozen toplevel pages --%> - <% include Navigation %> -
-
- $Layout -
-
- <% include Footer %> -
-
- \ No newline at end of file From 2291fcb73c84e75207ec4f9b0d58b02f75659534 Mon Sep 17 00:00:00 2001 From: Daniel Hensby Date: Wed, 1 Feb 2017 11:27:59 +0000 Subject: [PATCH 11/11] FIX Tests that require DB need to state so --- .travis.yml | 24 ++++++++++++++++++++++++ composer.json | 3 +++ tests/MobileSiteConfigExtensionTest.php | 2 ++ 3 files changed, 29 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ba19b32 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +# See https://github.com/silverstripe-labs/silverstripe-travis-support for setup details + +language: php + +sudo: false + +matrix: + include: + - php: 5.3 + env: DB=MYSQL CORE_RELEASE=2.4 + - php: 5.4 + env: DB=PGSQL CORE_RELEASE=2.4 + - php: 5.5 + env: DB=SQLITE CORE_RELEASE=2.4 + - php: 5.6 + env: DB=MYSQL CORE_RELEASE=2.4 + +before_script: + - git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support + - php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require silverstripe/cms + - cd ~/builds/ss + +script: + - vendor/bin/phpunit mobile/tests/ \ No newline at end of file diff --git a/composer.json b/composer.json index 8a17bed..ba0d0e9 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,9 @@ "require": { "silverstripe/framework": "~2.3" }, + "require-dev": { + "phpunit/phpunit": "^3.7" + }, "suggests": { "silverstripe-themes/blackcandymobile": "*", "silverstripe-themes/jquerymobile": "*" diff --git a/tests/MobileSiteConfigExtensionTest.php b/tests/MobileSiteConfigExtensionTest.php index c2dc544..16c0cc8 100644 --- a/tests/MobileSiteConfigExtensionTest.php +++ b/tests/MobileSiteConfigExtensionTest.php @@ -5,6 +5,8 @@ */ class MobileSiteConfigExtensionTest extends SapphireTest { + protected $usesDatabase = true; + public function testMobileSiteTypesField() { $config = SiteConfig::current_site_config(); $fields = $config->getCMSFields();