From 674999874136714be031db8c31432eb2a4d50c2e Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Tue, 7 Feb 2017 14:43:11 -0200 Subject: [#952] Access log_format key correctly even if it's None This is the case of the infamous 'Unhandled error in Deferred' events that were not logging the traceback. --- service/pixelated/config/logger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service') diff --git a/service/pixelated/config/logger.py b/service/pixelated/config/logger.py index a1e825a6..c4d2dc76 100644 --- a/service/pixelated/config/logger.py +++ b/service/pixelated/config/logger.py @@ -44,9 +44,9 @@ def init(debug=False): def formatter(event): event['log_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(event['log_time'])) event['log_level'] = event['log_level'].name.upper() + event['log_format'] = event.get('log_format') or '' logstring = u'{log_time} [{log_namespace}] {log_level} ' + event['log_format'] + '\n' return logstring.format(**event) observers = [FileLogObserver(sys.stdout, formatter)] - globalLogBeginner.beginLoggingTo(observers) -- cgit v1.2.3 From d4ef82a55053a0a672935104dda2a06eae8579ac Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Tue, 7 Feb 2017 14:52:43 -0200 Subject: [#952] Log events even when formatting errors occur --- service/pixelated/config/logger.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'service') diff --git a/service/pixelated/config/logger.py b/service/pixelated/config/logger.py index c4d2dc76..6a4b76d0 100644 --- a/service/pixelated/config/logger.py +++ b/service/pixelated/config/logger.py @@ -42,11 +42,14 @@ def init(debug=False): logging.getLogger('gnupg').addFilter(PrivateKeyFilter()) def formatter(event): - event['log_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(event['log_time'])) - event['log_level'] = event['log_level'].name.upper() - event['log_format'] = event.get('log_format') or '' - logstring = u'{log_time} [{log_namespace}] {log_level} ' + event['log_format'] + '\n' - return logstring.format(**event) + try: + event['log_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(event['log_time'])) + event['log_level'] = event['log_level'].name.upper() + event['log_format'] = event.get('log_format') or '' + logstring = u'{log_time} [{log_namespace}] {log_level} ' + event['log_format'] + '\n' + return logstring.format(**event) + except Exception as e: + return "Error while formatting log event: {!r}\nOriginal event: {!r}\n".format(e, event) observers = [FileLogObserver(sys.stdout, formatter)] globalLogBeginner.beginLoggingTo(observers) -- cgit v1.2.3 From 2b8268f24dad481bf5274664b8699582f116d83d Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Tue, 7 Feb 2017 15:09:19 -0200 Subject: [#952] Get rid of extra empty line on unhandled errors --- service/pixelated/config/logger.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service') diff --git a/service/pixelated/config/logger.py b/service/pixelated/config/logger.py index 6a4b76d0..bc4ab8d4 100644 --- a/service/pixelated/config/logger.py +++ b/service/pixelated/config/logger.py @@ -45,8 +45,8 @@ def init(debug=False): try: event['log_time'] = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(event['log_time'])) event['log_level'] = event['log_level'].name.upper() - event['log_format'] = event.get('log_format') or '' - logstring = u'{log_time} [{log_namespace}] {log_level} ' + event['log_format'] + '\n' + event['log_format'] = str(event['log_format']) + '\n' if event.get('log_format') else '' + logstring = u'{log_time} [{log_namespace}] {log_level} ' + event['log_format'] return logstring.format(**event) except Exception as e: return "Error while formatting log event: {!r}\nOriginal event: {!r}\n".format(e, event) -- cgit v1.2.3 From 2bfd4b8da51310da0e11d87f64f57990d93d79e0 Mon Sep 17 00:00:00 2001 From: Tayane Fernandes Date: Thu, 9 Feb 2017 13:33:30 -0200 Subject: [#922] Rename backup account flow To differentiate between the account recovery flow and the set backup email flow, we renamed all resources and url to reflect this. with @anikarni --- .../resources/account_recovery_resource.py | 46 ---------------------- .../pixelated/resources/backup_account_resource.py | 46 ++++++++++++++++++++++ service/pixelated/resources/root_resource.py | 4 +- .../resources/test_account_recovery_resource.py | 43 -------------------- .../unit/resources/test_backup_account_resource.py | 43 ++++++++++++++++++++ 5 files changed, 91 insertions(+), 91 deletions(-) delete mode 100644 service/pixelated/resources/account_recovery_resource.py create mode 100644 service/pixelated/resources/backup_account_resource.py delete mode 100644 service/test/unit/resources/test_account_recovery_resource.py create mode 100644 service/test/unit/resources/test_backup_account_resource.py (limited to 'service') diff --git a/service/pixelated/resources/account_recovery_resource.py b/service/pixelated/resources/account_recovery_resource.py deleted file mode 100644 index a69cac9a..00000000 --- a/service/pixelated/resources/account_recovery_resource.py +++ /dev/null @@ -1,46 +0,0 @@ -# -# Copyright (c) 2017 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see . - -import os -from xml.sax import SAXParseException - -from pixelated.resources import BaseResource -from twisted.python.filepath import FilePath -from pixelated.resources import get_static_folder -from twisted.web.http import OK -from twisted.web.template import Element, XMLFile, renderElement - - -class AccountRecoveryPage(Element): - loader = XMLFile(FilePath(os.path.join(get_static_folder(), 'account_recovery.html'))) - - def __init__(self): - super(AccountRecoveryPage, self).__init__() - - -class AccountRecoveryResource(BaseResource): - isLeaf = True - - def __init__(self, services_factory): - BaseResource.__init__(self, services_factory) - - def render_GET(self, request): - request.setResponseCode(OK) - return self._render_template(request) - - def _render_template(self, request): - site = AccountRecoveryPage() - return renderElement(request, site) diff --git a/service/pixelated/resources/backup_account_resource.py b/service/pixelated/resources/backup_account_resource.py new file mode 100644 index 00000000..5d9cb032 --- /dev/null +++ b/service/pixelated/resources/backup_account_resource.py @@ -0,0 +1,46 @@ +# +# Copyright (c) 2017 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +import os +from xml.sax import SAXParseException + +from pixelated.resources import BaseResource +from twisted.python.filepath import FilePath +from pixelated.resources import get_static_folder +from twisted.web.http import OK +from twisted.web.template import Element, XMLFile, renderElement + + +class BackupAccountPage(Element): + loader = XMLFile(FilePath(os.path.join(get_static_folder(), 'backup_account.html'))) + + def __init__(self): + super(BackupAccountPage, self).__init__() + + +class BackupAccountResource(BaseResource): + isLeaf = True + + def __init__(self, services_factory): + BaseResource.__init__(self, services_factory) + + def render_GET(self, request): + request.setResponseCode(OK) + return self._render_template(request) + + def _render_template(self, request): + site = BackupAccountPage() + return renderElement(request, site) diff --git a/service/pixelated/resources/root_resource.py b/service/pixelated/resources/root_resource.py index a97bd049..206cb3be 100644 --- a/service/pixelated/resources/root_resource.py +++ b/service/pixelated/resources/root_resource.py @@ -23,7 +23,7 @@ from pixelated.resources import BaseResource, UnAuthorizedResource, UnavailableR from pixelated.resources import get_startup_folder, get_static_folder from pixelated.resources.attachments_resource import AttachmentsResource from pixelated.resources.sandbox_resource import SandboxResource -from pixelated.resources.account_recovery_resource import AccountRecoveryResource +from pixelated.resources.backup_account_resource import BackupAccountResource from pixelated.resources.contacts_resource import ContactsResource from pixelated.resources.features_resource import FeaturesResource from pixelated.resources.feedback_resource import FeedbackResource @@ -89,7 +89,7 @@ class RootResource(BaseResource): return csrf_input and csrf_input == xsrf_token def initialize(self, provider=None, disclaimer_banner=None, authenticator=None): - self._child_resources.add('recovery', AccountRecoveryResource(self._services_factory)) + self._child_resources.add('backup-account', BackupAccountResource(self._services_factory)) self._child_resources.add('sandbox', SandboxResource(self._static_folder)) self._child_resources.add('assets', File(self._static_folder)) self._child_resources.add('keys', KeysResource(self._services_factory)) diff --git a/service/test/unit/resources/test_account_recovery_resource.py b/service/test/unit/resources/test_account_recovery_resource.py deleted file mode 100644 index 01ffaed2..00000000 --- a/service/test/unit/resources/test_account_recovery_resource.py +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright (c) 2017 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see . - -import os - -from mock import MagicMock, patch -from twisted.trial import unittest -from twisted.web.test.requesthelper import DummyRequest - -from pixelated.resources.account_recovery_resource import AccountRecoveryResource -from test.unit.resources import DummySite - - -class TestAccountRecoveryResource(unittest.TestCase): - def setUp(self): - self.services_factory = MagicMock() - self.resource = AccountRecoveryResource(self.services_factory) - self.web = DummySite(self.resource) - - def test_get(self): - request = DummyRequest(['/recovery']) - request.method = 'GET' - d = self.web.get(request) - - def assert_200_when_user_logged_in(_): - self.assertEqual(200, request.responseCode) - self.assertIn("DOCTYPE html", request.written[0]) - - d.addCallback(assert_200_when_user_logged_in) - return d diff --git a/service/test/unit/resources/test_backup_account_resource.py b/service/test/unit/resources/test_backup_account_resource.py new file mode 100644 index 00000000..21ae5aab --- /dev/null +++ b/service/test/unit/resources/test_backup_account_resource.py @@ -0,0 +1,43 @@ +# +# Copyright (c) 2017 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . + +import os + +from mock import MagicMock, patch +from twisted.trial import unittest +from twisted.web.test.requesthelper import DummyRequest + +from pixelated.resources.backup_account_resource import BackupAccountResource +from test.unit.resources import DummySite + + +class TestBackupAccountResource(unittest.TestCase): + def setUp(self): + self.services_factory = MagicMock() + self.resource = BackupAccountResource(self.services_factory) + self.web = DummySite(self.resource) + + def test_get(self): + request = DummyRequest(['/backup-account']) + request.method = 'GET' + d = self.web.get(request) + + def assert_200_when_user_logged_in(_): + self.assertEqual(200, request.responseCode) + self.assertIn("DOCTYPE html", request.written[0]) + + d.addCallback(assert_200_when_user_logged_in) + return d -- cgit v1.2.3 From cf7d2c516a897e6b19e0e11fd8c104e68a0951ad Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Thu, 9 Feb 2017 19:43:48 -0200 Subject: [#907] Remove unused login error handler The handle_error_deferred method is supposed to return the error message before the request is finished. This is not the case during the user services setup, since the request was already finished and returned with the interstitial page. --- service/pixelated/resources/login_resource.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'service') diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index 4d78174f..424e051b 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -20,7 +20,7 @@ from xml.sax import SAXParseException from pixelated.authentication import Authenticator from pixelated.config.leap import BootstrapUserServices from pixelated.resources import BaseResource, UnAuthorizedResource, IPixelatedSession -from pixelated.resources import handle_error_deferred, get_startup_folder +from pixelated.resources import get_startup_folder from twisted.cred.error import UnauthorizedLogin from twisted.internet import defer from twisted.logger import Logger @@ -139,8 +139,6 @@ class LoginResource(BaseResource): d = self._handle_login(request) d.addCallbacks(render_response, render_error) - d.addErrback(handle_error_deferred, request) - return NOT_DONE_YET @defer.inlineCallbacks @@ -151,7 +149,7 @@ class LoginResource(BaseResource): defer.returnValue(user_auth) def _complete_bootstrap(self, user_auth, request): - def log_error(error): + def login_error(error): log.error('Login error during %s services setup: %s \n %s' % (user_auth.username, error.getErrorMessage(), error.getTraceback())) def set_session_cookies(_): @@ -162,4 +160,4 @@ class LoginResource(BaseResource): password = request.args['password'][0] d = self._bootstrap_user_services.setup(user_auth, password, language) d.addCallback(set_session_cookies) - d.addErrback(log_error) + d.addErrback(login_error) -- cgit v1.2.3 From 29034222ca16c29e9301b769802a2e49446e9075 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Fri, 10 Feb 2017 14:12:04 -0200 Subject: [#907] Add login status to session --- service/pixelated/resources/login_resource.py | 14 ++++--- service/pixelated/resources/session.py | 15 ++++++++ service/test/unit/resources/test_login_resource.py | 45 +++++++++++++++++++++- 3 files changed, 68 insertions(+), 6 deletions(-) (limited to 'service') diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index 424e051b..ddc22b2a 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -149,15 +149,19 @@ class LoginResource(BaseResource): defer.returnValue(user_auth) def _complete_bootstrap(self, user_auth, request): - def login_error(error): + def login_error(error, session): log.error('Login error during %s services setup: %s \n %s' % (user_auth.username, error.getErrorMessage(), error.getTraceback())) + session.login_error() - def set_session_cookies(_): - session = IPixelatedSession(request.getSession()) + def set_session_cookies(_, session): session.user_uuid = user_auth.uuid + session.login_completed() language = parse_accept_language(request.getAllHeaders()) password = request.args['password'][0] + session = IPixelatedSession(request.getSession()) + session.login_started() + d = self._bootstrap_user_services.setup(user_auth, password, language) - d.addCallback(set_session_cookies) - d.addErrback(login_error) + d.addCallback(set_session_cookies, session) + d.addErrback(login_error, session) diff --git a/service/pixelated/resources/session.py b/service/pixelated/resources/session.py index 9ade8d29..84f2ebeb 100644 --- a/service/pixelated/resources/session.py +++ b/service/pixelated/resources/session.py @@ -21,6 +21,7 @@ from twisted.web.server import Session class IPixelatedSession(Interface): user_uuid = Attribute('The uuid of the currently logged in user') + login_status = Attribute('The status during user login') class PixelatedSession(object): @@ -28,12 +29,26 @@ class PixelatedSession(object): def __init__(self, session): self.user_uuid = None + self.login_status = None def is_logged_in(self): return self.user_uuid is not None def expire(self): self.user_uuid = None + self.login_status = None + + def login_started(self): + self.login_status = 'started' + + def login_completed(self): + self.login_status = 'completed' + + def login_error(self): + self.login_status = 'error' + + def check_login_status(self): + return self.login_status registerAdapter(PixelatedSession, Session, IPixelatedSession) diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py index cec57123..6dea7abb 100644 --- a/service/test/unit/resources/test_login_resource.py +++ b/service/test/unit/resources/test_login_resource.py @@ -259,7 +259,7 @@ class TestLoginPOST(unittest.TestCase): @patch('pixelated.config.leap.BootstrapUserServices.setup') @patch('pixelated.authentication.Authenticator.authenticate') - def test_successful_adds_cookies_to_indicat_logged_in_status_when_services_are_loaded(self, mock_authenticate, mock_user_bootstrap_setup): + def test_successful_adds_cookies_to_indicate_logged_in_status_when_services_are_loaded(self, mock_authenticate, mock_user_bootstrap_setup): mock_authenticate.return_value = self.user_auth irrelevant = None mock_user_bootstrap_setup.return_value = defer.succeed(irrelevant) @@ -271,3 +271,46 @@ class TestLoginPOST(unittest.TestCase): d.addCallback(assert_login_setup_service_for_user) return d + + @patch('pixelated.resources.session.PixelatedSession.login_started') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_session_adds_login_started_status_after_authentication(self, mock_authenticate, mock_login_started): + mock_authenticate.return_value = self.user_auth + + d = self.web.get(self.request) + + def assert_login_started_called(_): + mock_login_started.assert_called_once() + + d.addCallback(assert_login_started_called) + return d + + @patch('pixelated.resources.session.PixelatedSession.login_completed') + @patch('pixelated.config.leap.BootstrapUserServices.setup') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_session_adds_login_completed_status_when_services_setup_finishes(self, mock_authenticate, mock_user_bootstrap_setup, mock_login_completed): + mock_authenticate.return_value = self.user_auth + mock_user_bootstrap_setup.return_value = defer.succeed(None) + + d = self.web.get(self.request) + + def assert_login_completed_called(_): + mock_login_completed.assert_called_once() + + d.addCallback(assert_login_completed_called) + return d + + @patch('pixelated.resources.session.PixelatedSession.login_error') + @patch('pixelated.config.leap.BootstrapUserServices.setup') + @patch('pixelated.authentication.Authenticator.authenticate') + def test_session_adds_login_error_status_when_services_setup_gets_error(self, mock_authenticate, mock_user_bootstrap_setup, mock_login_error): + mock_authenticate.return_value = self.user_auth + mock_user_bootstrap_setup.return_value = defer.fail(Exception('Could not setup user services')) + + d = self.web.get(self.request) + + def assert_login_error_called(_): + mock_login_error.assert_called_once() + + d.addCallback(assert_login_error_called) + return d -- cgit v1.2.3 From 8639b2ce3fa922cdb0871235d3791ab0fb65e810 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Fri, 10 Feb 2017 15:38:03 -0200 Subject: [#907] Encapsulate user_uuid on login complete with @akanim --- service/pixelated/resources/login_resource.py | 3 +-- service/pixelated/resources/session.py | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'service') diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index ddc22b2a..74369605 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -154,8 +154,7 @@ class LoginResource(BaseResource): session.login_error() def set_session_cookies(_, session): - session.user_uuid = user_auth.uuid - session.login_completed() + session.login_completed(user_auth.uuid) language = parse_accept_language(request.getAllHeaders()) password = request.args['password'][0] diff --git a/service/pixelated/resources/session.py b/service/pixelated/resources/session.py index 84f2ebeb..5f48a090 100644 --- a/service/pixelated/resources/session.py +++ b/service/pixelated/resources/session.py @@ -41,7 +41,8 @@ class PixelatedSession(object): def login_started(self): self.login_status = 'started' - def login_completed(self): + def login_completed(self, user_uuid): + self.user_uuid = user_uuid self.login_status = 'completed' def login_error(self): -- cgit v1.2.3 From 00f35893e37ec8cec8a0cb10b41400ad7e782ed5 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Fri, 10 Feb 2017 16:18:03 -0200 Subject: [#907] Change interstitial to query for new status resource with @akanim --- service/pixelated/assets/Interstitial.js | 6 +++--- service/pixelated/resources/login_resource.py | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) (limited to 'service') diff --git a/service/pixelated/assets/Interstitial.js b/service/pixelated/assets/Interstitial.js index ac5a789a..cda56a4b 100644 --- a/service/pixelated/assets/Interstitial.js +++ b/service/pixelated/assets/Interstitial.js @@ -1,7 +1,7 @@ if ($('#hive').length) { var hive = new Snap('#hive'); var img_width = $('#hive').width(); - var left_pos = img_width * .5; + var left_pos = img_width * 0.5; var pixelated = hive.path("M12.4,20.3v31.8l28,15.8l28-15.8V20.3l-28-15.8L12.4,20.3z M39.2,56.4l-16.3-9V27.9l16.3,9.3L39.2,56.4z M57.7,47.4l-16.1,9l0-19.2l16.1-9.4V47.4z M57.7,25.2L40.4,35.5L22.9,25.2l17.5-9.4L57.7,25.2z").transform("translate(319, 50)").attr("fill", "#908e8e"); var all = hive.group().transform("matrix(2, 0, 0, 2, -100, -100)"); @@ -42,9 +42,9 @@ $(function () { var handler = setInterval(function () { $.ajax({ method: 'GET', - url: '/' + url: '/login/status' }).success(function (data) { - if (/Pixelated Mail/g.test(data)) { + if (data === 'completed' || data === 'error') { window.location="/"; } }); diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index 74369605..2a9be77b 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -106,6 +106,8 @@ class LoginResource(BaseResource): return self if path == 'login': return self + if path == 'status': + return LoginStatusResource(self._services_factory) if not self.is_logged_in(request): return UnAuthorizedResource() return NoResource() @@ -164,3 +166,14 @@ class LoginResource(BaseResource): d = self._bootstrap_user_services.setup(user_auth, password, language) d.addCallback(set_session_cookies, session) d.addErrback(login_error, session) + + +class LoginStatusResource(BaseResource): + isLeaf = True + + def __init__(self, services_factory): + BaseResource.__init__(self, services_factory) + + def render_GET(self, request): + session = IPixelatedSession(request.getSession()) + return format(session.check_login_status()) -- cgit v1.2.3 From 0edf2078caf98be00bcd48846acec563df630616 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Mon, 13 Feb 2017 12:54:59 -0200 Subject: [#907] Rename successful login variables and methods --- service/pixelated/resources/login_resource.py | 6 +++--- service/pixelated/resources/session.py | 2 +- service/test/unit/resources/test_login_resource.py | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'service') diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index 2a9be77b..77ebca70 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -155,8 +155,8 @@ class LoginResource(BaseResource): log.error('Login error during %s services setup: %s \n %s' % (user_auth.username, error.getErrorMessage(), error.getTraceback())) session.login_error() - def set_session_cookies(_, session): - session.login_completed(user_auth.uuid) + def login_successful(_, session): + session.login_successful(user_auth.uuid) language = parse_accept_language(request.getAllHeaders()) password = request.args['password'][0] @@ -164,7 +164,7 @@ class LoginResource(BaseResource): session.login_started() d = self._bootstrap_user_services.setup(user_auth, password, language) - d.addCallback(set_session_cookies, session) + d.addCallback(login_successful, session) d.addErrback(login_error, session) diff --git a/service/pixelated/resources/session.py b/service/pixelated/resources/session.py index 5f48a090..5dfa52e6 100644 --- a/service/pixelated/resources/session.py +++ b/service/pixelated/resources/session.py @@ -41,7 +41,7 @@ class PixelatedSession(object): def login_started(self): self.login_status = 'started' - def login_completed(self, user_uuid): + def login_successful(self, user_uuid): self.user_uuid = user_uuid self.login_status = 'completed' diff --git a/service/test/unit/resources/test_login_resource.py b/service/test/unit/resources/test_login_resource.py index 6dea7abb..834b9710 100644 --- a/service/test/unit/resources/test_login_resource.py +++ b/service/test/unit/resources/test_login_resource.py @@ -285,19 +285,19 @@ class TestLoginPOST(unittest.TestCase): d.addCallback(assert_login_started_called) return d - @patch('pixelated.resources.session.PixelatedSession.login_completed') + @patch('pixelated.resources.session.PixelatedSession.login_successful') @patch('pixelated.config.leap.BootstrapUserServices.setup') @patch('pixelated.authentication.Authenticator.authenticate') - def test_session_adds_login_completed_status_when_services_setup_finishes(self, mock_authenticate, mock_user_bootstrap_setup, mock_login_completed): + def test_session_adds_login_successful_status_when_services_setup_finishes(self, mock_authenticate, mock_user_bootstrap_setup, mock_login_successful): mock_authenticate.return_value = self.user_auth mock_user_bootstrap_setup.return_value = defer.succeed(None) d = self.web.get(self.request) - def assert_login_completed_called(_): - mock_login_completed.assert_called_once() + def assert_login_successful_called(_): + mock_login_successful.assert_called_once() - d.addCallback(assert_login_completed_called) + d.addCallback(assert_login_successful_called) return d @patch('pixelated.resources.session.PixelatedSession.login_error') -- cgit v1.2.3 From 7fdf9f62c785835c4ea0863dae36bee9611221a5 Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Mon, 13 Feb 2017 15:23:11 -0200 Subject: [#907] Change login status to return json with @anikarni --- service/pixelated/assets/Interstitial.js | 2 +- service/pixelated/resources/login_resource.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'service') diff --git a/service/pixelated/assets/Interstitial.js b/service/pixelated/assets/Interstitial.js index cda56a4b..2eaa7a1c 100644 --- a/service/pixelated/assets/Interstitial.js +++ b/service/pixelated/assets/Interstitial.js @@ -44,7 +44,7 @@ $(function () { method: 'GET', url: '/login/status' }).success(function (data) { - if (data === 'completed' || data === 'error') { + if (data.status === 'completed' || data.status === 'error') { window.location="/"; } }); diff --git a/service/pixelated/resources/login_resource.py b/service/pixelated/resources/login_resource.py index 77ebca70..4bbceb89 100644 --- a/service/pixelated/resources/login_resource.py +++ b/service/pixelated/resources/login_resource.py @@ -20,7 +20,7 @@ from xml.sax import SAXParseException from pixelated.authentication import Authenticator from pixelated.config.leap import BootstrapUserServices from pixelated.resources import BaseResource, UnAuthorizedResource, IPixelatedSession -from pixelated.resources import get_startup_folder +from pixelated.resources import get_startup_folder, respond_json from twisted.cred.error import UnauthorizedLogin from twisted.internet import defer from twisted.logger import Logger @@ -176,4 +176,5 @@ class LoginStatusResource(BaseResource): def render_GET(self, request): session = IPixelatedSession(request.getSession()) - return format(session.check_login_status()) + response = {'status': str(session.check_login_status())} + return respond_json(response, request) -- cgit v1.2.3 From d80b44f079b5fd3d9bf51962542516b9f6340f3a Mon Sep 17 00:00:00 2001 From: Anike Arni Date: Tue, 3 Jan 2017 11:24:35 -0200 Subject: Uses leap fork to test soledad streaming changes --- service/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service') diff --git a/service/requirements.txt b/service/requirements.txt index ad990332..fb87f846 100644 --- a/service/requirements.txt +++ b/service/requirements.txt @@ -8,6 +8,6 @@ whoosh==2.6.0 Twisted==16.1.1 -e 'git+https://0xacab.org/pixelated/leap_pycommon.git@develop#egg=leap.common' -e 'git+https://0xacab.org/pixelated/bitmask-dev.git@feat_fetch_remote_on_expiry#egg=leap.bitmask' --e 'git+https://0xacab.org/pixelated/soledad.git@develop#egg=leap.soledad.common&subdirectory=common/' --e 'git+https://0xacab.org/pixelated/soledad.git@develop#egg=leap.soledad.client&subdirectory=client/' +-e 'git+https://0xacab.org/leap/soledad.git@develop#egg=leap.soledad.common&subdirectory=common/' +-e 'git+https://0xacab.org/leap/soledad.git@develop#egg=leap.soledad.client&subdirectory=client/' -e . -- cgit v1.2.3 From 9c6e2a7f40f3e96b203e1528ab974286e27a8d32 Mon Sep 17 00:00:00 2001 From: Anike Arni Date: Wed, 18 Jan 2017 14:14:15 -0200 Subject: Revert "Revert "[#888] Fix soledad class contract to be compatible with new merge. with @thaissiqueira."" This reverts commit 1e6e165a3fc397e45884eaec1122ba0cc5ff923e. --- service/pixelated/config/sessions.py | 3 +-- service/test/support/integration/app_test_client.py | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'service') diff --git a/service/pixelated/config/sessions.py b/service/pixelated/config/sessions.py index eb233a9f..594b8e35 100644 --- a/service/pixelated/config/sessions.py +++ b/service/pixelated/config/sessions.py @@ -95,8 +95,7 @@ class LeapSessionFactory(object): server_url=server_url, cert_file=api_cert, shared_db=None, - auth_token=user_token, - defer_encryption=False) + auth_token=user_token) defer.returnValue(soledad) except (WrongMacError, UnknownMacMethodError), e: raise SoledadWrongPassphraseException(e) diff --git a/service/test/support/integration/app_test_client.py b/service/test/support/integration/app_test_client.py index d52c85c0..0ff1df31 100644 --- a/service/test/support/integration/app_test_client.py +++ b/service/test/support/integration/app_test_client.py @@ -437,9 +437,7 @@ def initialize_soledad(tempdir, uuid): secret_path, local_db_path, server_url, - cert_file, - defer_encryption=False, - syncable=False) + cert_file) yield SoledadMailAdaptor().initialize_store(_soledad) -- cgit v1.2.3 From 038d21cecd47ab185cfe575d5f51aa34b5ad6178 Mon Sep 17 00:00:00 2001 From: Anike Arni Date: Wed, 18 Jan 2017 16:17:43 -0200 Subject: Use version of soledad from pixelated streaming branch --- service/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service') diff --git a/service/requirements.txt b/service/requirements.txt index fb87f846..2f39f88f 100644 --- a/service/requirements.txt +++ b/service/requirements.txt @@ -8,6 +8,6 @@ whoosh==2.6.0 Twisted==16.1.1 -e 'git+https://0xacab.org/pixelated/leap_pycommon.git@develop#egg=leap.common' -e 'git+https://0xacab.org/pixelated/bitmask-dev.git@feat_fetch_remote_on_expiry#egg=leap.bitmask' --e 'git+https://0xacab.org/leap/soledad.git@develop#egg=leap.soledad.common&subdirectory=common/' --e 'git+https://0xacab.org/leap/soledad.git@develop#egg=leap.soledad.client&subdirectory=client/' +-e 'git+https://0xacab.org/pixelated/soledad.git@streaming-branch#egg=leap.soledad.common&subdirectory=common/' +-e 'git+https://0xacab.org/pixelated/soledad.git@streaming-branch#egg=leap.soledad.client&subdirectory=client/' -e . -- cgit v1.2.3 From d5869b8e2f7a53ba95a0df6f2fd7129930b8a5c3 Mon Sep 17 00:00:00 2001 From: Thais Siqueira Date: Tue, 14 Feb 2017 16:04:54 -0200 Subject: Use soledad 0.9.2 version --- service/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service') diff --git a/service/requirements.txt b/service/requirements.txt index 2f39f88f..ca80da7c 100644 --- a/service/requirements.txt +++ b/service/requirements.txt @@ -8,6 +8,6 @@ whoosh==2.6.0 Twisted==16.1.1 -e 'git+https://0xacab.org/pixelated/leap_pycommon.git@develop#egg=leap.common' -e 'git+https://0xacab.org/pixelated/bitmask-dev.git@feat_fetch_remote_on_expiry#egg=leap.bitmask' --e 'git+https://0xacab.org/pixelated/soledad.git@streaming-branch#egg=leap.soledad.common&subdirectory=common/' --e 'git+https://0xacab.org/pixelated/soledad.git@streaming-branch#egg=leap.soledad.client&subdirectory=client/' +-e 'git+https://0xacab.org/leap/soledad.git@0.9.2#egg=leap.soledad.common&subdirectory=common/' +-e 'git+https://0xacab.org/leap/soledad.git@0.9.2#egg=leap.soledad.client&subdirectory=client/' -e . -- cgit v1.2.3 From f465aaffc4a520b6026a1bfda58371b8c5265664 Mon Sep 17 00:00:00 2001 From: Thais Siqueira Date: Wed, 15 Feb 2017 11:48:28 -0200 Subject: Change the soledad branch to point to master --- service/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service') diff --git a/service/requirements.txt b/service/requirements.txt index ca80da7c..d642c8e8 100644 --- a/service/requirements.txt +++ b/service/requirements.txt @@ -8,6 +8,6 @@ whoosh==2.6.0 Twisted==16.1.1 -e 'git+https://0xacab.org/pixelated/leap_pycommon.git@develop#egg=leap.common' -e 'git+https://0xacab.org/pixelated/bitmask-dev.git@feat_fetch_remote_on_expiry#egg=leap.bitmask' --e 'git+https://0xacab.org/leap/soledad.git@0.9.2#egg=leap.soledad.common&subdirectory=common/' --e 'git+https://0xacab.org/leap/soledad.git@0.9.2#egg=leap.soledad.client&subdirectory=client/' +-e 'git+https://0xacab.org/leap/soledad.git@master#egg=leap.soledad.common&subdirectory=common/' +-e 'git+https://0xacab.org/leap/soledad.git@master#egg=leap.soledad.client&subdirectory=client/' -e . -- cgit v1.2.3 From 49fd4083b742fb13f7c759c4edee3f8fb2818097 Mon Sep 17 00:00:00 2001 From: Thais Siqueira Date: Wed, 15 Feb 2017 15:22:12 -0200 Subject: [#888] Using soledad master branch from pixelated fork with @tayanefernandes --- service/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'service') diff --git a/service/requirements.txt b/service/requirements.txt index d642c8e8..dace91b2 100644 --- a/service/requirements.txt +++ b/service/requirements.txt @@ -8,6 +8,6 @@ whoosh==2.6.0 Twisted==16.1.1 -e 'git+https://0xacab.org/pixelated/leap_pycommon.git@develop#egg=leap.common' -e 'git+https://0xacab.org/pixelated/bitmask-dev.git@feat_fetch_remote_on_expiry#egg=leap.bitmask' --e 'git+https://0xacab.org/leap/soledad.git@master#egg=leap.soledad.common&subdirectory=common/' --e 'git+https://0xacab.org/leap/soledad.git@master#egg=leap.soledad.client&subdirectory=client/' +-e 'git+https://0xacab.org/pixelated/soledad.git@master#egg=leap.soledad.common&subdirectory=common/' +-e 'git+https://0xacab.org/pixelated/soledad.git@master#egg=leap.soledad.client&subdirectory=client/' -e . -- cgit v1.2.3 From 0b966e696c6a99f825510d406008fc9b9936077e Mon Sep 17 00:00:00 2001 From: Tulio Casagrande Date: Mon, 13 Feb 2017 18:43:15 -0200 Subject: [#907] Convert login page to react with @anikarni --- service/pixelated/assets/Interstitial.html | 18 --- service/pixelated/assets/Interstitial.js | 58 ---------- .../pixelated/assets/_login_disclaimer_banner.html | 9 -- service/pixelated/assets/favicon.png | Bin 592 -> 0 bytes service/pixelated/assets/hive-bg.png | Bin 3356 -> 0 bytes service/pixelated/assets/index.html | 9 -- service/pixelated/assets/jquery-2.1.3.min.js | 4 - service/pixelated/assets/login.html | 36 ------ service/pixelated/assets/normalize.min.css | 1 - service/pixelated/assets/opensans.css | 69 ----------- service/pixelated/assets/pixelated-logo-orange.svg | 29 ----- service/pixelated/assets/pixelated.css | 128 --------------------- service/pixelated/assets/snap.svg-min.js | 20 ---- service/pixelated/resources/login_resource.py | 12 +- service/pixelated/resources/root_resource.py | 4 +- service/test/unit/resources/test_login_resource.py | 18 +-- 16 files changed, 13 insertions(+), 402 deletions(-) delete mode 100644 service/pixelated/assets/Interstitial.html delete mode 100644 service/pixelated/assets/Interstitial.js delete mode 100644 service/pixelated/assets/_login_disclaimer_banner.html delete mode 100644 service/pixelated/assets/favicon.png delete mode 100644 service/pixelated/assets/hive-bg.png delete mode 100644 service/pixelated/assets/index.html delete mode 100644 service/pixelated/assets/jquery-2.1.3.min.js delete mode 100644 service/pixelated/assets/login.html delete mode 100644 service/pixelated/assets/normalize.min.css delete mode 100644 service/pixelated/assets/opensans.css delete mode 100644 service/pixelated/assets/pixelated-logo-orange.svg delete mode 100644 service/pixelated/assets/pixelated.css delete mode 100644 service/pixelated/assets/snap.svg-min.js (limited to 'service') diff --git a/service/pixelated/assets/Interstitial.html b/service/pixelated/assets/Interstitial.html deleted file mode 100644 index bc6cc738..00000000 --- a/service/pixelated/assets/Interstitial.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - -
- -
- - - - diff --git a/service/pixelated/assets/Interstitial.js b/service/pixelated/assets/Interstitial.js deleted file mode 100644 index 2eaa7a1c..00000000 --- a/service/pixelated/assets/Interstitial.js +++ /dev/null @@ -1,58 +0,0 @@ -if ($('#hive').length) { - var hive = new Snap('#hive'); - var img_width = $('#hive').width(); - var left_pos = img_width * 0.5; - - var pixelated = hive.path("M12.4,20.3v31.8l28,15.8l28-15.8V20.3l-28-15.8L12.4,20.3z M39.2,56.4l-16.3-9V27.9l16.3,9.3L39.2,56.4z M57.7,47.4l-16.1,9l0-19.2l16.1-9.4V47.4z M57.7,25.2L40.4,35.5L22.9,25.2l17.5-9.4L57.7,25.2z").transform("translate(319, 50)").attr("fill", "#908e8e"); - var all = hive.group().transform("matrix(2, 0, 0, 2, -100, -100)"); - - var height = 50; - var width = 58; - var rows = (($(window).height() / height) / 2) + 1; - var cols = (($(window).width() / width) / 2) + 1; - - - for (var j = 0; j < rows; j++) { - for (var i = 0; i < cols; i++) { - x = i * width + (j%2*width/2); - y = j * height; - all.add(pixelated.clone().transform("translate("+x+","+y+")")); - } - } - - all.add(pixelated); - - var brightenLogo = function () { - var glowPosition = Math.floor(Math.random()*rows*cols); - - all[glowPosition].animate({fill: "#FFF"}, 1000, function() { - darkenLogo(all[glowPosition]); - }); - }; - - var darkenLogo = function (el) { - el.animate({fill: "#908e8e"}, 1000, brightenLogo); - }; - - brightenLogo(); - -} - -$(function () { - var handler = setInterval(function () { - $.ajax({ - method: 'GET', - url: '/login/status' - }).success(function (data) { - if (data.status === 'completed' || data.status === 'error') { - window.location="/"; - } - }); - }, 2000); - - $('#hive-section').height($(window).height()); - - $(window).resize(function() { - window.location.reload(true); - }); -}); diff --git a/service/pixelated/assets/_login_disclaimer_banner.html b/service/pixelated/assets/_login_disclaimer_banner.html deleted file mode 100644 index dfc63030..00000000 --- a/service/pixelated/assets/_login_disclaimer_banner.html +++ /dev/null @@ -1,9 +0,0 @@ -
-
    -

    Some disclaimer

    -
  • - please supply the option --banner with an XML compatible file -
    to override this default message
    -
  • -
-
diff --git a/service/pixelated/assets/favicon.png b/service/pixelated/assets/favicon.png deleted file mode 100644 index e14841c7..00000000 Binary files a/service/pixelated/assets/favicon.png and /dev/null differ diff --git a/service/pixelated/assets/hive-bg.png b/service/pixelated/assets/hive-bg.png deleted file mode 100644 index 77316967..00000000 Binary files a/service/pixelated/assets/hive-bg.png and /dev/null differ diff --git a/service/pixelated/assets/index.html b/service/pixelated/assets/index.html deleted file mode 100644 index c095577e..00000000 --- a/service/pixelated/assets/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - click here - - - diff --git a/service/pixelated/assets/jquery-2.1.3.min.js b/service/pixelated/assets/jquery-2.1.3.min.js deleted file mode 100644 index 25714ed2..00000000 --- a/service/pixelated/assets/jquery-2.1.3.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.1.3 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.3",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)+1>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=hb(),z=hb(),A=hb(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N=M.replace("w","w#"),O="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+N+"))|)"+L+"*\\]",P=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+O+")*)|.*)\\)|)",Q=new RegExp(L+"+","g"),R=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),S=new RegExp("^"+L+"*,"+L+"*"),T=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),U=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),V=new RegExp(P),W=new RegExp("^"+N+"$"),X={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+O),PSEUDO:new RegExp("^"+P),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},eb=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(fb){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function gb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],k=b.nodeType,"string"!=typeof a||!a||1!==k&&9!==k&&11!==k)return d;if(!e&&p){if(11!==k&&(f=_.exec(a)))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return H.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName)return H.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=1!==k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+rb(o[l]);w=ab.test(a)&&pb(b.parentNode)||b,x=o.join(",")}if(x)try{return H.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function hb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ib(a){return a[u]=!0,a}function jb(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function kb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function lb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function nb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function ob(a){return ib(function(b){return b=+b,ib(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function pb(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=gb.support={},f=gb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=gb.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=g.documentElement,e=g.defaultView,e&&e!==e.top&&(e.addEventListener?e.addEventListener("unload",eb,!1):e.attachEvent&&e.attachEvent("onunload",eb)),p=!f(g),c.attributes=jb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=jb(function(a){return a.appendChild(g.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(g.getElementsByClassName),c.getById=jb(function(a){return o.appendChild(a).id=u,!g.getElementsByName||!g.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(g.querySelectorAll))&&(jb(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),jb(function(a){var b=g.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&jb(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",P)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===g||a.ownerDocument===v&&t(v,a)?-1:b===g||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,h=[a],i=[b];if(!e||!f)return a===g?-1:b===g?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return lb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?lb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},g):n},gb.matches=function(a,b){return gb(a,null,null,b)},gb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return gb(b,n,null,[a]).length>0},gb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},gb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},gb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},gb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=gb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=gb.selectors={cacheLength:50,createPseudo:ib,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||gb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&gb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=gb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(Q," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||gb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ib(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ib(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?ib(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ib(function(a){return function(b){return gb(a,b).length>0}}),contains:ib(function(a){return a=a.replace(cb,db),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ib(function(a){return W.test(a||"")||gb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:ob(function(){return[0]}),last:ob(function(a,b){return[b-1]}),eq:ob(function(a,b,c){return[0>c?c+b:c]}),even:ob(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:ob(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:ob(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:ob(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function sb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function tb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ub(a,b,c){for(var d=0,e=b.length;e>d;d++)gb(a,b[d],c);return c}function vb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function wb(a,b,c,d,e,f){return d&&!d[u]&&(d=wb(d)),e&&!e[u]&&(e=wb(e,f)),ib(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ub(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:vb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=vb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=vb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function xb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=sb(function(a){return a===b},h,!0),l=sb(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[sb(tb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return wb(i>1&&tb(m),i>1&&rb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&xb(a.slice(i,e)),f>e&&xb(a=a.slice(e)),f>e&&rb(a))}m.push(c)}return tb(m)}function yb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=F.call(i));s=vb(s)}H.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&gb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?ib(f):f}return h=gb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=xb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,yb(e,d)),f.selector=a}return f},i=gb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&pb(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&rb(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&pb(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=jb(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),jb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||kb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&jb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||kb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),jb(function(a){return null==a.getAttribute("disabled")})||kb(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),gb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+K.uid++}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c) -},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("