diff options
Diffstat (limited to 'debug_toolbar')
43 files changed, 1837 insertions, 1533 deletions
diff --git a/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.mo b/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.mo Binary files differnew file mode 100644 index 0000000..0fa0a13 --- /dev/null +++ b/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.mo diff --git a/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.po b/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 0000000..80a1bd2 --- /dev/null +++ b/debug_toolbar/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,367 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Percy Pérez-Pinedo, 2009. +# +# +msgid "" +msgstr "" +"Project-Id-Version: Django Debug Toolbar 0.8.4\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-01-22 08:58+0000\n" +"PO-Revision-Date: 2011-01-22 08:58+0000\n" +"Last-Translator: Eduardo Cereto Carvalho <eduardocereto@gmail.com>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: panels/cache.py:92 +#, python-format +msgid "Cache: %.2fms" +msgstr "Cache: %.2fms" + +#: panels/cache.py:95 +msgid "Cache Usage" +msgstr "Uso do Cache" + +#: panels/headers.py:36 panels/headers.py:39 +msgid "HTTP Headers" +msgstr "Cabeçalhos HTTP" + +#: panels/logger.py:56 +msgid "Logging" +msgstr "Logs" + +#: panels/logger.py:63 +msgid "Log Messages" +msgstr "Mensagens de Log" + +#: panels/request_vars.py:13 panels/request_vars.py:16 +msgid "Request Vars" +msgstr "Variáveis do Request" + +#: panels/settings_vars.py:16 +msgid "Settings" +msgstr "Configurações" + +#: panels/settings_vars.py:19 +#, python-format +msgid "Settings from <code>%s</code>" +msgstr "Configurações de <code>%s</code>" + +#: panels/signals.py:39 panels/signals.py:42 +msgid "Signals" +msgstr "Sinais" + +#: panels/sql.py:146 +msgid "SQL" +msgstr "SQL" + +#: panels/sql.py:160 +msgid "SQL Queries" +msgstr "Queries SQL" + +#: panels/template.py:47 +msgid "Templates" +msgstr "Templates" + +#: panels/template.py:52 +#, python-format +msgid "Templates (%(num_templates)s rendered)" +msgstr "Templates (%(num_templates)s renderizados)" + +#: panels/timer.py:35 templates/debug_toolbar/panels/cache.html:39 +#: templates/debug_toolbar/panels/logger.html:7 +#: templates/debug_toolbar/panels/sql.html:5 +#: templates/debug_toolbar/panels/sql_explain.html:11 +#: templates/debug_toolbar/panels/sql_profile.html:12 +#: templates/debug_toolbar/panels/sql_select.html:11 +msgid "Time" +msgstr "Tempo" + +#: panels/timer.py:47 +msgid "Resource Usage" +msgstr "Uso de Recursos" + +#: panels/timer.py:78 +msgid "User CPU time" +msgstr "Tempo de CPU do usuário" + +#: panels/timer.py:79 +msgid "System CPU time" +msgstr "Tempo de CPU do sistema" + +#: panels/timer.py:80 +msgid "Total CPU time" +msgstr "Tempo de CPU total" + +#: panels/timer.py:81 +msgid "Elapsed time" +msgstr "Tempo decorrido" + +#: panels/timer.py:82 +msgid "Context switches" +msgstr "Alterações de contexto" + +#: panels/version.py:20 panels/version.py:29 +msgid "Versions" +msgstr "Versões" + +#: templates/debug_toolbar/base.html:23 +msgid "Hide Toolbar" +msgstr "Esconder Barra" + +#: templates/debug_toolbar/base.html:23 +msgid "Hide" +msgstr "Esconder" + +#: templates/debug_toolbar/base.html:48 +msgid "Show Toolbar" +msgstr "Mostrar Barra" + +#: templates/debug_toolbar/base.html:54 +msgid "Close" +msgstr "Fechar" + +#: templates/debug_toolbar/redirect.html:7 +#: templates/debug_toolbar/panels/logger.html:9 +msgid "Location" +msgstr "Localização" + +#: templates/debug_toolbar/redirect.html:9 +msgid "" +"The Django Debug Toolbar has intercepted a redirect to the above URL for " +"debug viewing purposes. You can click the above link to continue with the " +"redirect as normal. If you'd like to disable this feature, set the " +"<code>DEBUG_TOOLBAR_CONFIG</code> dictionary's key " +"<code>INTERCEPT_REDIRECTS</code> to <code>False</code>." +msgstr "" +"A Barra de Debug do Django interceptou um redirecionamento para a URL acima por " +"propósito de debug. Você pode clicar no link acima para continuar com o " +"redirecionamento normal. Se você gostaria de desabilitar essa funcionalidade, configure a " +"chave <code></code> do dicionário " +"<code>DEBUG_TOOLBAR_CONFIG</code> para <code>False</code>" + +#: templates/debug_toolbar/panels/cache.html:14 +msgid "Total Calls" +msgstr "Total de Chamadas" + +#: templates/debug_toolbar/panels/cache.html:16 +msgid "Total Time" +msgstr "Tempo Total" + +#: templates/debug_toolbar/panels/cache.html:18 +msgid "Hits" +msgstr "Hits" + +#: templates/debug_toolbar/panels/cache.html:20 +msgid "Misses" +msgstr "Misses" + +#: templates/debug_toolbar/panels/cache.html:35 +msgid "Breakdown" +msgstr "Breakdown" + +#: templates/debug_toolbar/panels/cache.html:40 +msgid "Type" +msgstr "Tipo" + +#: templates/debug_toolbar/panels/cache.html:41 +msgid "Parameters" +msgstr "Parâmetros" + +#: templates/debug_toolbar/panels/cache.html:42 +msgid "Function" +msgstr "Função" + +#: templates/debug_toolbar/panels/headers.html:5 +msgid "Key" +msgstr "Chave" + +#: templates/debug_toolbar/panels/headers.html:6 +#: templates/debug_toolbar/panels/request_vars.html:37 +#: templates/debug_toolbar/panels/request_vars.html:63 +#: templates/debug_toolbar/panels/request_vars.html:85 +#: templates/debug_toolbar/panels/request_vars.html:107 +#: templates/debug_toolbar/panels/settings_vars.html:6 +#: templates/debug_toolbar/panels/timer.html:10 +msgid "Value" +msgstr "Valor" + +#: templates/debug_toolbar/panels/logger.html:6 +msgid "Level" +msgstr "Nível" + +#: templates/debug_toolbar/panels/logger.html:8 +msgid "Message" +msgstr "Mensagem" + +#: templates/debug_toolbar/panels/logger.html:24 +msgid "No messages logged" +msgstr "Nenhuma mensagem logada" + +#: templates/debug_toolbar/panels/request_vars.html:3 +msgid "View information" +msgstr "Informações da View" + +#: templates/debug_toolbar/panels/request_vars.html:7 +msgid "View Function" +msgstr "Função View" + +#: templates/debug_toolbar/panels/request_vars.html:8 +msgid "args" +msgstr "args" + +#: templates/debug_toolbar/panels/request_vars.html:9 +msgid "kwargs" +msgstr "kwargs" + +#: templates/debug_toolbar/panels/request_vars.html:27 +msgid "COOKIES Variables" +msgstr "Variáveis do COOKIE" + +#: templates/debug_toolbar/panels/request_vars.html:36 +#: templates/debug_toolbar/panels/request_vars.html:62 +#: templates/debug_toolbar/panels/request_vars.html:84 +#: templates/debug_toolbar/panels/request_vars.html:106 +msgid "Variable" +msgstr "Variável" + +#: templates/debug_toolbar/panels/request_vars.html:50 +msgid "No COOKIE data" +msgstr "Não há dados de COOKIE" + +#: templates/debug_toolbar/panels/request_vars.html:53 +msgid "SESSION Variables" +msgstr "Variáveis de SESSION" + +#: templates/debug_toolbar/panels/request_vars.html:76 +msgid "No SESSION data" +msgstr "Não há dados de SESSION" + +#: templates/debug_toolbar/panels/request_vars.html:79 +msgid "GET Variables" +msgstr "Variáveis de GET" + +#: templates/debug_toolbar/panels/request_vars.html:98 +msgid "No GET data" +msgstr "Não há dados de GET" + +#: templates/debug_toolbar/panels/request_vars.html:101 +msgid "POST Variables" +msgstr "Variáveis de POST" + +#: templates/debug_toolbar/panels/request_vars.html:120 +msgid "No POST data" +msgstr "Não há dados de POST" + +#: templates/debug_toolbar/panels/settings_vars.html:5 +msgid "Setting" +msgstr "Configuração" + +#: templates/debug_toolbar/panels/signals.html:5 +msgid "Signal" +msgstr "Sinais" + +#: templates/debug_toolbar/panels/signals.html:6 +msgid "Providing Args" +msgstr "Argumentos Fornecidos" + +#: templates/debug_toolbar/panels/signals.html:7 +msgid "Receivers" +msgstr "Recebedores" + +#: templates/debug_toolbar/panels/sql.html:6 +msgid "Action" +msgstr "Ação" + +#: templates/debug_toolbar/panels/sql.html:7 +msgid "Stacktrace" +msgstr "Stacktrace" + +#: templates/debug_toolbar/panels/sql.html:8 +msgid "Query" +msgstr "Query" + +#: templates/debug_toolbar/panels/sql.html:38 +msgid "Line" +msgstr "Linha" + +#: templates/debug_toolbar/panels/sql.html:39 +msgid "Method" +msgstr "Método" + +#: templates/debug_toolbar/panels/sql.html:40 +msgid "File" +msgstr "Arquivo" + +#: templates/debug_toolbar/panels/sql_explain.html:3 +#: templates/debug_toolbar/panels/sql_profile.html:3 +#: templates/debug_toolbar/panels/sql_select.html:3 +#: templates/debug_toolbar/panels/template_source.html:3 +msgid "Back" +msgstr "Voltar" + +#: templates/debug_toolbar/panels/sql_explain.html:4 +msgid "SQL Explained" +msgstr "SQL Explicada" + +#: templates/debug_toolbar/panels/sql_explain.html:9 +#: templates/debug_toolbar/panels/sql_profile.html:10 +#: templates/debug_toolbar/panels/sql_select.html:9 +msgid "Executed SQL" +msgstr "SQL Executada" + +#: templates/debug_toolbar/panels/sql_profile.html:4 +msgid "SQL Profiled" +msgstr "Perfil da SQL" + +#: templates/debug_toolbar/panels/sql_profile.html:35 +msgid "Error" +msgstr "Erro" + +#: templates/debug_toolbar/panels/sql_select.html:4 +msgid "SQL Selected" +msgstr "SQL Selecionada" + +#: templates/debug_toolbar/panels/sql_select.html:34 +msgid "Empty set" +msgstr "Conjunto vazio" + +#: templates/debug_toolbar/panels/template_source.html:4 +msgid "Template Source" +msgstr "Origem do Template" + +#: templates/debug_toolbar/panels/templates.html:2 +msgid "Template path" +msgstr "Caminho do Template" + +#: templates/debug_toolbar/panels/templates.html:13 +msgid "Template" +msgstr "Template" + +#: templates/debug_toolbar/panels/templates.html:21 +#: templates/debug_toolbar/panels/templates.html:37 +msgid "Toggle Context" +msgstr "Mostrar/Esconder Contexto" + +#: templates/debug_toolbar/panels/templates.html:28 +#: templates/debug_toolbar/panels/templates.html:43 +msgid "None" +msgstr "Nenhum" + +#: templates/debug_toolbar/panels/templates.html:31 +msgid "Context processor" +msgstr "Processador do Contexto" + +#: templates/debug_toolbar/panels/timer.html:9 +msgid "Resource" +msgstr "Recurso" + +#: templates/debug_toolbar/panels/versions.html:6 +msgid "Package" +msgstr "Pacote" + +#: templates/debug_toolbar/panels/versions.html:7 +msgid "Version" +msgstr "Versão" diff --git a/debug_toolbar/management/commands/debugsqlshell.py b/debug_toolbar/management/commands/debugsqlshell.py index 6bb16de..8878d25 100644 --- a/debug_toolbar/management/commands/debugsqlshell.py +++ b/debug_toolbar/management/commands/debugsqlshell.py @@ -2,8 +2,8 @@ import os from optparse import make_option from datetime import datetime -from django.core.management.base import NoArgsCommand from django.db.backends import util +from django.core.management.commands.shell import Command from debug_toolbar.utils import sqlparse @@ -21,61 +21,3 @@ class PrintQueryWrapper(util.CursorDebugWrapper): print util.CursorDebugWrapper = PrintQueryWrapper - -# The rest is copy/paste from django/core/management/commands/shell.py - -class Command(NoArgsCommand): - option_list = NoArgsCommand.option_list + ( - make_option('--plain', action='store_true', dest='plain', - help='Tells Django to use plain Python, not IPython.'), - ) - help = "Runs a Python interactive interpreter. Tries to use IPython, if it's available." - - requires_model_validation = False - - def handle_noargs(self, **options): - # XXX: (Temporary) workaround for ticket #1796: force early loading of all - # models from installed apps. - from django.db.models.loading import get_models - loaded_models = get_models() - - use_plain = options.get('plain', False) - - try: - if use_plain: - # Don't bother loading IPython, because the user wants plain Python. - raise ImportError - import IPython - # Explicitly pass an empty list as arguments, because otherwise IPython - # would use sys.argv from this script. - shell = IPython.Shell.IPShell(argv=[]) - shell.mainloop() - except ImportError: - import code - # Set up a dictionary to serve as the environment for the shell, so - # that tab completion works on objects that are imported at runtime. - # See ticket 5082. - imported_objects = {} - try: # Try activating rlcompleter, because it's handy. - import readline - except ImportError: - pass - else: - # We don't have to wrap the following import in a 'try', because - # we already know 'readline' was imported successfully. - import rlcompleter - readline.set_completer(rlcompleter.Completer(imported_objects).complete) - readline.parse_and_bind("tab:complete") - - # We want to honor both $PYTHONSTARTUP and .pythonrc.py, so follow system - # conventions and get $PYTHONSTARTUP first then import user. - if not use_plain: - pythonrc = os.environ.get("PYTHONSTARTUP") - if pythonrc and os.path.isfile(pythonrc): - try: - execfile(pythonrc) - except NameError: - pass - # This will import .pythonrc.py as a side-effect - import user - code.interact(local=imported_objects) diff --git a/debug_toolbar/media/debug_toolbar/Makefile b/debug_toolbar/media/debug_toolbar/Makefile deleted file mode 100644 index 95f91bb..0000000 --- a/debug_toolbar/media/debug_toolbar/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Make file to compress and join all JS files -all: compress_js compress_css - -compress_js: - java -jar ~/bin/yuicompressor.jar js/jquery.js > js/toolbar.min.js - java -jar ~/bin/yuicompressor.jar js/toolbar.js >> js/toolbar.min.js - -compress_css: - java -jar ~/bin/yuicompressor.jar --type css css/toolbar.css > css/toolbar.min.css diff --git a/debug_toolbar/media/debug_toolbar/css/toolbar.css b/debug_toolbar/media/debug_toolbar/css/toolbar.css index 820617f..4770ade 100644 --- a/debug_toolbar/media/debug_toolbar/css/toolbar.css +++ b/debug_toolbar/media/debug_toolbar/css/toolbar.css @@ -369,19 +369,17 @@ position:relative; } -#djDebug .djDebugCollapse { - display: inline-block; - background: #ddd; - background: url(data:image/gif;base64,R0lGODlhBgAKAJEDAJGRkdra2qysrP///yH5BAEAAAMALAAAAAAGAAoAAAIPnI+JIRImABBQ0sGc2qoAADs=) 0 3px repeat-x; - width: 18px; - text-indent: -10000em; +#djDebug .djDebugCollapsed { + display: none; + text-decoration: none; + color: #333; } -#djDebug .djSelected .djDebugCollapse { - background: inherit; - text-indent: 0; - width: auto; - display: inline; + +#djDebug .djDebugUncollapsed { + color: #333; + text-decoration: none; } + #djDebug .djUnselected { display: none; } @@ -547,8 +545,13 @@ #djDebug .djSQLDetailsDiv { margin-top:0.8em; } -#djDebug .djSQLDetailsDiv pre { - color: #777; +#djDebug pre { + white-space: pre-wrap; /* CSS-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ + color: #555; border:1px solid #ccc; border-collapse:collapse; background-color:#fff; diff --git a/debug_toolbar/media/debug_toolbar/css/toolbar.min.css b/debug_toolbar/media/debug_toolbar/css/toolbar.min.css index 5088442..aa30728 100644 --- a/debug_toolbar/media/debug_toolbar/css/toolbar.min.css +++ b/debug_toolbar/media/debug_toolbar/css/toolbar.min.css @@ -1 +1 @@ -.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.clearfix{display:inline-block;}/* Hides from IE-mac \*/ .clearfix{display:block;}* html .clearfix{height:1%;}/* end hide from IE-mac */ #djDebug{color:#000;background:#FFF;}#djDebug,#djDebug div,#djDebug span,#djDebug applet,#djDebug object,#djDebug iframe,#djDebug h1,#djDebug h2,#djDebug h3,#djDebug h4,#djDebug h5,#djDebug h6,#djDebug p,#djDebug blockquote,#djDebug pre,#djDebug a,#djDebug abbr,#djDebug acronym,#djDebug address,#djDebug big,#djDebug cite,#djDebug code,#djDebug del,#djDebug dfn,#djDebug em,#djDebug font,#djDebug img,#djDebug ins,#djDebug kbd,#djDebug q,#djDebug s,#djDebug samp,#djDebug small,#djDebug strike,#djDebug strong,#djDebug sub,#djDebug sup,#djDebug tt,#djDebug var,#djDebug b,#djDebug u,#djDebug i,#djDebug center,#djDebug dl,#djDebug dt,#djDebug dd,#djDebug ol,#djDebug ul,#djDebug li,#djDebug fieldset,#djDebug form,#djDebug label,#djDebug legend,#djDebug table,#djDebug caption,#djDebug tbody,#djDebug tfoot,#djDebug thead,#djDebug tr,#djDebug th,#djDebug td{margin:0;padding:0;border:0;outline:0;font-size:12px;line-height:1.5em;color:#000;vertical-align:baseline;background:transparent;font-family:sans-serif;text-align:left;}#djDebug #djDebugToolbar{background:#111;width:200px;z-index:100000000;position:fixed;top:0;bottom:0;right:0;opacity:.9;}#djDebug #djDebugToolbar small{color:#999;}#djDebug #djDebugToolbar ul{margin:0;padding:0;list-style:none;}#djDebug #djDebugToolbar li{border-bottom:1px solid #222;color:#fff;display:block;font-weight:bold;float:none;margin:0;padding:0;position:relative;width:auto;}#djDebug #djDebugToolbar li>a,#djDebug #djDebugToolbar li>div.contentless{font-weight:normal;font-style:normal;text-decoration:none;display:block;font-size:16px;padding:10px 10px 5px 25px;color:#fff;}#djDebug #djDebugToolbar li a:hover{color:#111;background-color:#ffc;}#djDebug #djDebugToolbar li.active{background-image:url(../img/indicator.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAgFJREFUeNqUlE1LAmEQx11fesNeDLt08hZ4KcgvIF7EgxcR9CT4IQwErx47WhFBdvPgwUNQeOiogiLRQSQUQaKD6Vpba7ar20izMe4+bjTwY5/Zl//OMzPPcCaTaRUwAxbTjynAdAHq84XGARuADQXN+MGEIJG1QmCaOZVK7WKUdmCdYMf7K/hDKwagwjRLPp9/cLvdzUKh8Ab+GgosExGz5hvFSJAbDAYKmFSpVM4DgUABX57l6wsYAR/AO64/MQUyyauiE1SdTqdTC4fDZ61W6x0FRUAAXvEqElGJCP5qzG3H5XIdFovFdCgUOgB3B3AC28AmyekSKSDH3LL2piRJcjabvU4kEnfg8sAL0Me1GulYE+ViQdWq1ep9NBrN9vv9J3B7KPyKOf3EtNAe1VVwzjwez36pVDoKBoMu3KpNs13dlg0FZ+ZwOJx+v3+PHATO6H2r0UOe54fJZPIil8vVSLtMjE7LQsFGo/EYiUSuut3uM/aimjPJSFQnCE0+hVNzE4/Hb1FoyOjBCasHdYKiKPLpdPo0k8k0GY1NKyvTyjIFe71eLRaLHZfLZYFx9AS8jhgR6gXb7faJ1+u9FATBglWU8cMxRjki0RmOMmu9Xo/4fL4y9pmVzEMZBcakGPJfw3YWzRY2rA19dWLLBMNCaAXXNHNPIVFO/zOtZ/YtwADKQgq0l7HbRAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:left center;background-color:#333;padding-left:10px;}#djDebug #djDebugToolbar li.active a:hover{color:#b36a60;background-color:transparent;}#djDebug #djDebugToolbar li small{font-size:12px;color:#999;font-style:normal;text-decoration:none;font-variant:small-caps;}#djDebug #djDebugToolbarHandle{position:fixed;background:#fff;border:1px solid #111;top:30px;right:0;z-index:100000000;opacity:.75;}#djDebug a#djShowToolBarButton{display:block;height:75px;width:30px;border-right:none;border-bottom:4px solid #fff;border-top:4px solid #fff;border-left:4px solid #fff;color:#fff;font-size:10px;font-weight:bold;text-decoration:none;text-align:center;text-indent:-999999px;background:#000 url(../img/djdt_vertical.png) no-repeat left center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABLCAYAAAACnsWZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAATCSURBVGiB7ZlvSBtnHMe/sckZY5aMw06r7aTLjGOwTKOMEWYs7M2EaaUdjG6+GDoQ9mIyupUxGIONwVZfDHwxg2E4igym24s5sFB0oDRq1yi1G0RijTjhjJBI86fR/LvbC+nFs7ncXR7jMsgXDp67e57vffI8v/s9z3NRAeBQxCr7rwGkVAIkVQmQVCVAUpUASVX0gGqxGxaLBTabDVqtFn6/H5OTk4jFYifJxovLdgwNDXGH1dDQkLVeoY+iH+KiBxSNwaOy2+0wmUyKzH0+H7xer2Koo5IVg/loZGSkuGOwtraW2KOggHt7e8QesmMwEomAZVlF5uvr64qBjko2YEtLC9bW1ogfqFRFn2b+v4CpVIovsyyrOP6OSyrksS8uKysDTdNQq9XY3d1FIpEoAFpGshJma2sr53A4OI/Hw7EsK0jIDMNw4+PjXFdXVyEWDLkr6PV6bmJiQvbs4XK5uJqampMBpCiKW1hYUDzF+Xw+zmAwFB5wcHBQMdxjDQ8PHwug6EtC0zS2trag0+kE16enp7G4uAiv14tUKgWz2Qyr1YrOzk6oVCq+XjweR11dHYLBYDZ7RcpK3tvbK+iRcDjMdXR0iP5Sm83GMQwjaNPX11e4IR4dHRU8bGBgQNKsp6dH0MbpdBYO0OVyCR5mNBolzTQaDZdOp/k2c3NzxICiMwlN03x5e3sboVBIrCqvZDIJhmH4c6PRKNlGSqKrGYqi+HJFRQX6+/tlGWq12qxlEmXt2pWVlbxTzGMtLS0VbogjkQjxLw+Hw8QeooA7OzvE5n6/n9hDNAbdbrfibeZRLS8vE7UH8lxunaSKfkUte9MEAAa6EhrqVNZ7HAc8DETBpo935a1oiJ1zH6O5rUH0fmI/iQ2PH1Nji/jpuxlwHHn0KOpBKVFaDRqbz6Gx+RysdjOudn9P7FmwGGy/+DLa3rQQ++QNmEykEA3t8UcsGn+izhvvvEIEBxAM8c2xO/iy74bgWu35KjhmPkLt+SoAwFnTaTI6HPMQMxsBLM1mvgdqdVSO2vKkqAdvXL+FuzOrYFkOd/9YzVqHfsbAlze95NNlnht3FQx0JU6pyxDejSGZyHyFOGs6DWu7GVVnjLh3+wGWZ8m+sMoGfLG1Ht3vvwZruxn1jdWCDVJgO4R7tx9gauwO5iZXiIAUA+r05fhi9D28/pZVluH9+XV8ctmBoJ98qQVIAGooNUZmr+KlV59TZMpsBHCl6Ss8Cu+T8uV+iz/4+qJiOOAg3Xz47eW8oQ5LtAcNdCWmtr55IlX8Oe3BX4sb2PTuIJ1Ko95cjResz6Kt0yKIy0Q8hY66awgFHxEBiqaZC91NArhYZB+fvu3E/M2/s9a32Ey4/ks/qs4c7OSocjUudDfhtx9cRICiQ9zc9rzgfPjzSVE44ODlGLr2q+BaPuFxVKKA9eZqwfnvP85Lmt362Q2WzURMfWN1jtryJApooCv5cmA7hGhI+j+PVDKNAPOQP9cbKwjxcsSghsrcKq/Q4FK/XZYhpdVk2h0q5ytRwFg0k8OeelqHzxzvKjbPtgRTKtEhjkXIzQuaqIM75FNV0C/9wUlKokPscW8SLzhXl/8hag+UNu7kKgGSqgRIqhIgqUqApCp6wH8B9cAOKo9Os8wAAAAASUVORK5CYII=);opacity:.5;}#djDebug a#djShowToolBarButton:hover{background-color:#111;padding-right:6px;border-top-color:#FFE761;border-left-color:#FFE761;border-bottom-color:#FFE761;opacity:1.0;}#djDebug code{display:block;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;white-space:pre;overflow:auto;}#djDebug tr.djDebugOdd{background-color:#f5f5f5;}#djDebug .panelContent{display:none;position:fixed;margin:0;top:0;right:200px;bottom:0;left:0;background-color:#eee;color:#666;z-index:100000000;}#djDebug .panelContent>div{border-bottom:1px solid #ddd;}#djDebug .djDebugPanelTitle{position:absolute;background-color:#ffc;color:#666;padding-left:20px;top:0;right:0;left:0;height:50px;}#djDebug .djDebugPanelTitle code{display:inline;font-size:inherit;}#djDebug .djDebugPanelContent{position:absolute;top:50px;right:0;bottom:0;left:0;height:auto;padding:5px 0 0 20px;}#djDebug .djDebugPanelContent .scroll{height:100%;overflow:auto;display:block;padding:0 10px 0 0;}#djDebug h3{font-size:24px;font-weight:normal;line-height:50px;}#djDebug h4{font-size:20px;font-weight:bold;margin-top:.8em;}#djDebug .panelContent table{border:1px solid #ccc;border-collapse:collapse;width:100%;background-color:#fff;display:block;margin-top:.8em;overflow:auto;}#djDebug .panelContent tbody td,#djDebug .panelContent tbody th{vertical-align:top;padding:2px 3px;}#djDebug .panelContent thead th{padding:1px 6px 1px 3px;text-align:left;font-weight:bold;font-size:14px;}#djDebug .panelContent tbody th{width:12em;text-align:right;color:#666;padding-right:.5em;}#djDebug .djTemplateHideContextDiv{background-color:#fff;}#djDebug .panelContent .djDebugClose{text-indent:-9999999px;display:block;position:absolute;top:4px;right:15px;height:40px;width:40px;background:url(../img/close.png) no-repeat center center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7dJREFUeNqsWM1PE0EU3+7ShdJKoTRA8UYgIUKM3rmaEI0euXsw0YMHIZEbxBijEiIHLkb/A44SDYlXzkYPGBM+ri1NWz7aUmhp6+9tps10mLfdfrzkl2535r39zc77mvUdHh4abUoUCAD3xP/fQAFItWJkYmLC+e1p8eGPgQcC08ycf8BPgW2vhr0SeQa8AWIe5k4LvATiwCrwtZmS2WT8IfAL+OKRhCoxoftH2GqLyBLwHbhvdC53ha2lVrfmE/DKzbLP5yubplnt7e310f+rq6tqpVLxVatVy0VtHbgNLHohsupGIhQKFQG7v79f+8CLiwsjl8sVAZsxQbYTwFrDwpTwpaj4ptPu6+vLDw4OBkHA014QobOzs3yhUAgyUx4BP2rhq/rIe53GwMBAeXx83DMJEpobi8WCpMtMWeOc9TkwoyMRjUattrMedBkyM+KZN4isqDMDgUCuExIyGbKlGVpRiSzo8kQ4HA4ZXRLGVuzo6GhBJjKviw6dT5TLZSOTyRinp6cGQrV+n67hnEY6nTaur6+1PkM2NWTm5fCd0xDRhh89CKHpXCMijLGxMef6+PjYiRSSUqlUv6/arOlKMlcjQlV0qsGDTZPehpYIxurXRCSRSFByq5NQ56hvhWwj8cm2p7A9UdKYVBX8fn+F2+tIJGIgmzaQkUnYtm0MDw+zvsLYniQiEc2q/WxxwmqRHxrISA9xxiyLDzTGdsRsJwJoK3QPo3vctnhpAzLqTexhiVOg6JAdU5bLy0vHZ+Ro8mg7Q0QO1LvwenZZJycnN3yCIPsMRRYnjO0DU/SY+wprW7fiWmjKJMgnUIcafEaeoxZCJWJI9lH4UjV2u6pSPp/XJR9jaGiIKrERDAbrjllzYOQJZ4zm6ISxuSsntB3gqTyazWZtMowa0aBFb4HegC6aRkZG2C2hLSObmqEdOcVvUdJUZyBlZ7tVa1ASdEUvjW3ZUqvvO82e3kqlUuVOSZANvBFd0fugawM2VKclOT8/tzohQ7pkgzn/rHNdvLbLJkPxeDzHRRIXIaTDkCB57XacoJPZW8bZQpSskslk0Y0QjdEcmstsB8myegrsYbqmENfJU3dOpZyOEwjdCqLIWUyxWKygVzHFccJ2eVkbar/qdq5ZFC3/R5dUb6EBsqQmyEtLuawj0eykRwpPgL0uRO+esLXW7tmX9nEWeAEk2yCQFLqzzb4MeK3Zn4FRsapNEXqGy2eJTTF3VOh27bOE/Ia2pQ81YeCO+P+XknGrH2pq8l+AAQDv/n2Gmq99BgAAAABJRU5ErkJggg==);}#djDebug .panelContent .djDebugClose:hover{background-image:url(../img/close_hover.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABCVJREFUeNqsWG1IU1EYfjfd0i1bTc2WFTW3tG2aFWlEf4KkMIrCvhH6U9DnjxTyV0ZEXxIVGBH1JyKIPiBK8kf1syCKwu8M3VQsK7OV6ba2udZ7bmd6d+85827zhYftnnPe5z73nvc95z1X5XQ6IUHLQqQjiul1E8KHGIqHxGw2C7+pcd58E6KMooAzphPxnKJBKbFSIfsRpxAmBWMLKI4iviBOIm5O5qSepL8c8R5xQ6EIqZmobzPlSkhINeIpYhkkb0WUqzreqbmEOBaTOjQGf/0+CHz7Klxqc+aAehrGbkrM2b6IyEVUKRFyMpYI38dW8HS0gc/5kdmfnpcPepsD0vMLeRSEm6ivEzeqJOlLsuIJyzs40Au/Xr+CP64uRXORZraCoXQ1aHMX8YZsRDRG0lcqpA1hl3p4mt+C+/nThILDWLYR9EtXsrraEY6IEHGwHmCJGG16k7AIYsTX0/KO1WWn95QJqZWODHxyws8XjUmnjPtZg8DFsFqpkB2sdWL4zWuYKuNwmVwu1w6xkA2s7GAFpnaGAcxbd8H8snJQa7QTUZ+aCrlr10NexR5Iy8yW+REuwsmwDeL0XSOLjfYW5pNZtldC9orS/4FoK4LWa5cgHP4L9n1HILNoudCuM82F1qsXgcXJSOs1ESFkF7WKe8JBfxifQMVMY8/o+P+Z+TYoPFwNoYAfMh3FE2udz8d8CPJWCLdKM03MbcXpySJTY5EtmsNuFW+uex4/gJFe14SYxUuiRHi/fIaue7f5CzKb20KEGKWtYx4Pl2jM54WW+joY6euR9Xm/DkDT5bMQHB3h+7O5jepEMiAUDDBvRtpCfn9CWUWEuGUbkF7PdSDZQQLTaC+S9Rks+VB4qCoqmxRyu4mQbmlrisEY5hEtLN8ynh2RmBjt74sK4LyK3VwhHO5uNa0xoxYMEtVk02KZbk7uxB400C/ERPOVc1EBrMsxcTdCScYQ68L9ZiiyjryUprC+wM5c0PoaH4EmIwMCv4eh6+6t8VghAWzdtVdYzHoaHjKFEE6GvRTvvmSZvScd8f3hHfjT2z0lS3zaQgtkb6tkde3EN3I/kjX3ET9kwVdSOmV7jaF0Fav5BxEh3X3PyPaVBVaYta48aRGkJtHOt7C6zrPKgMvSoCU2vbhEIEpGBKcw6qQ1LLNmrWaVioRIk2kUtvK4SsWSVaCdl8cbcjxW8UxOZqcRJ2TThITZCO+HZvB2dsQsnnUFNtAtWRpLZ430FKjinH0VHSdCXg8EhwaFS03WbEjR6Sc7TkRCoErp2beKlvwX+EtkKqRkGATEYTXSY4SSkx5x2Eyr7WStnXLVJXr2JfPoQBxEDCYgYJD6Oib7MqC0DLiOyKFPVU9TD2J8lqinY3Oo75R9lhC/oQbRhxoSIDZ63UGK9Xg/1ETsnwADAJrrTk7nZiozAAAAAElFTkSuQmCC);}#djDebug .panelContent .djDebugClose.djDebugBack{background-image:url(../img/back.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7FJREFUeNrMWM1PE0EU3+7S7bZdKSFNSIFgJJAgINE7VxOi0SP/gYkePAiJ3CDGGJUQOXAx+h9wlGhIvHI2fgQ08mEkkjZNIZR2+7Httr63zMoyOzPdthx8yS+bnZn3m9/OvDcfG9jd3ZVatDggDLhO3j8DioBMMySDg4P2s6PJzu8AbhKMcNr8AHwkWPNL7FfIPcATQMJH2xGCh4AkYAHwtpGT3KD+FuAT4I1PEbQliO8XwtWSkFnAe8ANqX2bIFyzzU7NK8AjEXMgELBkWa6HQqEAvpfL5XqtVgvU63VF4LYE6APM+BGyIBKh67oJUCORCLPDQqEg5fN5E6ByKJA7BVg892FU+mJWvGN5a5pmdHV1RUGAr7lAQdls1igWi1FOk9uAD0760jHynOXR2dlp9fb2+haBhm0TiUQUfTlNFnnBeh8wxhIRj8eVllc98OWIGSN9eoTM0y3D4XC+HRFuMcjFqJqnhUyz1olYLKa730uVCrMjXrmIy1ln9vb2pt1CpljZQcdE1ihIW/sHHrayWbHLq1ZNGDPIyaiacguZZAhhph+K+fpr39Ppqcg/wtHhcE46QnAXHT4XwbJssjJECwbtp1EqS99AjNNpSD0r//77wH7yRgW5qeJhmJ44ChmiHYLBIHOMY9GINDrQ9y8uHDEoEMs7FNl+x5HhieFwD6GQbs8GJMtBbtCBmIkrA3anOD0YH2ci+21RWJ4vldibG5u7W5b+E8O95oguhM0LP1PhBauTOfj1Tnxg+c+DpD0aOFq6pjE75HAfoZAdunGlUpH9iLh6uc9+nsaFt5xlHO4dmZwxtynVKm5avIUrqoWkaxAnTmdOnGC5SARyIjdVvA0bX8ZRt0E7GYZhNgpWb0b1c0UIODfcC9o6XZvL5VTYwrnp6zaMEyd9eYZcyMmoWncLWQUcemIim82xFjTeQiey4+Nj1qZ3CNOySu++zxhzeimTyVjtpiZywIiwNr0XrGPAMh20aCcnJ0o7YtAXOTj3nyXeKZ55ykaiZDKZZ2WS6KiIPhwRaI9F1wm8mT3lBJueSqWkdDptigRhHbbBtpzpQJujb4EdnFOTzjvJ4+kcYF8nFEWpqapqf4xpmjXLsmRynVAFg7VMn1dF95oZcuR/yWPDDqvVKsIp8nOknGOJaHTTQ4e7gM0L2NM2Cddiq3dfnMdxwANAugUBaeI73ujPgN9jwGtAD/mqFZJ6kuC3xApp20N8L+y3hHuE1lw/amKAUfK+hYtxsz9qHPsrwACHs5P9Qys/0AAAAABJRU5ErkJggg==);}#djDebug .panelContent .djDebugClose.djDebugBack:hover{background-image:url(../img/back_hover.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA6hJREFUeNrMWF1Ik1EYPtt0pkuGa/aDJTY3nNvSfkglvEwQpa7CbrosKAghBedNikKgEgVe1m03SVeJXmSXBmIozpxpuiUS/eicSc75m73vx/nGt7Nzvm8/BR14+Pjec85znp297znv++kCgQBJs1kBuYDz9H0KEAWEUiGx2WzSMyvFxa8B6iicgjFzgBGKwWSJdUnuyB1AF+BUisK/AToBz7V2RK9B1ACYBDxLQwShc3Cuj3IJm5qQVsAQ4ALJvFVQrlbRAJGPPAE8UKU+2Ce/d6Jk98d36dV44iTR54DvGlTd7jGgCNCSjJBONRHR+Q8kMjtDooF5bn9uaRkxuTwkt+yciAK5UX2fmrNiVLzmzd77ukR+jr0j28GFpP6LIzYHMVdfIcais6IhjYBh2VlZITMANzsj4ntPwiNDaTmHpa6RmCov87r8AA8vau7yRGxOjactAhvOjUxP8LrcdM0EIR3syN0vAbL+djjjkAm/GZS4OK2DFdLEOyc2xsfi/3frcb4/COxqXPI5EwwGm5RC6nnRwTpmgdNNKpq9iZFiLZTsWXkmoRDkQk5Oq1cKqU3wDf80lxDFXGzvTlhUFqm2OwLOWlkI3qIOZc/h3s4hL0y3QyvSM7+4hFxq74otGg2txuyVzW3SU7QryM2YHfD3WFGIPeHQ3AjreETrc34y3d8b8wtZDApE+/5WRHrHnRGJEXDbUYiFte5HIsLtRTGTPR3Sovj3oH8oRaIotB8t5h9kAm6LnvwnDe+acILRJPZ+ZeTgr5f9A+2u2/el3cDd2lz+zF+Qzx1GIYus1WC2oEPptET4+vukp+wXrJ3XBNyLeppjxoWILjtHh5eW6OD6tbxEJno6Y4vJfoJ2NRHIidyMeQHum5DsI6PsJJPTremsvIgSiVDhHFXevnjMvmRHrL56QbaXFuN2hLeQyB43psROCm/c4nXdhB0ZkHdkALDGjjBXVXMPNNFBp9bM1TU88xqKYG/fR+woY7GDFFxtyDg0MScxnrHzunpEGdon9rj/h4kR1j/logKrlZcqIlH2MYt0laeUKlbVEOPpUtGQNq0CqxvwUDR766OPbM3NqibPeU4XySuvVNPplZNnUc6aUjlxACG8Rx01GyLHgKmBQbOKfaosJ7Rq3xaa8vcK6WBBQ75ZQgrNy5YRyVR6OOE6zbYzbX7K1ZdOyUloNe8B3AOspCFghc71aH0Z0KX4feSvf5bQctZkP9Sgg7jo+ywm6+l+qPkjwADNS26fFM/O1QAAAABJRU5ErkJggg==);}#djDebug .panelContent dt,#djDebug .panelContent dd{display:block;}#djDebug .panelContent dt{margin-top:.75em;}#djDebug .panelContent dd{margin-left:10px;}#djDebug a.toggleTemplate{padding:4px;background-color:#bbb;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.toggleTemplate:hover{padding:4px;background-color:#444;color:#ffe761;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.djTemplateShowContext,#djDebug a.djTemplateShowContext span.toggleArrow{color:#999;}#djDebug a.djTemplateShowContext:hover,#djDebug a.djTemplateShowContext:hover span.toggleArrow{color:#000;cursor:pointer;}#djDebug .djDebugSqlWrap{position:relative;}#djDebug .djDebugCollapse{display:inline-block;background:#ddd;background:url(data:image/gif;base64,R0lGODlhBgAKAJEDAJGRkdra2qysrP///yH5BAEAAAMALAAAAAAGAAoAAAIPnI+JIRImABBQ0sGc2qoAADs=) 0 3px repeat-x;width:18px;text-indent:-10000em;}#djDebug .djSelected .djDebugCollapse{background:inherit;text-indent:0;width:auto;display:inline;}#djDebug .djUnselected{display:none;}#djDebug tr.djHiddenByDefault{display:none;}#djDebug tr.djSelected{display:table-row;}#djDebug .djDebugSql{z-index:100000002;}#djDebug .djSQLDetailsDiv tbody th{text-align:left;}#djDebug .djSqlExplain td{white-space:pre;}#djDebug span.djDebugLineChart{background-color:#777;height:3px;position:absolute;bottom:0;top:0;left:0;display:block;z-index:1000000001;}#djDebug span.djDebugLineChartWarning{background-color:#900;}#djDebug .highlight{color:#000;}#djDebug .highlight .err{color:#000;}#djDebug .highlight .g{color:#000;}#djDebug .highlight .k{color:#000;font-weight:bold;}#djDebug .highlight .o{color:#000;}#djDebug .highlight .n{color:#000;}#djDebug .highlight .mi{color:#000;font-weight:bold;}#djDebug .highlight .l{color:#000;}#djDebug .highlight .x{color:#000;}#djDebug .highlight .p{color:#000;}#djDebug .highlight .m{color:#000;font-weight:bold;}#djDebug .highlight .s{color:#333;}#djDebug .highlight .w{color:#888;}#djDebug .highlight .il{color:#000;font-weight:bold;}#djDebug .highlight .na{color:#333;}#djDebug .highlight .nt{color:#000;font-weight:bold;}#djDebug .highlight .nv{color:#333;}#djDebug .highlight .s2{color:#333;}#djDebug .highlight .cp{color:#333;}#djDebug .timeline{width:30%;}#djDebug .djDebugTimeline{position:relative;height:100%;min-height:100%;}#djDebug div.djDebugLineChart{position:absolute;left:0;right:0;top:0;bottom:0;vertical-align:middle;}#djDebug div.djDebugLineChart strong{text-indent:-10000em;display:block;font-weight:normal;vertical-align:middle;background-color:#ccc;}#djDebug div.djDebugLineChartWarning strong{background-color:#900;}#djDebug .djDebugInTransaction div.djDebugLineChart strong{background-color:#d3ff82;}#djDebug .djDebugStartTransaction div.djDebugLineChart strong{border-left:1px solid #94b24d;}#djDebug .djDebugEndTransaction div.djDebugLineChart strong{border-right:1px solid #94b24d;}#djDebug .djDebugHover div.djDebugLineChart strong{background-color:#000;}#djDebug .djDebugInTransaction.djDebugHover div.djDebugLineChart strong{background-color:#94b24d;}#djDebug .panelContent ul.stats{position:relative;}#djDebug .panelContent ul.stats li{width:30%;float:left;}#djDebug .panelContent ul.stats li strong.label{display:block;}#djDebug .panelContent ul.stats li span.color{height:12px;width:3px;display:inline-block;}#djDebug .panelContent ul.stats li span.info{display:block;padding-left:5px;}#djDebug .panelcontent thead th{white-space:nowrap;}#djDebug .djDebugRowWarning .time{color:red;}#djdebug .panelcontent table .toggle{width:14px;padding-top:3px;}#djdebug .panelcontent table .actions{min-width:70px;}#djdebug .panelcontent table .color{width:3px;}#djdebug .panelcontent table .color span{width:3px;height:12px;overflow:hidden;padding:0;}#djDebug .djToggleSwitch{text-decoration:none;border:1px solid #999;height:12px;width:12px;line-height:12px;text-align:center;color:#777;display:inline-block;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF',endColorstr='#DCDCDC');background:-webkit-gradient(linear,left top,left bottom,from(#FFF),to(#DCDCDC));background:-moz-linear-gradient(center top,#FFF 0,#DCDCDC 100%) repeat scroll 0 0 transparent;}#djDebug .djNoToggleSwitch{height:14px;width:14px;display:inline-block;}#djDebug .djSQLDetailsDiv{margin-top:.8em;}#djDebug .djSQLDetailsDiv pre{color:#777;border:1px solid #ccc;border-collapse:collapse;background-color:#fff;display:block;overflow:auto;padding:2px 3px;margin-bottom:3px;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;}#djDebug .stack span{color:#000;font-weight:bold;}#djDebug .stack span.path{color:#777;font-weight:normal;}#djDebug .stack span.code{font-weight:normal;}@media print{#djDebug{display:none;}}
\ No newline at end of file +.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}.clearfix{display:inline-block;}/* Hides from IE-mac \*/ .clearfix{display:block;}* html .clearfix{height:1%;}/* end hide from IE-mac */ #djDebug{color:#000;background:#FFF;}#djDebug,#djDebug div,#djDebug span,#djDebug applet,#djDebug object,#djDebug iframe,#djDebug h1,#djDebug h2,#djDebug h3,#djDebug h4,#djDebug h5,#djDebug h6,#djDebug p,#djDebug blockquote,#djDebug pre,#djDebug a,#djDebug abbr,#djDebug acronym,#djDebug address,#djDebug big,#djDebug cite,#djDebug code,#djDebug del,#djDebug dfn,#djDebug em,#djDebug font,#djDebug img,#djDebug ins,#djDebug kbd,#djDebug q,#djDebug s,#djDebug samp,#djDebug small,#djDebug strike,#djDebug strong,#djDebug sub,#djDebug sup,#djDebug tt,#djDebug var,#djDebug b,#djDebug u,#djDebug i,#djDebug center,#djDebug dl,#djDebug dt,#djDebug dd,#djDebug ol,#djDebug ul,#djDebug li,#djDebug fieldset,#djDebug form,#djDebug label,#djDebug legend,#djDebug table,#djDebug caption,#djDebug tbody,#djDebug tfoot,#djDebug thead,#djDebug tr,#djDebug th,#djDebug td{margin:0;padding:0;border:0;outline:0;font-size:12px;line-height:1.5em;color:#000;vertical-align:baseline;background:transparent;font-family:sans-serif;text-align:left;}#djDebug #djDebugToolbar{background:#111;width:200px;z-index:100000000;position:fixed;top:0;bottom:0;right:0;opacity:.9;}#djDebug #djDebugToolbar small{color:#999;}#djDebug #djDebugToolbar ul{margin:0;padding:0;list-style:none;}#djDebug #djDebugToolbar li{border-bottom:1px solid #222;color:#fff;display:block;font-weight:bold;float:none;margin:0;padding:0;position:relative;width:auto;}#djDebug #djDebugToolbar li>a,#djDebug #djDebugToolbar li>div.contentless{font-weight:normal;font-style:normal;text-decoration:none;display:block;font-size:16px;padding:10px 10px 5px 25px;color:#fff;}#djDebug #djDebugToolbar li a:hover{color:#111;background-color:#ffc;}#djDebug #djDebugToolbar li.active{background-image:url(../img/indicator.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAgFJREFUeNqUlE1LAmEQx11fesNeDLt08hZ4KcgvIF7EgxcR9CT4IQwErx47WhFBdvPgwUNQeOiogiLRQSQUQaKD6Vpba7ar20izMe4+bjTwY5/Zl//OMzPPcCaTaRUwAxbTjynAdAHq84XGARuADQXN+MGEIJG1QmCaOZVK7WKUdmCdYMf7K/hDKwagwjRLPp9/cLvdzUKh8Ab+GgosExGz5hvFSJAbDAYKmFSpVM4DgUABX57l6wsYAR/AO64/MQUyyauiE1SdTqdTC4fDZ61W6x0FRUAAXvEqElGJCP5qzG3H5XIdFovFdCgUOgB3B3AC28AmyekSKSDH3LL2piRJcjabvU4kEnfg8sAL0Me1GulYE+ViQdWq1ep9NBrN9vv9J3B7KPyKOf3EtNAe1VVwzjwez36pVDoKBoMu3KpNs13dlg0FZ+ZwOJx+v3+PHATO6H2r0UOe54fJZPIil8vVSLtMjE7LQsFGo/EYiUSuut3uM/aimjPJSFQnCE0+hVNzE4/Hb1FoyOjBCasHdYKiKPLpdPo0k8k0GY1NKyvTyjIFe71eLRaLHZfLZYFx9AS8jhgR6gXb7faJ1+u9FATBglWU8cMxRjki0RmOMmu9Xo/4fL4y9pmVzEMZBcakGPJfw3YWzRY2rA19dWLLBMNCaAXXNHNPIVFO/zOtZ/YtwADKQgq0l7HbRAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:left center;background-color:#333;padding-left:10px;}#djDebug #djDebugToolbar li.active a:hover{color:#b36a60;background-color:transparent;}#djDebug #djDebugToolbar li small{font-size:12px;color:#999;font-style:normal;text-decoration:none;font-variant:small-caps;}#djDebug #djDebugToolbarHandle{position:fixed;background:#fff;border:1px solid #111;top:30px;right:0;z-index:100000000;opacity:.75;}#djDebug a#djShowToolBarButton{display:block;height:75px;width:30px;border-right:none;border-bottom:4px solid #fff;border-top:4px solid #fff;border-left:4px solid #fff;color:#fff;font-size:10px;font-weight:bold;text-decoration:none;text-align:center;text-indent:-999999px;background:#000 url(../img/djdt_vertical.png) no-repeat left center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABLCAYAAAACnsWZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAATCSURBVGiB7ZlvSBtnHMe/sckZY5aMw06r7aTLjGOwTKOMEWYs7M2EaaUdjG6+GDoQ9mIyupUxGIONwVZfDHwxg2E4igym24s5sFB0oDRq1yi1G0RijTjhjJBI86fR/LvbC+nFs7ncXR7jMsgXDp67e57vffI8v/s9z3NRAeBQxCr7rwGkVAIkVQmQVCVAUpUASVX0gGqxGxaLBTabDVqtFn6/H5OTk4jFYifJxovLdgwNDXGH1dDQkLVeoY+iH+KiBxSNwaOy2+0wmUyKzH0+H7xer2Koo5IVg/loZGSkuGOwtraW2KOggHt7e8QesmMwEomAZVlF5uvr64qBjko2YEtLC9bW1ogfqFRFn2b+v4CpVIovsyyrOP6OSyrksS8uKysDTdNQq9XY3d1FIpEoAFpGshJma2sr53A4OI/Hw7EsK0jIDMNw4+PjXFdXVyEWDLkr6PV6bmJiQvbs4XK5uJqampMBpCiKW1hYUDzF+Xw+zmAwFB5wcHBQMdxjDQ8PHwug6EtC0zS2trag0+kE16enp7G4uAiv14tUKgWz2Qyr1YrOzk6oVCq+XjweR11dHYLBYDZ7RcpK3tvbK+iRcDjMdXR0iP5Sm83GMQwjaNPX11e4IR4dHRU8bGBgQNKsp6dH0MbpdBYO0OVyCR5mNBolzTQaDZdOp/k2c3NzxICiMwlN03x5e3sboVBIrCqvZDIJhmH4c6PRKNlGSqKrGYqi+HJFRQX6+/tlGWq12qxlEmXt2pWVlbxTzGMtLS0VbogjkQjxLw+Hw8QeooA7OzvE5n6/n9hDNAbdbrfibeZRLS8vE7UH8lxunaSKfkUte9MEAAa6EhrqVNZ7HAc8DETBpo935a1oiJ1zH6O5rUH0fmI/iQ2PH1Nji/jpuxlwHHn0KOpBKVFaDRqbz6Gx+RysdjOudn9P7FmwGGy/+DLa3rQQ++QNmEykEA3t8UcsGn+izhvvvEIEBxAM8c2xO/iy74bgWu35KjhmPkLt+SoAwFnTaTI6HPMQMxsBLM1mvgdqdVSO2vKkqAdvXL+FuzOrYFkOd/9YzVqHfsbAlze95NNlnht3FQx0JU6pyxDejSGZyHyFOGs6DWu7GVVnjLh3+wGWZ8m+sMoGfLG1Ht3vvwZruxn1jdWCDVJgO4R7tx9gauwO5iZXiIAUA+r05fhi9D28/pZVluH9+XV8ctmBoJ98qQVIAGooNUZmr+KlV59TZMpsBHCl6Ss8Cu+T8uV+iz/4+qJiOOAg3Xz47eW8oQ5LtAcNdCWmtr55IlX8Oe3BX4sb2PTuIJ1Ko95cjResz6Kt0yKIy0Q8hY66awgFHxEBiqaZC91NArhYZB+fvu3E/M2/s9a32Ey4/ks/qs4c7OSocjUudDfhtx9cRICiQ9zc9rzgfPjzSVE44ODlGLr2q+BaPuFxVKKA9eZqwfnvP85Lmt362Q2WzURMfWN1jtryJApooCv5cmA7hGhI+j+PVDKNAPOQP9cbKwjxcsSghsrcKq/Q4FK/XZYhpdVk2h0q5ytRwFg0k8OeelqHzxzvKjbPtgRTKtEhjkXIzQuaqIM75FNV0C/9wUlKokPscW8SLzhXl/8hag+UNu7kKgGSqgRIqhIgqUqApCp6wH8B9cAOKo9Os8wAAAAASUVORK5CYII=);opacity:.5;}#djDebug a#djShowToolBarButton:hover{background-color:#111;padding-right:6px;border-top-color:#FFE761;border-left-color:#FFE761;border-bottom-color:#FFE761;opacity:1.0;}#djDebug code{display:block;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;white-space:pre;overflow:auto;}#djDebug tr.djDebugOdd{background-color:#f5f5f5;}#djDebug .panelContent{display:none;position:fixed;margin:0;top:0;right:200px;bottom:0;left:0;background-color:#eee;color:#666;z-index:100000000;}#djDebug .panelContent>div{border-bottom:1px solid #ddd;}#djDebug .djDebugPanelTitle{position:absolute;background-color:#ffc;color:#666;padding-left:20px;top:0;right:0;left:0;height:50px;}#djDebug .djDebugPanelTitle code{display:inline;font-size:inherit;}#djDebug .djDebugPanelContent{position:absolute;top:50px;right:0;bottom:0;left:0;height:auto;padding:5px 0 0 20px;}#djDebug .djDebugPanelContent .scroll{height:100%;overflow:auto;display:block;padding:0 10px 0 0;}#djDebug h3{font-size:24px;font-weight:normal;line-height:50px;}#djDebug h4{font-size:20px;font-weight:bold;margin-top:.8em;}#djDebug .panelContent table{border:1px solid #ccc;border-collapse:collapse;width:100%;background-color:#fff;display:block;margin-top:.8em;overflow:auto;}#djDebug .panelContent tbody td,#djDebug .panelContent tbody th{vertical-align:top;padding:2px 3px;}#djDebug .panelContent thead th{padding:1px 6px 1px 3px;text-align:left;font-weight:bold;font-size:14px;}#djDebug .panelContent tbody th{width:12em;text-align:right;color:#666;padding-right:.5em;}#djDebug .djTemplateHideContextDiv{background-color:#fff;}#djDebug .panelContent .djDebugClose{text-indent:-9999999px;display:block;position:absolute;top:4px;right:15px;height:40px;width:40px;background:url(../img/close.png) no-repeat center center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7dJREFUeNqsWM1PE0EU3+7ShdJKoTRA8UYgIUKM3rmaEI0euXsw0YMHIZEbxBijEiIHLkb/A44SDYlXzkYPGBM+ri1NWz7aUmhp6+9tps10mLfdfrzkl2535r39zc77mvUdHh4abUoUCAD3xP/fQAFItWJkYmLC+e1p8eGPgQcC08ycf8BPgW2vhr0SeQa8AWIe5k4LvATiwCrwtZmS2WT8IfAL+OKRhCoxoftH2GqLyBLwHbhvdC53ha2lVrfmE/DKzbLP5yubplnt7e310f+rq6tqpVLxVatVy0VtHbgNLHohsupGIhQKFQG7v79f+8CLiwsjl8sVAZsxQbYTwFrDwpTwpaj4ptPu6+vLDw4OBkHA014QobOzs3yhUAgyUx4BP2rhq/rIe53GwMBAeXx83DMJEpobi8WCpMtMWeOc9TkwoyMRjUattrMedBkyM+KZN4isqDMDgUCuExIyGbKlGVpRiSzo8kQ4HA4ZXRLGVuzo6GhBJjKviw6dT5TLZSOTyRinp6cGQrV+n67hnEY6nTaur6+1PkM2NWTm5fCd0xDRhh89CKHpXCMijLGxMef6+PjYiRSSUqlUv6/arOlKMlcjQlV0qsGDTZPehpYIxurXRCSRSFByq5NQ56hvhWwj8cm2p7A9UdKYVBX8fn+F2+tIJGIgmzaQkUnYtm0MDw+zvsLYniQiEc2q/WxxwmqRHxrISA9xxiyLDzTGdsRsJwJoK3QPo3vctnhpAzLqTexhiVOg6JAdU5bLy0vHZ+Ro8mg7Q0QO1LvwenZZJycnN3yCIPsMRRYnjO0DU/SY+wprW7fiWmjKJMgnUIcafEaeoxZCJWJI9lH4UjV2u6pSPp/XJR9jaGiIKrERDAbrjllzYOQJZ4zm6ISxuSsntB3gqTyazWZtMowa0aBFb4HegC6aRkZG2C2hLSObmqEdOcVvUdJUZyBlZ7tVa1ASdEUvjW3ZUqvvO82e3kqlUuVOSZANvBFd0fugawM2VKclOT8/tzohQ7pkgzn/rHNdvLbLJkPxeDzHRRIXIaTDkCB57XacoJPZW8bZQpSskslk0Y0QjdEcmstsB8myegrsYbqmENfJU3dOpZyOEwjdCqLIWUyxWKygVzHFccJ2eVkbar/qdq5ZFC3/R5dUb6EBsqQmyEtLuawj0eykRwpPgL0uRO+esLXW7tmX9nEWeAEk2yCQFLqzzb4MeK3Zn4FRsapNEXqGy2eJTTF3VOh27bOE/Ia2pQ81YeCO+P+XknGrH2pq8l+AAQDv/n2Gmq99BgAAAABJRU5ErkJggg==);}#djDebug .panelContent .djDebugClose:hover{background-image:url(../img/close_hover.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAABCVJREFUeNqsWG1IU1EYfjfd0i1bTc2WFTW3tG2aFWlEf4KkMIrCvhH6U9DnjxTyV0ZEXxIVGBH1JyKIPiBK8kf1syCKwu8M3VQsK7OV6ba2udZ7bmd6d+85827zhYftnnPe5z73nvc95z1X5XQ6IUHLQqQjiul1E8KHGIqHxGw2C7+pcd58E6KMooAzphPxnKJBKbFSIfsRpxAmBWMLKI4iviBOIm5O5qSepL8c8R5xQ6EIqZmobzPlSkhINeIpYhkkb0WUqzreqbmEOBaTOjQGf/0+CHz7Klxqc+aAehrGbkrM2b6IyEVUKRFyMpYI38dW8HS0gc/5kdmfnpcPepsD0vMLeRSEm6ivEzeqJOlLsuIJyzs40Au/Xr+CP64uRXORZraCoXQ1aHMX8YZsRDRG0lcqpA1hl3p4mt+C+/nThILDWLYR9EtXsrraEY6IEHGwHmCJGG16k7AIYsTX0/KO1WWn95QJqZWODHxyws8XjUmnjPtZg8DFsFqpkB2sdWL4zWuYKuNwmVwu1w6xkA2s7GAFpnaGAcxbd8H8snJQa7QTUZ+aCrlr10NexR5Iy8yW+REuwsmwDeL0XSOLjfYW5pNZtldC9orS/4FoK4LWa5cgHP4L9n1HILNoudCuM82F1qsXgcXJSOs1ESFkF7WKe8JBfxifQMVMY8/o+P+Z+TYoPFwNoYAfMh3FE2udz8d8CPJWCLdKM03MbcXpySJTY5EtmsNuFW+uex4/gJFe14SYxUuiRHi/fIaue7f5CzKb20KEGKWtYx4Pl2jM54WW+joY6euR9Xm/DkDT5bMQHB3h+7O5jepEMiAUDDBvRtpCfn9CWUWEuGUbkF7PdSDZQQLTaC+S9Rks+VB4qCoqmxRyu4mQbmlrisEY5hEtLN8ynh2RmBjt74sK4LyK3VwhHO5uNa0xoxYMEtVk02KZbk7uxB400C/ERPOVc1EBrMsxcTdCScYQ68L9ZiiyjryUprC+wM5c0PoaH4EmIwMCv4eh6+6t8VghAWzdtVdYzHoaHjKFEE6GvRTvvmSZvScd8f3hHfjT2z0lS3zaQgtkb6tkde3EN3I/kjX3ET9kwVdSOmV7jaF0Fav5BxEh3X3PyPaVBVaYta48aRGkJtHOt7C6zrPKgMvSoCU2vbhEIEpGBKcw6qQ1LLNmrWaVioRIk2kUtvK4SsWSVaCdl8cbcjxW8UxOZqcRJ2TThITZCO+HZvB2dsQsnnUFNtAtWRpLZ430FKjinH0VHSdCXg8EhwaFS03WbEjR6Sc7TkRCoErp2beKlvwX+EtkKqRkGATEYTXSY4SSkx5x2Eyr7WStnXLVJXr2JfPoQBxEDCYgYJD6Oib7MqC0DLiOyKFPVU9TD2J8lqinY3Oo75R9lhC/oQbRhxoSIDZ63UGK9Xg/1ETsnwADAJrrTk7nZiozAAAAAElFTkSuQmCC);}#djDebug .panelContent .djDebugClose.djDebugBack{background-image:url(../img/back.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA7FJREFUeNrMWM1PE0EU3+7S7bZdKSFNSIFgJJAgINE7VxOi0SP/gYkePAiJ3CDGGJUQOXAx+h9wlGhIvHI2fgQ08mEkkjZNIZR2+7Httr63zMoyOzPdthx8yS+bnZn3m9/OvDcfG9jd3ZVatDggDLhO3j8DioBMMySDg4P2s6PJzu8AbhKMcNr8AHwkWPNL7FfIPcATQMJH2xGCh4AkYAHwtpGT3KD+FuAT4I1PEbQliO8XwtWSkFnAe8ANqX2bIFyzzU7NK8AjEXMgELBkWa6HQqEAvpfL5XqtVgvU63VF4LYE6APM+BGyIBKh67oJUCORCLPDQqEg5fN5E6ByKJA7BVg892FU+mJWvGN5a5pmdHV1RUGAr7lAQdls1igWi1FOk9uAD0760jHynOXR2dlp9fb2+haBhm0TiUQUfTlNFnnBeh8wxhIRj8eVllc98OWIGSN9eoTM0y3D4XC+HRFuMcjFqJqnhUyz1olYLKa730uVCrMjXrmIy1ln9vb2pt1CpljZQcdE1ihIW/sHHrayWbHLq1ZNGDPIyaiacguZZAhhph+K+fpr39Ppqcg/wtHhcE46QnAXHT4XwbJssjJECwbtp1EqS99AjNNpSD0r//77wH7yRgW5qeJhmJ44ChmiHYLBIHOMY9GINDrQ9y8uHDEoEMs7FNl+x5HhieFwD6GQbs8GJMtBbtCBmIkrA3anOD0YH2ci+21RWJ4vldibG5u7W5b+E8O95oguhM0LP1PhBauTOfj1Tnxg+c+DpD0aOFq6pjE75HAfoZAdunGlUpH9iLh6uc9+nsaFt5xlHO4dmZwxtynVKm5avIUrqoWkaxAnTmdOnGC5SARyIjdVvA0bX8ZRt0E7GYZhNgpWb0b1c0UIODfcC9o6XZvL5VTYwrnp6zaMEyd9eYZcyMmoWncLWQUcemIim82xFjTeQiey4+Nj1qZ3CNOySu++zxhzeimTyVjtpiZywIiwNr0XrGPAMh20aCcnJ0o7YtAXOTj3nyXeKZ55ykaiZDKZZ2WS6KiIPhwRaI9F1wm8mT3lBJueSqWkdDptigRhHbbBtpzpQJujb4EdnFOTzjvJ4+kcYF8nFEWpqapqf4xpmjXLsmRynVAFg7VMn1dF95oZcuR/yWPDDqvVKsIp8nOknGOJaHTTQ4e7gM0L2NM2Cddiq3dfnMdxwANAugUBaeI73ujPgN9jwGtAD/mqFZJ6kuC3xApp20N8L+y3hHuE1lw/amKAUfK+hYtxsz9qHPsrwACHs5P9Qys/0AAAAABJRU5ErkJggg==);}#djDebug .panelContent .djDebugClose.djDebugBack:hover{background-image:url(../img/back_hover.png);background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAiCAYAAAA6RwvCAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA6hJREFUeNrMWF1Ik1EYPtt0pkuGa/aDJTY3nNvSfkglvEwQpa7CbrosKAghBedNikKgEgVe1m03SVeJXmSXBmIozpxpuiUS/eicSc75m73vx/nGt7Nzvm8/BR14+Pjec85znp297znv++kCgQBJs1kBuYDz9H0KEAWEUiGx2WzSMyvFxa8B6iicgjFzgBGKwWSJdUnuyB1AF+BUisK/AToBz7V2RK9B1ACYBDxLQwShc3Cuj3IJm5qQVsAQ4ALJvFVQrlbRAJGPPAE8UKU+2Ce/d6Jk98d36dV44iTR54DvGlTd7jGgCNCSjJBONRHR+Q8kMjtDooF5bn9uaRkxuTwkt+yciAK5UX2fmrNiVLzmzd77ukR+jr0j28GFpP6LIzYHMVdfIcais6IhjYBh2VlZITMANzsj4ntPwiNDaTmHpa6RmCov87r8AA8vau7yRGxOjactAhvOjUxP8LrcdM0EIR3syN0vAbL+djjjkAm/GZS4OK2DFdLEOyc2xsfi/3frcb4/COxqXPI5EwwGm5RC6nnRwTpmgdNNKpq9iZFiLZTsWXkmoRDkQk5Oq1cKqU3wDf80lxDFXGzvTlhUFqm2OwLOWlkI3qIOZc/h3s4hL0y3QyvSM7+4hFxq74otGg2txuyVzW3SU7QryM2YHfD3WFGIPeHQ3AjreETrc34y3d8b8wtZDApE+/5WRHrHnRGJEXDbUYiFte5HIsLtRTGTPR3Sovj3oH8oRaIotB8t5h9kAm6LnvwnDe+acILRJPZ+ZeTgr5f9A+2u2/el3cDd2lz+zF+Qzx1GIYus1WC2oEPptET4+vukp+wXrJ3XBNyLeppjxoWILjtHh5eW6OD6tbxEJno6Y4vJfoJ2NRHIidyMeQHum5DsI6PsJJPTremsvIgSiVDhHFXevnjMvmRHrL56QbaXFuN2hLeQyB43psROCm/c4nXdhB0ZkHdkALDGjjBXVXMPNNFBp9bM1TU88xqKYG/fR+woY7GDFFxtyDg0MScxnrHzunpEGdon9rj/h4kR1j/logKrlZcqIlH2MYt0laeUKlbVEOPpUtGQNq0CqxvwUDR766OPbM3NqibPeU4XySuvVNPplZNnUc6aUjlxACG8Rx01GyLHgKmBQbOKfaosJ7Rq3xaa8vcK6WBBQ75ZQgrNy5YRyVR6OOE6zbYzbX7K1ZdOyUloNe8B3AOspCFghc71aH0Z0KX4feSvf5bQctZkP9Sgg7jo+ywm6+l+qPkjwADNS26fFM/O1QAAAABJRU5ErkJggg==);}#djDebug .panelContent dt,#djDebug .panelContent dd{display:block;}#djDebug .panelContent dt{margin-top:.75em;}#djDebug .panelContent dd{margin-left:10px;}#djDebug a.toggleTemplate{padding:4px;background-color:#bbb;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.toggleTemplate:hover{padding:4px;background-color:#444;color:#ffe761;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.djTemplateShowContext,#djDebug a.djTemplateShowContext span.toggleArrow{color:#999;}#djDebug a.djTemplateShowContext:hover,#djDebug a.djTemplateShowContext:hover span.toggleArrow{color:#000;cursor:pointer;}#djDebug .djDebugSqlWrap{position:relative;}#djDebug .djDebugCollapsed{display:none;text-decoration:none;color:#333;}#djDebug .djDebugUncollapsed{color:#333;text-decoration:none;}#djDebug .djUnselected{display:none;}#djDebug tr.djHiddenByDefault{display:none;}#djDebug tr.djSelected{display:table-row;}#djDebug .djDebugSql{z-index:100000002;}#djDebug .djSQLDetailsDiv tbody th{text-align:left;}#djDebug .djSqlExplain td{white-space:pre;}#djDebug span.djDebugLineChart{background-color:#777;height:3px;position:absolute;bottom:0;top:0;left:0;display:block;z-index:1000000001;}#djDebug span.djDebugLineChartWarning{background-color:#900;}#djDebug .highlight{color:#000;}#djDebug .highlight .err{color:#000;}#djDebug .highlight .g{color:#000;}#djDebug .highlight .k{color:#000;font-weight:bold;}#djDebug .highlight .o{color:#000;}#djDebug .highlight .n{color:#000;}#djDebug .highlight .mi{color:#000;font-weight:bold;}#djDebug .highlight .l{color:#000;}#djDebug .highlight .x{color:#000;}#djDebug .highlight .p{color:#000;}#djDebug .highlight .m{color:#000;font-weight:bold;}#djDebug .highlight .s{color:#333;}#djDebug .highlight .w{color:#888;}#djDebug .highlight .il{color:#000;font-weight:bold;}#djDebug .highlight .na{color:#333;}#djDebug .highlight .nt{color:#000;font-weight:bold;}#djDebug .highlight .nv{color:#333;}#djDebug .highlight .s2{color:#333;}#djDebug .highlight .cp{color:#333;}#djDebug .timeline{width:30%;}#djDebug .djDebugTimeline{position:relative;height:100%;min-height:100%;}#djDebug div.djDebugLineChart{position:absolute;left:0;right:0;top:0;bottom:0;vertical-align:middle;}#djDebug div.djDebugLineChart strong{text-indent:-10000em;display:block;font-weight:normal;vertical-align:middle;background-color:#ccc;}#djDebug div.djDebugLineChartWarning strong{background-color:#900;}#djDebug .djDebugInTransaction div.djDebugLineChart strong{background-color:#d3ff82;}#djDebug .djDebugStartTransaction div.djDebugLineChart strong{border-left:1px solid #94b24d;}#djDebug .djDebugEndTransaction div.djDebugLineChart strong{border-right:1px solid #94b24d;}#djDebug .djDebugHover div.djDebugLineChart strong{background-color:#000;}#djDebug .djDebugInTransaction.djDebugHover div.djDebugLineChart strong{background-color:#94b24d;}#djDebug .panelContent ul.stats{position:relative;}#djDebug .panelContent ul.stats li{width:30%;float:left;}#djDebug .panelContent ul.stats li strong.label{display:block;}#djDebug .panelContent ul.stats li span.color{height:12px;width:3px;display:inline-block;}#djDebug .panelContent ul.stats li span.info{display:block;padding-left:5px;}#djDebug .panelcontent thead th{white-space:nowrap;}#djDebug .djDebugRowWarning .time{color:red;}#djdebug .panelcontent table .toggle{width:14px;padding-top:3px;}#djdebug .panelcontent table .actions{min-width:70px;}#djdebug .panelcontent table .color{width:3px;}#djdebug .panelcontent table .color span{width:3px;height:12px;overflow:hidden;padding:0;}#djDebug .djToggleSwitch{text-decoration:none;border:1px solid #999;height:12px;width:12px;line-height:12px;text-align:center;color:#777;display:inline-block;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFF',endColorstr='#DCDCDC');background:-webkit-gradient(linear,left top,left bottom,from(#FFF),to(#DCDCDC));background:-moz-linear-gradient(center top,#FFF 0,#DCDCDC 100%) repeat scroll 0 0 transparent;}#djDebug .djNoToggleSwitch{height:14px;width:14px;display:inline-block;}#djDebug .djSQLDetailsDiv{margin-top:.8em;}#djDebug pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;color:#555;border:1px solid #ccc;border-collapse:collapse;background-color:#fff;display:block;overflow:auto;padding:2px 3px;margin-bottom:3px;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;}#djDebug .stack span{color:#000;font-weight:bold;}#djDebug .stack span.path{color:#777;font-weight:normal;}#djDebug .stack span.code{font-weight:normal;}@media print{#djDebug{display:none;}}
\ No newline at end of file diff --git a/debug_toolbar/media/debug_toolbar/js/toolbar.js b/debug_toolbar/media/debug_toolbar/js/toolbar.js index c763fd2..3d66769 100644 --- a/debug_toolbar/media/debug_toolbar/js/toolbar.js +++ b/debug_toolbar/media/debug_toolbar/js/toolbar.js @@ -51,6 +51,11 @@ window.djdt = (function(window, document, jQuery) { djdt.toggle_content($(this).parent().next()); return false; }); + $('#djDebug a.djDebugToggle').click(function(e) { + e.preventDefault(); + $(this).parent().find('.djDebugCollapsed').toggle(); + $(this).parent().find('.djDebugUncollapsed').toggle() + }); $('#djDebug a.djToggleSwitch').click(function(e) { e.preventDefault(); var btn = $(this); @@ -60,6 +65,8 @@ window.djdt = (function(window, document, jQuery) { return; } + btn.parents('.djDebugPanelContent').find('#sqlMain_' + id).find('.djDebugCollapsed').toggle(open_me); + btn.parents('.djDebugPanelContent').find('#sqlMain_' + id).find('.djDebugUncollapsed').toggle(!open_me); $(this).parents('.djDebugPanelContent').find('.djToggleDetails_' + id).each(function(){ var $this = $(this); if (open_me) { @@ -198,4 +205,4 @@ window.djdt = (function(window, document, jQuery) { djdt.init(); }); return djdt; -}(window, document, jQuery.noConflict())); +}(window, document, jQuery.noConflict(true))); diff --git a/debug_toolbar/media/debug_toolbar/js/toolbar.min.js b/debug_toolbar/media/debug_toolbar/js/toolbar.min.js index b72b0b5..4f843e2 100644 --- a/debug_toolbar/media/debug_toolbar/js/toolbar.min.js +++ b/debug_toolbar/media/debug_toolbar/js/toolbar.min.js @@ -20,4 +20,4 @@ * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ -}(function(){var a5=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,a6=0,a8=Object.prototype.toString,a0=false,aZ=true;[0,0].sort(function(){aZ=false;return 0});var aW=function(bh,bc,bk,bl){bk=bk||[];var bn=bc=bc||aa;if(bc.nodeType!==1&&bc.nodeType!==9){return[]}if(!bh||typeof bh!=="string"){return bk}var bi=[],be,bp,bs,bd,bg=true,bf=aX(bc),bm=bh;while((a5.exec(""),be=a5.exec(bm))!==null){bm=be[3];bi.push(be[1]);if(be[2]){bd=be[3];break}}if(bi.length>1&&a1.exec(bh)){if(bi.length===2&&a2.relative[bi[0]]){bp=a9(bi[0]+bi[1],bc)}else{bp=a2.relative[bi[0]]?[bc]:aW(bi.shift(),bc);while(bi.length){bh=bi.shift();if(a2.relative[bh]){bh+=bi.shift()}bp=a9(bh,bp)}}}else{if(!bl&&bi.length>1&&bc.nodeType===9&&!bf&&a2.match.ID.test(bi[0])&&!a2.match.ID.test(bi[bi.length-1])){var bo=aW.find(bi.shift(),bc,bf);bc=bo.expr?aW.filter(bo.expr,bo.set)[0]:bo.set[0]}if(bc){var bo=bl?{expr:bi.pop(),set:a4(bl)}:aW.find(bi.pop(),bi.length===1&&(bi[0]==="~"||bi[0]==="+")&&bc.parentNode?bc.parentNode:bc,bf);bp=bo.expr?aW.filter(bo.expr,bo.set):bo.set;if(bi.length>0){bs=a4(bp)}else{bg=false}while(bi.length){var br=bi.pop(),bq=br;if(!a2.relative[br]){br=""}else{bq=bi.pop()}if(bq==null){bq=bc}a2.relative[br](bs,bq,bf)}}else{bs=bi=[]}}if(!bs){bs=bp}if(!bs){aW.error(br||bh)}if(a8.call(bs)==="[object Array]"){if(!bg){bk.push.apply(bk,bs)}else{if(bc&&bc.nodeType===1){for(var bj=0;bs[bj]!=null;bj++){if(bs[bj]&&(bs[bj]===true||bs[bj].nodeType===1&&a3(bc,bs[bj]))){bk.push(bp[bj])}}}else{for(var bj=0;bs[bj]!=null;bj++){if(bs[bj]&&bs[bj].nodeType===1){bk.push(bp[bj])}}}}}else{a4(bs,bk)}if(bd){aW(bd,bn,bk,bl);aW.uniqueSort(bk)}return bk};aW.uniqueSort=function(bd){if(a7){a0=aZ;bd.sort(a7);if(a0){for(var bc=1;bc<bd.length;bc++){if(bd[bc]===bd[bc-1]){bd.splice(bc--,1)}}}}return bd};aW.matches=function(bc,bd){return aW(bc,null,null,bd)};aW.find=function(bj,bc,bk){var bi,bg;if(!bj){return[]}for(var bf=0,be=a2.order.length;bf<be;bf++){var bh=a2.order[bf],bg;if((bg=a2.leftMatch[bh].exec(bj))){var bd=bg[1];bg.splice(1,1);if(bd.substr(bd.length-1)!=="\\"){bg[1]=(bg[1]||"").replace(/\\/g,"");bi=a2.find[bh](bg,bc,bk);if(bi!=null){bj=bj.replace(a2.match[bh],"");break}}}}if(!bi){bi=bc.getElementsByTagName("*")}return{set:bi,expr:bj}};aW.filter=function(bn,bm,bq,bg){var be=bn,bs=[],bk=bm,bi,bc,bj=bm&&bm[0]&&aX(bm[0]);while(bn&&bm.length){for(var bl in a2.filter){if((bi=a2.leftMatch[bl].exec(bn))!=null&&bi[2]){var bd=a2.filter[bl],br,bp,bf=bi[1];bc=false;bi.splice(1,1);if(bf.substr(bf.length-1)==="\\"){continue}if(bk===bs){bs=[]}if(a2.preFilter[bl]){bi=a2.preFilter[bl](bi,bk,bq,bs,bg,bj);if(!bi){bc=br=true}else{if(bi===true){continue}}}if(bi){for(var bh=0;(bp=bk[bh])!=null;bh++){if(bp){br=bd(bp,bi,bh,bk);var bo=bg^!!br;if(bq&&br!=null){if(bo){bc=true}else{bk[bh]=false}}else{if(bo){bs.push(bp);bc=true}}}}}if(br!==B){if(!bq){bk=bs}bn=bn.replace(a2.match[bl],"");if(!bc){return[]}break}}}if(bn===be){if(bc==null){aW.error(bn)}else{break}}be=bn}return bk};aW.error=function(bc){throw"Syntax error, unrecognized expression: "+bc};var a2=aW.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(bc){return bc.getAttribute("href")}},relative:{"+":function(bi,bd){var bf=typeof bd==="string",bh=bf&&!/\W/.test(bd),bj=bf&&!bh;if(bh){bd=bd.toLowerCase()}for(var be=0,bc=bi.length,bg;be<bc;be++){if((bg=bi[be])){while((bg=bg.previousSibling)&&bg.nodeType!==1){}bi[be]=bj||bg&&bg.nodeName.toLowerCase()===bd?bg||false:bg===bd}}if(bj){aW.filter(bd,bi,true)}},">":function(bi,bd){var bg=typeof bd==="string";if(bg&&!/\W/.test(bd)){bd=bd.toLowerCase();for(var be=0,bc=bi.length;be<bc;be++){var bh=bi[be];if(bh){var bf=bh.parentNode;bi[be]=bf.nodeName.toLowerCase()===bd?bf:false}}}else{for(var be=0,bc=bi.length;be<bc;be++){var bh=bi[be];if(bh){bi[be]=bg?bh.parentNode:bh.parentNode===bd}}if(bg){aW.filter(bd,bi,true)}}},"":function(bf,bd,bh){var be=a6++,bc=ba;if(typeof bd==="string"&&!/\W/.test(bd)){var bg=bd=bd.toLowerCase();bc=aU}bc("parentNode",bd,be,bf,bg,bh)},"~":function(bf,bd,bh){var be=a6++,bc=ba;if(typeof bd==="string"&&!/\W/.test(bd)){var bg=bd=bd.toLowerCase();bc=aU}bc("previousSibling",bd,be,bf,bg,bh)}},find:{ID:function(bd,be,bf){if(typeof be.getElementById!=="undefined"&&!bf){var bc=be.getElementById(bd[1]);return bc?[bc]:[]}},NAME:function(be,bh){if(typeof bh.getElementsByName!=="undefined"){var bd=[],bg=bh.getElementsByName(be[1]);for(var bf=0,bc=bg.length;bf<bc;bf++){if(bg[bf].getAttribute("name")===be[1]){bd.push(bg[bf])}}return bd.length===0?null:bd}},TAG:function(bc,bd){return bd.getElementsByTagName(bc[1])}},preFilter:{CLASS:function(bf,bd,be,bc,bi,bj){bf=" "+bf[1].replace(/\\/g,"")+" ";if(bj){return bf}for(var bg=0,bh;(bh=bd[bg])!=null;bg++){if(bh){if(bi^(bh.className&&(" "+bh.className+" ").replace(/[\t\n]/g," ").indexOf(bf)>=0)){if(!be){bc.push(bh)}}else{if(be){bd[bg]=false}}}}return false},ID:function(bc){return bc[1].replace(/\\/g,"")},TAG:function(bd,bc){return bd[1].toLowerCase()},CHILD:function(bc){if(bc[1]==="nth"){var bd=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(bc[2]==="even"&&"2n"||bc[2]==="odd"&&"2n+1"||!/\D/.test(bc[2])&&"0n+"+bc[2]||bc[2]);bc[2]=(bd[1]+(bd[2]||1))-0;bc[3]=bd[3]-0}bc[0]=a6++;return bc},ATTR:function(bg,bd,be,bc,bh,bi){var bf=bg[1].replace(/\\/g,"");if(!bi&&a2.attrMap[bf]){bg[1]=a2.attrMap[bf]}if(bg[2]==="~="){bg[4]=" "+bg[4]+" "}return bg},PSEUDO:function(bg,bd,be,bc,bh){if(bg[1]==="not"){if((a5.exec(bg[3])||"").length>1||/^\w/.test(bg[3])){bg[3]=aW(bg[3],null,null,bd)}else{var bf=aW.filter(bg[3],bd,be,true^bh);if(!be){bc.push.apply(bc,bf)}return false}}else{if(a2.match.POS.test(bg[0])||a2.match.CHILD.test(bg[0])){return true}}return bg},POS:function(bc){bc.unshift(true);return bc}},filters:{enabled:function(bc){return bc.disabled===false&&bc.type!=="hidden"},disabled:function(bc){return bc.disabled===true},checked:function(bc){return bc.checked===true},selected:function(bc){bc.parentNode.selectedIndex;return bc.selected===true},parent:function(bc){return !!bc.firstChild},empty:function(bc){return !bc.firstChild},has:function(be,bd,bc){return !!aW(bc[3],be).length},header:function(bc){return/h\d/i.test(bc.nodeName)},text:function(bc){return"text"===bc.type},radio:function(bc){return"radio"===bc.type},checkbox:function(bc){return"checkbox"===bc.type},file:function(bc){return"file"===bc.type},password:function(bc){return"password"===bc.type},submit:function(bc){return"submit"===bc.type},image:function(bc){return"image"===bc.type},reset:function(bc){return"reset"===bc.type},button:function(bc){return"button"===bc.type||bc.nodeName.toLowerCase()==="button"},input:function(bc){return/input|select|textarea|button/i.test(bc.nodeName)}},setFilters:{first:function(bd,bc){return bc===0},last:function(be,bd,bc,bf){return bd===bf.length-1},even:function(bd,bc){return bc%2===0},odd:function(bd,bc){return bc%2===1},lt:function(be,bd,bc){return bd<bc[3]-0},gt:function(be,bd,bc){return bd>bc[3]-0},nth:function(be,bd,bc){return bc[3]-0===bd},eq:function(be,bd,bc){return bc[3]-0===bd}},filter:{PSEUDO:function(bi,be,bf,bj){var bd=be[1],bg=a2.filters[bd];if(bg){return bg(bi,bf,be,bj)}else{if(bd==="contains"){return(bi.textContent||bi.innerText||aV([bi])||"").indexOf(be[3])>=0}else{if(bd==="not"){var bh=be[3];for(var bf=0,bc=bh.length;bf<bc;bf++){if(bh[bf]===bi){return false}}return true}else{aW.error("Syntax error, unrecognized expression: "+bd)}}}},CHILD:function(bc,bf){var bi=bf[1],bd=bc;switch(bi){case"only":case"first":while((bd=bd.previousSibling)){if(bd.nodeType===1){return false}}if(bi==="first"){return true}bd=bc;case"last":while((bd=bd.nextSibling)){if(bd.nodeType===1){return false}}return true;case"nth":var be=bf[2],bl=bf[3];if(be===1&&bl===0){return true}var bh=bf[0],bk=bc.parentNode;if(bk&&(bk.sizcache!==bh||!bc.nodeIndex)){var bg=0;for(bd=bk.firstChild;bd;bd=bd.nextSibling){if(bd.nodeType===1){bd.nodeIndex=++bg}}bk.sizcache=bh}var bj=bc.nodeIndex-bl;if(be===0){return bj===0}else{return(bj%be===0&&bj/be>=0)}}},ID:function(bd,bc){return bd.nodeType===1&&bd.getAttribute("id")===bc},TAG:function(bd,bc){return(bc==="*"&&bd.nodeType===1)||bd.nodeName.toLowerCase()===bc},CLASS:function(bd,bc){return(" "+(bd.className||bd.getAttribute("class"))+" ").indexOf(bc)>-1},ATTR:function(bh,bf){var be=bf[1],bc=a2.attrHandle[be]?a2.attrHandle[be](bh):bh[be]!=null?bh[be]:bh.getAttribute(be),bi=bc+"",bg=bf[2],bd=bf[4];return bc==null?bg==="!=":bg==="="?bi===bd:bg==="*="?bi.indexOf(bd)>=0:bg==="~="?(" "+bi+" ").indexOf(bd)>=0:!bd?bi&&bc!==false:bg==="!="?bi!==bd:bg==="^="?bi.indexOf(bd)===0:bg==="$="?bi.substr(bi.length-bd.length)===bd:bg==="|="?bi===bd||bi.substr(0,bd.length+1)===bd+"-":false},POS:function(bg,bd,be,bh){var bc=bd[2],bf=a2.setFilters[bc];if(bf){return bf(bg,be,bd,bh)}}}};var a1=a2.match.POS;for(var aY in a2.match){a2.match[aY]=new RegExp(a2.match[aY].source+/(?![^\[]*\])(?![^\(]*\))/.source);a2.leftMatch[aY]=new RegExp(/(^(?:.|\r|\n)*?)/.source+a2.match[aY].source.replace(/\\(\d+)/g,function(bd,bc){return"\\"+(bc-0+1)}))}var a4=function(bd,bc){bd=Array.prototype.slice.call(bd,0);if(bc){bc.push.apply(bc,bd);return bc}return bd};try{Array.prototype.slice.call(aa.documentElement.childNodes,0)}catch(bb){a4=function(bg,bf){var bd=bf||[];if(a8.call(bg)==="[object Array]"){Array.prototype.push.apply(bd,bg)}else{if(typeof bg.length==="number"){for(var be=0,bc=bg.length;be<bc;be++){bd.push(bg[be])}}else{for(var be=0;bg[be];be++){bd.push(bg[be])}}}return bd}}var a7;if(aa.documentElement.compareDocumentPosition){a7=function(bd,bc){if(!bd.compareDocumentPosition||!bc.compareDocumentPosition){if(bd==bc){a0=true}return bd.compareDocumentPosition?-1:1}var be=bd.compareDocumentPosition(bc)&4?-1:bd===bc?0:1;if(be===0){a0=true}return be}}else{if("sourceIndex" in aa.documentElement){a7=function(bd,bc){if(!bd.sourceIndex||!bc.sourceIndex){if(bd==bc){a0=true}return bd.sourceIndex?-1:1}var be=bd.sourceIndex-bc.sourceIndex;if(be===0){a0=true}return be}}else{if(aa.createRange){a7=function(bf,bd){if(!bf.ownerDocument||!bd.ownerDocument){if(bf==bd){a0=true}return bf.ownerDocument?-1:1}var be=bf.ownerDocument.createRange(),bc=bd.ownerDocument.createRange();be.setStart(bf,0);be.setEnd(bf,0);bc.setStart(bd,0);bc.setEnd(bd,0);var bg=be.compareBoundaryPoints(Range.START_TO_END,bc);if(bg===0){a0=true}return bg}}}}function aV(bc){var bd="",bf;for(var be=0;bc[be];be++){bf=bc[be];if(bf.nodeType===3||bf.nodeType===4){bd+=bf.nodeValue}else{if(bf.nodeType!==8){bd+=aV(bf.childNodes)}}}return bd}(function(){var bd=aa.createElement("div"),be="script"+(new Date).getTime();bd.innerHTML="<a name='"+be+"'/>";var bc=aa.documentElement;bc.insertBefore(bd,bc.firstChild);if(aa.getElementById(be)){a2.find.ID=function(bg,bh,bi){if(typeof bh.getElementById!=="undefined"&&!bi){var bf=bh.getElementById(bg[1]);return bf?bf.id===bg[1]||typeof bf.getAttributeNode!=="undefined"&&bf.getAttributeNode("id").nodeValue===bg[1]?[bf]:B:[]}};a2.filter.ID=function(bh,bf){var bg=typeof bh.getAttributeNode!=="undefined"&&bh.getAttributeNode("id");return bh.nodeType===1&&bg&&bg.nodeValue===bf}}bc.removeChild(bd);bc=bd=null})();(function(){var bc=aa.createElement("div");bc.appendChild(aa.createComment(""));if(bc.getElementsByTagName("*").length>0){a2.find.TAG=function(bd,bh){var bg=bh.getElementsByTagName(bd[1]);if(bd[1]==="*"){var bf=[];for(var be=0;bg[be];be++){if(bg[be].nodeType===1){bf.push(bg[be])}}bg=bf}return bg}}bc.innerHTML="<a href='#'></a>";if(bc.firstChild&&typeof bc.firstChild.getAttribute!=="undefined"&&bc.firstChild.getAttribute("href")!=="#"){a2.attrHandle.href=function(bd){return bd.getAttribute("href",2)}}bc=null})();if(aa.querySelectorAll){(function(){var bc=aW,be=aa.createElement("div");be.innerHTML="<p class='TEST'></p>";if(be.querySelectorAll&&be.querySelectorAll(".TEST").length===0){return}aW=function(bi,bh,bf,bg){bh=bh||aa;if(!bg&&bh.nodeType===9&&!aX(bh)){try{return a4(bh.querySelectorAll(bi),bf)}catch(bj){}}return bc(bi,bh,bf,bg)};for(var bd in bc){aW[bd]=bc[bd]}be=null})()}(function(){var bc=aa.createElement("div");bc.innerHTML="<div class='test e'></div><div class='test'></div>";if(!bc.getElementsByClassName||bc.getElementsByClassName("e").length===0){return}bc.lastChild.className="e";if(bc.getElementsByClassName("e").length===1){return}a2.order.splice(1,0,"CLASS");a2.find.CLASS=function(bd,be,bf){if(typeof be.getElementsByClassName!=="undefined"&&!bf){return be.getElementsByClassName(bd[1])}};bc=null})();function aU(bd,bi,bh,bl,bj,bk){for(var bf=0,be=bl.length;bf<be;bf++){var bc=bl[bf];if(bc){bc=bc[bd];var bg=false;while(bc){if(bc.sizcache===bh){bg=bl[bc.sizset];break}if(bc.nodeType===1&&!bk){bc.sizcache=bh;bc.sizset=bf}if(bc.nodeName.toLowerCase()===bi){bg=bc;break}bc=bc[bd]}bl[bf]=bg}}}function ba(bd,bi,bh,bl,bj,bk){for(var bf=0,be=bl.length;bf<be;bf++){var bc=bl[bf];if(bc){bc=bc[bd];var bg=false;while(bc){if(bc.sizcache===bh){bg=bl[bc.sizset];break}if(bc.nodeType===1){if(!bk){bc.sizcache=bh;bc.sizset=bf}if(typeof bi!=="string"){if(bc===bi){bg=true;break}}else{if(aW.filter(bi,[bc]).length>0){bg=bc;break}}}bc=bc[bd]}bl[bf]=bg}}}var a3=aa.compareDocumentPosition?function(bd,bc){return bd.compareDocumentPosition(bc)&16}:function(bd,bc){return bd!==bc&&(bd.contains?bd.contains(bc):true)};var aX=function(bc){var bd=(bc?bc.ownerDocument||bc:0).documentElement;return bd?bd.nodeName!=="HTML":false};var a9=function(bc,bj){var bf=[],bg="",bh,be=bj.nodeType?[bj]:bj;while((bh=a2.match.PSEUDO.exec(bc))){bg+=bh[0];bc=bc.replace(a2.match.PSEUDO,"")}bc=a2.relative[bc]?bc+"*":bc;for(var bi=0,bd=be.length;bi<bd;bi++){aW(bc,be[bi],bf)}return aW.filter(bg,bf)};a.find=aW;a.expr=aW.selectors;a.expr[":"]=a.expr.filters;a.unique=aW.uniqueSort;a.getText=aV;a.isXMLDoc=aX;a.contains=a3;return;aI.Sizzle=aW})();var M=/Until$/,X=/^(?:parents|prevUntil|prevAll)/,aH=/,/,D=Array.prototype.slice;var ag=function(aX,aW,aU){if(a.isFunction(aW)){return a.grep(aX,function(aZ,aY){return !!aW.call(aZ,aY,aZ)===aU})}else{if(aW.nodeType){return a.grep(aX,function(aZ,aY){return(aZ===aW)===aU})}else{if(typeof aW==="string"){var aV=a.grep(aX,function(aY){return aY.nodeType===1});if(aS.test(aW)){return a.filter(aW,aV,!aU)}else{aW=a.filter(aW,aV)}}}}return a.grep(aX,function(aZ,aY){return(a.inArray(aZ,aW)>=0)===aU})};a.fn.extend({find:function(aU){var aW=this.pushStack("","find",aU),aZ=0;for(var aX=0,aV=this.length;aX<aV;aX++){aZ=aW.length;a.find(aU,this[aX],aW);if(aX>0){for(var a0=aZ;a0<aW.length;a0++){for(var aY=0;aY<aZ;aY++){if(aW[aY]===aW[a0]){aW.splice(a0--,1);break}}}}}return aW},has:function(aV){var aU=a(aV);return this.filter(function(){for(var aX=0,aW=aU.length;aX<aW;aX++){if(a.contains(this,aU[aX])){return true}}})},not:function(aU){return this.pushStack(ag(this,aU,false),"not",aU)},filter:function(aU){return this.pushStack(ag(this,aU,true),"filter",aU)},is:function(aU){return !!aU&&a.filter(aU,this).length>0},closest:function(a3,aU){if(a.isArray(a3)){var a0=[],a2=this[0],aZ,aY={},aW;if(a2&&a3.length){for(var aX=0,aV=a3.length;aX<aV;aX++){aW=a3[aX];if(!aY[aW]){aY[aW]=a.expr.match.POS.test(aW)?a(aW,aU||this.context):aW}}while(a2&&a2.ownerDocument&&a2!==aU){for(aW in aY){aZ=aY[aW];if(aZ.jquery?aZ.index(a2)>-1:a(a2).is(aZ)){a0.push({selector:aW,elem:a2});delete aY[aW]}}a2=a2.parentNode}}return a0}var a1=a.expr.match.POS.test(a3)?a(a3,aU||this.context):null;return this.map(function(a4,a5){while(a5&&a5.ownerDocument&&a5!==aU){if(a1?a1.index(a5)>-1:a(a5).is(a3)){return a5}a5=a5.parentNode}return null})},index:function(aU){if(!aU||typeof aU==="string"){return a.inArray(this[0],aU?a(aU):this.parent().children())}return a.inArray(aU.jquery?aU[0]:aU,this)},add:function(aU,aV){var aX=typeof aU==="string"?a(aU,aV||this.context):a.makeArray(aU),aW=a.merge(this.get(),aX);return this.pushStack(x(aX[0])||x(aW[0])?aW:a.unique(aW))},andSelf:function(){return this.add(this.prevObject)}});function x(aU){return !aU||!aU.parentNode||aU.parentNode.nodeType===11}a.each({parent:function(aV){var aU=aV.parentNode;return aU&&aU.nodeType!==11?aU:null},parents:function(aU){return a.dir(aU,"parentNode")},parentsUntil:function(aV,aU,aW){return a.dir(aV,"parentNode",aW)},next:function(aU){return a.nth(aU,2,"nextSibling")},prev:function(aU){return a.nth(aU,2,"previousSibling")},nextAll:function(aU){return a.dir(aU,"nextSibling")},prevAll:function(aU){return a.dir(aU,"previousSibling")},nextUntil:function(aV,aU,aW){return a.dir(aV,"nextSibling",aW)},prevUntil:function(aV,aU,aW){return a.dir(aV,"previousSibling",aW)},siblings:function(aU){return a.sibling(aU.parentNode.firstChild,aU)},children:function(aU){return a.sibling(aU.firstChild)},contents:function(aU){return a.nodeName(aU,"iframe")?aU.contentDocument||aU.contentWindow.document:a.makeArray(aU.childNodes)}},function(aU,aV){a.fn[aU]=function(aY,aW){var aX=a.map(this,aV,aY);if(!M.test(aU)){aW=aY}if(aW&&typeof aW==="string"){aX=a.filter(aW,aX)}aX=this.length>1?a.unique(aX):aX;if((this.length>1||aH.test(aW))&&X.test(aU)){aX=aX.reverse()}return this.pushStack(aX,aU,D.call(arguments).join(","))}});a.extend({filter:function(aW,aU,aV){if(aV){aW=":not("+aW+")"}return a.find.matches(aW,aU)},dir:function(aW,aV,aY){var aU=[],aX=aW[aV];while(aX&&aX.nodeType!==9&&(aY===B||aX.nodeType!==1||!a(aX).is(aY))){if(aX.nodeType===1){aU.push(aX)}aX=aX[aV]}return aU},nth:function(aY,aU,aW,aX){aU=aU||1;var aV=0;for(;aY;aY=aY[aW]){if(aY.nodeType===1&&++aV===aU){break}}return aY},sibling:function(aW,aV){var aU=[];for(;aW;aW=aW.nextSibling){if(aW.nodeType===1&&aW!==aV){aU.push(aW)}}return aU}});var S=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,F=/(<([\w:]+)[^>]*?)\/>/g,aj=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,c=/<([\w:]+)/,t=/<tbody/i,J=/<|&\w+;/,l=/checked\s*(?:[^=]|=\s*.checked.)/i,p=function(aV,aW,aU){return aj.test(aU)?aV:aW+"></"+aU+">"},ab={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};ab.optgroup=ab.option;ab.tbody=ab.tfoot=ab.colgroup=ab.caption=ab.thead;ab.th=ab.td;if(!a.support.htmlSerialize){ab._default=[1,"div<div>","</div>"]}a.fn.extend({text:function(aU){if(a.isFunction(aU)){return this.each(function(aW){var aV=a(this);aV.text(aU.call(this,aW,aV.text()))})}if(typeof aU!=="object"&&aU!==B){return this.empty().append((this[0]&&this[0].ownerDocument||aa).createTextNode(aU))}return a.getText(this)},wrapAll:function(aU){if(a.isFunction(aU)){return this.each(function(aW){a(this).wrapAll(aU.call(this,aW))})}if(this[0]){var aV=a(aU,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){aV.insertBefore(this[0])}aV.map(function(){var aW=this;while(aW.firstChild&&aW.firstChild.nodeType===1){aW=aW.firstChild}return aW}).append(this)}return this},wrapInner:function(aU){if(a.isFunction(aU)){return this.each(function(aV){a(this).wrapInner(aU.call(this,aV))})}return this.each(function(){var aV=a(this),aW=aV.contents();if(aW.length){aW.wrapAll(aU)}else{aV.append(aU)}})},wrap:function(aU){return this.each(function(){a(this).wrapAll(aU)})},unwrap:function(){return this.parent().each(function(){if(!a.nodeName(this,"body")){a(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(aU){if(this.nodeType===1){this.appendChild(aU)}})},prepend:function(){return this.domManip(arguments,true,function(aU){if(this.nodeType===1){this.insertBefore(aU,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(aV){this.parentNode.insertBefore(aV,this)})}else{if(arguments.length){var aU=a(arguments[0]);aU.push.apply(aU,this.toArray());return this.pushStack(aU,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(aV){this.parentNode.insertBefore(aV,this.nextSibling)})}else{if(arguments.length){var aU=this.pushStack(this,"after",arguments);aU.push.apply(aU,a(arguments[0]).toArray());return aU}}},clone:function(aV){var aU=this.map(function(){if(!a.support.noCloneEvent&&!a.isXMLDoc(this)){var aX=this.outerHTML,aW=this.ownerDocument;if(!aX){var aY=aW.createElement("div");aY.appendChild(this.cloneNode(true));aX=aY.innerHTML}return a.clean([aX.replace(S,"").replace(Y,"")],aW)[0]}else{return this.cloneNode(true)}});if(aV===true){q(this,aU);q(this.find("*"),aU.find("*"))}return aU},html:function(aW){if(aW===B){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(S,""):null}else{if(typeof aW==="string"&&!/<script/i.test(aW)&&(a.support.leadingWhitespace||!Y.test(aW))&&!ab[(c.exec(aW)||["",""])[1].toLowerCase()]){aW=aW.replace(F,p);try{for(var aV=0,aU=this.length;aV<aU;aV++){if(this[aV].nodeType===1){a.cleanData(this[aV].getElementsByTagName("*"));this[aV].innerHTML=aW}}}catch(aX){this.empty().append(aW)}}else{if(a.isFunction(aW)){this.each(function(a0){var aZ=a(this),aY=aZ.html();aZ.empty().append(function(){return aW.call(this,a0,aY)})})}else{this.empty().append(aW)}}}return this},replaceWith:function(aU){if(this[0]&&this[0].parentNode){if(!a.isFunction(aU)){aU=a(aU).detach()}else{return this.each(function(aX){var aW=a(this),aV=aW.html();aW.replaceWith(aU.call(this,aX,aV))})}return this.each(function(){var aW=this.nextSibling,aV=this.parentNode;a(this).remove();if(aW){a(aW).before(aU)}else{a(aV).append(aU)}})}else{return this.pushStack(a(a.isFunction(aU)?aU():aU),"replaceWith",aU)}},detach:function(aU){return this.remove(aU,true)},domManip:function(aZ,a3,a2){var aW,aY,a1=aZ[0],aV=[];if(!a.support.checkClone&&arguments.length===3&&typeof a1==="string"&&l.test(a1)){return this.each(function(){a(this).domManip(aZ,a3,a2,true)})}if(a.isFunction(a1)){return this.each(function(a5){var a4=a(this);aZ[0]=a1.call(this,a5,a3?a4.html():B);a4.domManip(aZ,a3,a2)})}if(this[0]){if(aZ[0]&&aZ[0].parentNode&&aZ[0].parentNode.nodeType===11){aW={fragment:aZ[0].parentNode}}else{aW=H(aZ,this,aV)}aY=aW.fragment.firstChild;if(aY){a3=a3&&a.nodeName(aY,"tr");for(var aX=0,aU=this.length;aX<aU;aX++){a2.call(a3?a0(this[aX],aY):this[aX],aW.cacheable||this.length>1||aX>0?aW.fragment.cloneNode(true):aW.fragment)}}if(aV){a.each(aV,aR)}}return this;function a0(a4,a5){return a.nodeName(a4,"table")?(a4.getElementsByTagName("tbody")[0]||a4.appendChild(a4.ownerDocument.createElement("tbody"))):a4}}});function q(aW,aU){var aV=0;aU.each(function(){if(this.nodeName!==(aW[aV]&&aW[aV].nodeName)){return}var a1=a.data(aW[aV++]),a0=a.data(this,a1),aX=a1&&a1.events;if(aX){delete a0.handle;a0.events={};for(var aZ in aX){for(var aY in aX[aZ]){a.event.add(this,aZ,aX[aZ][aY],aX[aZ][aY].data)}}}})}function H(aZ,aX,aV){var aY,aU,aW,a0;if(aZ.length===1&&typeof aZ[0]==="string"&&aZ[0].length<512&&aZ[0].indexOf("<option")<0&&(a.support.checkClone||!l.test(aZ[0]))){aU=true;aW=a.fragments[aZ[0]];if(aW){if(aW!==1){aY=aW}}}if(!aY){a0=(aX&&aX[0]?aX[0].ownerDocument||aX[0]:aa);aY=a0.createDocumentFragment();a.clean(aZ,a0,aY,aV)}if(aU){a.fragments[aZ[0]]=aW?aY:1}return{fragment:aY,cacheable:aU}}a.fragments={};a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(aU,aV){a.fn[aU]=function(aW){var aZ=[],a1=a(aW);for(var a0=0,aX=a1.length;a0<aX;a0++){var aY=(a0>0?this.clone(true):this).get();a.fn[aV].apply(a(a1[a0]),aY);aZ=aZ.concat(aY)}return this.pushStack(aZ,aU,a1.selector)}});a.each({remove:function(aU,aV){if(!aU||a.filter(aU,[this]).length){if(!aV&&this.nodeType===1){a.cleanData(this.getElementsByTagName("*"));a.cleanData([this])}if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){if(this.nodeType===1){a.cleanData(this.getElementsByTagName("*"))}while(this.firstChild){this.removeChild(this.firstChild)}}},function(aU,aV){a.fn[aU]=function(){return this.each(aV,arguments)}});a.extend({clean:function(aV,aZ,aX,aU){aZ=aZ||aa;if(typeof aZ.createElement==="undefined"){aZ=aZ.ownerDocument||aZ[0]&&aZ[0].ownerDocument||aa}var aW=[];a.each(aV,function(a6,a3){if(typeof a3==="number"){a3+=""}if(!a3){return}if(typeof a3==="string"&&!J.test(a3)){a3=aZ.createTextNode(a3)}else{if(typeof a3==="string"){a3=a3.replace(F,p);var a8=(c.exec(a3)||["",""])[1].toLowerCase(),a2=ab[a8]||ab._default,a5=a2[0],a0=aZ.createElement("div");a0.innerHTML=a2[1]+a3+a2[2];while(a5--){a0=a0.lastChild}if(!a.support.tbody){var a1=t.test(a3),a7=a8==="table"&&!a1?a0.firstChild&&a0.firstChild.childNodes:a2[1]==="<table>"&&!a1?a0.childNodes:[];for(var a4=a7.length-1;a4>=0;--a4){if(a.nodeName(a7[a4],"tbody")&&!a7[a4].childNodes.length){a7[a4].parentNode.removeChild(a7[a4])}}}if(!a.support.leadingWhitespace&&Y.test(a3)){a0.insertBefore(aZ.createTextNode(Y.exec(a3)[0]),a0.firstChild)}a3=a.makeArray(a0.childNodes)}}if(a3.nodeType){aW.push(a3)}else{aW=a.merge(aW,a3)}});if(aX){for(var aY=0;aW[aY];aY++){if(aU&&a.nodeName(aW[aY],"script")&&(!aW[aY].type||aW[aY].type.toLowerCase()==="text/javascript")){aU.push(aW[aY].parentNode?aW[aY].parentNode.removeChild(aW[aY]):aW[aY])}else{if(aW[aY].nodeType===1){aW.splice.apply(aW,[aY+1,0].concat(a.makeArray(aW[aY].getElementsByTagName("script"))))}aX.appendChild(aW[aY])}}}return aW},cleanData:function(aU){for(var aV=0,aW,aX;(aW=aU[aV])!=null;aV++){a.event.remove(aW);a.removeData(aW)}}});var ap=/z-?index|font-?weight|opacity|zoom|line-?height/i,T=/alpha\([^)]*\)/,Z=/opacity=([^)]*)/,af=/float/i,aw=/-([a-z])/ig,v=/([A-Z])/g,aK=/^-?\d+(?:px)?$/i,aQ=/^-?\d/,aG={position:"absolute",visibility:"hidden",display:"block"},V=["Left","Right"],aA=["Top","Bottom"],ai=aa.defaultView&&aa.defaultView.getComputedStyle,aJ=a.support.cssFloat?"cssFloat":"styleFloat",k=function(aU,aV){return aV.toUpperCase()};a.fn.css=function(aU,aV){return al(this,aU,aV,true,function(aX,aW,aY){if(aY===B){return a.curCSS(aX,aW)}if(typeof aY==="number"&&!ap.test(aW)){aY+="px"}a.style(aX,aW,aY)})};a.extend({style:function(aY,aV,aZ){if(!aY||aY.nodeType===3||aY.nodeType===8){return B}if((aV==="width"||aV==="height")&&parseFloat(aZ)<0){aZ=B}var aX=aY.style||aY,a0=aZ!==B;if(!a.support.opacity&&aV==="opacity"){if(a0){aX.zoom=1;var aU=parseInt(aZ,10)+""==="NaN"?"":"alpha(opacity="+aZ*100+")";var aW=aX.filter||a.curCSS(aY,"filter")||"";aX.filter=T.test(aW)?aW.replace(T,aU):aU}return aX.filter&&aX.filter.indexOf("opacity=")>=0?(parseFloat(Z.exec(aX.filter)[1])/100)+"":""}if(af.test(aV)){aV=aJ}aV=aV.replace(aw,k);if(a0){aX[aV]=aZ}return aX[aV]},css:function(aX,aV,aZ,aU){if(aV==="width"||aV==="height"){var a1,aW=aG,a0=aV==="width"?V:aA;function aY(){a1=aV==="width"?aX.offsetWidth:aX.offsetHeight;if(aU==="border"){return}a.each(a0,function(){if(!aU){a1-=parseFloat(a.curCSS(aX,"padding"+this,true))||0}if(aU==="margin"){a1+=parseFloat(a.curCSS(aX,"margin"+this,true))||0}else{a1-=parseFloat(a.curCSS(aX,"border"+this+"Width",true))||0}})}if(aX.offsetWidth!==0){aY()}else{a.swap(aX,aW,aY)}return Math.max(0,Math.round(a1))}return a.curCSS(aX,aV,aZ)},curCSS:function(a0,aV,aW){var a3,aU=a0.style,aX;if(!a.support.opacity&&aV==="opacity"&&a0.currentStyle){a3=Z.test(a0.currentStyle.filter||"")?(parseFloat(RegExp.$1)/100)+"":"";return a3===""?"1":a3}if(af.test(aV)){aV=aJ}if(!aW&&aU&&aU[aV]){a3=aU[aV]}else{if(ai){if(af.test(aV)){aV="float"}aV=aV.replace(v,"-$1").toLowerCase();var a2=a0.ownerDocument.defaultView;if(!a2){return null}var a4=a2.getComputedStyle(a0,null);if(a4){a3=a4.getPropertyValue(aV)}if(aV==="opacity"&&a3===""){a3="1"}}else{if(a0.currentStyle){var aZ=aV.replace(aw,k);a3=a0.currentStyle[aV]||a0.currentStyle[aZ];if(!aK.test(a3)&&aQ.test(a3)){var aY=aU.left,a1=a0.runtimeStyle.left;a0.runtimeStyle.left=a0.currentStyle.left;aU.left=aZ==="fontSize"?"1em":(a3||0);a3=aU.pixelLeft+"px";aU.left=aY;a0.runtimeStyle.left=a1}}}}return a3},swap:function(aX,aW,aY){var aU={};for(var aV in aW){aU[aV]=aX.style[aV];aX.style[aV]=aW[aV]}aY.call(aX);for(var aV in aW){aX.style[aV]=aU[aV]}}});if(a.expr&&a.expr.filters){a.expr.filters.hidden=function(aX){var aV=aX.offsetWidth,aU=aX.offsetHeight,aW=aX.nodeName.toLowerCase()==="tr";return aV===0&&aU===0&&!aW?true:aV>0&&aU>0&&!aW?false:a.curCSS(aX,"display")==="none"};a.expr.filters.visible=function(aU){return !a.expr.filters.hidden(aU)}}var ae=aL(),aF=/<script(.|\s)*?\/script>/gi,o=/select|textarea/i,ay=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,r=/=\?(&|$)/,C=/\?/,aT=/(\?|&)_=.*?(&|$)/,A=/^(\w+:)?\/\/([^\/?#]+)/,h=/%20/g;a.fn.extend({_load:a.fn.load,load:function(aW,aZ,a0){if(typeof aW!=="string"){return this._load(aW)}else{if(!this.length){return this}}var aY=aW.indexOf(" ");if(aY>=0){var aU=aW.slice(aY,aW.length);aW=aW.slice(0,aY)}var aX="GET";if(aZ){if(a.isFunction(aZ)){a0=aZ;aZ=null}else{if(typeof aZ==="object"){aZ=a.param(aZ,a.ajaxSettings.traditional);aX="POST"}}}var aV=this;a.ajax({url:aW,type:aX,dataType:"html",data:aZ,complete:function(a2,a1){if(a1==="success"||a1==="notmodified"){aV.html(aU?a("<div />").append(a2.responseText.replace(aF,"")).find(aU):a2.responseText)}if(a0){aV.each(a0,[a2.responseText,a1,a2])}}});return this},serialize:function(){return a.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?a.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||o.test(this.nodeName)||ay.test(this.type))}).map(function(aU,aV){var aW=a(this).val();return aW==null?null:a.isArray(aW)?a.map(aW,function(aY,aX){return{name:aV.name,value:aY}}):{name:aV.name,value:aW}}).get()}});a.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(aU,aV){a.fn[aV]=function(aW){return this.bind(aV,aW)}});a.extend({get:function(aU,aW,aX,aV){if(a.isFunction(aW)){aV=aV||aX;aX=aW;aW=null}return a.ajax({type:"GET",url:aU,data:aW,success:aX,dataType:aV})},getScript:function(aU,aV){return a.get(aU,null,aV,"script")},getJSON:function(aU,aV,aW){return a.get(aU,aV,aW,"json")},post:function(aU,aW,aX,aV){if(a.isFunction(aW)){aV=aV||aX;aX=aW;aW={}}return a.ajax({type:"POST",url:aU,data:aW,success:aX,dataType:aV})},ajaxSetup:function(aU){a.extend(a.ajaxSettings,aU)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:aI.XMLHttpRequest&&(aI.location.protocol!=="file:"||!aI.ActiveXObject)?function(){return new aI.XMLHttpRequest()}:function(){try{return new aI.ActiveXObject("Microsoft.XMLHTTP")}catch(aU){}},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(a9){var a4=a.extend(true,{},a.ajaxSettings,a9);var be,a8,bd,bf=a9&&a9.context||a4,aW=a4.type.toUpperCase();if(a4.data&&a4.processData&&typeof a4.data!=="string"){a4.data=a.param(a4.data,a4.traditional)}if(a4.dataType==="jsonp"){if(aW==="GET"){if(!r.test(a4.url)){a4.url+=(C.test(a4.url)?"&":"?")+(a4.jsonp||"callback")+"=?"}}else{if(!a4.data||!r.test(a4.data)){a4.data=(a4.data?a4.data+"&":"")+(a4.jsonp||"callback")+"=?"}}a4.dataType="json"}if(a4.dataType==="json"&&(a4.data&&r.test(a4.data)||r.test(a4.url))){be=a4.jsonpCallback||("jsonp"+ae++);if(a4.data){a4.data=(a4.data+"").replace(r,"="+be+"$1")}a4.url=a4.url.replace(r,"="+be+"$1");a4.dataType="script";aI[be]=aI[be]||function(bg){bd=bg;aZ();a2();aI[be]=B;try{delete aI[be]}catch(bh){}if(aX){aX.removeChild(bb)}}}if(a4.dataType==="script"&&a4.cache===null){a4.cache=false}if(a4.cache===false&&aW==="GET"){var aU=aL();var bc=a4.url.replace(aT,"$1_="+aU+"$2");a4.url=bc+((bc===a4.url)?(C.test(a4.url)?"&":"?")+"_="+aU:"")}if(a4.data&&aW==="GET"){a4.url+=(C.test(a4.url)?"&":"?")+a4.data}if(a4.global&&!a.active++){a.event.trigger("ajaxStart")}var a7=A.exec(a4.url),aY=a7&&(a7[1]&&a7[1]!==location.protocol||a7[2]!==location.host);if(a4.dataType==="script"&&aW==="GET"&&aY){var aX=aa.getElementsByTagName("head")[0]||aa.documentElement;var bb=aa.createElement("script");bb.src=a4.url;if(a4.scriptCharset){bb.charset=a4.scriptCharset}if(!be){var a6=false;bb.onload=bb.onreadystatechange=function(){if(!a6&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){a6=true;aZ();a2();bb.onload=bb.onreadystatechange=null;if(aX&&bb.parentNode){aX.removeChild(bb)}}}}aX.insertBefore(bb,aX.firstChild);return B}var a1=false;var a0=a4.xhr();if(!a0){return}if(a4.username){a0.open(aW,a4.url,a4.async,a4.username,a4.password)}else{a0.open(aW,a4.url,a4.async)}try{if(a4.data||a9&&a9.contentType){a0.setRequestHeader("Content-Type",a4.contentType)}if(a4.ifModified){if(a.lastModified[a4.url]){a0.setRequestHeader("If-Modified-Since",a.lastModified[a4.url])}if(a.etag[a4.url]){a0.setRequestHeader("If-None-Match",a.etag[a4.url])}}if(!aY){a0.setRequestHeader("X-Requested-With","XMLHttpRequest")}a0.setRequestHeader("Accept",a4.dataType&&a4.accepts[a4.dataType]?a4.accepts[a4.dataType]+", */*":a4.accepts._default)}catch(ba){}if(a4.beforeSend&&a4.beforeSend.call(bf,a0,a4)===false){if(a4.global&&!--a.active){a.event.trigger("ajaxStop")}a0.abort();return false}if(a4.global){a5("ajaxSend",[a0,a4])}var a3=a0.onreadystatechange=function(bg){if(!a0||a0.readyState===0||bg==="abort"){if(!a1){a2()}a1=true;if(a0){a0.onreadystatechange=a.noop}}else{if(!a1&&a0&&(a0.readyState===4||bg==="timeout")){a1=true;a0.onreadystatechange=a.noop;a8=bg==="timeout"?"timeout":!a.httpSuccess(a0)?"error":a4.ifModified&&a.httpNotModified(a0,a4.url)?"notmodified":"success";var bi;if(a8==="success"){try{bd=a.httpData(a0,a4.dataType,a4)}catch(bh){a8="parsererror";bi=bh}}if(a8==="success"||a8==="notmodified"){if(!be){aZ()}}else{a.handleError(a4,a0,a8,bi)}a2();if(bg==="timeout"){a0.abort()}if(a4.async){a0=null}}}};try{var aV=a0.abort;a0.abort=function(){if(a0){aV.call(a0)}a3("abort")}}catch(ba){}if(a4.async&&a4.timeout>0){setTimeout(function(){if(a0&&!a1){a3("timeout")}},a4.timeout)}try{a0.send(aW==="POST"||aW==="PUT"||aW==="DELETE"?a4.data:null)}catch(ba){a.handleError(a4,a0,null,ba);a2()}if(!a4.async){a3()}function aZ(){if(a4.success){a4.success.call(bf,bd,a8,a0)}if(a4.global){a5("ajaxSuccess",[a0,a4])}}function a2(){if(a4.complete){a4.complete.call(bf,a0,a8)}if(a4.global){a5("ajaxComplete",[a0,a4])}if(a4.global&&!--a.active){a.event.trigger("ajaxStop")}}function a5(bh,bg){(a4.context?a(a4.context):a.event).trigger(bh,bg)}return a0},handleError:function(aV,aX,aU,aW){if(aV.error){aV.error.call(aV.context||aV,aX,aU,aW)}if(aV.global){(aV.context?a(aV.context):a.event).trigger("ajaxError",[aX,aV,aW])}},active:0,httpSuccess:function(aV){try{return !aV.status&&location.protocol==="file:"||(aV.status>=200&&aV.status<300)||aV.status===304||aV.status===1223||aV.status===0}catch(aU){}return false},httpNotModified:function(aX,aU){var aW=aX.getResponseHeader("Last-Modified"),aV=aX.getResponseHeader("Etag");if(aW){a.lastModified[aU]=aW}if(aV){a.etag[aU]=aV}return aX.status===304||aX.status===0},httpData:function(aZ,aX,aW){var aV=aZ.getResponseHeader("content-type")||"",aU=aX==="xml"||!aX&&aV.indexOf("xml")>=0,aY=aU?aZ.responseXML:aZ.responseText;if(aU&&aY.documentElement.nodeName==="parsererror"){a.error("parsererror")}if(aW&&aW.dataFilter){aY=aW.dataFilter(aY,aX)}if(typeof aY==="string"){if(aX==="json"||!aX&&aV.indexOf("json")>=0){aY=a.parseJSON(aY)}else{if(aX==="script"||!aX&&aV.indexOf("javascript")>=0){a.globalEval(aY)}}}return aY},param:function(aU,aX){var aV=[];if(aX===B){aX=a.ajaxSettings.traditional}if(a.isArray(aU)||aU.jquery){a.each(aU,function(){aZ(this.name,this.value)})}else{for(var aY in aU){aW(aY,aU[aY])}}return aV.join("&").replace(h,"+");function aW(a0,a1){if(a.isArray(a1)){a.each(a1,function(a3,a2){if(aX){aZ(a0,a2)}else{aW(a0+"["+(typeof a2==="object"||a.isArray(a2)?a3:"")+"]",a2)}})}else{if(!aX&&a1!=null&&typeof a1==="object"){a.each(a1,function(a3,a2){aW(a0+"["+a3+"]",a2)})}else{aZ(a0,a1)}}}function aZ(a0,a1){a1=a.isFunction(a1)?a1():a1;aV[aV.length]=encodeURIComponent(a0)+"="+encodeURIComponent(a1)}}});var E={},ad=/toggle|show|hide/,ar=/^([+-]=)?([\d+-.]+)(.*)$/,aB,ah=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];a.fn.extend({show:function(aV,a3){if(aV||aV===0){return this.animate(az("show",3),aV,a3)}else{for(var a0=0,aX=this.length;a0<aX;a0++){var aU=a.data(this[a0],"olddisplay");this[a0].style.display=aU||"";if(a.css(this[a0],"display")==="none"){var a2=this[a0].nodeName,a1;if(E[a2]){a1=E[a2]}else{var aW=a("<"+a2+" />").appendTo("body");a1=aW.css("display");if(a1==="none"){a1="block"}aW.remove();E[a2]=a1}a.data(this[a0],"olddisplay",a1)}}for(var aZ=0,aY=this.length;aZ<aY;aZ++){this[aZ].style.display=a.data(this[aZ],"olddisplay")||""}return this}},hide:function(aZ,a0){if(aZ||aZ===0){return this.animate(az("hide",3),aZ,a0)}else{for(var aY=0,aV=this.length;aY<aV;aY++){var aU=a.data(this[aY],"olddisplay");if(!aU&&aU!=="none"){a.data(this[aY],"olddisplay",a.css(this[aY],"display"))}}for(var aX=0,aW=this.length;aX<aW;aX++){this[aX].style.display="none"}return this}},_toggle:a.fn.toggle,toggle:function(aW,aV){var aU=typeof aW==="boolean";if(a.isFunction(aW)&&a.isFunction(aV)){this._toggle.apply(this,arguments)}else{if(aW==null||aU){this.each(function(){var aX=aU?aW:a(this).is(":hidden");a(this)[aX?"show":"hide"]()})}else{this.animate(az("toggle",3),aW,aV)}}return this},fadeTo:function(aU,aW,aV){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:aW},aU,aV)},animate:function(aY,aV,aX,aW){var aU=a.speed(aV,aX,aW);if(a.isEmptyObject(aY)){return this.each(aU.complete)}return this[aU.queue===false?"each":"queue"](function(){var a1=a.extend({},aU),a3,a2=this.nodeType===1&&a(this).is(":hidden"),aZ=this;for(a3 in aY){var a0=a3.replace(aw,k);if(a3!==a0){aY[a0]=aY[a3];delete aY[a3];a3=a0}if(aY[a3]==="hide"&&a2||aY[a3]==="show"&&!a2){return a1.complete.call(this)}if((a3==="height"||a3==="width")&&this.style){a1.display=a.css(this,"display");a1.overflow=this.style.overflow}if(a.isArray(aY[a3])){(a1.specialEasing=a1.specialEasing||{})[a3]=aY[a3][1];aY[a3]=aY[a3][0]}}if(a1.overflow!=null){this.style.overflow="hidden"}a1.curAnim=a.extend({},aY);a.each(aY,function(a5,a9){var a8=new a.fx(aZ,a1,a5);if(ad.test(a9)){a8[a9==="toggle"?a2?"show":"hide":a9](aY)}else{var a7=ar.exec(a9),ba=a8.cur(true)||0;if(a7){var a4=parseFloat(a7[2]),a6=a7[3]||"px";if(a6!=="px"){aZ.style[a5]=(a4||1)+a6;ba=((a4||1)/a8.cur(true))*ba;aZ.style[a5]=ba+a6}if(a7[1]){a4=((a7[1]==="-="?-1:1)*a4)+ba}a8.custom(ba,a4,a6)}else{a8.custom(ba,a9,"")}}});return true})},stop:function(aV,aU){var aW=a.timers;if(aV){this.queue([])}this.each(function(){for(var aX=aW.length-1;aX>=0;aX--){if(aW[aX].elem===this){if(aU){aW[aX](true)}aW.splice(aX,1)}}});if(!aU){this.dequeue()}return this}});a.each({slideDown:az("show",1),slideUp:az("hide",1),slideToggle:az("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(aU,aV){a.fn[aU]=function(aW,aX){return this.animate(aV,aW,aX)}});a.extend({speed:function(aW,aX,aV){var aU=aW&&typeof aW==="object"?aW:{complete:aV||!aV&&aX||a.isFunction(aW)&&aW,duration:aW,easing:aV&&aX||aX&&!a.isFunction(aX)&&aX};aU.duration=a.fx.off?0:typeof aU.duration==="number"?aU.duration:a.fx.speeds[aU.duration]||a.fx.speeds._default;aU.old=aU.complete;aU.complete=function(){if(aU.queue!==false){a(this).dequeue()}if(a.isFunction(aU.old)){aU.old.call(this)}};return aU},easing:{linear:function(aW,aX,aU,aV){return aU+aV*aW},swing:function(aW,aX,aU,aV){return((-Math.cos(aW*Math.PI)/2)+0.5)*aV+aU}},timers:[],fx:function(aV,aU,aW){this.options=aU;this.elem=aV;this.prop=aW;if(!aU.orig){aU.orig={}}}});a.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(a.fx.step[this.prop]||a.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(aV){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var aU=parseFloat(a.css(this.elem,this.prop,aV));return aU&&aU>-10000?aU:parseFloat(a.curCSS(this.elem,this.prop))||0},custom:function(aY,aX,aW){this.startTime=aL();this.start=aY;this.end=aX;this.unit=aW||this.unit||"px";this.now=this.start;this.pos=this.state=0;var aU=this;function aV(aZ){return aU.step(aZ)}aV.elem=this.elem;if(aV()&&a.timers.push(aV)&&!aB){aB=setInterval(a.fx.tick,13)}},show:function(){this.options.orig[this.prop]=a.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());a(this.elem).show()},hide:function(){this.options.orig[this.prop]=a.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(aX){var a2=aL(),aY=true;if(aX||a2>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var aZ in this.options.curAnim){if(this.options.curAnim[aZ]!==true){aY=false}}if(aY){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;var aW=a.data(this.elem,"olddisplay");this.elem.style.display=aW?aW:this.options.display;if(a.css(this.elem,"display")==="none"){this.elem.style.display="block"}}if(this.options.hide){a(this.elem).hide()}if(this.options.hide||this.options.show){for(var aU in this.options.curAnim){a.style(this.elem,aU,this.options.orig[aU])}}this.options.complete.call(this.elem)}return false}else{var aV=a2-this.startTime;this.state=aV/this.options.duration;var a0=this.options.specialEasing&&this.options.specialEasing[this.prop];var a1=this.options.easing||(a.easing.swing?"swing":"linear");this.pos=a.easing[a0||a1](this.state,aV,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};a.extend(a.fx,{tick:function(){var aV=a.timers;for(var aU=0;aU<aV.length;aU++){if(!aV[aU]()){aV.splice(aU--,1)}}if(!aV.length){a.fx.stop()}},stop:function(){clearInterval(aB);aB=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(aU){a.style(aU.elem,"opacity",aU.now)},_default:function(aU){if(aU.elem.style&&aU.elem.style[aU.prop]!=null){aU.elem.style[aU.prop]=(aU.prop==="width"||aU.prop==="height"?Math.max(0,aU.now):aU.now)+aU.unit}else{aU.elem[aU.prop]=aU.now}}}});if(a.expr&&a.expr.filters){a.expr.filters.animated=function(aU){return a.grep(a.timers,function(aV){return aU===aV.elem}).length}}function az(aV,aU){var aW={};a.each(ah.concat.apply([],ah.slice(0,aU)),function(){aW[this]=aV});return aW}if("getBoundingClientRect" in aa.documentElement){a.fn.offset=function(a3){var aW=this[0];if(a3){return this.each(function(a4){a.offset.setOffset(this,a3,a4)})}if(!aW||!aW.ownerDocument){return null}if(aW===aW.ownerDocument.body){return a.offset.bodyOffset(aW)}var aY=aW.getBoundingClientRect(),a2=aW.ownerDocument,aZ=a2.body,aU=a2.documentElement,aX=aU.clientTop||aZ.clientTop||0,a0=aU.clientLeft||aZ.clientLeft||0,a1=aY.top+(self.pageYOffset||a.support.boxModel&&aU.scrollTop||aZ.scrollTop)-aX,aV=aY.left+(self.pageXOffset||a.support.boxModel&&aU.scrollLeft||aZ.scrollLeft)-a0;return{top:a1,left:aV}}}else{a.fn.offset=function(a5){var aZ=this[0];if(a5){return this.each(function(a6){a.offset.setOffset(this,a5,a6)})}if(!aZ||!aZ.ownerDocument){return null}if(aZ===aZ.ownerDocument.body){return a.offset.bodyOffset(aZ)}a.offset.initialize();var aW=aZ.offsetParent,aV=aZ,a4=aZ.ownerDocument,a2,aX=a4.documentElement,a0=a4.body,a1=a4.defaultView,aU=a1?a1.getComputedStyle(aZ,null):aZ.currentStyle,a3=aZ.offsetTop,aY=aZ.offsetLeft;while((aZ=aZ.parentNode)&&aZ!==a0&&aZ!==aX){if(a.offset.supportsFixedPosition&&aU.position==="fixed"){break}a2=a1?a1.getComputedStyle(aZ,null):aZ.currentStyle;a3-=aZ.scrollTop;aY-=aZ.scrollLeft;if(aZ===aW){a3+=aZ.offsetTop;aY+=aZ.offsetLeft;if(a.offset.doesNotAddBorder&&!(a.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(aZ.nodeName))){a3+=parseFloat(a2.borderTopWidth)||0;aY+=parseFloat(a2.borderLeftWidth)||0}aV=aW,aW=aZ.offsetParent}if(a.offset.subtractsBorderForOverflowNotVisible&&a2.overflow!=="visible"){a3+=parseFloat(a2.borderTopWidth)||0;aY+=parseFloat(a2.borderLeftWidth)||0}aU=a2}if(aU.position==="relative"||aU.position==="static"){a3+=a0.offsetTop;aY+=a0.offsetLeft}if(a.offset.supportsFixedPosition&&aU.position==="fixed"){a3+=Math.max(aX.scrollTop,a0.scrollTop);aY+=Math.max(aX.scrollLeft,a0.scrollLeft)}return{top:a3,left:aY}}}a.offset={initialize:function(){var aU=aa.body,aV=aa.createElement("div"),aY,a0,aZ,a1,aW=parseFloat(a.curCSS(aU,"marginTop",true))||0,aX="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.extend(aV.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});aV.innerHTML=aX;aU.insertBefore(aV,aU.firstChild);aY=aV.firstChild;a0=aY.firstChild;a1=aY.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(a0.offsetTop!==5);this.doesAddBorderForTableAndCells=(a1.offsetTop===5);a0.style.position="fixed",a0.style.top="20px";this.supportsFixedPosition=(a0.offsetTop===20||a0.offsetTop===15);a0.style.position=a0.style.top="";aY.style.overflow="hidden",aY.style.position="relative";this.subtractsBorderForOverflowNotVisible=(a0.offsetTop===-5);this.doesNotIncludeMarginInBodyOffset=(aU.offsetTop!==aW);aU.removeChild(aV);aU=aV=aY=a0=aZ=a1=null;a.offset.initialize=a.noop},bodyOffset:function(aU){var aW=aU.offsetTop,aV=aU.offsetLeft;a.offset.initialize();if(a.offset.doesNotIncludeMarginInBodyOffset){aW+=parseFloat(a.curCSS(aU,"marginTop",true))||0;aV+=parseFloat(a.curCSS(aU,"marginLeft",true))||0}return{top:aW,left:aV}},setOffset:function(aZ,aV,aW){if(/static/.test(a.curCSS(aZ,"position"))){aZ.style.position="relative"}var aY=a(aZ),a1=aY.offset(),aU=parseInt(a.curCSS(aZ,"top",true),10)||0,a0=parseInt(a.curCSS(aZ,"left",true),10)||0;if(a.isFunction(aV)){aV=aV.call(aZ,aW,a1)}var aX={top:(aV.top-a1.top)+aU,left:(aV.left-a1.left)+a0};if("using" in aV){aV.using.call(aZ,aX)}else{aY.css(aX)}}};a.fn.extend({position:function(){if(!this[0]){return null}var aW=this[0],aV=this.offsetParent(),aX=this.offset(),aU=/^body|html$/i.test(aV[0].nodeName)?{top:0,left:0}:aV.offset();aX.top-=parseFloat(a.curCSS(aW,"marginTop",true))||0;aX.left-=parseFloat(a.curCSS(aW,"marginLeft",true))||0;aU.top+=parseFloat(a.curCSS(aV[0],"borderTopWidth",true))||0;aU.left+=parseFloat(a.curCSS(aV[0],"borderLeftWidth",true))||0;return{top:aX.top-aU.top,left:aX.left-aU.left}},offsetParent:function(){return this.map(function(){var aU=this.offsetParent||aa.body;while(aU&&(!/^body|html$/i.test(aU.nodeName)&&a.css(aU,"position")==="static")){aU=aU.offsetParent}return aU})}});a.each(["Left","Top"],function(aV,aU){var aW="scroll"+aU;a.fn[aW]=function(aZ){var aX=this[0],aY;if(!aX){return null}if(aZ!==B){return this.each(function(){aY=ak(this);if(aY){aY.scrollTo(!aV?aZ:a(aY).scrollLeft(),aV?aZ:a(aY).scrollTop())}else{this[aW]=aZ}})}else{aY=ak(aX);return aY?("pageXOffset" in aY)?aY[aV?"pageYOffset":"pageXOffset"]:a.support.boxModel&&aY.document.documentElement[aW]||aY.document.body[aW]:aX[aW]}}});function ak(aU){return("scrollTo" in aU&&aU.document)?aU:aU.nodeType===9?aU.defaultView||aU.parentWindow:false}a.each(["Height","Width"],function(aV,aU){var aW=aU.toLowerCase();a.fn["inner"+aU]=function(){return this[0]?a.css(this[0],aW,false,"padding"):null};a.fn["outer"+aU]=function(aX){return this[0]?a.css(this[0],aW,false,aX?"margin":"border"):null};a.fn[aW]=function(aX){var aY=this[0];if(!aY){return aX==null?null:this}if(a.isFunction(aX)){return this.each(function(a0){var aZ=a(this);aZ[aW](aX.call(this,a0,aZ[aW]()))})}return("scrollTo" in aY&&aY.document)?aY.document.compatMode==="CSS1Compat"&&aY.document.documentElement["client"+aU]||aY.document.body["client"+aU]:(aY.nodeType===9)?Math.max(aY.documentElement["client"+aU],aY.body["scroll"+aU],aY.documentElement["scroll"+aU],aY.body["offset"+aU],aY.documentElement["offset"+aU]):aX===B?a.css(aY,aW):this.css(aW,typeof aX==="string"?aX:aX+"px")}});aI.jQuery=aI.$=a})(window);window.djdt=(function(b,a,e){e.cookie=function(h,p,s){if(typeof p!="undefined"){s=s||{};if(p===null){p="";s.expires=-1}var l="";if(s.expires&&(typeof s.expires=="number"||s.expires.toUTCString)){var m;if(typeof s.expires=="number"){m=new Date();m.setTime(m.getTime()+(s.expires*24*60*60*1000))}else{m=s.expires}l="; expires="+m.toUTCString()}var r=s.path?"; path="+(s.path):"";var n=s.domain?"; domain="+(s.domain):"";var g=s.secure?"; secure":"";a.cookie=[h,"=",encodeURIComponent(p),l,r,n,g].join("")}else{var k=null;if(a.cookie&&a.cookie!=""){var q=a.cookie.split(";");for(var o=0;o<q.length;o++){var j=c.trim(q[o]);if(j.substring(0,h.length+1)==(h+"=")){k=decodeURIComponent(j.substring(h.length+1));break}}}return k}};var c=e;var f="djdt";var d={jQuery:e,events:{ready:[]},isReady:false,init:function(){c("#djDebug").show();var i=null;c("#djDebugPanelList li a").click(function(){if(!this.className){return false}i=c("#djDebug #"+this.className);if(i.is(":visible")){c(a).trigger("close.djDebug");c(this).parent().removeClass("active")}else{c(".panelContent").hide();i.show();c("#djDebugToolbar li").removeClass("active");c(this).parent().addClass("active")}return false});c("#djDebug a.djDebugClose").click(function(){c(a).trigger("close.djDebug");c("#djDebugToolbar li").removeClass("active");return false});c("#djDebug a.remoteCall").click(function(){c("#djDebugWindow").load(this.href,function(k,j,m){if(j=="error"){var l='<div class="djDebugPanelTitle"><a class="djDebugClose djDebugBack" href="">Back</a><h3>'+m.status+": "+m.statusText+"</h3></div>";c("#djDebugWindow").html(l)}c("#djDebugWindow a.djDebugBack").click(function(){c(this).parent().parent().hide();return false})});c("#djDebugWindow").show();return false});c("#djDebugTemplatePanel a.djTemplateShowContext").click(function(){d.toggle_arrow(c(this).children(".toggleArrow"));d.toggle_content(c(this).parent().next());return false});c("#djDebug a.djToggleSwitch").click(function(l){l.preventDefault();var j=c(this);var m=j.attr("data-toggle-id");var k=j.text()==j.attr("data-toggle-open");if(m==""||!m){return}c(this).parents(".djDebugPanelContent").find(".djToggleDetails_"+m).each(function(){var n=c(this);if(k){n.addClass("djSelected");n.removeClass("djUnselected");j.text(j.attr("data-toggle-close"));n.find(".djToggleSwitch").text(j.text())}else{n.removeClass("djSelected");n.addClass("djUnselected");j.text(j.attr("data-toggle-open"));n.find(".djToggleSwitch").text(j.text())}});return});function g(j){id=j.attr("id");return c('.djDebugProfileRow[id^="'+id+'_"]')}function h(j){subcalls=g(j);depth=parseInt(j.attr("depth"))+1;return subcalls.filter("[depth="+depth+"]")}c(".djDebugProfileRow .djDebugProfileToggle").click(function(){row=c(this).closest(".djDebugProfileRow");subcalls=g(row);if(subcalls.css("display")=="none"){h(row).show()}else{subcalls.hide()}});c("#djHideToolBarButton").click(function(){d.hide_toolbar(true);return false});c("#djShowToolBarButton").click(function(){d.show_toolbar();return false});c(a).bind("close.djDebug",function(){if(c("#djDebugWindow").is(":visible")){c("#djDebugWindow").hide();return}if(c(".panelContent").is(":visible")){c(".panelContent").hide();return}if(c("#djDebugToolbar").is(":visible")){d.hide_toolbar(true);return}});if(c.cookie(f)){d.hide_toolbar(false)}else{d.show_toolbar(false)}c("#djDebug .djDebugHoverable").hover(function(){c(this).addClass("djDebugHover")},function(){c(this).removeClass("djDebugHover")});d.isReady=true;c.each(d.events.ready,function(j,k){k(d)})},toggle_content:function(g){if(g.is(":visible")){g.hide()}else{g.show()}},close:function(){c(a).trigger("close.djDebug");return false},hide_toolbar:function(g){c("#djDebugWindow").hide();c(".panelContent").hide();c("#djDebugToolbar li").removeClass("active");c("#djDebugToolbar").hide("fast");c("#djDebugToolbarHandle").show();c(a).unbind("keydown.djDebug");if(g){c.cookie(f,"hide",{path:"/",expires:10})}},show_toolbar:function(g){c(a).bind("keydown.djDebug",function(h){if(h.keyCode==27){d.close()}});c("#djDebugToolbarHandle").hide();if(g){c("#djDebugToolbar").show("fast")}else{c("#djDebugToolbar").show()}c.cookie(f,null,{path:"/",expires:-1})},toggle_arrow:function(h){var g=String.fromCharCode(9654);var i=String.fromCharCode(9660);h.html(h.html()==g?i:g)},ready:function(g){if(d.isReady){g(d)}else{d.events.ready.push(g)}}};c(a).ready(function(){d.init()});return d}(window,document,jQuery.noConflict()));
\ No newline at end of file +}(function(){var a5=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,a6=0,a8=Object.prototype.toString,a0=false,aZ=true;[0,0].sort(function(){aZ=false;return 0});var aW=function(bh,bc,bk,bl){bk=bk||[];var bn=bc=bc||aa;if(bc.nodeType!==1&&bc.nodeType!==9){return[]}if(!bh||typeof bh!=="string"){return bk}var bi=[],be,bp,bs,bd,bg=true,bf=aX(bc),bm=bh;while((a5.exec(""),be=a5.exec(bm))!==null){bm=be[3];bi.push(be[1]);if(be[2]){bd=be[3];break}}if(bi.length>1&&a1.exec(bh)){if(bi.length===2&&a2.relative[bi[0]]){bp=a9(bi[0]+bi[1],bc)}else{bp=a2.relative[bi[0]]?[bc]:aW(bi.shift(),bc);while(bi.length){bh=bi.shift();if(a2.relative[bh]){bh+=bi.shift()}bp=a9(bh,bp)}}}else{if(!bl&&bi.length>1&&bc.nodeType===9&&!bf&&a2.match.ID.test(bi[0])&&!a2.match.ID.test(bi[bi.length-1])){var bo=aW.find(bi.shift(),bc,bf);bc=bo.expr?aW.filter(bo.expr,bo.set)[0]:bo.set[0]}if(bc){var bo=bl?{expr:bi.pop(),set:a4(bl)}:aW.find(bi.pop(),bi.length===1&&(bi[0]==="~"||bi[0]==="+")&&bc.parentNode?bc.parentNode:bc,bf);bp=bo.expr?aW.filter(bo.expr,bo.set):bo.set;if(bi.length>0){bs=a4(bp)}else{bg=false}while(bi.length){var br=bi.pop(),bq=br;if(!a2.relative[br]){br=""}else{bq=bi.pop()}if(bq==null){bq=bc}a2.relative[br](bs,bq,bf)}}else{bs=bi=[]}}if(!bs){bs=bp}if(!bs){aW.error(br||bh)}if(a8.call(bs)==="[object Array]"){if(!bg){bk.push.apply(bk,bs)}else{if(bc&&bc.nodeType===1){for(var bj=0;bs[bj]!=null;bj++){if(bs[bj]&&(bs[bj]===true||bs[bj].nodeType===1&&a3(bc,bs[bj]))){bk.push(bp[bj])}}}else{for(var bj=0;bs[bj]!=null;bj++){if(bs[bj]&&bs[bj].nodeType===1){bk.push(bp[bj])}}}}}else{a4(bs,bk)}if(bd){aW(bd,bn,bk,bl);aW.uniqueSort(bk)}return bk};aW.uniqueSort=function(bd){if(a7){a0=aZ;bd.sort(a7);if(a0){for(var bc=1;bc<bd.length;bc++){if(bd[bc]===bd[bc-1]){bd.splice(bc--,1)}}}}return bd};aW.matches=function(bc,bd){return aW(bc,null,null,bd)};aW.find=function(bj,bc,bk){var bi,bg;if(!bj){return[]}for(var bf=0,be=a2.order.length;bf<be;bf++){var bh=a2.order[bf],bg;if((bg=a2.leftMatch[bh].exec(bj))){var bd=bg[1];bg.splice(1,1);if(bd.substr(bd.length-1)!=="\\"){bg[1]=(bg[1]||"").replace(/\\/g,"");bi=a2.find[bh](bg,bc,bk);if(bi!=null){bj=bj.replace(a2.match[bh],"");break}}}}if(!bi){bi=bc.getElementsByTagName("*")}return{set:bi,expr:bj}};aW.filter=function(bn,bm,bq,bg){var be=bn,bs=[],bk=bm,bi,bc,bj=bm&&bm[0]&&aX(bm[0]);while(bn&&bm.length){for(var bl in a2.filter){if((bi=a2.leftMatch[bl].exec(bn))!=null&&bi[2]){var bd=a2.filter[bl],br,bp,bf=bi[1];bc=false;bi.splice(1,1);if(bf.substr(bf.length-1)==="\\"){continue}if(bk===bs){bs=[]}if(a2.preFilter[bl]){bi=a2.preFilter[bl](bi,bk,bq,bs,bg,bj);if(!bi){bc=br=true}else{if(bi===true){continue}}}if(bi){for(var bh=0;(bp=bk[bh])!=null;bh++){if(bp){br=bd(bp,bi,bh,bk);var bo=bg^!!br;if(bq&&br!=null){if(bo){bc=true}else{bk[bh]=false}}else{if(bo){bs.push(bp);bc=true}}}}}if(br!==B){if(!bq){bk=bs}bn=bn.replace(a2.match[bl],"");if(!bc){return[]}break}}}if(bn===be){if(bc==null){aW.error(bn)}else{break}}be=bn}return bk};aW.error=function(bc){throw"Syntax error, unrecognized expression: "+bc};var a2=aW.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(bc){return bc.getAttribute("href")}},relative:{"+":function(bi,bd){var bf=typeof bd==="string",bh=bf&&!/\W/.test(bd),bj=bf&&!bh;if(bh){bd=bd.toLowerCase()}for(var be=0,bc=bi.length,bg;be<bc;be++){if((bg=bi[be])){while((bg=bg.previousSibling)&&bg.nodeType!==1){}bi[be]=bj||bg&&bg.nodeName.toLowerCase()===bd?bg||false:bg===bd}}if(bj){aW.filter(bd,bi,true)}},">":function(bi,bd){var bg=typeof bd==="string";if(bg&&!/\W/.test(bd)){bd=bd.toLowerCase();for(var be=0,bc=bi.length;be<bc;be++){var bh=bi[be];if(bh){var bf=bh.parentNode;bi[be]=bf.nodeName.toLowerCase()===bd?bf:false}}}else{for(var be=0,bc=bi.length;be<bc;be++){var bh=bi[be];if(bh){bi[be]=bg?bh.parentNode:bh.parentNode===bd}}if(bg){aW.filter(bd,bi,true)}}},"":function(bf,bd,bh){var be=a6++,bc=ba;if(typeof bd==="string"&&!/\W/.test(bd)){var bg=bd=bd.toLowerCase();bc=aU}bc("parentNode",bd,be,bf,bg,bh)},"~":function(bf,bd,bh){var be=a6++,bc=ba;if(typeof bd==="string"&&!/\W/.test(bd)){var bg=bd=bd.toLowerCase();bc=aU}bc("previousSibling",bd,be,bf,bg,bh)}},find:{ID:function(bd,be,bf){if(typeof be.getElementById!=="undefined"&&!bf){var bc=be.getElementById(bd[1]);return bc?[bc]:[]}},NAME:function(be,bh){if(typeof bh.getElementsByName!=="undefined"){var bd=[],bg=bh.getElementsByName(be[1]);for(var bf=0,bc=bg.length;bf<bc;bf++){if(bg[bf].getAttribute("name")===be[1]){bd.push(bg[bf])}}return bd.length===0?null:bd}},TAG:function(bc,bd){return bd.getElementsByTagName(bc[1])}},preFilter:{CLASS:function(bf,bd,be,bc,bi,bj){bf=" "+bf[1].replace(/\\/g,"")+" ";if(bj){return bf}for(var bg=0,bh;(bh=bd[bg])!=null;bg++){if(bh){if(bi^(bh.className&&(" "+bh.className+" ").replace(/[\t\n]/g," ").indexOf(bf)>=0)){if(!be){bc.push(bh)}}else{if(be){bd[bg]=false}}}}return false},ID:function(bc){return bc[1].replace(/\\/g,"")},TAG:function(bd,bc){return bd[1].toLowerCase()},CHILD:function(bc){if(bc[1]==="nth"){var bd=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(bc[2]==="even"&&"2n"||bc[2]==="odd"&&"2n+1"||!/\D/.test(bc[2])&&"0n+"+bc[2]||bc[2]);bc[2]=(bd[1]+(bd[2]||1))-0;bc[3]=bd[3]-0}bc[0]=a6++;return bc},ATTR:function(bg,bd,be,bc,bh,bi){var bf=bg[1].replace(/\\/g,"");if(!bi&&a2.attrMap[bf]){bg[1]=a2.attrMap[bf]}if(bg[2]==="~="){bg[4]=" "+bg[4]+" "}return bg},PSEUDO:function(bg,bd,be,bc,bh){if(bg[1]==="not"){if((a5.exec(bg[3])||"").length>1||/^\w/.test(bg[3])){bg[3]=aW(bg[3],null,null,bd)}else{var bf=aW.filter(bg[3],bd,be,true^bh);if(!be){bc.push.apply(bc,bf)}return false}}else{if(a2.match.POS.test(bg[0])||a2.match.CHILD.test(bg[0])){return true}}return bg},POS:function(bc){bc.unshift(true);return bc}},filters:{enabled:function(bc){return bc.disabled===false&&bc.type!=="hidden"},disabled:function(bc){return bc.disabled===true},checked:function(bc){return bc.checked===true},selected:function(bc){bc.parentNode.selectedIndex;return bc.selected===true},parent:function(bc){return !!bc.firstChild},empty:function(bc){return !bc.firstChild},has:function(be,bd,bc){return !!aW(bc[3],be).length},header:function(bc){return/h\d/i.test(bc.nodeName)},text:function(bc){return"text"===bc.type},radio:function(bc){return"radio"===bc.type},checkbox:function(bc){return"checkbox"===bc.type},file:function(bc){return"file"===bc.type},password:function(bc){return"password"===bc.type},submit:function(bc){return"submit"===bc.type},image:function(bc){return"image"===bc.type},reset:function(bc){return"reset"===bc.type},button:function(bc){return"button"===bc.type||bc.nodeName.toLowerCase()==="button"},input:function(bc){return/input|select|textarea|button/i.test(bc.nodeName)}},setFilters:{first:function(bd,bc){return bc===0},last:function(be,bd,bc,bf){return bd===bf.length-1},even:function(bd,bc){return bc%2===0},odd:function(bd,bc){return bc%2===1},lt:function(be,bd,bc){return bd<bc[3]-0},gt:function(be,bd,bc){return bd>bc[3]-0},nth:function(be,bd,bc){return bc[3]-0===bd},eq:function(be,bd,bc){return bc[3]-0===bd}},filter:{PSEUDO:function(bi,be,bf,bj){var bd=be[1],bg=a2.filters[bd];if(bg){return bg(bi,bf,be,bj)}else{if(bd==="contains"){return(bi.textContent||bi.innerText||aV([bi])||"").indexOf(be[3])>=0}else{if(bd==="not"){var bh=be[3];for(var bf=0,bc=bh.length;bf<bc;bf++){if(bh[bf]===bi){return false}}return true}else{aW.error("Syntax error, unrecognized expression: "+bd)}}}},CHILD:function(bc,bf){var bi=bf[1],bd=bc;switch(bi){case"only":case"first":while((bd=bd.previousSibling)){if(bd.nodeType===1){return false}}if(bi==="first"){return true}bd=bc;case"last":while((bd=bd.nextSibling)){if(bd.nodeType===1){return false}}return true;case"nth":var be=bf[2],bl=bf[3];if(be===1&&bl===0){return true}var bh=bf[0],bk=bc.parentNode;if(bk&&(bk.sizcache!==bh||!bc.nodeIndex)){var bg=0;for(bd=bk.firstChild;bd;bd=bd.nextSibling){if(bd.nodeType===1){bd.nodeIndex=++bg}}bk.sizcache=bh}var bj=bc.nodeIndex-bl;if(be===0){return bj===0}else{return(bj%be===0&&bj/be>=0)}}},ID:function(bd,bc){return bd.nodeType===1&&bd.getAttribute("id")===bc},TAG:function(bd,bc){return(bc==="*"&&bd.nodeType===1)||bd.nodeName.toLowerCase()===bc},CLASS:function(bd,bc){return(" "+(bd.className||bd.getAttribute("class"))+" ").indexOf(bc)>-1},ATTR:function(bh,bf){var be=bf[1],bc=a2.attrHandle[be]?a2.attrHandle[be](bh):bh[be]!=null?bh[be]:bh.getAttribute(be),bi=bc+"",bg=bf[2],bd=bf[4];return bc==null?bg==="!=":bg==="="?bi===bd:bg==="*="?bi.indexOf(bd)>=0:bg==="~="?(" "+bi+" ").indexOf(bd)>=0:!bd?bi&&bc!==false:bg==="!="?bi!==bd:bg==="^="?bi.indexOf(bd)===0:bg==="$="?bi.substr(bi.length-bd.length)===bd:bg==="|="?bi===bd||bi.substr(0,bd.length+1)===bd+"-":false},POS:function(bg,bd,be,bh){var bc=bd[2],bf=a2.setFilters[bc];if(bf){return bf(bg,be,bd,bh)}}}};var a1=a2.match.POS;for(var aY in a2.match){a2.match[aY]=new RegExp(a2.match[aY].source+/(?![^\[]*\])(?![^\(]*\))/.source);a2.leftMatch[aY]=new RegExp(/(^(?:.|\r|\n)*?)/.source+a2.match[aY].source.replace(/\\(\d+)/g,function(bd,bc){return"\\"+(bc-0+1)}))}var a4=function(bd,bc){bd=Array.prototype.slice.call(bd,0);if(bc){bc.push.apply(bc,bd);return bc}return bd};try{Array.prototype.slice.call(aa.documentElement.childNodes,0)}catch(bb){a4=function(bg,bf){var bd=bf||[];if(a8.call(bg)==="[object Array]"){Array.prototype.push.apply(bd,bg)}else{if(typeof bg.length==="number"){for(var be=0,bc=bg.length;be<bc;be++){bd.push(bg[be])}}else{for(var be=0;bg[be];be++){bd.push(bg[be])}}}return bd}}var a7;if(aa.documentElement.compareDocumentPosition){a7=function(bd,bc){if(!bd.compareDocumentPosition||!bc.compareDocumentPosition){if(bd==bc){a0=true}return bd.compareDocumentPosition?-1:1}var be=bd.compareDocumentPosition(bc)&4?-1:bd===bc?0:1;if(be===0){a0=true}return be}}else{if("sourceIndex" in aa.documentElement){a7=function(bd,bc){if(!bd.sourceIndex||!bc.sourceIndex){if(bd==bc){a0=true}return bd.sourceIndex?-1:1}var be=bd.sourceIndex-bc.sourceIndex;if(be===0){a0=true}return be}}else{if(aa.createRange){a7=function(bf,bd){if(!bf.ownerDocument||!bd.ownerDocument){if(bf==bd){a0=true}return bf.ownerDocument?-1:1}var be=bf.ownerDocument.createRange(),bc=bd.ownerDocument.createRange();be.setStart(bf,0);be.setEnd(bf,0);bc.setStart(bd,0);bc.setEnd(bd,0);var bg=be.compareBoundaryPoints(Range.START_TO_END,bc);if(bg===0){a0=true}return bg}}}}function aV(bc){var bd="",bf;for(var be=0;bc[be];be++){bf=bc[be];if(bf.nodeType===3||bf.nodeType===4){bd+=bf.nodeValue}else{if(bf.nodeType!==8){bd+=aV(bf.childNodes)}}}return bd}(function(){var bd=aa.createElement("div"),be="script"+(new Date).getTime();bd.innerHTML="<a name='"+be+"'/>";var bc=aa.documentElement;bc.insertBefore(bd,bc.firstChild);if(aa.getElementById(be)){a2.find.ID=function(bg,bh,bi){if(typeof bh.getElementById!=="undefined"&&!bi){var bf=bh.getElementById(bg[1]);return bf?bf.id===bg[1]||typeof bf.getAttributeNode!=="undefined"&&bf.getAttributeNode("id").nodeValue===bg[1]?[bf]:B:[]}};a2.filter.ID=function(bh,bf){var bg=typeof bh.getAttributeNode!=="undefined"&&bh.getAttributeNode("id");return bh.nodeType===1&&bg&&bg.nodeValue===bf}}bc.removeChild(bd);bc=bd=null})();(function(){var bc=aa.createElement("div");bc.appendChild(aa.createComment(""));if(bc.getElementsByTagName("*").length>0){a2.find.TAG=function(bd,bh){var bg=bh.getElementsByTagName(bd[1]);if(bd[1]==="*"){var bf=[];for(var be=0;bg[be];be++){if(bg[be].nodeType===1){bf.push(bg[be])}}bg=bf}return bg}}bc.innerHTML="<a href='#'></a>";if(bc.firstChild&&typeof bc.firstChild.getAttribute!=="undefined"&&bc.firstChild.getAttribute("href")!=="#"){a2.attrHandle.href=function(bd){return bd.getAttribute("href",2)}}bc=null})();if(aa.querySelectorAll){(function(){var bc=aW,be=aa.createElement("div");be.innerHTML="<p class='TEST'></p>";if(be.querySelectorAll&&be.querySelectorAll(".TEST").length===0){return}aW=function(bi,bh,bf,bg){bh=bh||aa;if(!bg&&bh.nodeType===9&&!aX(bh)){try{return a4(bh.querySelectorAll(bi),bf)}catch(bj){}}return bc(bi,bh,bf,bg)};for(var bd in bc){aW[bd]=bc[bd]}be=null})()}(function(){var bc=aa.createElement("div");bc.innerHTML="<div class='test e'></div><div class='test'></div>";if(!bc.getElementsByClassName||bc.getElementsByClassName("e").length===0){return}bc.lastChild.className="e";if(bc.getElementsByClassName("e").length===1){return}a2.order.splice(1,0,"CLASS");a2.find.CLASS=function(bd,be,bf){if(typeof be.getElementsByClassName!=="undefined"&&!bf){return be.getElementsByClassName(bd[1])}};bc=null})();function aU(bd,bi,bh,bl,bj,bk){for(var bf=0,be=bl.length;bf<be;bf++){var bc=bl[bf];if(bc){bc=bc[bd];var bg=false;while(bc){if(bc.sizcache===bh){bg=bl[bc.sizset];break}if(bc.nodeType===1&&!bk){bc.sizcache=bh;bc.sizset=bf}if(bc.nodeName.toLowerCase()===bi){bg=bc;break}bc=bc[bd]}bl[bf]=bg}}}function ba(bd,bi,bh,bl,bj,bk){for(var bf=0,be=bl.length;bf<be;bf++){var bc=bl[bf];if(bc){bc=bc[bd];var bg=false;while(bc){if(bc.sizcache===bh){bg=bl[bc.sizset];break}if(bc.nodeType===1){if(!bk){bc.sizcache=bh;bc.sizset=bf}if(typeof bi!=="string"){if(bc===bi){bg=true;break}}else{if(aW.filter(bi,[bc]).length>0){bg=bc;break}}}bc=bc[bd]}bl[bf]=bg}}}var a3=aa.compareDocumentPosition?function(bd,bc){return bd.compareDocumentPosition(bc)&16}:function(bd,bc){return bd!==bc&&(bd.contains?bd.contains(bc):true)};var aX=function(bc){var bd=(bc?bc.ownerDocument||bc:0).documentElement;return bd?bd.nodeName!=="HTML":false};var a9=function(bc,bj){var bf=[],bg="",bh,be=bj.nodeType?[bj]:bj;while((bh=a2.match.PSEUDO.exec(bc))){bg+=bh[0];bc=bc.replace(a2.match.PSEUDO,"")}bc=a2.relative[bc]?bc+"*":bc;for(var bi=0,bd=be.length;bi<bd;bi++){aW(bc,be[bi],bf)}return aW.filter(bg,bf)};a.find=aW;a.expr=aW.selectors;a.expr[":"]=a.expr.filters;a.unique=aW.uniqueSort;a.getText=aV;a.isXMLDoc=aX;a.contains=a3;return;aI.Sizzle=aW})();var M=/Until$/,X=/^(?:parents|prevUntil|prevAll)/,aH=/,/,D=Array.prototype.slice;var ag=function(aX,aW,aU){if(a.isFunction(aW)){return a.grep(aX,function(aZ,aY){return !!aW.call(aZ,aY,aZ)===aU})}else{if(aW.nodeType){return a.grep(aX,function(aZ,aY){return(aZ===aW)===aU})}else{if(typeof aW==="string"){var aV=a.grep(aX,function(aY){return aY.nodeType===1});if(aS.test(aW)){return a.filter(aW,aV,!aU)}else{aW=a.filter(aW,aV)}}}}return a.grep(aX,function(aZ,aY){return(a.inArray(aZ,aW)>=0)===aU})};a.fn.extend({find:function(aU){var aW=this.pushStack("","find",aU),aZ=0;for(var aX=0,aV=this.length;aX<aV;aX++){aZ=aW.length;a.find(aU,this[aX],aW);if(aX>0){for(var a0=aZ;a0<aW.length;a0++){for(var aY=0;aY<aZ;aY++){if(aW[aY]===aW[a0]){aW.splice(a0--,1);break}}}}}return aW},has:function(aV){var aU=a(aV);return this.filter(function(){for(var aX=0,aW=aU.length;aX<aW;aX++){if(a.contains(this,aU[aX])){return true}}})},not:function(aU){return this.pushStack(ag(this,aU,false),"not",aU)},filter:function(aU){return this.pushStack(ag(this,aU,true),"filter",aU)},is:function(aU){return !!aU&&a.filter(aU,this).length>0},closest:function(a3,aU){if(a.isArray(a3)){var a0=[],a2=this[0],aZ,aY={},aW;if(a2&&a3.length){for(var aX=0,aV=a3.length;aX<aV;aX++){aW=a3[aX];if(!aY[aW]){aY[aW]=a.expr.match.POS.test(aW)?a(aW,aU||this.context):aW}}while(a2&&a2.ownerDocument&&a2!==aU){for(aW in aY){aZ=aY[aW];if(aZ.jquery?aZ.index(a2)>-1:a(a2).is(aZ)){a0.push({selector:aW,elem:a2});delete aY[aW]}}a2=a2.parentNode}}return a0}var a1=a.expr.match.POS.test(a3)?a(a3,aU||this.context):null;return this.map(function(a4,a5){while(a5&&a5.ownerDocument&&a5!==aU){if(a1?a1.index(a5)>-1:a(a5).is(a3)){return a5}a5=a5.parentNode}return null})},index:function(aU){if(!aU||typeof aU==="string"){return a.inArray(this[0],aU?a(aU):this.parent().children())}return a.inArray(aU.jquery?aU[0]:aU,this)},add:function(aU,aV){var aX=typeof aU==="string"?a(aU,aV||this.context):a.makeArray(aU),aW=a.merge(this.get(),aX);return this.pushStack(x(aX[0])||x(aW[0])?aW:a.unique(aW))},andSelf:function(){return this.add(this.prevObject)}});function x(aU){return !aU||!aU.parentNode||aU.parentNode.nodeType===11}a.each({parent:function(aV){var aU=aV.parentNode;return aU&&aU.nodeType!==11?aU:null},parents:function(aU){return a.dir(aU,"parentNode")},parentsUntil:function(aV,aU,aW){return a.dir(aV,"parentNode",aW)},next:function(aU){return a.nth(aU,2,"nextSibling")},prev:function(aU){return a.nth(aU,2,"previousSibling")},nextAll:function(aU){return a.dir(aU,"nextSibling")},prevAll:function(aU){return a.dir(aU,"previousSibling")},nextUntil:function(aV,aU,aW){return a.dir(aV,"nextSibling",aW)},prevUntil:function(aV,aU,aW){return a.dir(aV,"previousSibling",aW)},siblings:function(aU){return a.sibling(aU.parentNode.firstChild,aU)},children:function(aU){return a.sibling(aU.firstChild)},contents:function(aU){return a.nodeName(aU,"iframe")?aU.contentDocument||aU.contentWindow.document:a.makeArray(aU.childNodes)}},function(aU,aV){a.fn[aU]=function(aY,aW){var aX=a.map(this,aV,aY);if(!M.test(aU)){aW=aY}if(aW&&typeof aW==="string"){aX=a.filter(aW,aX)}aX=this.length>1?a.unique(aX):aX;if((this.length>1||aH.test(aW))&&X.test(aU)){aX=aX.reverse()}return this.pushStack(aX,aU,D.call(arguments).join(","))}});a.extend({filter:function(aW,aU,aV){if(aV){aW=":not("+aW+")"}return a.find.matches(aW,aU)},dir:function(aW,aV,aY){var aU=[],aX=aW[aV];while(aX&&aX.nodeType!==9&&(aY===B||aX.nodeType!==1||!a(aX).is(aY))){if(aX.nodeType===1){aU.push(aX)}aX=aX[aV]}return aU},nth:function(aY,aU,aW,aX){aU=aU||1;var aV=0;for(;aY;aY=aY[aW]){if(aY.nodeType===1&&++aV===aU){break}}return aY},sibling:function(aW,aV){var aU=[];for(;aW;aW=aW.nextSibling){if(aW.nodeType===1&&aW!==aV){aU.push(aW)}}return aU}});var S=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,F=/(<([\w:]+)[^>]*?)\/>/g,aj=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,c=/<([\w:]+)/,t=/<tbody/i,J=/<|&\w+;/,l=/checked\s*(?:[^=]|=\s*.checked.)/i,p=function(aV,aW,aU){return aj.test(aU)?aV:aW+"></"+aU+">"},ab={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};ab.optgroup=ab.option;ab.tbody=ab.tfoot=ab.colgroup=ab.caption=ab.thead;ab.th=ab.td;if(!a.support.htmlSerialize){ab._default=[1,"div<div>","</div>"]}a.fn.extend({text:function(aU){if(a.isFunction(aU)){return this.each(function(aW){var aV=a(this);aV.text(aU.call(this,aW,aV.text()))})}if(typeof aU!=="object"&&aU!==B){return this.empty().append((this[0]&&this[0].ownerDocument||aa).createTextNode(aU))}return a.getText(this)},wrapAll:function(aU){if(a.isFunction(aU)){return this.each(function(aW){a(this).wrapAll(aU.call(this,aW))})}if(this[0]){var aV=a(aU,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){aV.insertBefore(this[0])}aV.map(function(){var aW=this;while(aW.firstChild&&aW.firstChild.nodeType===1){aW=aW.firstChild}return aW}).append(this)}return this},wrapInner:function(aU){if(a.isFunction(aU)){return this.each(function(aV){a(this).wrapInner(aU.call(this,aV))})}return this.each(function(){var aV=a(this),aW=aV.contents();if(aW.length){aW.wrapAll(aU)}else{aV.append(aU)}})},wrap:function(aU){return this.each(function(){a(this).wrapAll(aU)})},unwrap:function(){return this.parent().each(function(){if(!a.nodeName(this,"body")){a(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(aU){if(this.nodeType===1){this.appendChild(aU)}})},prepend:function(){return this.domManip(arguments,true,function(aU){if(this.nodeType===1){this.insertBefore(aU,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(aV){this.parentNode.insertBefore(aV,this)})}else{if(arguments.length){var aU=a(arguments[0]);aU.push.apply(aU,this.toArray());return this.pushStack(aU,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(aV){this.parentNode.insertBefore(aV,this.nextSibling)})}else{if(arguments.length){var aU=this.pushStack(this,"after",arguments);aU.push.apply(aU,a(arguments[0]).toArray());return aU}}},clone:function(aV){var aU=this.map(function(){if(!a.support.noCloneEvent&&!a.isXMLDoc(this)){var aX=this.outerHTML,aW=this.ownerDocument;if(!aX){var aY=aW.createElement("div");aY.appendChild(this.cloneNode(true));aX=aY.innerHTML}return a.clean([aX.replace(S,"").replace(Y,"")],aW)[0]}else{return this.cloneNode(true)}});if(aV===true){q(this,aU);q(this.find("*"),aU.find("*"))}return aU},html:function(aW){if(aW===B){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(S,""):null}else{if(typeof aW==="string"&&!/<script/i.test(aW)&&(a.support.leadingWhitespace||!Y.test(aW))&&!ab[(c.exec(aW)||["",""])[1].toLowerCase()]){aW=aW.replace(F,p);try{for(var aV=0,aU=this.length;aV<aU;aV++){if(this[aV].nodeType===1){a.cleanData(this[aV].getElementsByTagName("*"));this[aV].innerHTML=aW}}}catch(aX){this.empty().append(aW)}}else{if(a.isFunction(aW)){this.each(function(a0){var aZ=a(this),aY=aZ.html();aZ.empty().append(function(){return aW.call(this,a0,aY)})})}else{this.empty().append(aW)}}}return this},replaceWith:function(aU){if(this[0]&&this[0].parentNode){if(!a.isFunction(aU)){aU=a(aU).detach()}else{return this.each(function(aX){var aW=a(this),aV=aW.html();aW.replaceWith(aU.call(this,aX,aV))})}return this.each(function(){var aW=this.nextSibling,aV=this.parentNode;a(this).remove();if(aW){a(aW).before(aU)}else{a(aV).append(aU)}})}else{return this.pushStack(a(a.isFunction(aU)?aU():aU),"replaceWith",aU)}},detach:function(aU){return this.remove(aU,true)},domManip:function(aZ,a3,a2){var aW,aY,a1=aZ[0],aV=[];if(!a.support.checkClone&&arguments.length===3&&typeof a1==="string"&&l.test(a1)){return this.each(function(){a(this).domManip(aZ,a3,a2,true)})}if(a.isFunction(a1)){return this.each(function(a5){var a4=a(this);aZ[0]=a1.call(this,a5,a3?a4.html():B);a4.domManip(aZ,a3,a2)})}if(this[0]){if(aZ[0]&&aZ[0].parentNode&&aZ[0].parentNode.nodeType===11){aW={fragment:aZ[0].parentNode}}else{aW=H(aZ,this,aV)}aY=aW.fragment.firstChild;if(aY){a3=a3&&a.nodeName(aY,"tr");for(var aX=0,aU=this.length;aX<aU;aX++){a2.call(a3?a0(this[aX],aY):this[aX],aW.cacheable||this.length>1||aX>0?aW.fragment.cloneNode(true):aW.fragment)}}if(aV){a.each(aV,aR)}}return this;function a0(a4,a5){return a.nodeName(a4,"table")?(a4.getElementsByTagName("tbody")[0]||a4.appendChild(a4.ownerDocument.createElement("tbody"))):a4}}});function q(aW,aU){var aV=0;aU.each(function(){if(this.nodeName!==(aW[aV]&&aW[aV].nodeName)){return}var a1=a.data(aW[aV++]),a0=a.data(this,a1),aX=a1&&a1.events;if(aX){delete a0.handle;a0.events={};for(var aZ in aX){for(var aY in aX[aZ]){a.event.add(this,aZ,aX[aZ][aY],aX[aZ][aY].data)}}}})}function H(aZ,aX,aV){var aY,aU,aW,a0;if(aZ.length===1&&typeof aZ[0]==="string"&&aZ[0].length<512&&aZ[0].indexOf("<option")<0&&(a.support.checkClone||!l.test(aZ[0]))){aU=true;aW=a.fragments[aZ[0]];if(aW){if(aW!==1){aY=aW}}}if(!aY){a0=(aX&&aX[0]?aX[0].ownerDocument||aX[0]:aa);aY=a0.createDocumentFragment();a.clean(aZ,a0,aY,aV)}if(aU){a.fragments[aZ[0]]=aW?aY:1}return{fragment:aY,cacheable:aU}}a.fragments={};a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(aU,aV){a.fn[aU]=function(aW){var aZ=[],a1=a(aW);for(var a0=0,aX=a1.length;a0<aX;a0++){var aY=(a0>0?this.clone(true):this).get();a.fn[aV].apply(a(a1[a0]),aY);aZ=aZ.concat(aY)}return this.pushStack(aZ,aU,a1.selector)}});a.each({remove:function(aU,aV){if(!aU||a.filter(aU,[this]).length){if(!aV&&this.nodeType===1){a.cleanData(this.getElementsByTagName("*"));a.cleanData([this])}if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){if(this.nodeType===1){a.cleanData(this.getElementsByTagName("*"))}while(this.firstChild){this.removeChild(this.firstChild)}}},function(aU,aV){a.fn[aU]=function(){return this.each(aV,arguments)}});a.extend({clean:function(aV,aZ,aX,aU){aZ=aZ||aa;if(typeof aZ.createElement==="undefined"){aZ=aZ.ownerDocument||aZ[0]&&aZ[0].ownerDocument||aa}var aW=[];a.each(aV,function(a6,a3){if(typeof a3==="number"){a3+=""}if(!a3){return}if(typeof a3==="string"&&!J.test(a3)){a3=aZ.createTextNode(a3)}else{if(typeof a3==="string"){a3=a3.replace(F,p);var a8=(c.exec(a3)||["",""])[1].toLowerCase(),a2=ab[a8]||ab._default,a5=a2[0],a0=aZ.createElement("div");a0.innerHTML=a2[1]+a3+a2[2];while(a5--){a0=a0.lastChild}if(!a.support.tbody){var a1=t.test(a3),a7=a8==="table"&&!a1?a0.firstChild&&a0.firstChild.childNodes:a2[1]==="<table>"&&!a1?a0.childNodes:[];for(var a4=a7.length-1;a4>=0;--a4){if(a.nodeName(a7[a4],"tbody")&&!a7[a4].childNodes.length){a7[a4].parentNode.removeChild(a7[a4])}}}if(!a.support.leadingWhitespace&&Y.test(a3)){a0.insertBefore(aZ.createTextNode(Y.exec(a3)[0]),a0.firstChild)}a3=a.makeArray(a0.childNodes)}}if(a3.nodeType){aW.push(a3)}else{aW=a.merge(aW,a3)}});if(aX){for(var aY=0;aW[aY];aY++){if(aU&&a.nodeName(aW[aY],"script")&&(!aW[aY].type||aW[aY].type.toLowerCase()==="text/javascript")){aU.push(aW[aY].parentNode?aW[aY].parentNode.removeChild(aW[aY]):aW[aY])}else{if(aW[aY].nodeType===1){aW.splice.apply(aW,[aY+1,0].concat(a.makeArray(aW[aY].getElementsByTagName("script"))))}aX.appendChild(aW[aY])}}}return aW},cleanData:function(aU){for(var aV=0,aW,aX;(aW=aU[aV])!=null;aV++){a.event.remove(aW);a.removeData(aW)}}});var ap=/z-?index|font-?weight|opacity|zoom|line-?height/i,T=/alpha\([^)]*\)/,Z=/opacity=([^)]*)/,af=/float/i,aw=/-([a-z])/ig,v=/([A-Z])/g,aK=/^-?\d+(?:px)?$/i,aQ=/^-?\d/,aG={position:"absolute",visibility:"hidden",display:"block"},V=["Left","Right"],aA=["Top","Bottom"],ai=aa.defaultView&&aa.defaultView.getComputedStyle,aJ=a.support.cssFloat?"cssFloat":"styleFloat",k=function(aU,aV){return aV.toUpperCase()};a.fn.css=function(aU,aV){return al(this,aU,aV,true,function(aX,aW,aY){if(aY===B){return a.curCSS(aX,aW)}if(typeof aY==="number"&&!ap.test(aW)){aY+="px"}a.style(aX,aW,aY)})};a.extend({style:function(aY,aV,aZ){if(!aY||aY.nodeType===3||aY.nodeType===8){return B}if((aV==="width"||aV==="height")&&parseFloat(aZ)<0){aZ=B}var aX=aY.style||aY,a0=aZ!==B;if(!a.support.opacity&&aV==="opacity"){if(a0){aX.zoom=1;var aU=parseInt(aZ,10)+""==="NaN"?"":"alpha(opacity="+aZ*100+")";var aW=aX.filter||a.curCSS(aY,"filter")||"";aX.filter=T.test(aW)?aW.replace(T,aU):aU}return aX.filter&&aX.filter.indexOf("opacity=")>=0?(parseFloat(Z.exec(aX.filter)[1])/100)+"":""}if(af.test(aV)){aV=aJ}aV=aV.replace(aw,k);if(a0){aX[aV]=aZ}return aX[aV]},css:function(aX,aV,aZ,aU){if(aV==="width"||aV==="height"){var a1,aW=aG,a0=aV==="width"?V:aA;function aY(){a1=aV==="width"?aX.offsetWidth:aX.offsetHeight;if(aU==="border"){return}a.each(a0,function(){if(!aU){a1-=parseFloat(a.curCSS(aX,"padding"+this,true))||0}if(aU==="margin"){a1+=parseFloat(a.curCSS(aX,"margin"+this,true))||0}else{a1-=parseFloat(a.curCSS(aX,"border"+this+"Width",true))||0}})}if(aX.offsetWidth!==0){aY()}else{a.swap(aX,aW,aY)}return Math.max(0,Math.round(a1))}return a.curCSS(aX,aV,aZ)},curCSS:function(a0,aV,aW){var a3,aU=a0.style,aX;if(!a.support.opacity&&aV==="opacity"&&a0.currentStyle){a3=Z.test(a0.currentStyle.filter||"")?(parseFloat(RegExp.$1)/100)+"":"";return a3===""?"1":a3}if(af.test(aV)){aV=aJ}if(!aW&&aU&&aU[aV]){a3=aU[aV]}else{if(ai){if(af.test(aV)){aV="float"}aV=aV.replace(v,"-$1").toLowerCase();var a2=a0.ownerDocument.defaultView;if(!a2){return null}var a4=a2.getComputedStyle(a0,null);if(a4){a3=a4.getPropertyValue(aV)}if(aV==="opacity"&&a3===""){a3="1"}}else{if(a0.currentStyle){var aZ=aV.replace(aw,k);a3=a0.currentStyle[aV]||a0.currentStyle[aZ];if(!aK.test(a3)&&aQ.test(a3)){var aY=aU.left,a1=a0.runtimeStyle.left;a0.runtimeStyle.left=a0.currentStyle.left;aU.left=aZ==="fontSize"?"1em":(a3||0);a3=aU.pixelLeft+"px";aU.left=aY;a0.runtimeStyle.left=a1}}}}return a3},swap:function(aX,aW,aY){var aU={};for(var aV in aW){aU[aV]=aX.style[aV];aX.style[aV]=aW[aV]}aY.call(aX);for(var aV in aW){aX.style[aV]=aU[aV]}}});if(a.expr&&a.expr.filters){a.expr.filters.hidden=function(aX){var aV=aX.offsetWidth,aU=aX.offsetHeight,aW=aX.nodeName.toLowerCase()==="tr";return aV===0&&aU===0&&!aW?true:aV>0&&aU>0&&!aW?false:a.curCSS(aX,"display")==="none"};a.expr.filters.visible=function(aU){return !a.expr.filters.hidden(aU)}}var ae=aL(),aF=/<script(.|\s)*?\/script>/gi,o=/select|textarea/i,ay=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,r=/=\?(&|$)/,C=/\?/,aT=/(\?|&)_=.*?(&|$)/,A=/^(\w+:)?\/\/([^\/?#]+)/,h=/%20/g;a.fn.extend({_load:a.fn.load,load:function(aW,aZ,a0){if(typeof aW!=="string"){return this._load(aW)}else{if(!this.length){return this}}var aY=aW.indexOf(" ");if(aY>=0){var aU=aW.slice(aY,aW.length);aW=aW.slice(0,aY)}var aX="GET";if(aZ){if(a.isFunction(aZ)){a0=aZ;aZ=null}else{if(typeof aZ==="object"){aZ=a.param(aZ,a.ajaxSettings.traditional);aX="POST"}}}var aV=this;a.ajax({url:aW,type:aX,dataType:"html",data:aZ,complete:function(a2,a1){if(a1==="success"||a1==="notmodified"){aV.html(aU?a("<div />").append(a2.responseText.replace(aF,"")).find(aU):a2.responseText)}if(a0){aV.each(a0,[a2.responseText,a1,a2])}}});return this},serialize:function(){return a.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?a.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||o.test(this.nodeName)||ay.test(this.type))}).map(function(aU,aV){var aW=a(this).val();return aW==null?null:a.isArray(aW)?a.map(aW,function(aY,aX){return{name:aV.name,value:aY}}):{name:aV.name,value:aW}}).get()}});a.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(aU,aV){a.fn[aV]=function(aW){return this.bind(aV,aW)}});a.extend({get:function(aU,aW,aX,aV){if(a.isFunction(aW)){aV=aV||aX;aX=aW;aW=null}return a.ajax({type:"GET",url:aU,data:aW,success:aX,dataType:aV})},getScript:function(aU,aV){return a.get(aU,null,aV,"script")},getJSON:function(aU,aV,aW){return a.get(aU,aV,aW,"json")},post:function(aU,aW,aX,aV){if(a.isFunction(aW)){aV=aV||aX;aX=aW;aW={}}return a.ajax({type:"POST",url:aU,data:aW,success:aX,dataType:aV})},ajaxSetup:function(aU){a.extend(a.ajaxSettings,aU)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:aI.XMLHttpRequest&&(aI.location.protocol!=="file:"||!aI.ActiveXObject)?function(){return new aI.XMLHttpRequest()}:function(){try{return new aI.ActiveXObject("Microsoft.XMLHTTP")}catch(aU){}},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(a9){var a4=a.extend(true,{},a.ajaxSettings,a9);var be,a8,bd,bf=a9&&a9.context||a4,aW=a4.type.toUpperCase();if(a4.data&&a4.processData&&typeof a4.data!=="string"){a4.data=a.param(a4.data,a4.traditional)}if(a4.dataType==="jsonp"){if(aW==="GET"){if(!r.test(a4.url)){a4.url+=(C.test(a4.url)?"&":"?")+(a4.jsonp||"callback")+"=?"}}else{if(!a4.data||!r.test(a4.data)){a4.data=(a4.data?a4.data+"&":"")+(a4.jsonp||"callback")+"=?"}}a4.dataType="json"}if(a4.dataType==="json"&&(a4.data&&r.test(a4.data)||r.test(a4.url))){be=a4.jsonpCallback||("jsonp"+ae++);if(a4.data){a4.data=(a4.data+"").replace(r,"="+be+"$1")}a4.url=a4.url.replace(r,"="+be+"$1");a4.dataType="script";aI[be]=aI[be]||function(bg){bd=bg;aZ();a2();aI[be]=B;try{delete aI[be]}catch(bh){}if(aX){aX.removeChild(bb)}}}if(a4.dataType==="script"&&a4.cache===null){a4.cache=false}if(a4.cache===false&&aW==="GET"){var aU=aL();var bc=a4.url.replace(aT,"$1_="+aU+"$2");a4.url=bc+((bc===a4.url)?(C.test(a4.url)?"&":"?")+"_="+aU:"")}if(a4.data&&aW==="GET"){a4.url+=(C.test(a4.url)?"&":"?")+a4.data}if(a4.global&&!a.active++){a.event.trigger("ajaxStart")}var a7=A.exec(a4.url),aY=a7&&(a7[1]&&a7[1]!==location.protocol||a7[2]!==location.host);if(a4.dataType==="script"&&aW==="GET"&&aY){var aX=aa.getElementsByTagName("head")[0]||aa.documentElement;var bb=aa.createElement("script");bb.src=a4.url;if(a4.scriptCharset){bb.charset=a4.scriptCharset}if(!be){var a6=false;bb.onload=bb.onreadystatechange=function(){if(!a6&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){a6=true;aZ();a2();bb.onload=bb.onreadystatechange=null;if(aX&&bb.parentNode){aX.removeChild(bb)}}}}aX.insertBefore(bb,aX.firstChild);return B}var a1=false;var a0=a4.xhr();if(!a0){return}if(a4.username){a0.open(aW,a4.url,a4.async,a4.username,a4.password)}else{a0.open(aW,a4.url,a4.async)}try{if(a4.data||a9&&a9.contentType){a0.setRequestHeader("Content-Type",a4.contentType)}if(a4.ifModified){if(a.lastModified[a4.url]){a0.setRequestHeader("If-Modified-Since",a.lastModified[a4.url])}if(a.etag[a4.url]){a0.setRequestHeader("If-None-Match",a.etag[a4.url])}}if(!aY){a0.setRequestHeader("X-Requested-With","XMLHttpRequest")}a0.setRequestHeader("Accept",a4.dataType&&a4.accepts[a4.dataType]?a4.accepts[a4.dataType]+", */*":a4.accepts._default)}catch(ba){}if(a4.beforeSend&&a4.beforeSend.call(bf,a0,a4)===false){if(a4.global&&!--a.active){a.event.trigger("ajaxStop")}a0.abort();return false}if(a4.global){a5("ajaxSend",[a0,a4])}var a3=a0.onreadystatechange=function(bg){if(!a0||a0.readyState===0||bg==="abort"){if(!a1){a2()}a1=true;if(a0){a0.onreadystatechange=a.noop}}else{if(!a1&&a0&&(a0.readyState===4||bg==="timeout")){a1=true;a0.onreadystatechange=a.noop;a8=bg==="timeout"?"timeout":!a.httpSuccess(a0)?"error":a4.ifModified&&a.httpNotModified(a0,a4.url)?"notmodified":"success";var bi;if(a8==="success"){try{bd=a.httpData(a0,a4.dataType,a4)}catch(bh){a8="parsererror";bi=bh}}if(a8==="success"||a8==="notmodified"){if(!be){aZ()}}else{a.handleError(a4,a0,a8,bi)}a2();if(bg==="timeout"){a0.abort()}if(a4.async){a0=null}}}};try{var aV=a0.abort;a0.abort=function(){if(a0){aV.call(a0)}a3("abort")}}catch(ba){}if(a4.async&&a4.timeout>0){setTimeout(function(){if(a0&&!a1){a3("timeout")}},a4.timeout)}try{a0.send(aW==="POST"||aW==="PUT"||aW==="DELETE"?a4.data:null)}catch(ba){a.handleError(a4,a0,null,ba);a2()}if(!a4.async){a3()}function aZ(){if(a4.success){a4.success.call(bf,bd,a8,a0)}if(a4.global){a5("ajaxSuccess",[a0,a4])}}function a2(){if(a4.complete){a4.complete.call(bf,a0,a8)}if(a4.global){a5("ajaxComplete",[a0,a4])}if(a4.global&&!--a.active){a.event.trigger("ajaxStop")}}function a5(bh,bg){(a4.context?a(a4.context):a.event).trigger(bh,bg)}return a0},handleError:function(aV,aX,aU,aW){if(aV.error){aV.error.call(aV.context||aV,aX,aU,aW)}if(aV.global){(aV.context?a(aV.context):a.event).trigger("ajaxError",[aX,aV,aW])}},active:0,httpSuccess:function(aV){try{return !aV.status&&location.protocol==="file:"||(aV.status>=200&&aV.status<300)||aV.status===304||aV.status===1223||aV.status===0}catch(aU){}return false},httpNotModified:function(aX,aU){var aW=aX.getResponseHeader("Last-Modified"),aV=aX.getResponseHeader("Etag");if(aW){a.lastModified[aU]=aW}if(aV){a.etag[aU]=aV}return aX.status===304||aX.status===0},httpData:function(aZ,aX,aW){var aV=aZ.getResponseHeader("content-type")||"",aU=aX==="xml"||!aX&&aV.indexOf("xml")>=0,aY=aU?aZ.responseXML:aZ.responseText;if(aU&&aY.documentElement.nodeName==="parsererror"){a.error("parsererror")}if(aW&&aW.dataFilter){aY=aW.dataFilter(aY,aX)}if(typeof aY==="string"){if(aX==="json"||!aX&&aV.indexOf("json")>=0){aY=a.parseJSON(aY)}else{if(aX==="script"||!aX&&aV.indexOf("javascript")>=0){a.globalEval(aY)}}}return aY},param:function(aU,aX){var aV=[];if(aX===B){aX=a.ajaxSettings.traditional}if(a.isArray(aU)||aU.jquery){a.each(aU,function(){aZ(this.name,this.value)})}else{for(var aY in aU){aW(aY,aU[aY])}}return aV.join("&").replace(h,"+");function aW(a0,a1){if(a.isArray(a1)){a.each(a1,function(a3,a2){if(aX){aZ(a0,a2)}else{aW(a0+"["+(typeof a2==="object"||a.isArray(a2)?a3:"")+"]",a2)}})}else{if(!aX&&a1!=null&&typeof a1==="object"){a.each(a1,function(a3,a2){aW(a0+"["+a3+"]",a2)})}else{aZ(a0,a1)}}}function aZ(a0,a1){a1=a.isFunction(a1)?a1():a1;aV[aV.length]=encodeURIComponent(a0)+"="+encodeURIComponent(a1)}}});var E={},ad=/toggle|show|hide/,ar=/^([+-]=)?([\d+-.]+)(.*)$/,aB,ah=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];a.fn.extend({show:function(aV,a3){if(aV||aV===0){return this.animate(az("show",3),aV,a3)}else{for(var a0=0,aX=this.length;a0<aX;a0++){var aU=a.data(this[a0],"olddisplay");this[a0].style.display=aU||"";if(a.css(this[a0],"display")==="none"){var a2=this[a0].nodeName,a1;if(E[a2]){a1=E[a2]}else{var aW=a("<"+a2+" />").appendTo("body");a1=aW.css("display");if(a1==="none"){a1="block"}aW.remove();E[a2]=a1}a.data(this[a0],"olddisplay",a1)}}for(var aZ=0,aY=this.length;aZ<aY;aZ++){this[aZ].style.display=a.data(this[aZ],"olddisplay")||""}return this}},hide:function(aZ,a0){if(aZ||aZ===0){return this.animate(az("hide",3),aZ,a0)}else{for(var aY=0,aV=this.length;aY<aV;aY++){var aU=a.data(this[aY],"olddisplay");if(!aU&&aU!=="none"){a.data(this[aY],"olddisplay",a.css(this[aY],"display"))}}for(var aX=0,aW=this.length;aX<aW;aX++){this[aX].style.display="none"}return this}},_toggle:a.fn.toggle,toggle:function(aW,aV){var aU=typeof aW==="boolean";if(a.isFunction(aW)&&a.isFunction(aV)){this._toggle.apply(this,arguments)}else{if(aW==null||aU){this.each(function(){var aX=aU?aW:a(this).is(":hidden");a(this)[aX?"show":"hide"]()})}else{this.animate(az("toggle",3),aW,aV)}}return this},fadeTo:function(aU,aW,aV){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:aW},aU,aV)},animate:function(aY,aV,aX,aW){var aU=a.speed(aV,aX,aW);if(a.isEmptyObject(aY)){return this.each(aU.complete)}return this[aU.queue===false?"each":"queue"](function(){var a1=a.extend({},aU),a3,a2=this.nodeType===1&&a(this).is(":hidden"),aZ=this;for(a3 in aY){var a0=a3.replace(aw,k);if(a3!==a0){aY[a0]=aY[a3];delete aY[a3];a3=a0}if(aY[a3]==="hide"&&a2||aY[a3]==="show"&&!a2){return a1.complete.call(this)}if((a3==="height"||a3==="width")&&this.style){a1.display=a.css(this,"display");a1.overflow=this.style.overflow}if(a.isArray(aY[a3])){(a1.specialEasing=a1.specialEasing||{})[a3]=aY[a3][1];aY[a3]=aY[a3][0]}}if(a1.overflow!=null){this.style.overflow="hidden"}a1.curAnim=a.extend({},aY);a.each(aY,function(a5,a9){var a8=new a.fx(aZ,a1,a5);if(ad.test(a9)){a8[a9==="toggle"?a2?"show":"hide":a9](aY)}else{var a7=ar.exec(a9),ba=a8.cur(true)||0;if(a7){var a4=parseFloat(a7[2]),a6=a7[3]||"px";if(a6!=="px"){aZ.style[a5]=(a4||1)+a6;ba=((a4||1)/a8.cur(true))*ba;aZ.style[a5]=ba+a6}if(a7[1]){a4=((a7[1]==="-="?-1:1)*a4)+ba}a8.custom(ba,a4,a6)}else{a8.custom(ba,a9,"")}}});return true})},stop:function(aV,aU){var aW=a.timers;if(aV){this.queue([])}this.each(function(){for(var aX=aW.length-1;aX>=0;aX--){if(aW[aX].elem===this){if(aU){aW[aX](true)}aW.splice(aX,1)}}});if(!aU){this.dequeue()}return this}});a.each({slideDown:az("show",1),slideUp:az("hide",1),slideToggle:az("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(aU,aV){a.fn[aU]=function(aW,aX){return this.animate(aV,aW,aX)}});a.extend({speed:function(aW,aX,aV){var aU=aW&&typeof aW==="object"?aW:{complete:aV||!aV&&aX||a.isFunction(aW)&&aW,duration:aW,easing:aV&&aX||aX&&!a.isFunction(aX)&&aX};aU.duration=a.fx.off?0:typeof aU.duration==="number"?aU.duration:a.fx.speeds[aU.duration]||a.fx.speeds._default;aU.old=aU.complete;aU.complete=function(){if(aU.queue!==false){a(this).dequeue()}if(a.isFunction(aU.old)){aU.old.call(this)}};return aU},easing:{linear:function(aW,aX,aU,aV){return aU+aV*aW},swing:function(aW,aX,aU,aV){return((-Math.cos(aW*Math.PI)/2)+0.5)*aV+aU}},timers:[],fx:function(aV,aU,aW){this.options=aU;this.elem=aV;this.prop=aW;if(!aU.orig){aU.orig={}}}});a.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(a.fx.step[this.prop]||a.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(aV){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var aU=parseFloat(a.css(this.elem,this.prop,aV));return aU&&aU>-10000?aU:parseFloat(a.curCSS(this.elem,this.prop))||0},custom:function(aY,aX,aW){this.startTime=aL();this.start=aY;this.end=aX;this.unit=aW||this.unit||"px";this.now=this.start;this.pos=this.state=0;var aU=this;function aV(aZ){return aU.step(aZ)}aV.elem=this.elem;if(aV()&&a.timers.push(aV)&&!aB){aB=setInterval(a.fx.tick,13)}},show:function(){this.options.orig[this.prop]=a.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());a(this.elem).show()},hide:function(){this.options.orig[this.prop]=a.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(aX){var a2=aL(),aY=true;if(aX||a2>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var aZ in this.options.curAnim){if(this.options.curAnim[aZ]!==true){aY=false}}if(aY){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;var aW=a.data(this.elem,"olddisplay");this.elem.style.display=aW?aW:this.options.display;if(a.css(this.elem,"display")==="none"){this.elem.style.display="block"}}if(this.options.hide){a(this.elem).hide()}if(this.options.hide||this.options.show){for(var aU in this.options.curAnim){a.style(this.elem,aU,this.options.orig[aU])}}this.options.complete.call(this.elem)}return false}else{var aV=a2-this.startTime;this.state=aV/this.options.duration;var a0=this.options.specialEasing&&this.options.specialEasing[this.prop];var a1=this.options.easing||(a.easing.swing?"swing":"linear");this.pos=a.easing[a0||a1](this.state,aV,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};a.extend(a.fx,{tick:function(){var aV=a.timers;for(var aU=0;aU<aV.length;aU++){if(!aV[aU]()){aV.splice(aU--,1)}}if(!aV.length){a.fx.stop()}},stop:function(){clearInterval(aB);aB=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(aU){a.style(aU.elem,"opacity",aU.now)},_default:function(aU){if(aU.elem.style&&aU.elem.style[aU.prop]!=null){aU.elem.style[aU.prop]=(aU.prop==="width"||aU.prop==="height"?Math.max(0,aU.now):aU.now)+aU.unit}else{aU.elem[aU.prop]=aU.now}}}});if(a.expr&&a.expr.filters){a.expr.filters.animated=function(aU){return a.grep(a.timers,function(aV){return aU===aV.elem}).length}}function az(aV,aU){var aW={};a.each(ah.concat.apply([],ah.slice(0,aU)),function(){aW[this]=aV});return aW}if("getBoundingClientRect" in aa.documentElement){a.fn.offset=function(a3){var aW=this[0];if(a3){return this.each(function(a4){a.offset.setOffset(this,a3,a4)})}if(!aW||!aW.ownerDocument){return null}if(aW===aW.ownerDocument.body){return a.offset.bodyOffset(aW)}var aY=aW.getBoundingClientRect(),a2=aW.ownerDocument,aZ=a2.body,aU=a2.documentElement,aX=aU.clientTop||aZ.clientTop||0,a0=aU.clientLeft||aZ.clientLeft||0,a1=aY.top+(self.pageYOffset||a.support.boxModel&&aU.scrollTop||aZ.scrollTop)-aX,aV=aY.left+(self.pageXOffset||a.support.boxModel&&aU.scrollLeft||aZ.scrollLeft)-a0;return{top:a1,left:aV}}}else{a.fn.offset=function(a5){var aZ=this[0];if(a5){return this.each(function(a6){a.offset.setOffset(this,a5,a6)})}if(!aZ||!aZ.ownerDocument){return null}if(aZ===aZ.ownerDocument.body){return a.offset.bodyOffset(aZ)}a.offset.initialize();var aW=aZ.offsetParent,aV=aZ,a4=aZ.ownerDocument,a2,aX=a4.documentElement,a0=a4.body,a1=a4.defaultView,aU=a1?a1.getComputedStyle(aZ,null):aZ.currentStyle,a3=aZ.offsetTop,aY=aZ.offsetLeft;while((aZ=aZ.parentNode)&&aZ!==a0&&aZ!==aX){if(a.offset.supportsFixedPosition&&aU.position==="fixed"){break}a2=a1?a1.getComputedStyle(aZ,null):aZ.currentStyle;a3-=aZ.scrollTop;aY-=aZ.scrollLeft;if(aZ===aW){a3+=aZ.offsetTop;aY+=aZ.offsetLeft;if(a.offset.doesNotAddBorder&&!(a.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(aZ.nodeName))){a3+=parseFloat(a2.borderTopWidth)||0;aY+=parseFloat(a2.borderLeftWidth)||0}aV=aW,aW=aZ.offsetParent}if(a.offset.subtractsBorderForOverflowNotVisible&&a2.overflow!=="visible"){a3+=parseFloat(a2.borderTopWidth)||0;aY+=parseFloat(a2.borderLeftWidth)||0}aU=a2}if(aU.position==="relative"||aU.position==="static"){a3+=a0.offsetTop;aY+=a0.offsetLeft}if(a.offset.supportsFixedPosition&&aU.position==="fixed"){a3+=Math.max(aX.scrollTop,a0.scrollTop);aY+=Math.max(aX.scrollLeft,a0.scrollLeft)}return{top:a3,left:aY}}}a.offset={initialize:function(){var aU=aa.body,aV=aa.createElement("div"),aY,a0,aZ,a1,aW=parseFloat(a.curCSS(aU,"marginTop",true))||0,aX="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.extend(aV.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});aV.innerHTML=aX;aU.insertBefore(aV,aU.firstChild);aY=aV.firstChild;a0=aY.firstChild;a1=aY.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(a0.offsetTop!==5);this.doesAddBorderForTableAndCells=(a1.offsetTop===5);a0.style.position="fixed",a0.style.top="20px";this.supportsFixedPosition=(a0.offsetTop===20||a0.offsetTop===15);a0.style.position=a0.style.top="";aY.style.overflow="hidden",aY.style.position="relative";this.subtractsBorderForOverflowNotVisible=(a0.offsetTop===-5);this.doesNotIncludeMarginInBodyOffset=(aU.offsetTop!==aW);aU.removeChild(aV);aU=aV=aY=a0=aZ=a1=null;a.offset.initialize=a.noop},bodyOffset:function(aU){var aW=aU.offsetTop,aV=aU.offsetLeft;a.offset.initialize();if(a.offset.doesNotIncludeMarginInBodyOffset){aW+=parseFloat(a.curCSS(aU,"marginTop",true))||0;aV+=parseFloat(a.curCSS(aU,"marginLeft",true))||0}return{top:aW,left:aV}},setOffset:function(aZ,aV,aW){if(/static/.test(a.curCSS(aZ,"position"))){aZ.style.position="relative"}var aY=a(aZ),a1=aY.offset(),aU=parseInt(a.curCSS(aZ,"top",true),10)||0,a0=parseInt(a.curCSS(aZ,"left",true),10)||0;if(a.isFunction(aV)){aV=aV.call(aZ,aW,a1)}var aX={top:(aV.top-a1.top)+aU,left:(aV.left-a1.left)+a0};if("using" in aV){aV.using.call(aZ,aX)}else{aY.css(aX)}}};a.fn.extend({position:function(){if(!this[0]){return null}var aW=this[0],aV=this.offsetParent(),aX=this.offset(),aU=/^body|html$/i.test(aV[0].nodeName)?{top:0,left:0}:aV.offset();aX.top-=parseFloat(a.curCSS(aW,"marginTop",true))||0;aX.left-=parseFloat(a.curCSS(aW,"marginLeft",true))||0;aU.top+=parseFloat(a.curCSS(aV[0],"borderTopWidth",true))||0;aU.left+=parseFloat(a.curCSS(aV[0],"borderLeftWidth",true))||0;return{top:aX.top-aU.top,left:aX.left-aU.left}},offsetParent:function(){return this.map(function(){var aU=this.offsetParent||aa.body;while(aU&&(!/^body|html$/i.test(aU.nodeName)&&a.css(aU,"position")==="static")){aU=aU.offsetParent}return aU})}});a.each(["Left","Top"],function(aV,aU){var aW="scroll"+aU;a.fn[aW]=function(aZ){var aX=this[0],aY;if(!aX){return null}if(aZ!==B){return this.each(function(){aY=ak(this);if(aY){aY.scrollTo(!aV?aZ:a(aY).scrollLeft(),aV?aZ:a(aY).scrollTop())}else{this[aW]=aZ}})}else{aY=ak(aX);return aY?("pageXOffset" in aY)?aY[aV?"pageYOffset":"pageXOffset"]:a.support.boxModel&&aY.document.documentElement[aW]||aY.document.body[aW]:aX[aW]}}});function ak(aU){return("scrollTo" in aU&&aU.document)?aU:aU.nodeType===9?aU.defaultView||aU.parentWindow:false}a.each(["Height","Width"],function(aV,aU){var aW=aU.toLowerCase();a.fn["inner"+aU]=function(){return this[0]?a.css(this[0],aW,false,"padding"):null};a.fn["outer"+aU]=function(aX){return this[0]?a.css(this[0],aW,false,aX?"margin":"border"):null};a.fn[aW]=function(aX){var aY=this[0];if(!aY){return aX==null?null:this}if(a.isFunction(aX)){return this.each(function(a0){var aZ=a(this);aZ[aW](aX.call(this,a0,aZ[aW]()))})}return("scrollTo" in aY&&aY.document)?aY.document.compatMode==="CSS1Compat"&&aY.document.documentElement["client"+aU]||aY.document.body["client"+aU]:(aY.nodeType===9)?Math.max(aY.documentElement["client"+aU],aY.body["scroll"+aU],aY.documentElement["scroll"+aU],aY.body["offset"+aU],aY.documentElement["offset"+aU]):aX===B?a.css(aY,aW):this.css(aW,typeof aX==="string"?aX:aX+"px")}});aI.jQuery=aI.$=a})(window);window.djdt=(function(b,a,e){e.cookie=function(h,p,s){if(typeof p!="undefined"){s=s||{};if(p===null){p="";s.expires=-1}var l="";if(s.expires&&(typeof s.expires=="number"||s.expires.toUTCString)){var m;if(typeof s.expires=="number"){m=new Date();m.setTime(m.getTime()+(s.expires*24*60*60*1000))}else{m=s.expires}l="; expires="+m.toUTCString()}var r=s.path?"; path="+(s.path):"";var n=s.domain?"; domain="+(s.domain):"";var g=s.secure?"; secure":"";a.cookie=[h,"=",encodeURIComponent(p),l,r,n,g].join("")}else{var k=null;if(a.cookie&&a.cookie!=""){var q=a.cookie.split(";");for(var o=0;o<q.length;o++){var j=c.trim(q[o]);if(j.substring(0,h.length+1)==(h+"=")){k=decodeURIComponent(j.substring(h.length+1));break}}}return k}};var c=e;var f="djdt";var d={jQuery:e,events:{ready:[]},isReady:false,init:function(){c("#djDebug").show();var i=null;c("#djDebugPanelList li a").click(function(){if(!this.className){return false}i=c("#djDebug #"+this.className);if(i.is(":visible")){c(a).trigger("close.djDebug");c(this).parent().removeClass("active")}else{c(".panelContent").hide();i.show();c("#djDebugToolbar li").removeClass("active");c(this).parent().addClass("active")}return false});c("#djDebug a.djDebugClose").click(function(){c(a).trigger("close.djDebug");c("#djDebugToolbar li").removeClass("active");return false});c("#djDebug a.remoteCall").click(function(){c("#djDebugWindow").load(this.href,function(k,j,m){if(j=="error"){var l='<div class="djDebugPanelTitle"><a class="djDebugClose djDebugBack" href="">Back</a><h3>'+m.status+": "+m.statusText+"</h3></div>";c("#djDebugWindow").html(l)}c("#djDebugWindow a.djDebugBack").click(function(){c(this).parent().parent().hide();return false})});c("#djDebugWindow").show();return false});c("#djDebugTemplatePanel a.djTemplateShowContext").click(function(){d.toggle_arrow(c(this).children(".toggleArrow"));d.toggle_content(c(this).parent().next());return false});c("#djDebug a.djDebugToggle").click(function(j){j.preventDefault();c(this).parent().find(".djDebugCollapsed").toggle();c(this).parent().find(".djDebugUncollapsed").toggle()});c("#djDebug a.djToggleSwitch").click(function(l){l.preventDefault();var j=c(this);var m=j.attr("data-toggle-id");var k=j.text()==j.attr("data-toggle-open");if(m==""||!m){return}j.parents(".djDebugPanelContent").find("#sqlMain_"+m).find(".djDebugCollapsed").toggle(k);j.parents(".djDebugPanelContent").find("#sqlMain_"+m).find(".djDebugUncollapsed").toggle(!k);c(this).parents(".djDebugPanelContent").find(".djToggleDetails_"+m).each(function(){var n=c(this);if(k){n.addClass("djSelected");n.removeClass("djUnselected");j.text(j.attr("data-toggle-close"));n.find(".djToggleSwitch").text(j.text())}else{n.removeClass("djSelected");n.addClass("djUnselected");j.text(j.attr("data-toggle-open"));n.find(".djToggleSwitch").text(j.text())}});return});function g(j){id=j.attr("id");return c('.djDebugProfileRow[id^="'+id+'_"]')}function h(j){subcalls=g(j);depth=parseInt(j.attr("depth"))+1;return subcalls.filter("[depth="+depth+"]")}c(".djDebugProfileRow .djDebugProfileToggle").click(function(){row=c(this).closest(".djDebugProfileRow");subcalls=g(row);if(subcalls.css("display")=="none"){h(row).show()}else{subcalls.hide()}});c("#djHideToolBarButton").click(function(){d.hide_toolbar(true);return false});c("#djShowToolBarButton").click(function(){d.show_toolbar();return false});c(a).bind("close.djDebug",function(){if(c("#djDebugWindow").is(":visible")){c("#djDebugWindow").hide();return}if(c(".panelContent").is(":visible")){c(".panelContent").hide();return}if(c("#djDebugToolbar").is(":visible")){d.hide_toolbar(true);return}});if(c.cookie(f)){d.hide_toolbar(false)}else{d.show_toolbar(false)}c("#djDebug .djDebugHoverable").hover(function(){c(this).addClass("djDebugHover")},function(){c(this).removeClass("djDebugHover")});d.isReady=true;c.each(d.events.ready,function(j,k){k(d)})},toggle_content:function(g){if(g.is(":visible")){g.hide()}else{g.show()}},close:function(){c(a).trigger("close.djDebug");return false},hide_toolbar:function(g){c("#djDebugWindow").hide();c(".panelContent").hide();c("#djDebugToolbar li").removeClass("active");c("#djDebugToolbar").hide("fast");c("#djDebugToolbarHandle").show();c(a).unbind("keydown.djDebug");if(g){c.cookie(f,"hide",{path:"/",expires:10})}},show_toolbar:function(g){c(a).bind("keydown.djDebug",function(h){if(h.keyCode==27){d.close()}});c("#djDebugToolbarHandle").hide();if(g){c("#djDebugToolbar").show("fast")}else{c("#djDebugToolbar").show()}c.cookie(f,null,{path:"/",expires:-1})},toggle_arrow:function(h){var g=String.fromCharCode(9654);var i=String.fromCharCode(9660);h.html(h.html()==g?i:g)},ready:function(g){if(d.isReady){g(d)}else{d.events.ready.push(g)}}};c(a).ready(function(){d.init()});return d}(window,document,jQuery.noConflict(true)));
\ No newline at end of file diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index de4ae9c..f49a29f 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -1,13 +1,15 @@ """ Debug Toolbar middleware """ +import imp import thread from django.conf import settings +from django.conf.urls.defaults import include, patterns from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.utils.encoding import smart_unicode -from django.conf.urls.defaults import include, patterns +from django.utils.importlib import import_module import debug_toolbar.urls from debug_toolbar.toolbar.loader import DebugToolbar @@ -32,13 +34,13 @@ class DebugToolbarMiddleware(object): on outgoing response. """ debug_toolbars = {} - + @classmethod def get_current(cls): return cls.debug_toolbars.get(thread.get_ident()) def __init__(self): - self.override_url = True + self._urlconfs = {} # Set method to use to decide to show toolbar self.show_toolbar = self._show_toolbar # default @@ -57,32 +59,39 @@ class DebugToolbarMiddleware(object): self.tag = u'</' + tag + u'>' def _show_toolbar(self, request): + if getattr(settings, 'TEST', False): + return False + x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', None) if x_forwarded_for: remote_addr = x_forwarded_for.split(',')[0].strip() else: remote_addr = request.META.get('REMOTE_ADDR', None) - if not remote_addr in settings.INTERNAL_IPS \ - or (request.is_ajax() and \ - not debug_toolbar.urls._PREFIX in request.path) \ - or not (settings.DEBUG or getattr(settings, 'TEST', False)): - return False - return True + + # if not internal ip, and not DEBUG + return remote_addr in settings.INTERNAL_IPS and bool(settings.DEBUG) def process_request(self, request): __traceback_hide__ = True if self.show_toolbar(request): - if self.override_url: - original_urlconf = __import__(getattr(request, 'urlconf', settings.ROOT_URLCONF), {}, {}, ['*']) - debug_toolbar.urls.urlpatterns += patterns('', - ('', include(original_urlconf)), - ) - if hasattr(original_urlconf, 'handler404'): - debug_toolbar.urls.handler404 = original_urlconf.handler404 - if hasattr(original_urlconf, 'handler500'): - debug_toolbar.urls.handler500 = original_urlconf.handler500 - self.override_url = False - request.urlconf = 'debug_toolbar.urls' + + urlconf = getattr(request, 'urlconf', settings.ROOT_URLCONF) + if isinstance(urlconf, basestring): + urlconf = import_module(getattr(request, 'urlconf', settings.ROOT_URLCONF)) + + if urlconf not in self._urlconfs: + new_urlconf = imp.new_module('urlconf') + new_urlconf.urlpatterns = debug_toolbar.urls.urlpatterns + \ + urlconf.urlpatterns + + if hasattr(urlconf, 'handler404'): + new_urlconf.handler404 = urlconf.handler404 + if hasattr(urlconf, 'handler500'): + new_urlconf.handler500 = urlconf.handler500 + + self._urlconfs[urlconf] = new_urlconf + + request.urlconf = self._urlconfs[urlconf] toolbar = DebugToolbar(request) for panel in toolbar.panels: @@ -119,7 +128,7 @@ class DebugToolbarMiddleware(object): for panel in toolbar.panels: panel.process_response(request, response) response.content = replace_insensitive( - smart_unicode(response.content), + smart_unicode(response.content), self.tag, smart_unicode(toolbar.render_toolbar() + self.tag)) if response.get('Content-Length', None): diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index fa2e4b6..b4f11fb 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -1,48 +1,67 @@ -"""Base DebugPanel class""" +from django.template.defaultfilters import slugify +from django.template.loader import render_to_string +from debug_toolbar.middleware import DebugToolbarMiddleware + class DebugPanel(object): """ Base class for debug panels. """ - # name = Base + # name = 'Base' + # template = 'debug_toolbar/panels/base.html' has_content = False # If content returns something, set to true in subclass - + # We'll maintain a local context instance so we can expose our template # context variables to panels which need them: context = {} - + # Panel methods def __init__(self, context={}): self.context.update(context) - + self.slug = slugify(self.name) + def dom_id(self): return 'djDebug%sPanel' % (self.name.replace(' ', '')) - + def nav_title(self): """Title showing in toolbar""" raise NotImplementedError - + def nav_subtitle(self): """Subtitle showing until title in toolbar""" return '' - + def title(self): """Title showing in panel""" raise NotImplementedError - + def url(self): raise NotImplementedError - + def content(self): - raise NotImplementedError - + if self.has_content: + context = self.context.copy() + context.update(self.get_stats()) + return render_to_string(self.template, context) + + def record_stats(self, stats): + toolbar = DebugToolbarMiddleware.get_current() + panel_stats = toolbar.stats.get(self.slug) + if panel_stats: + panel_stats.update(stats) + else: + toolbar.stats[self.slug] = stats + + def get_stats(self): + toolbar = DebugToolbarMiddleware.get_current() + return toolbar.stats.get(self.slug, {}) + # Standard middleware methods def process_request(self, request): pass - + def process_view(self, request, view_func, view_args, view_kwargs): pass - + def process_response(self, request, response): pass - diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index 5617ec2..620be86 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -3,7 +3,6 @@ import inspect from django.core import cache from django.core.cache.backends.base import BaseCache -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel @@ -12,7 +11,7 @@ class CacheStatTracker(BaseCache): def __init__(self, cache): self.cache = cache self.reset() - + def reset(self): self.calls = [] self.hits = 0 @@ -22,11 +21,11 @@ class CacheStatTracker(BaseCache): self.get_many = 0 self.deletes = 0 self.total_time = 0 - + def _get_func_info(self): stack = inspect.stack()[2] return (stack[1], stack[2], stack[3], stack[4]) - + def get(self, key, default=None): t = time.time() value = self.cache.get(key, default) @@ -39,7 +38,7 @@ class CacheStatTracker(BaseCache): self.gets += 1 self.calls.append((this_time, 'get', (key,), self._get_func_info())) return value - + def set(self, key, value, timeout=None): t = time.time() self.cache.set(key, value, timeout) @@ -47,7 +46,7 @@ class CacheStatTracker(BaseCache): self.total_time += this_time * 1000 self.sets += 1 self.calls.append((this_time, 'set', (key, value, timeout), self._get_func_info())) - + def delete(self, key): t = time.time() self.cache.delete(key) @@ -55,7 +54,7 @@ class CacheStatTracker(BaseCache): self.total_time += this_time * 1000 self.deletes += 1 self.calls.append((this_time, 'delete', (key,), self._get_func_info())) - + def get_many(self, keys): t = time.time() results = self.cache.get_many(keys) @@ -74,10 +73,11 @@ class CacheDebugPanel(DebugPanel): Panel that displays the cache statistics. """ name = 'Cache' + template = 'debug_toolbar/panels/cache.html' has_content = True - + def __init__(self, *args, **kwargs): - super(self.__class__, self).__init__(*args, **kwargs) + super(CacheDebugPanel, self).__init__(*args, **kwargs) # This is hackish but to prevent threading issues is somewhat needed if isinstance(cache.cache, CacheStatTracker): cache.cache.reset() @@ -85,21 +85,19 @@ class CacheDebugPanel(DebugPanel): else: self.cache = CacheStatTracker(cache.cache) cache.cache = self.cache - + def nav_title(self): return _('Cache: %.2fms') % self.cache.total_time - + def title(self): return _('Cache Usage') - + def url(self): return '' - - def content(self): - context = self.context.copy() - context.update({ + + def process_response(self, request, response): + self.record_stats({ 'cache_calls': len(self.cache.calls), 'cache_time': self.cache.total_time, 'cache': self.cache, }) - return render_to_string('debug_toolbar/panels/cache.html', context) diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py index 1e929f6..181e88d 100644 --- a/debug_toolbar/panels/headers.py +++ b/debug_toolbar/panels/headers.py @@ -1,12 +1,13 @@ -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel + class HeaderDebugPanel(DebugPanel): """ A panel to display HTTP headers. """ name = 'Header' + template = 'debug_toolbar/panels/headers.html' has_content = True # List of headers we want to display header_filter = ( @@ -31,24 +32,22 @@ class HeaderDebugPanel(DebugPanel): 'SERVER_PROTOCOL', 'SERVER_SOFTWARE', ) - + def nav_title(self): return _('HTTP Headers') - + def title(self): return _('HTTP Headers') - + def url(self): return '' - + def process_request(self, request): self.headers = dict( [(k, request.META[k]) for k in self.header_filter if k in request.META] ) - - def content(self): - context = self.context.copy() - context.update({ + + def process_response(self, request, response): + self.record_stats({ 'headers': self.headers }) - return render_to_string('debug_toolbar/panels/headers.html', context) diff --git a/debug_toolbar/panels/logger.py b/debug_toolbar/panels/logger.py index 5e82a13..55ae9bd 100644 --- a/debug_toolbar/panels/logger.py +++ b/debug_toolbar/panels/logger.py @@ -4,7 +4,6 @@ try: import threading except ImportError: threading = None -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel @@ -15,15 +14,15 @@ class LogCollector(object): raise NotImplementedError("threading module is not available, \ the logging panel cannot be used without it") self.records = {} # a dictionary that maps threads to log records - + def add_record(self, record, thread=None): # Avoid logging SQL queries since they are already in the SQL panel # TODO: Make this check whether SQL panel is enabled if record.get('channel', '') == 'django.db.backends': return - + self.get_records(thread).append(record) - + def get_records(self, thread=None): """ Returns a list of records for the provided thread, of if none is provided, @@ -34,7 +33,7 @@ class LogCollector(object): if thread not in self.records: self.records[thread] = [] return self.records[thread] - + def clear_records(self, thread=None): if thread is None: thread = threading.currentThread() @@ -46,7 +45,7 @@ class ThreadTrackingHandler(logging.Handler): def __init__(self, collector): logging.Handler.__init__(self) self.collector = collector - + def emit(self, record): record = { 'message': record.getMessage(), @@ -76,7 +75,7 @@ if logbook_supported: def __init__(self, collector): logbook.handlers.Handler.__init__(self, bubble=True) self.collector = collector - + def emit(self, record): record = { 'message': record.message, @@ -87,40 +86,37 @@ if logbook_supported: 'channel': record.channel, } self.collector.add_record(record) - - + + logbook_handler = LogbookThreadTrackingHandler(collector) logbook_handler.push_application() # register with logbook class LoggingPanel(DebugPanel): name = 'Logging' + template = 'debug_toolbar/panels/logger.html' has_content = True - + def process_request(self, request): collector.clear_records() - + + def process_response(self, request, response): + records = self.get_and_delete() + self.record_stats({'records': records}) + def get_and_delete(self): records = collector.get_records() collector.clear_records() return records - + def nav_title(self): return _("Logging") - + def nav_subtitle(self): # FIXME l10n: use ngettext return "%s message%s" % (len(collector.get_records()), (len(collector.get_records()) == 1) and '' or 's') - + def title(self): return _('Log Messages') - + def url(self): return '' - - def content(self): - records = self.get_and_delete() - context = self.context.copy() - context.update({'records': records}) - - return render_to_string('debug_toolbar/panels/logger.html', context) - diff --git a/debug_toolbar/panels/profiling.py b/debug_toolbar/panels/profiling.py index 95a1a4d..8913621 100644 --- a/debug_toolbar/panels/profiling.py +++ b/debug_toolbar/panels/profiling.py @@ -1,13 +1,22 @@ from __future__ import division -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from django.utils.safestring import mark_safe from debug_toolbar.panels import DebugPanel +try: + from line_profiler import LineProfiler, show_func + DJ_PROFILE_USE_LINE_PROFILER = True +except ImportError: + DJ_PROFILE_USE_LINE_PROFILER = False + + +from cStringIO import StringIO import cProfile from pstats import Stats from colorsys import hsv_to_rgb +import os + class DjangoDebugToolbarStats(Stats): __root = None @@ -19,16 +28,11 @@ class DjangoDebugToolbarStats(Stats): self.__root = func break return self.__root - - def print_call_tree_node(self, function, depth, max_depth, cum_filter=0.1): - self.print_line(function, depth=depth) - if depth < max_depth: - for called in self.all_callees[function].keys(): - if self.stats[called][3] >= cum_filter: - self.print_call_tree_node(called, depth+1, max_depth, cum_filter=cum_filter) + class FunctionCall(object): - def __init__(self, statobj, func, depth=0, stats=None, id=0, parent_ids=[], hsv=(0,0.5,1)): + def __init__(self, statobj, func, depth=0, stats=None, + id=0, parent_ids=[], hsv=(0,0.5,1)): self.statobj = statobj self.func = func if stats: @@ -39,6 +43,7 @@ class FunctionCall(object): self.id = id self.parent_ids = parent_ids self.hsv = hsv + self._line_stats_text = None def parent_classes(self): return self.parent_classes @@ -60,9 +65,9 @@ class FunctionCall(object): file_name, line_num, method = self.func idx = file_name.find('/site-packages/') if idx > -1: - file_name=file_name[idx+14:] + file_name = file_name[idx+14:] - file_path, file_name = file_name.rsplit('/', 1) + file_path, file_name = file_name.rsplit(os.sep, 1) return mark_safe('<span class="path">{0}/</span><span class="file">{1}</span> in <span class="func">{3}</span>(<span class="lineno">{2}</span>)'.format( file_path, @@ -73,7 +78,7 @@ class FunctionCall(object): def subfuncs(self): i=0 - h,s,v = self.hsv + h, s, v = self.hsv count = len(self.statobj.all_callees[self.func]) for func, stats in self.statobj.all_callees[self.func].iteritems(): i += 1 @@ -83,8 +88,8 @@ class FunctionCall(object): else: s1 = s*(stats[3]/self.stats[3]) yield FunctionCall(self.statobj, - func, - self.depth+1, + func, + self.depth+1, stats=stats, id=str(self.id) + '_' + str(i), parent_ids=self.parent_ids + [self.id], @@ -102,69 +107,97 @@ class FunctionCall(object): def tottime_per_call(self): cc, nc, tt, ct = self.stats - + if nc == 0: return 0 - + return tt/nc def cumtime_per_call(self): cc, nc, tt, ct = self.stats - + if cc == 0: return 0 - + return ct/cc - + def indent(self): return 16 * self.depth + + def line_stats_text(self): + if self._line_stats_text is None and DJ_PROFILE_USE_LINE_PROFILER: + lstats = self.statobj.line_stats + if self.func in lstats.timings: + out = StringIO() + fn, lineno, name = self.func + show_func(fn, lineno, name, lstats.timings[self.func], lstats.unit, stream=out) + self._line_stats_text = out.getvalue() + else: + self._line_stats_text = False + return self._line_stats_text class ProfilingDebugPanel(DebugPanel): """ Panel that displays the Django version. """ name = 'Profiling' + template = 'debug_toolbar/panels/profiling.html' has_content = True - + def nav_title(self): return _('Profiling') - + def url(self): return '' def title(self): return _('Profiling') - + + def _unwrap_closure_and_profile(self, func): + if not hasattr(func, 'func_code'): + return + self.line_profiler.add_function(func) + if func.func_closure: + for cell in func.func_closure: + if hasattr(cell.cell_contents, 'func_code'): + self._unwrap_closure_and_profile(cell.cell_contents) + def process_view(self, request, view_func, view_args, view_kwargs): __traceback_hide__ = True self.profiler = cProfile.Profile() args = (request,) + view_args - return self.profiler.runcall(view_func, *args, **view_kwargs) - - def process_response(self, request, response): - self.profiler.create_stats() - self.stats = DjangoDebugToolbarStats(self.profiler) - return response - + if DJ_PROFILE_USE_LINE_PROFILER: + self.line_profiler = LineProfiler() + self._unwrap_closure_and_profile(view_func) + self.line_profiler.enable_by_count() + out = self.profiler.runcall(view_func, *args, **view_kwargs) + self.line_profiler.disable_by_count() + else: + self.line_profiler = None + out = self.profiler.runcall(view_func, *args, **view_kwargs) + return out + def add_node(self, func_list, func, max_depth, cum_time=0.1): func_list.append(func) func.has_subfuncs = False if func.depth < max_depth: for subfunc in func.subfuncs(): - if subfunc.stats[3] >= cum_time: + if (subfunc.stats[3] >= cum_time or + (hasattr(self.stats, 'line_stats') and + (subfunc.func in self.stats.line_stats.timings))): func.has_subfuncs = True self.add_node(func_list, subfunc, max_depth, cum_time=cum_time) - def content(self): - + def process_response(self, request, response): + self.profiler.create_stats() + self.stats = DjangoDebugToolbarStats(self.profiler) + if DJ_PROFILE_USE_LINE_PROFILER: + self.stats.line_stats = self.line_profiler.get_stats() self.stats.calc_callees() + root = FunctionCall(self.stats, self.stats.get_root_func(), depth=0) func_list = [] self.add_node(func_list, root, 10, root.stats[3]/8) - context = self.context.copy() - context.update({ - 'func_list': func_list, - }) - - return render_to_string('debug_toolbar/panels/profiling.html', context) + + self.stats_record({'func_list': func_list}) diff --git a/debug_toolbar/panels/request_vars.py b/debug_toolbar/panels/request_vars.py index 632068e..ee9cdc5 100644 --- a/debug_toolbar/panels/request_vars.py +++ b/debug_toolbar/panels/request_vars.py @@ -1,52 +1,59 @@ -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ + from debug_toolbar.panels import DebugPanel +from debug_toolbar.utils import get_name_from_obj class RequestVarsDebugPanel(DebugPanel): """ A panel to display request variables (POST/GET, session, cookies). """ name = 'RequestVars' + template = 'debug_toolbar/panels/request_vars.html' has_content = True - + + def __init__(self, *args, **kwargs): + DebugPanel.__init__(self, *args, **kwargs) + self.view_func = None + self.view_args = None + self.view_kwargs = None + def nav_title(self): return _('Request Vars') - + def title(self): return _('Request Vars') - + def url(self): return '' - + def process_request(self, request): self.request = request - + def process_view(self, request, view_func, view_args, view_kwargs): self.view_func = view_func self.view_args = view_args self.view_kwargs = view_kwargs - - def content(self): - context = self.context.copy() - - if hasattr(self.view_func, '__name__'): - view_name = self.view_func.__name__ - elif hasattr(self.view_func, '__class__'): - view_name = self.view_func.__class__.__name__ - else: - view_name = '<unknown>' - - context.update({ + + def process_response(self, request, response): + self.record_stats({ 'get': [(k, self.request.GET.getlist(k)) for k in self.request.GET], 'post': [(k, self.request.POST.getlist(k)) for k in self.request.POST], 'cookies': [(k, self.request.COOKIES.get(k)) for k in self.request.COOKIES], - 'view_func': '%s.%s' % (self.view_func.__module__, view_name), - 'view_args': self.view_args, - 'view_kwargs': self.view_kwargs }) + + if hasattr(self, 'view_func'): + if self.view_func is not None: + name = get_name_from_obj(self.view_func) + else: + name = '<no view>' + + self.record_stats({ + 'view_func': name, + 'view_args': self.view_args, + 'view_kwargs': self.view_kwargs + }) + if hasattr(self.request, 'session'): - context.update({ + self.record_stats({ 'session': [(k, self.request.session.get(k)) for k in self.request.session.iterkeys()] }) - - return render_to_string('debug_toolbar/panels/request_vars.html', context) diff --git a/debug_toolbar/panels/settings_vars.py b/debug_toolbar/panels/settings_vars.py index ebb4464..e154dda 100644 --- a/debug_toolbar/panels/settings_vars.py +++ b/debug_toolbar/panels/settings_vars.py @@ -1,5 +1,4 @@ from django.conf import settings -from django.template.loader import render_to_string from django.views.debug import get_safe_settings from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel @@ -10,20 +9,19 @@ class SettingsVarsDebugPanel(DebugPanel): A panel to display all variables in django.conf.settings """ name = 'SettingsVars' + template = 'debug_toolbar/panels/settings_vars.html' has_content = True - + def nav_title(self): return _('Settings') - + def title(self): return _('Settings from <code>%s</code>') % settings.SETTINGS_MODULE - + def url(self): return '' - - def content(self): - context = self.context.copy() - context.update({ + + def process_response(self, request, response): + self.record_stats({ 'settings': get_safe_settings(), }) - return render_to_string('debug_toolbar/panels/settings_vars.html', context) diff --git a/debug_toolbar/panels/signals.py b/debug_toolbar/panels/signals.py index dbd3725..205b3c5 100644 --- a/debug_toolbar/panels/signals.py +++ b/debug_toolbar/panels/signals.py @@ -6,7 +6,6 @@ from django.core.signals import request_started, request_finished, \ from django.db.models.signals import class_prepared, pre_init, post_init, \ pre_save, post_save, pre_delete, post_delete, post_syncdb from django.dispatch.dispatcher import WEAKREF_TYPES -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ try: @@ -18,8 +17,9 @@ from debug_toolbar.panels import DebugPanel class SignalDebugPanel(DebugPanel): name = "Signals" + template = 'debug_toolbar/panels/signals.html' has_content = True - + SIGNALS = { 'request_started': request_started, 'request_finished': request_finished, @@ -34,16 +34,16 @@ class SignalDebugPanel(DebugPanel): 'post_delete': post_delete, 'post_syncdb': post_syncdb, } - + def nav_title(self): return _("Signals") - + def title(self): return _("Signals") - + def url(self): return '' - + def signals(self): signals = self.SIGNALS.copy() if hasattr(settings, 'DEBUG_TOOLBAR_CONFIG'): @@ -57,8 +57,8 @@ class SignalDebugPanel(DebugPanel): signals[parts[-1]] = getattr(sys.modules[path], parts[-1]) return signals signals = property(signals) - - def content(self): + + def process_response(self, request, response): signals = [] keys = self.signals.keys() keys.sort() @@ -80,8 +80,5 @@ class SignalDebugPanel(DebugPanel): text = "function %s" % receiver.__name__ receivers.append(text) signals.append((name, signal, receivers)) - - context = self.context.copy() - context.update({'signals': signals}) - - return render_to_string('debug_toolbar/panels/signals.html', context) + + self.record_stats({'signals': signals}) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index c6b5996..b27e6c0 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -2,7 +2,6 @@ import re import uuid from django.db.backends import BaseDatabaseWrapper -from django.template.loader import render_to_string from django.utils.html import escape from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _, ungettext_lazy as __ @@ -14,11 +13,12 @@ from debug_toolbar.utils import sqlparse from debug_toolbar.utils.tracking.db import CursorWrapper from debug_toolbar.utils.tracking import replace_call + # Inject our tracking cursor @replace_call(BaseDatabaseWrapper.cursor) def cursor(func, self): result = func(self) - + djdt = DebugToolbarMiddleware.get_current() if not djdt: return result @@ -26,6 +26,7 @@ def cursor(func, self): return CursorWrapper(result, self, logger=logger) + def get_isolation_level_display(engine, level): if engine == 'psycopg2': import psycopg2.extensions @@ -41,6 +42,7 @@ def get_isolation_level_display(engine, level): return choices.get(level) + def get_transaction_status_display(engine, level): if engine == 'psycopg2': import psycopg2.extensions @@ -56,16 +58,18 @@ def get_transaction_status_display(engine, level): return choices.get(level) + class SQLDebugPanel(DebugPanel): """ Panel that displays information about the SQL queries run while processing the request. """ name = 'SQL' + template = 'debug_toolbar/panels/sql.html' has_content = True - + def __init__(self, *args, **kwargs): - super(self.__class__, self).__init__(*args, **kwargs) + super(SQLDebugPanel, self).__init__(*args, **kwargs) self._offset = dict((k, len(connections[k].queries)) for k in connections) self._sql_time = 0 self._num_queries = 0 @@ -78,20 +82,20 @@ class SQLDebugPanel(DebugPanel): conn = connections[alias].connection if not conn: return None - + engine = conn.__class__.__module__.split('.', 1)[0] if engine == 'psycopg2': cur_status = conn.get_transaction_status() else: raise ValueError(engine) - + last_status = self._transaction_status.get(alias) self._transaction_status[alias] = cur_status - + if not cur_status: # No available state return None - + if cur_status != last_status: if cur_status: self._transaction_ids[alias] = uuid.uuid4().hex @@ -112,10 +116,10 @@ class SQLDebugPanel(DebugPanel): self._databases[alias]['num_queries'] += 1 self._sql_time += kwargs['duration'] self._num_queries += 1 - + def nav_title(self): return _('SQL') - + def nav_subtitle(self): # TODO l10n: use ngettext return "%d %s in %.2fms" % ( @@ -123,18 +127,18 @@ class SQLDebugPanel(DebugPanel): (self._num_queries == 1) and 'query' or 'queries', self._sql_time ) - + def title(self): count = len(self._databases) return __('SQL Queries from %(count)d connection', 'SQL Queries from %(count)d connections', count) % dict( count=count, ) - + def url(self): return '' - - def content(self): + + def process_response(self, request, response): if self._queries: width_ratio_tally = 0 colors = [ @@ -157,7 +161,7 @@ class SQLDebugPanel(DebugPanel): nn = 0 rgb[nn] = nc db['rgb_color'] = rgb - + trans_ids = {} trans_id = None i = 0 @@ -183,30 +187,34 @@ class SQLDebugPanel(DebugPanel): query['rgb_color'] = self._databases[alias]['rgb_color'] try: query['width_ratio'] = (query['duration'] / self._sql_time) * 100 + query['width_ratio_relative'] = 100.0 * query['width_ratio'] / (100.0 - width_ratio_tally) except ZeroDivisionError: query['width_ratio'] = 0 + query['width_ratio_relative'] = 0 query['start_offset'] = width_ratio_tally query['end_offset'] = query['width_ratio'] + query['start_offset'] width_ratio_tally += query['width_ratio'] - + stacktrace = [] for frame in query['stacktrace']: params = map(escape, frame[0].rsplit('/', 1) + list(frame[1:])) - stacktrace.append('<span class="path">{0}/</span><span class="file">{1}</span> in <span class="func">{3}</span>(<span class="lineno">{2}</span>)\n <span class="code">{4}</span>'.format(*params)) + try: + stacktrace.append(u'<span class="path">{0}/</span><span class="file">{1}</span> in <span class="func">{3}</span>(<span class="lineno">{2}</span>)\n <span class="code">{4}</span>'.format(*params)) + except IndexError: + # This frame doesn't have the expected format, so skip it and move on to the next one + continue query['stacktrace'] = mark_safe('\n'.join(stacktrace)) i += 1 - + if trans_id: self._queries[i-1][1]['ends_trans'] = True - context = self.context.copy() - context.update({ + self.record_stats({ 'databases': sorted(self._databases.items(), key=lambda x: -x[1]['time_spent']), 'queries': [q for a, q in self._queries], 'sql_time': self._sql_time, }) - return render_to_string('debug_toolbar/panels/sql.html', context) class BoldKeywordFilter(sqlparse.filters.Filter): """sqlparse filter to bold SQL keywords""" @@ -220,8 +228,11 @@ class BoldKeywordFilter(sqlparse.filters.Filter): if is_keyword: yield sqlparse.tokens.Text, '</strong>' + def swap_fields(sql): - return re.sub('SELECT</strong> (.*) <strong>FROM', 'SELECT</strong> <span class="djDebugCollapse">\g<1></span> <strong>FROM', sql) + return re.sub('SELECT</strong> (.*) <strong>FROM', 'SELECT</strong> <a class="djDebugUncollapsed djDebugToggle" href="#">•••</a> ' + + '<a class="djDebugCollapsed djDebugToggle" href="#">\g<1></a> <strong>FROM', sql) + def reformat_sql(sql): stack = sqlparse.engine.FilterStack() diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py index 44b8b3e..5c20fcd 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template.py @@ -4,10 +4,11 @@ from pprint import pformat from django import http from django.conf import settings from django.template.context import get_standard_processors -from django.template.loader import render_to_string from django.test.signals import template_rendered from django.utils.translation import ugettext_lazy as _ +from django.db.models.query import QuerySet from debug_toolbar.panels import DebugPanel +from debug_toolbar.utils.tracking.db import recording, SQLQueryTriggered # Code taken and adapted from Simon Willison and Django Snippets: # http://www.djangosnippets.org/snippets/766/ @@ -27,6 +28,7 @@ else: Template.original_render = Template._render Template._render = instrumented_test_render + # MONSTER monkey-patch old_template_init = Template.__init__ def new_template_init(self, template_string, origin=None, name='<Unknown Template>'): @@ -34,36 +36,76 @@ def new_template_init(self, template_string, origin=None, name='<Unknown Templat self.origin = origin Template.__init__ = new_template_init + class TemplateDebugPanel(DebugPanel): """ A panel that lists all templates used during processing of a response. """ name = 'Template' + template = 'debug_toolbar/panels/templates.html' has_content = True - + def __init__(self, *args, **kwargs): - super(self.__class__, self).__init__(*args, **kwargs) + super(TemplateDebugPanel, self).__init__(*args, **kwargs) self.templates = [] template_rendered.connect(self._store_template_info) - + def _store_template_info(self, sender, **kwargs): + context_data = kwargs['context'] + + context_list = [] + for context_layer in context_data.dicts: + temp_layer = {} + if hasattr(context_layer, 'items'): + for key, value in context_layer.items(): + # Replace any request elements - they have a large + # unicode representation and the request data is + # already made available from the Request Vars panel. + if isinstance(value, http.HttpRequest): + temp_layer[key] = '<<request>>' + # Replace the debugging sql_queries element. The SQL + # data is already made available from the SQL panel. + elif key == 'sql_queries' and isinstance(value, list): + temp_layer[key] = '<<sql_queries>>' + # Replace LANGUAGES, which is available in i18n context processor + elif key == 'LANGUAGES' and isinstance(value, tuple): + temp_layer[key] = '<<languages>>' + # QuerySet would trigger the database: user can run the query from SQL Panel + elif isinstance(value, QuerySet): + model_name = "%s.%s" % (value.model._meta.app_label, value.model.__name__) + temp_layer[key] = '<<queryset of %s>>' % model_name + else: + try: + recording(False) + pformat(value) # this MAY trigger a db query + except SQLQueryTriggered: + temp_layer[key] = '<<triggers database query>>' + else: + temp_layer[key] = value + finally: + recording(True) + try: + context_list.append(pformat(temp_layer)) + except UnicodeEncodeError: + pass + kwargs['context'] = context_list self.templates.append(kwargs) - + def nav_title(self): return _('Templates') - + def title(self): num_templates = len([t for t in self.templates if not (t['template'].name and t['template'].name.startswith('debug_toolbar/'))]) return _('Templates (%(num_templates)s rendered)') % {'num_templates': num_templates} - + def url(self): return '' - + def process_request(self, request): self.request = request - - def content(self): + + def process_response(self, request, response): context_processors = dict( [ ("%s.%s" % (k.__module__, k.__name__), @@ -78,6 +120,8 @@ class TemplateDebugPanel(DebugPanel): # Skip templates that we are generating through the debug toolbar. if template.name and template.name.startswith('debug_toolbar/'): continue + if not hasattr(template, 'origin'): + continue if template.origin and template.origin.name: template.origin_name = template.origin.name else: @@ -85,36 +129,12 @@ class TemplateDebugPanel(DebugPanel): info['template'] = template # Clean up context for better readability if getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}).get('SHOW_TEMPLATE_CONTEXT', True): - context_data = template_data.get('context', None) - - context_list = [] - for context_layer in context_data.dicts: - if hasattr(context_layer, 'items'): - for key, value in context_layer.items(): - # Replace any request elements - they have a large - # unicode representation and the request data is - # already made available from the Request Vars panel. - if isinstance(value, http.HttpRequest): - context_layer[key] = '<<request>>' - # Replace the debugging sql_queries element. The SQL - # data is already made available from the SQL panel. - elif key == 'sql_queries' and isinstance(value, list): - context_layer[key] = '<<sql_queries>>' - # Replace LANGUAGES, which is available in i18n context processor - elif key == 'LANGUAGES' and isinstance(value, tuple): - context_layer[key] = '<<languages>>' - try: - context_list.append(pformat(context_layer)) - except UnicodeEncodeError: - pass + context_list = template_data.get('context', []) info['context'] = '\n'.join(context_list) template_context.append(info) - - context = self.context.copy() - context.update({ + + self.record_stats({ 'templates': template_context, 'template_dirs': [normpath(x) for x in settings.TEMPLATE_DIRS], 'context_processors': context_processors, }) - - return render_to_string('debug_toolbar/panels/templates.html', context) diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py index d866166..7c0febf 100644 --- a/debug_toolbar/panels/timer.py +++ b/debug_toolbar/panels/timer.py @@ -7,11 +7,13 @@ from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ from debug_toolbar.panels import DebugPanel + class TimerDebugPanel(DebugPanel): """ Panel that displays the time a response took in milliseconds. """ name = 'Timer' + template = 'debug_toolbar/panels/timer.html' try: # if resource module not available, don't show content panel resource except NameError: @@ -20,47 +22,23 @@ class TimerDebugPanel(DebugPanel): else: has_content = True has_resource = True - + def process_request(self, request): self._start_time = time.time() if self.has_resource: self._start_rusage = resource.getrusage(resource.RUSAGE_SELF) - + def process_response(self, request, response): - self.total_time = (time.time() - self._start_time) * 1000 + total_time = (time.time() - self._start_time) * 1000 if self.has_resource: self._end_rusage = resource.getrusage(resource.RUSAGE_SELF) - - def nav_title(self): - return _('Time') - - def nav_subtitle(self): - # TODO l10n - if self.has_resource: - utime = self._end_rusage.ru_utime - self._start_rusage.ru_utime - stime = self._end_rusage.ru_stime - self._start_rusage.ru_stime - return 'CPU: %0.2fms (%0.2fms)' % ((utime + stime) * 1000.0, self.total_time) - else: - return 'TOTAL: %0.2fms' % (self.total_time) - - def title(self): - return _('Resource Usage') - - def url(self): - return '' - - def _elapsed_ru(self, name): - return getattr(self._end_rusage, name) - getattr(self._start_rusage, name) - - def content(self): - + utime = 1000 * self._elapsed_ru('ru_utime') stime = 1000 * self._elapsed_ru('ru_stime') vcsw = self._elapsed_ru('ru_nvcsw') ivcsw = self._elapsed_ru('ru_nivcsw') minflt = self._elapsed_ru('ru_minflt') majflt = self._elapsed_ru('ru_majflt') - # these are documented as not meaningful under Linux. If you're running BSD # feel free to enable them, and add any others that I hadn't gotten to before # I noticed that I was getting nothing but zeroes and that the docs agreed. :-( @@ -72,22 +50,63 @@ class TimerDebugPanel(DebugPanel): # srss = self._end_rusage.ru_ixrss # urss = self._end_rusage.ru_idrss # usrss = self._end_rusage.ru_isrss - + + self.record_stats({ + 'total_time': total_time, + 'utime': utime, + 'stime': stime, + 'vcsw': vcsw, + 'ivcsw': ivcsw, + 'minflt': minflt, + 'majflt': majflt, +# 'blkin': blkin, +# 'blkout': blkout, +# 'swap': swap, +# 'rss': rss, +# 'urss': urss, +# 'srss': srss, +# 'usrss': usrss, + }) + + def nav_title(self): + return _('Time') + + def nav_subtitle(self): + stats = self.get_stats() + + # TODO l10n + if self.has_resource: + utime = self._end_rusage.ru_utime - self._start_rusage.ru_utime + stime = self._end_rusage.ru_stime - self._start_rusage.ru_stime + return 'CPU: %0.2fms (%0.2fms)' % ((utime + stime) * 1000.0, stats['total_time']) + else: + return 'TOTAL: %0.2fms' % (stats['total_time']) + + def title(self): + return _('Resource Usage') + + def url(self): + return '' + + def _elapsed_ru(self, name): + return getattr(self._end_rusage, name) - getattr(self._start_rusage, name) + + def content(self): + stats = self.get_stats() + # TODO l10n on values rows = ( - (_('User CPU time'), '%0.3f msec' % utime), - (_('System CPU time'), '%0.3f msec' % stime), - (_('Total CPU time'), '%0.3f msec' % (utime + stime)), - (_('Elapsed time'), '%0.3f msec' % self.total_time), - (_('Context switches'), '%d voluntary, %d involuntary' % (vcsw, ivcsw)), -# ('Memory use', '%d max RSS, %d shared, %d unshared' % (rss, srss, urss + usrss)), -# ('Page faults', '%d no i/o, %d requiring i/o' % (minflt, majflt)), -# ('Disk operations', '%d in, %d out, %d swapout' % (blkin, blkout, swap)), + (_('User CPU time'), '%0.3f msec' % stats['utime']), + (_('System CPU time'), '%0.3f msec' % stats['stime']), + (_('Total CPU time'), '%0.3f msec' % (stats['utime'] + stats['stime'])), + (_('Elapsed time'), '%0.3f msec' % stats['total_time']), + (_('Context switches'), '%d voluntary, %d involuntary' % (stats['vcsw'], stats['ivcsw'])), +# ('Memory use', '%d max RSS, %d shared, %d unshared' % (stats['rss'], stats.['srss'], +# stats['urss'] + stats['usrss'])), +# ('Page faults', '%d no i/o, %d requiring i/o' % (stats['minflt'], stats['majflt'])), +# ('Disk operations', '%d in, %d out, %d swapout' % (stats['blkin'], stats['blkout'], stats['swap'])), ) - + context = self.context.copy() - context.update({ - 'rows': rows, - }) - - return render_to_string('debug_toolbar/panels/timer.html', context) + context.update({'rows': rows,}) + return render_to_string(self.template, context) diff --git a/debug_toolbar/panels/version.py b/debug_toolbar/panels/version.py index f0d8fbc..4e58971 100644 --- a/debug_toolbar/panels/version.py +++ b/debug_toolbar/panels/version.py @@ -2,10 +2,8 @@ import sys import django from django.conf import settings -from django.template.loader import render_to_string from django.utils.translation import ugettext_lazy as _ -import debug_toolbar from debug_toolbar.panels import DebugPanel @@ -14,21 +12,22 @@ class VersionDebugPanel(DebugPanel): Panel that displays the Django version. """ name = 'Version' + template = 'debug_toolbar/panels/versions.html' has_content = True - + def nav_title(self): return _('Versions') - + def nav_subtitle(self): return 'Django %s' % django.get_version() - + def url(self): return '' def title(self): return _('Versions') - - def content(self): + + def process_response(self, request, response): versions = {} versions['Python'] = '%d.%d.%d' % sys.version_info[:3] for app in settings.INSTALLED_APPS + ['django']: @@ -50,11 +49,8 @@ class VersionDebugPanel(DebugPanel): if isinstance(version, (list, tuple)): version = '.'.join(str(o) for o in version) versions[name] = version - - context = self.context.copy() - context.update({ + + self.record_stats({ 'versions': versions, 'paths': sys.path, }) - - return render_to_string('debug_toolbar/panels/versions.html', context) diff --git a/debug_toolbar/runtests.py b/debug_toolbar/runtests.py deleted file mode 100644 index f16882a..0000000 --- a/debug_toolbar/runtests.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -import sys -from os.path import dirname, abspath - -from django.conf import settings - -if not settings.configured: - settings.configure( - DATABASE_ENGINE='sqlite3', - # HACK: this fixes our threaded runserver remote tests - # DATABASE_NAME='test_sentry', - # TEST_DATABASE_NAME='test_sentry', - INSTALLED_APPS=[ - 'django.contrib.auth', - 'django.contrib.admin', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - - 'debug_toolbar', - - 'debug_toolbar.tests', - ], - ROOT_URLCONF='', - DEBUG=False, - SITE_ID=1, - ) - import djcelery - djcelery.setup_loader() - -from django.test.simple import run_tests - -def runtests(*test_args): - if 'south' in settings.INSTALLED_APPS: - from south.management.commands import patch_for_test_db_setup - patch_for_test_db_setup() - - if not test_args: - test_args = ['debug_toolbar'] - parent = dirname(abspath(__file__)) - sys.path.insert(0, parent) - failures = run_tests(test_args, verbosity=1, interactive=True) - sys.exit(failures) - - -if __name__ == '__main__': - runtests(*sys.argv[1:])
\ No newline at end of file diff --git a/debug_toolbar/templates/debug_toolbar/panels/profiling.html b/debug_toolbar/templates/debug_toolbar/panels/profiling.html index ebc91cc..f2d43de 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/profiling.html +++ b/debug_toolbar/templates/debug_toolbar/panels/profiling.html @@ -4,17 +4,17 @@ <thead> <tr> <th>{% trans "Call" %}</th> - <th>{% trans "TotTime" %}</th> - <th>{% trans "Per" %}</th> <th>{% trans "CumTime" %}</th> <th>{% trans "Per" %}</th> + <th>{% trans "TotTime" %}</th> + <th>{% trans "Per" %}</th> <th>{% trans "Count" %}</th> </tr> </thead> <tbody> {% for call in func_list %} <!-- style="background:{{ call.background }}" --> - <tr id="{{ call.id }}" class="djDebugProfileRow{% for parent_id in call.parent_ids %} djToggleDetails_{{ parent_id }}{% endfor %}" depth="{{ call.depth }}"> + <tr class="djDebugProfileRow{% for parent_id in call.parent_ids %} djToggleDetails_{{ parent_id }}{% endfor %}" depth="{{ call.depth }}"> <td> <div style="padding-left: {{ call.indent }}px;"> {% if call.has_subfuncs %} @@ -25,12 +25,19 @@ <span class="stack">{{ call.func_std_string }}</span> </div> </td> - <td>{{ call.tottime|floatformat:3 }}</td> - <td>{{ call.tottime_per_call|floatformat:3 }}</td> <td>{{ call.cumtime|floatformat:3 }}</td> <td>{{ call.cumtime_per_call|floatformat:3 }}</td> + <td>{{ call.tottime|floatformat:3 }}</td> + <td>{{ call.tottime_per_call|floatformat:3 }}</td> <td>{{ call.count }}</td> </tr> + {% if call.line_stats_text %} + <tr class="djToggleDetails_{{ call.id }}{% for parent_id in call.parent_ids %} djToggleDetails_{{ parent_id }}{% endfor %}"> + <td colspan="6"> + <div style="padding-left: {{ call.indent }}px;"><pre>{{ call.line_stats_text }}</pre></div> + </td> + </tr> + {% endif %} {% endfor %} </tbody> -</table> +</table>
\ No newline at end of file diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql.html b/debug_toolbar/templates/debug_toolbar/panels/sql.html index f6f231c..9b282ca 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/sql.html +++ b/debug_toolbar/templates/debug_toolbar/panels/sql.html @@ -1,4 +1,5 @@ {% load i18n %} +{% load debug_toolbar_utils %} <div class="clearfix"> <ul class="stats"> {% for alias, info in databases %} @@ -34,7 +35,7 @@ </div> </td> <td class="timeline"> - <div class="djDebugTimeline"><div class="djDebugLineChart{% if query.is_slow %} djDebugLineChartWarning{% endif %}" style="left:{{ query.start_offset }}%;"><strong style="width:{{ query.width_ratio }}%;">{{ query.width_ratio }}%</strong></div></div> + <div class="djDebugTimeline"><div class="djDebugLineChart{% if query.is_slow %} djDebugLineChartWarning{% endif %}" style="left:{{ query.start_offset|dotted_number }}%;"><strong style="width:{{ query.width_ratio_relative|dotted_number }}%;">{{ query.width_ratio }}%</strong></div></div> </td> <td class="time"> {{ query.duration|floatformat:"2" }} diff --git a/debug_toolbar/tests/templates/404.html b/debug_toolbar/templatetags/__init__.py index e69de29..e69de29 100644 --- a/debug_toolbar/tests/templates/404.html +++ b/debug_toolbar/templatetags/__init__.py diff --git a/debug_toolbar/templatetags/debug_toolbar_utils.py b/debug_toolbar/templatetags/debug_toolbar_utils.py new file mode 100644 index 0000000..6b204eb --- /dev/null +++ b/debug_toolbar/templatetags/debug_toolbar_utils.py @@ -0,0 +1,11 @@ + +from django import template +from django.utils.numberformat import format + +register = template.Library() + +@register.filter +def dotted_number(number): + number = float(number) + return format(number, '.', 6) + diff --git a/debug_toolbar/tests/__init__.py b/debug_toolbar/tests/__init__.py deleted file mode 100644 index f853b10..0000000 --- a/debug_toolbar/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from tests import *
\ No newline at end of file diff --git a/debug_toolbar/tests/tests.py b/debug_toolbar/tests/tests.py deleted file mode 100644 index fe1904a..0000000 --- a/debug_toolbar/tests/tests.py +++ /dev/null @@ -1,174 +0,0 @@ -from debug_toolbar.middleware import DebugToolbarMiddleware -from debug_toolbar.panels.sql import SQLDebugPanel -from debug_toolbar.toolbar.loader import DebugToolbar -from debug_toolbar.utils.tracking import pre_dispatch, post_dispatch, callbacks - -from django.contrib.auth.models import User -from django.test import TestCase - -from dingus import Dingus -import thread - -class BaseTestCase(TestCase): - def setUp(self): - request = Dingus('request') - toolbar = DebugToolbar(request) - DebugToolbarMiddleware.debug_toolbars[thread.get_ident()] = toolbar - self.toolbar = toolbar - -class DebugToolbarTestCase(BaseTestCase): - urls = 'debug_toolbar.tests.urls' - - def test_middleware(self): - resp = self.client.get('/execute_sql/') - self.assertEquals(resp.status_code, 200) - -class SQLPanelTestCase(BaseTestCase): - def test_recording(self): - panel = self.toolbar.get_panel(SQLDebugPanel) - self.assertEquals(len(panel._queries), 0) - - list(User.objects.all()) - - # ensure query was logged - self.assertEquals(len(panel._queries), 1) - query = panel._queries[0] - self.assertEquals(query[0], 'default') - self.assertTrue('sql' in query[1]) - self.assertTrue('duration' in query[1]) - self.assertTrue('stacktrace' in query[1]) - -def module_func(*args, **kwargs): - """Used by dispatch tests""" - return 'blah' - -class TrackingTestCase(BaseTestCase): - @classmethod - def class_method(cls, *args, **kwargs): - return 'blah' - - def class_func(self, *args, **kwargs): - """Used by dispatch tests""" - return 'blah' - - def test_pre_hook(self): - foo = {} - - @pre_dispatch(module_func) - def test(**kwargs): - foo.update(kwargs) - - self.assertTrue(hasattr(module_func, '__wrapped__')) - self.assertEquals(len(callbacks['before']), 1) - - module_func('hi', foo='bar') - - self.assertTrue('sender' in foo, foo) - # best we can do - self.assertEquals(foo['sender'].__name__, 'module_func') - self.assertTrue('start' in foo, foo) - self.assertTrue(foo['start'] > 0) - self.assertTrue('stop' not in foo, foo) - self.assertTrue('args' in foo, foo) - self.assertTrue(len(foo['args']), 1) - self.assertEquals(foo['args'][0], 'hi') - self.assertTrue('kwargs' in foo, foo) - self.assertTrue(len(foo['kwargs']), 1) - self.assertTrue('foo' in foo['kwargs']) - self.assertEquals(foo['kwargs']['foo'], 'bar') - - callbacks['before'] = {} - - @pre_dispatch(TrackingTestCase.class_func) - def test(**kwargs): - foo.update(kwargs) - - self.assertTrue(hasattr(TrackingTestCase.class_func, '__wrapped__')) - self.assertEquals(len(callbacks['before']), 1) - - self.class_func('hello', foo='bar') - - self.assertTrue('sender' in foo, foo) - # best we can do - self.assertEquals(foo['sender'].__name__, 'class_func') - self.assertTrue('start' in foo, foo) - self.assertTrue(foo['start'] > 0) - self.assertTrue('stop' not in foo, foo) - self.assertTrue('args' in foo, foo) - self.assertTrue(len(foo['args']), 2) - self.assertEquals(foo['args'][1], 'hello') - self.assertTrue('kwargs' in foo, foo) - self.assertTrue(len(foo['kwargs']), 1) - self.assertTrue('foo' in foo['kwargs']) - self.assertEquals(foo['kwargs']['foo'], 'bar') - - # callbacks['before'] = {} - # - # @pre_dispatch(TrackingTestCase.class_method) - # def test(**kwargs): - # foo.update(kwargs) - # - # self.assertTrue(hasattr(TrackingTestCase.class_method, '__wrapped__')) - # self.assertEquals(len(callbacks['before']), 1) - # - # TrackingTestCase.class_method() - # - # self.assertTrue('sender' in foo, foo) - # # best we can do - # self.assertEquals(foo['sender'].__name__, 'class_method') - # self.assertTrue('start' in foo, foo) - # self.assertTrue('stop' not in foo, foo) - # self.assertTrue('args' in foo, foo) - - def test_post_hook(self): - foo = {} - - @post_dispatch(module_func) - def test(**kwargs): - foo.update(kwargs) - - self.assertTrue(hasattr(module_func, '__wrapped__')) - self.assertEquals(len(callbacks['after']), 1) - - module_func('hi', foo='bar') - - self.assertTrue('sender' in foo, foo) - # best we can do - self.assertEquals(foo['sender'].__name__, 'module_func') - self.assertTrue('start' in foo, foo) - self.assertTrue(foo['start'] > 0) - self.assertTrue('stop' in foo, foo) - self.assertTrue(foo['stop'] > foo['start']) - self.assertTrue('args' in foo, foo) - self.assertTrue(len(foo['args']), 1) - self.assertEquals(foo['args'][0], 'hi') - self.assertTrue('kwargs' in foo, foo) - self.assertTrue(len(foo['kwargs']), 1) - self.assertTrue('foo' in foo['kwargs']) - self.assertEquals(foo['kwargs']['foo'], 'bar') - - callbacks['after'] = {} - - @post_dispatch(TrackingTestCase.class_func) - def test(**kwargs): - foo.update(kwargs) - - self.assertTrue(hasattr(TrackingTestCase.class_func, '__wrapped__')) - self.assertEquals(len(callbacks['after']), 1) - - self.class_func('hello', foo='bar') - - self.assertTrue('sender' in foo, foo) - # best we can do - self.assertEquals(foo['sender'].__name__, 'class_func') - self.assertTrue('start' in foo, foo) - self.assertTrue(foo['start'] > 0) - self.assertTrue('stop' in foo, foo) - self.assertTrue(foo['stop'] > foo['start']) - self.assertTrue('args' in foo, foo) - self.assertTrue(len(foo['args']), 2) - self.assertEquals(foo['args'][1], 'hello') - self.assertTrue('kwargs' in foo, foo) - self.assertTrue(len(foo['kwargs']), 1) - self.assertTrue('foo' in foo['kwargs']) - self.assertEquals(foo['kwargs']['foo'], 'bar')
\ No newline at end of file diff --git a/debug_toolbar/tests/urls.py b/debug_toolbar/tests/urls.py deleted file mode 100644 index 7c99b03..0000000 --- a/debug_toolbar/tests/urls.py +++ /dev/null @@ -1,14 +0,0 @@ -""" -URLpatterns for the debug toolbar. - -These should not be loaded explicitly; the debug toolbar middleware will patch -this into the urlconf for the request. -""" -from django.conf.urls.defaults import * -from django.contrib import admin - -admin.autodiscover() - -urlpatterns = patterns('', - url(r'^execute_sql/$', 'debug_toolbar.tests.views.execute_sql'), -) diff --git a/debug_toolbar/tests/views.py b/debug_toolbar/tests/views.py deleted file mode 100644 index f989dcd..0000000 --- a/debug_toolbar/tests/views.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.contrib.auth.models import User -from django.http import HttpResponse - -def execute_sql(request): - list(User.objects.all()) - - return HttpResponse()
\ No newline at end of file diff --git a/debug_toolbar/toolbar/loader.py b/debug_toolbar/toolbar/loader.py index 3501c69..cf7a243 100644 --- a/debug_toolbar/toolbar/loader.py +++ b/debug_toolbar/toolbar/loader.py @@ -9,7 +9,7 @@ from django.utils.datastructures import SortedDict from django.utils.safestring import mark_safe class DebugToolbar(object): - + def __init__(self, request): self.request = request self._panels = SortedDict() @@ -38,25 +38,26 @@ class DebugToolbar(object): 'debug_toolbar.panels.logger.LoggingPanel', ) self.load_panels() + self.stats = {} def _get_panels(self): return self._panels.values() panels = property(_get_panels) - + def get_panel(self, cls): return self._panels[cls] - + def load_panels(self): """ Populate debug panels """ from django.conf import settings from django.core import exceptions - + # Check if settings has a DEBUG_TOOLBAR_PANELS, otherwise use default if hasattr(settings, 'DEBUG_TOOLBAR_PANELS'): self.default_panels = settings.DEBUG_TOOLBAR_PANELS - + for panel_path in self.default_panels: try: dot = panel_path.rindex('.') @@ -71,14 +72,14 @@ class DebugToolbar(object): panel_class = getattr(mod, panel_classname) except AttributeError: raise exceptions.ImproperlyConfigured, 'Toolbar Panel module "%s" does not define a "%s" class' % (panel_module, panel_classname) - + try: panel_instance = panel_class(context=self.template_context) except: raise # Bubble up problem loading panel - + self._panels[panel_class] = panel_instance - + def render_toolbar(self): """ Renders the overall Toolbar with panels inside. @@ -91,5 +92,5 @@ class DebugToolbar(object): 'js': mark_safe(open(os.path.join(media_path, 'js', 'toolbar.min.js'), 'r').read()), 'css': mark_safe(open(os.path.join(media_path, 'css', 'toolbar.min.css'), 'r').read()), }) - + return render_to_string('debug_toolbar/base.html', context) diff --git a/debug_toolbar/utils/__init__.py b/debug_toolbar/utils/__init__.py index 3f035e6..c4dc160 100644 --- a/debug_toolbar/utils/__init__.py +++ b/debug_toolbar/utils/__init__.py @@ -36,14 +36,18 @@ def tidy_stacktrace(stack): continue if socketserver_path in s_path: continue - trace.append((path, line_no, func_name, (''.join(text)).strip())) + if not text: + text = '' + else: + text = (''.join(text)).strip() + trace.append((path, line_no, func_name, text)) return trace def get_template_info(source, context_lines=3): line = 0 upto = 0 source_lines = [] - before = during = after = "" + # before = during = after = "" origin, (start, end) = source template_source = origin.reload() @@ -51,9 +55,9 @@ def get_template_info(source, context_lines=3): for num, next in enumerate(linebreak_iter(template_source)): if start >= upto and end <= next: line = num - before = template_source[upto:start] - during = template_source[start:end] - after = template_source[end:next] + # before = template_source[upto:start] + # during = template_source[start:end] + # after = template_source[end:next] source_lines.append((num, template_source[upto:next])) upto = next @@ -71,4 +75,18 @@ def get_template_info(source, context_lines=3): return { 'name': origin.name, 'context': context, - }
\ No newline at end of file + } + +def get_name_from_obj(obj): + if hasattr(obj, '__name__'): + name = obj.__name__ + elif hasattr(obj, '__class__') and hasattr(obj.__class__, '__name__'): + name = obj.__class__.__name__ + else: + name = '<unknown>' + + if hasattr(obj, '__module__'): + module = obj.__module__ + name = '%s.%s' % (module, name) + + return name
\ No newline at end of file diff --git a/debug_toolbar/utils/sqlparse/__init__.py b/debug_toolbar/utils/sqlparse/__init__.py index 69873ca..99db30e 100644 --- a/debug_toolbar/utils/sqlparse/__init__.py +++ b/debug_toolbar/utils/sqlparse/__init__.py @@ -6,10 +6,7 @@ """Parse SQL statements.""" -__version__ = '0.1.1' - - -import os +__version__ = '0.1.3' class SQLParseError(Exception): @@ -56,4 +53,3 @@ def split(sql): stack = engine.FilterStack() stack.split_statements = True return [unicode(stmt) for stmt in stack.run(sql)] - diff --git a/debug_toolbar/utils/sqlparse/engine/__init__.py b/debug_toolbar/utils/sqlparse/engine/__init__.py index cae0793..e838a3e 100644 --- a/debug_toolbar/utils/sqlparse/engine/__init__.py +++ b/debug_toolbar/utils/sqlparse/engine/__init__.py @@ -5,9 +5,7 @@ """filter""" -import re - -from debug_toolbar.utils.sqlparse import lexer, SQLParseError +from debug_toolbar.utils.sqlparse import lexer from debug_toolbar.utils.sqlparse.engine import grouping from debug_toolbar.utils.sqlparse.engine.filter import StatementFilter @@ -42,8 +40,8 @@ class FilterStack(object): stream = lexer.tokenize(sql) # Process token stream if self.preprocess: - for filter_ in self.preprocess: - stream = filter_.process(self, stream) + for filter_ in self.preprocess: + stream = filter_.process(self, stream) if (self.stmtprocess or self.postprocess or self.split_statements or self._grouping): @@ -51,6 +49,7 @@ class FilterStack(object): stream = splitter.process(self, stream) if self._grouping: + def _group(stream): for stmt in stream: grouping.group(stmt) @@ -58,23 +57,24 @@ class FilterStack(object): stream = _group(stream) if self.stmtprocess: - def _run(stream): + + def _run1(stream): ret = [] for stmt in stream: for filter_ in self.stmtprocess: filter_.process(self, stmt) ret.append(stmt) return ret - stream = _run(stream) + stream = _run1(stream) if self.postprocess: - def _run(stream): + + def _run2(stream): for stmt in stream: stmt.tokens = list(self._flatten(stmt.tokens)) for filter_ in self.postprocess: stmt = filter_.process(self, stmt) yield stmt - stream = _run(stream) + stream = _run2(stream) return stream - diff --git a/debug_toolbar/utils/sqlparse/engine/filter.py b/debug_toolbar/utils/sqlparse/engine/filter.py index 8d1c7b2..c1c0d6a 100644 --- a/debug_toolbar/utils/sqlparse/engine/filter.py +++ b/debug_toolbar/utils/sqlparse/engine/filter.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- +from debug_toolbar.utils.sqlparse.sql import Statement, Token from debug_toolbar.utils.sqlparse import tokens as T -from debug_toolbar.utils.sqlparse.engine.grouping import Statement, Token class TokenFilter(object): @@ -21,11 +21,13 @@ class StatementFilter(TokenFilter): self._in_declare = False self._in_dbldollar = False self._is_create = False + self._begin_depth = 0 def _reset(self): self._in_declare = False self._in_dbldollar = False self._is_create = False + self._begin_depth = 0 def _change_splitlevel(self, ttype, value): # PostgreSQL @@ -41,29 +43,32 @@ class StatementFilter(TokenFilter): return 0 # ANSI - if ttype is not T.Keyword: + if ttype not in T.Keyword: return 0 unified = value.upper() - if unified == 'DECLARE': + if unified == 'DECLARE' and self._is_create: self._in_declare = True return 1 if unified == 'BEGIN': - if self._in_declare: + self._begin_depth += 1 + if self._in_declare: # FIXME(andi): This makes no sense. return 0 return 0 if unified == 'END': # Should this respect a preceeding BEGIN? # In CASE ... WHEN ... END this results in a split level -1. + self._begin_depth = max(0, self._begin_depth-1) return -1 if ttype is T.Keyword.DDL and unified.startswith('CREATE'): self._is_create = True + return 0 - if unified in ('IF', 'FOR') and self._is_create: + if unified in ('IF', 'FOR') and self._is_create and self._begin_depth > 0: return 1 # Default diff --git a/debug_toolbar/utils/sqlparse/engine/grouping.py b/debug_toolbar/utils/sqlparse/engine/grouping.py index 532ccec..4e50c7b 100644 --- a/debug_toolbar/utils/sqlparse/engine/grouping.py +++ b/debug_toolbar/utils/sqlparse/engine/grouping.py @@ -1,16 +1,19 @@ # -*- coding: utf-8 -*- import itertools -import re -import types +from debug_toolbar.utils.sqlparse import sql from debug_toolbar.utils.sqlparse import tokens as T -from debug_toolbar.utils.sqlparse.sql import * +try: + next +except NameError: # Python < 2.6 + next = lambda i: i.next() def _group_left_right(tlist, ttype, value, cls, check_right=lambda t: True, + check_left=lambda t: True, include_semicolon=False): [_group_left_right(sgroup, ttype, value, cls, check_right, include_semicolon) for sgroup in tlist.get_sublists() @@ -20,14 +23,20 @@ def _group_left_right(tlist, ttype, value, cls, while token: right = tlist.token_next(tlist.token_index(token)) left = tlist.token_prev(tlist.token_index(token)) - if (right is None or not check_right(right) - or left is None): - token = tlist.token_next_match(tlist.token_index(token)+1, + if right is None or not check_right(right): + token = tlist.token_next_match(tlist.token_index(token) + 1, + ttype, value) + elif left is None or not check_right(left): + token = tlist.token_next_match(tlist.token_index(token) + 1, ttype, value) else: if include_semicolon: - right = tlist.token_next_match(tlist.token_index(right), - T.Punctuation, ';') + sright = tlist.token_next_match(tlist.token_index(right), + T.Punctuation, ';') + if sright is not None: + # only overwrite "right" if a semicolon is actually + # present. + right = sright tokens = tlist.tokens_between(left, right)[1:] if not isinstance(left, cls): new = cls([left]) @@ -38,9 +47,10 @@ def _group_left_right(tlist, ttype, value, cls, left.tokens.extend(tokens) for t in tokens: tlist.tokens.remove(t) - token = tlist.token_next_match(tlist.token_index(left)+1, + token = tlist.token_next_match(tlist.token_index(left) + 1, ttype, value) + def _group_matching(tlist, start_ttype, start_value, end_ttype, end_value, cls, include_semicolon=False, recurse=False): def _find_matching(i, tl, stt, sva, ett, eva): @@ -66,7 +76,7 @@ def _group_matching(tlist, start_ttype, start_value, end_ttype, end_value, end = _find_matching(tidx, tlist, start_ttype, start_value, end_ttype, end_value) if end is None: - idx = tidx+1 + idx = tidx + 1 else: if include_semicolon: next_ = tlist.token_next(tlist.token_index(end)) @@ -75,71 +85,102 @@ def _group_matching(tlist, start_ttype, start_value, end_ttype, end_value, group = tlist.group_tokens(cls, tlist.tokens_between(token, end)) _group_matching(group, start_ttype, start_value, end_ttype, end_value, cls, include_semicolon) - idx = tlist.token_index(group)+1 + idx = tlist.token_index(group) + 1 token = tlist.token_next_match(idx, start_ttype, start_value) + def group_if(tlist): - _group_matching(tlist, T.Keyword, 'IF', T.Keyword, 'END IF', If, True) + _group_matching(tlist, T.Keyword, 'IF', T.Keyword, 'END IF', sql.If, True) + def group_for(tlist): - _group_matching(tlist, T.Keyword, 'FOR', T.Keyword, 'END LOOP', For, True) + _group_matching(tlist, T.Keyword, 'FOR', T.Keyword, 'END LOOP', + sql.For, True) + def group_as(tlist): - _group_left_right(tlist, T.Keyword, 'AS', Identifier) + + def _right_valid(token): + # Currently limited to DML/DDL. Maybe additional more non SQL reserved + # keywords should appear here (see issue8). + return not token.ttype in (T.DML, T.DDL) + _group_left_right(tlist, T.Keyword, 'AS', sql.Identifier, + check_right=_right_valid) + def group_assignment(tlist): - _group_left_right(tlist, T.Assignment, ':=', Assignment, + _group_left_right(tlist, T.Assignment, ':=', sql.Assignment, include_semicolon=True) -def group_comparsion(tlist): - _group_left_right(tlist, T.Operator, None, Comparsion) + +def group_comparison(tlist): + + def _parts_valid(token): + return (token.ttype in (T.String.Symbol, T.Name, T.Number, + T.Number.Integer, T.Literal, + T.Literal.Number.Integer) + or isinstance(token, (sql.Identifier,))) + _group_left_right(tlist, T.Operator.Comparison, None, sql.Comparison, + check_left=_parts_valid, check_right=_parts_valid) def group_case(tlist): - _group_matching(tlist, T.Keyword, 'CASE', T.Keyword, 'END', Case, + _group_matching(tlist, T.Keyword, 'CASE', T.Keyword, 'END', sql.Case, include_semicolon=True, recurse=True) def group_identifier(tlist): def _consume_cycle(tl, i): - x = itertools.cycle((lambda y: y.match(T.Punctuation, '.'), - lambda y: y.ttype in (T.String.Symbol, - T.Name, - T.Wildcard))) + x = itertools.cycle(( + lambda y: (y.match(T.Punctuation, '.') + or y.ttype is T.Operator), + lambda y: (y.ttype in (T.String.Symbol, + T.Name, + T.Wildcard, + T.Literal.Number.Integer)))) for t in tl.tokens[i:]: - if x.next()(t): + if next(x)(t): yield t else: raise StopIteration # bottom up approach: group subgroups first [group_identifier(sgroup) for sgroup in tlist.get_sublists() - if not isinstance(sgroup, Identifier)] + if not isinstance(sgroup, sql.Identifier)] # real processing idx = 0 - token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name)) + token = tlist.token_next_by_instance(idx, sql.Function) + if token is None: + token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name)) while token: - identifier_tokens = [token]+list( + identifier_tokens = [token] + list( _consume_cycle(tlist, - tlist.token_index(token)+1)) - group = tlist.group_tokens(Identifier, identifier_tokens) - idx = tlist.token_index(group)+1 - token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name)) + tlist.token_index(token) + 1)) + if not (len(identifier_tokens) == 1 + and isinstance(identifier_tokens[0], sql.Function)): + group = tlist.group_tokens(sql.Identifier, identifier_tokens) + idx = tlist.token_index(group) + 1 + else: + idx += 1 + token = tlist.token_next_by_instance(idx, sql.Function) + if token is None: + token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name)) def group_identifier_list(tlist): [group_identifier_list(sgroup) for sgroup in tlist.get_sublists() - if not isinstance(sgroup, (Identifier, IdentifierList))] + if not isinstance(sgroup, sql.IdentifierList)] idx = 0 # Allowed list items - fend1_funcs = [lambda t: isinstance(t, Identifier), + fend1_funcs = [lambda t: isinstance(t, (sql.Identifier, sql.Function)), lambda t: t.is_whitespace(), + lambda t: t.ttype == T.Name, lambda t: t.ttype == T.Wildcard, lambda t: t.match(T.Keyword, 'null'), lambda t: t.ttype == T.Number.Integer, lambda t: t.ttype == T.String.Single, - lambda t: isinstance(t, Comparsion), + lambda t: isinstance(t, sql.Comparison), ] tcomma = tlist.token_next_match(idx, T.Punctuation, ',') start = None @@ -156,7 +197,7 @@ def group_identifier_list(tlist): if not bpassed or not apassed: # Something's wrong here, skip ahead to next "," start = None - tcomma = tlist.token_next_match(tlist.token_index(tcomma)+1, + tcomma = tlist.token_next_match(tlist.token_index(tcomma) + 1, T.Punctuation, ',') else: if start is None: @@ -165,25 +206,27 @@ def group_identifier_list(tlist): if next_ is None or not next_.match(T.Punctuation, ','): # Reached the end of the list tokens = tlist.tokens_between(start, after) - group = tlist.group_tokens(IdentifierList, tokens) + group = tlist.group_tokens(sql.IdentifierList, tokens) start = None - tcomma = tlist.token_next_match(tlist.token_index(group)+1, + tcomma = tlist.token_next_match(tlist.token_index(group) + 1, T.Punctuation, ',') else: tcomma = next_ def group_parenthesis(tlist): - _group_matching(tlist, T.Punctuation, '(', T.Punctuation, ')', Parenthesis) + _group_matching(tlist, T.Punctuation, '(', T.Punctuation, ')', + sql.Parenthesis) + def group_comments(tlist): [group_comments(sgroup) for sgroup in tlist.get_sublists() - if not isinstance(sgroup, Comment)] + if not isinstance(sgroup, sql.Comment)] idx = 0 token = tlist.token_next_by_type(idx, T.Comment) while token: tidx = tlist.token_index(token) - end = tlist.token_not_matching(tidx+1, + end = tlist.token_not_matching(tidx + 1, [lambda t: t.ttype in T.Comment, lambda t: t.is_whitespace()]) if end is None: @@ -192,49 +235,70 @@ def group_comments(tlist): eidx = tlist.token_index(end) grp_tokens = tlist.tokens_between(token, tlist.token_prev(eidx, False)) - group = tlist.group_tokens(Comment, grp_tokens) + group = tlist.group_tokens(sql.Comment, grp_tokens) idx = tlist.token_index(group) token = tlist.token_next_by_type(idx, T.Comment) + def group_where(tlist): [group_where(sgroup) for sgroup in tlist.get_sublists() - if not isinstance(sgroup, Where)] + if not isinstance(sgroup, sql.Where)] idx = 0 token = tlist.token_next_match(idx, T.Keyword, 'WHERE') stopwords = ('ORDER', 'GROUP', 'LIMIT', 'UNION') while token: tidx = tlist.token_index(token) - end = tlist.token_next_match(tidx+1, T.Keyword, stopwords) + end = tlist.token_next_match(tidx + 1, T.Keyword, stopwords) if end is None: - end = tlist.tokens[-1] + end = tlist._groupable_tokens[-1] else: - end = tlist.tokens[tlist.token_index(end)-1] - group = tlist.group_tokens(Where, tlist.tokens_between(token, end)) + end = tlist.tokens[tlist.token_index(end) - 1] + group = tlist.group_tokens(sql.Where, + tlist.tokens_between(token, end), + ignore_ws=True) idx = tlist.token_index(group) token = tlist.token_next_match(idx, T.Keyword, 'WHERE') + def group_aliased(tlist): [group_aliased(sgroup) for sgroup in tlist.get_sublists() - if not isinstance(sgroup, Identifier)] + if not isinstance(sgroup, (sql.Identifier, sql.Function))] idx = 0 - token = tlist.token_next_by_instance(idx, Identifier) + token = tlist.token_next_by_instance(idx, (sql.Identifier, sql.Function)) while token: next_ = tlist.token_next(tlist.token_index(token)) - if next_ is not None and isinstance(next_, Identifier): + if next_ is not None and isinstance(next_, (sql.Identifier, sql.Function)): grp = tlist.tokens_between(token, next_)[1:] token.tokens.extend(grp) for t in grp: tlist.tokens.remove(t) - idx = tlist.token_index(token)+1 - token = tlist.token_next_by_instance(idx, Identifier) + idx = tlist.token_index(token) + 1 + token = tlist.token_next_by_instance(idx, (sql.Identifier, sql.Function)) def group_typecasts(tlist): - _group_left_right(tlist, T.Punctuation, '::', Identifier) + _group_left_right(tlist, T.Punctuation, '::', sql.Identifier) + + +def group_functions(tlist): + [group_functions(sgroup) for sgroup in tlist.get_sublists() + if not isinstance(sgroup, sql.Function)] + idx = 0 + token = tlist.token_next_by_type(idx, T.Name) + while token: + next_ = tlist.token_next(token) + if not isinstance(next_, sql.Parenthesis): + idx = tlist.token_index(token) + 1 + else: + func = tlist.group_tokens(sql.Function, + tlist.tokens_between(token, next_)) + idx = tlist.token_index(func) + 1 + token = tlist.token_next_by_type(idx, T.Name) def group(tlist): for func in [group_parenthesis, + group_functions, group_comments, group_where, group_case, @@ -243,8 +307,8 @@ def group(tlist): group_as, group_aliased, group_assignment, - group_comparsion, + group_comparison, group_identifier_list, group_if, - group_for,]: + group_for]: func(tlist) diff --git a/debug_toolbar/utils/sqlparse/filters.py b/debug_toolbar/utils/sqlparse/filters.py index 3c92791..2d247e7 100644 --- a/debug_toolbar/utils/sqlparse/filters.py +++ b/debug_toolbar/utils/sqlparse/filters.py @@ -2,7 +2,6 @@ import re -from debug_toolbar.utils.sqlparse.engine import grouping from debug_toolbar.utils.sqlparse import tokens as T from debug_toolbar.utils.sqlparse import sql @@ -19,34 +18,6 @@ class TokenFilter(Filter): raise NotImplementedError -# FIXME: Should be removed -def rstrip(stream): - buff = [] - for token in stream: - if token.is_whitespace() and '\n' in token.value: - # assuming there's only one \n in value - before, rest = token.value.split('\n', 1) - token.value = '\n%s' % rest - buff = [] - yield token - elif token.is_whitespace(): - buff.append(token) - elif token.is_group(): - token.tokens = list(rstrip(token.tokens)) - # process group and look if it starts with a nl - if token.tokens and token.tokens[0].is_whitespace(): - before, rest = token.tokens[0].value.split('\n', 1) - token.tokens[0].value = '\n%s' % rest - buff = [] - while buff: - yield buff.pop(0) - yield token - else: - while buff: - yield buff.pop(0) - yield token - - # -------------------------- # token process @@ -74,17 +45,28 @@ class KeywordCaseFilter(_CaseFilter): class IdentifierCaseFilter(_CaseFilter): ttype = (T.Name, T.String.Symbol) + def process(self, stack, stream): + for ttype, value in stream: + if ttype in self.ttype and not value.strip()[0] == '"': + value = self.convert(value) + yield ttype, value + # ---------------------- # statement process class StripCommentsFilter(Filter): + def _get_next_comment(self, tlist): + # TODO(andi) Comment types should be unified, see related issue38 + token = tlist.token_next_by_instance(0, sql.Comment) + if token is None: + token = tlist.token_next_by_type(0, T.Comment) + return token + def _process(self, tlist): - idx = 0 - clss = set([x.__class__ for x in tlist.tokens]) - while grouping.Comment in clss: - token = tlist.token_next_by_instance(0, grouping.Comment) + token = self._get_next_comment(tlist) + while token: tidx = tlist.token_index(token) prev = tlist.token_prev(tidx, False) next_ = tlist.token_next(tidx, False) @@ -94,10 +76,10 @@ class StripCommentsFilter(Filter): and not prev.is_whitespace() and not next_.is_whitespace() and not (prev.match(T.Punctuation, '(') or next_.match(T.Punctuation, ')'))): - tlist.tokens[tidx] = grouping.Token(T.Whitespace, ' ') + tlist.tokens[tidx] = sql.Token(T.Whitespace, ' ') else: tlist.tokens.pop(tidx) - clss = set([x.__class__ for x in tlist.tokens]) + token = self._get_next_comment(tlist) def process(self, stack, stmt): [self.process(stack, sgroup) for sgroup in stmt.get_sublists()] @@ -149,24 +131,32 @@ class ReindentFilter(Filter): def _get_offset(self, token): all_ = list(self._curr_stmt.flatten()) idx = all_.index(token) - raw = ''.join(unicode(x) for x in all_[:idx+1]) + raw = ''.join(unicode(x) for x in all_[:idx + 1]) line = raw.splitlines()[-1] # Now take current offset into account and return relative offset. - full_offset = len(line)-(len(self.char*(self.width*self.indent))) + full_offset = len(line) - len(self.char * (self.width * self.indent)) return full_offset - self.offset def nl(self): # TODO: newline character should be configurable - ws = '\n'+(self.char*((self.indent*self.width)+self.offset)) - return grouping.Token(T.Whitespace, ws) + ws = '\n' + (self.char * ((self.indent * self.width) + self.offset)) + return sql.Token(T.Whitespace, ws) def _split_kwds(self, tlist): split_words = ('FROM', 'JOIN$', 'AND', 'OR', 'GROUP', 'ORDER', 'UNION', 'VALUES', - 'SET') - idx = 0 - token = tlist.token_next_match(idx, T.Keyword, split_words, + 'SET', 'BETWEEN') + def _next_token(i): + t = tlist.token_next_match(i, T.Keyword, split_words, regex=True) + if t and t.value.upper() == 'BETWEEN': + t = _next_token(tlist.token_index(t)+1) + if t and t.value.upper() == 'AND': + t = _next_token(tlist.token_index(t)+1) + return t + + idx = 0 + token = _next_token(idx) while token: prev = tlist.token_prev(tlist.token_index(token), False) offset = 1 @@ -181,8 +171,7 @@ class ReindentFilter(Filter): else: nl = self.nl() tlist.insert_before(token, nl) - token = tlist.token_next_match(tlist.token_index(nl)+offset, - T.Keyword, split_words, regex=True) + token = _next_token(tlist.token_index(nl) + offset) def _split_statements(self, tlist): idx = 0 @@ -195,7 +184,7 @@ class ReindentFilter(Filter): if prev: nl = self.nl() tlist.insert_before(token, nl) - token = tlist.token_next_by_type(tlist.token_index(token)+1, + token = tlist.token_next_by_type(tlist.token_index(token) + 1, (T.Keyword.DDL, T.Keyword.DML)) def _process(self, tlist): @@ -227,9 +216,9 @@ class ReindentFilter(Filter): def _process_identifierlist(self, tlist): identifiers = tlist.get_identifiers() - if len(identifiers) > 1: + if len(identifiers) > 1 and not tlist.within(sql.Function): first = list(identifiers[0].flatten())[0] - num_offset = self._get_offset(first)-len(first.value) + num_offset = self._get_offset(first) - len(first.value) self.offset += num_offset for token in identifiers[1:]: tlist.insert_before(token, self.nl()) @@ -237,16 +226,16 @@ class ReindentFilter(Filter): self._process_default(tlist) def _process_case(self, tlist): - cases = tlist.get_cases() is_first = True num_offset = None case = tlist.tokens[0] - outer_offset = self._get_offset(case)-len(case.value) + outer_offset = self._get_offset(case) - len(case.value) self.offset += outer_offset for cond, value in tlist.get_cases(): if is_first: + tcond = list(cond[0].flatten())[0] is_first = False - num_offset = self._get_offset(cond[0])-len(cond[0].value) + num_offset = self._get_offset(tcond) - len(tcond.value) self.offset += num_offset continue if cond is None: @@ -273,17 +262,17 @@ class ReindentFilter(Filter): [self._process(sgroup) for sgroup in tlist.get_sublists()] def process(self, stack, stmt): - if isinstance(stmt, grouping.Statement): + if isinstance(stmt, sql.Statement): self._curr_stmt = stmt self._process(stmt) - if isinstance(stmt, grouping.Statement): + if isinstance(stmt, sql.Statement): if self._last_stmt is not None: if self._last_stmt.to_unicode().endswith('\n'): nl = '\n' else: nl = '\n\n' stmt.tokens.insert(0, - grouping.Token(T.Whitespace, nl)) + sql.Token(T.Whitespace, nl)) if self._last_stmt != stmt: self._last_stmt = stmt @@ -292,7 +281,7 @@ class ReindentFilter(Filter): class RightMarginFilter(Filter): keep_together = ( -# grouping.TypeCast, grouping.Identifier, grouping.Alias, +# sql.TypeCast, sql.Identifier, sql.Alias, ) def __init__(self, width=79): @@ -317,7 +306,7 @@ class RightMarginFilter(Filter): indent = match.group() else: indent = '' - yield grouping.Token(T.Whitespace, '\n%s' % indent) + yield sql.Token(T.Whitespace, '\n%s' % indent) self.line = indent self.line += val yield token @@ -349,14 +338,14 @@ class OutputPythonFilter(Filter): def _process(self, stream, varname, count, has_nl): if count > 1: - yield grouping.Token(T.Whitespace, '\n') - yield grouping.Token(T.Name, varname) - yield grouping.Token(T.Whitespace, ' ') - yield grouping.Token(T.Operator, '=') - yield grouping.Token(T.Whitespace, ' ') + yield sql.Token(T.Whitespace, '\n') + yield sql.Token(T.Name, varname) + yield sql.Token(T.Whitespace, ' ') + yield sql.Token(T.Operator, '=') + yield sql.Token(T.Whitespace, ' ') if has_nl: - yield grouping.Token(T.Operator, '(') - yield grouping.Token(T.Text, "'") + yield sql.Token(T.Operator, '(') + yield sql.Token(T.Text, "'") cnt = 0 for token in stream: cnt += 1 @@ -364,20 +353,20 @@ class OutputPythonFilter(Filter): if cnt == 1: continue after_lb = token.value.split('\n', 1)[1] - yield grouping.Token(T.Text, " '") - yield grouping.Token(T.Whitespace, '\n') - for i in range(len(varname)+4): - yield grouping.Token(T.Whitespace, ' ') - yield grouping.Token(T.Text, "'") + yield sql.Token(T.Text, " '") + yield sql.Token(T.Whitespace, '\n') + for i in range(len(varname) + 4): + yield sql.Token(T.Whitespace, ' ') + yield sql.Token(T.Text, "'") if after_lb: # it's the indendation - yield grouping.Token(T.Whitespace, after_lb) + yield sql.Token(T.Whitespace, after_lb) continue elif token.value and "'" in token.value: token.value = token.value.replace("'", "\\'") - yield grouping.Token(T.Text, token.value or '') - yield grouping.Token(T.Text, "'") + yield sql.Token(T.Text, token.value or '') + yield sql.Token(T.Text, "'") if has_nl: - yield grouping.Token(T.Operator, ')') + yield sql.Token(T.Operator, ')') def process(self, stack, stmt): self.cnt += 1 @@ -398,36 +387,32 @@ class OutputPHPFilter(Filter): def _process(self, stream, varname): if self.count > 1: - yield grouping.Token(T.Whitespace, '\n') - yield grouping.Token(T.Name, varname) - yield grouping.Token(T.Whitespace, ' ') - yield grouping.Token(T.Operator, '=') - yield grouping.Token(T.Whitespace, ' ') - yield grouping.Token(T.Text, '"') - cnt = 0 + yield sql.Token(T.Whitespace, '\n') + yield sql.Token(T.Name, varname) + yield sql.Token(T.Whitespace, ' ') + yield sql.Token(T.Operator, '=') + yield sql.Token(T.Whitespace, ' ') + yield sql.Token(T.Text, '"') for token in stream: if token.is_whitespace() and '\n' in token.value: -# cnt += 1 -# if cnt == 1: -# continue after_lb = token.value.split('\n', 1)[1] - yield grouping.Token(T.Text, ' "') - yield grouping.Token(T.Operator, ';') - yield grouping.Token(T.Whitespace, '\n') - yield grouping.Token(T.Name, varname) - yield grouping.Token(T.Whitespace, ' ') - yield grouping.Token(T.Punctuation, '.') - yield grouping.Token(T.Operator, '=') - yield grouping.Token(T.Whitespace, ' ') - yield grouping.Token(T.Text, '"') + yield sql.Token(T.Text, ' "') + yield sql.Token(T.Operator, ';') + yield sql.Token(T.Whitespace, '\n') + yield sql.Token(T.Name, varname) + yield sql.Token(T.Whitespace, ' ') + yield sql.Token(T.Punctuation, '.') + yield sql.Token(T.Operator, '=') + yield sql.Token(T.Whitespace, ' ') + yield sql.Token(T.Text, '"') if after_lb: - yield grouping.Token(T.Text, after_lb) + yield sql.Token(T.Text, after_lb) continue elif '"' in token.value: token.value = token.value.replace('"', '\\"') - yield grouping.Token(T.Text, token.value) - yield grouping.Token(T.Text, '"') - yield grouping.Token(T.Punctuation, ';') + yield sql.Token(T.Text, token.value) + yield sql.Token(T.Text, '"') + yield sql.Token(T.Punctuation, ';') def process(self, stack, stmt): self.count += 1 @@ -437,4 +422,3 @@ class OutputPHPFilter(Filter): varname = self.varname stmt.tokens = tuple(self._process(stmt.tokens, varname)) return stmt - diff --git a/debug_toolbar/utils/sqlparse/formatter.py b/debug_toolbar/utils/sqlparse/formatter.py index 34e9fe0..3acece9 100644 --- a/debug_toolbar/utils/sqlparse/formatter.py +++ b/debug_toolbar/utils/sqlparse/formatter.py @@ -76,11 +76,11 @@ def build_filter_stack(stack, options): options: Dictionary with options validated by validate_options. """ # Token filter - if 'keyword_case' in options: + if options.get('keyword_case', None): stack.preprocess.append( filters.KeywordCaseFilter(options['keyword_case'])) - if 'identifier_case' in options: + if options.get('identifier_case', None): stack.preprocess.append( filters.IdentifierCaseFilter(options['identifier_case'])) @@ -118,5 +118,3 @@ def build_filter_stack(stack, options): stack.postprocess.append(fltr) return stack - - diff --git a/debug_toolbar/utils/sqlparse/keywords.py b/debug_toolbar/utils/sqlparse/keywords.py index cada139..4782cfe 100644 --- a/debug_toolbar/utils/sqlparse/keywords.py +++ b/debug_toolbar/utils/sqlparse/keywords.py @@ -1,590 +1,565 @@ -from debug_toolbar.utils.sqlparse.tokens import * +from debug_toolbar.utils.sqlparse import tokens KEYWORDS = { - 'ABORT': Keyword, - 'ABS': Keyword, - 'ABSOLUTE': Keyword, - 'ACCESS': Keyword, - 'ADA': Keyword, - 'ADD': Keyword, - 'ADMIN': Keyword, - 'AFTER': Keyword, - 'AGGREGATE': Keyword, - 'ALIAS': Keyword, - 'ALL': Keyword, - 'ALLOCATE': Keyword, - 'ANALYSE': Keyword, - 'ANALYZE': Keyword, - 'AND': Keyword, - 'ANY': Keyword, - 'ARE': Keyword, - 'AS': Keyword, - 'ASC': Keyword, - 'ASENSITIVE': Keyword, - 'ASSERTION': Keyword, - 'ASSIGNMENT': Keyword, - 'ASYMMETRIC': Keyword, - 'AT': Keyword, - 'ATOMIC': Keyword, - 'AUTHORIZATION': Keyword, - 'AVG': Keyword, - - 'BACKWARD': Keyword, - 'BEFORE': Keyword, - 'BEGIN': Keyword, - 'BETWEEN': Keyword, - 'BITVAR': Keyword, - 'BIT_LENGTH': Keyword, - 'BOTH': Keyword, - 'BREADTH': Keyword, - 'BY': Keyword, - -# 'C': Keyword, # most likely this is an alias - 'CACHE': Keyword, - 'CALL': Keyword, - 'CALLED': Keyword, - 'CARDINALITY': Keyword, - 'CASCADE': Keyword, - 'CASCADED': Keyword, - 'CASE': Keyword, - 'CAST': Keyword, - 'CATALOG': Keyword, - 'CATALOG_NAME': Keyword, - 'CHAIN': Keyword, - 'CHARACTERISTICS': Keyword, - 'CHARACTER_LENGTH': Keyword, - 'CHARACTER_SET_CATALOG': Keyword, - 'CHARACTER_SET_NAME': Keyword, - 'CHARACTER_SET_SCHEMA': Keyword, - 'CHAR_LENGTH': Keyword, - 'CHECK': Keyword, - 'CHECKED': Keyword, - 'CHECKPOINT': Keyword, - 'CLASS': Keyword, - 'CLASS_ORIGIN': Keyword, - 'CLOB': Keyword, - 'CLOSE': Keyword, - 'CLUSTER': Keyword, - 'COALSECE': Keyword, - 'COBOL': Keyword, - 'COLLATE': Keyword, - 'COLLATION': Keyword, - 'COLLATION_CATALOG': Keyword, - 'COLLATION_NAME': Keyword, - 'COLLATION_SCHEMA': Keyword, - 'COLUMN': Keyword, - 'COLUMN_NAME': Keyword, - 'COMMAND_FUNCTION': Keyword, - 'COMMAND_FUNCTION_CODE': Keyword, - 'COMMENT': Keyword, - 'COMMIT': Keyword, - 'COMMITTED': Keyword, - 'COMPLETION': Keyword, - 'CONDITION_NUMBER': Keyword, - 'CONNECT': Keyword, - 'CONNECTION': Keyword, - 'CONNECTION_NAME': Keyword, - 'CONSTRAINT': Keyword, - 'CONSTRAINTS': Keyword, - 'CONSTRAINT_CATALOG': Keyword, - 'CONSTRAINT_NAME': Keyword, - 'CONSTRAINT_SCHEMA': Keyword, - 'CONSTRUCTOR': Keyword, - 'CONTAINS': Keyword, - 'CONTINUE': Keyword, - 'CONVERSION': Keyword, - 'CONVERT': Keyword, - 'COPY': Keyword, - 'CORRESPONTING': Keyword, - 'COUNT': Keyword, - 'CREATEDB': Keyword, - 'CREATEUSER': Keyword, - 'CROSS': Keyword, - 'CUBE': Keyword, - 'CURRENT': Keyword, - 'CURRENT_DATE': Keyword, - 'CURRENT_PATH': Keyword, - 'CURRENT_ROLE': Keyword, - 'CURRENT_TIME': Keyword, - 'CURRENT_TIMESTAMP': Keyword, - 'CURRENT_USER': Keyword, - 'CURSOR': Keyword, - 'CURSOR_NAME': Keyword, - 'CYCLE': Keyword, - - 'DATA': Keyword, - 'DATABASE': Keyword, - 'DATETIME_INTERVAL_CODE': Keyword, - 'DATETIME_INTERVAL_PRECISION': Keyword, - 'DAY': Keyword, - 'DEALLOCATE': Keyword, - 'DECLARE': Keyword, - 'DEFAULT': Keyword, - 'DEFAULTS': Keyword, - 'DEFERRABLE': Keyword, - 'DEFERRED': Keyword, - 'DEFINED': Keyword, - 'DEFINER': Keyword, - 'DELIMITER': Keyword, - 'DELIMITERS': Keyword, - 'DEREF': Keyword, - 'DESC': Keyword, - 'DESCRIBE': Keyword, - 'DESCRIPTOR': Keyword, - 'DESTROY': Keyword, - 'DESTRUCTOR': Keyword, - 'DETERMINISTIC': Keyword, - 'DIAGNOSTICS': Keyword, - 'DICTIONARY': Keyword, - 'DISCONNECT': Keyword, - 'DISPATCH': Keyword, - 'DISTINCT': Keyword, - 'DO': Keyword, - 'DOMAIN': Keyword, - 'DYNAMIC': Keyword, - 'DYNAMIC_FUNCTION': Keyword, - 'DYNAMIC_FUNCTION_CODE': Keyword, - - 'EACH': Keyword, - 'ELSE': Keyword, - 'ENCODING': Keyword, - 'ENCRYPTED': Keyword, - 'END': Keyword, - 'END-EXEC': Keyword, - 'EQUALS': Keyword, - 'ESCAPE': Keyword, - 'EVERY': Keyword, - 'EXCEPT': Keyword, - 'ESCEPTION': Keyword, - 'EXCLUDING': Keyword, - 'EXCLUSIVE': Keyword, - 'EXEC': Keyword, - 'EXECUTE': Keyword, - 'EXISTING': Keyword, - 'EXISTS': Keyword, - 'EXTERNAL': Keyword, - 'EXTRACT': Keyword, - - 'FALSE': Keyword, - 'FETCH': Keyword, - 'FINAL': Keyword, - 'FIRST': Keyword, - 'FOR': Keyword, - 'FORCE': Keyword, - 'FOREIGN': Keyword, - 'FORTRAN': Keyword, - 'FORWARD': Keyword, - 'FOUND': Keyword, - 'FREE': Keyword, - 'FREEZE': Keyword, - 'FROM': Keyword, - 'FULL': Keyword, - 'FUNCTION': Keyword, - - 'G': Keyword, - 'GENERAL': Keyword, - 'GENERATED': Keyword, - 'GET': Keyword, - 'GLOBAL': Keyword, - 'GO': Keyword, - 'GOTO': Keyword, - 'GRANT': Keyword, - 'GRANTED': Keyword, - 'GROUP': Keyword, - 'GROUPING': Keyword, - - 'HANDLER': Keyword, - 'HAVING': Keyword, - 'HIERARCHY': Keyword, - 'HOLD': Keyword, - 'HOST': Keyword, - - 'IDENTITY': Keyword, - 'IF': Keyword, - 'IGNORE': Keyword, - 'ILIKE': Keyword, - 'IMMEDIATE': Keyword, - 'IMMUTABLE': Keyword, - - 'IMPLEMENTATION': Keyword, - 'IMPLICIT': Keyword, - 'IN': Keyword, - 'INCLUDING': Keyword, - 'INCREMENT': Keyword, - 'INDEX': Keyword, - - 'INDITCATOR': Keyword, - 'INFIX': Keyword, - 'INHERITS': Keyword, - 'INITIALIZE': Keyword, - 'INITIALLY': Keyword, - 'INNER': Keyword, - 'INOUT': Keyword, - 'INPUT': Keyword, - 'INSENSITIVE': Keyword, - 'INSTANTIABLE': Keyword, - 'INSTEAD': Keyword, - 'INTERSECT': Keyword, - 'INTO': Keyword, - 'INVOKER': Keyword, - 'IS': Keyword, - 'ISNULL': Keyword, - 'ISOLATION': Keyword, - 'ITERATE': Keyword, - - 'JOIN': Keyword, - - 'K': Keyword, - 'KEY': Keyword, - 'KEY_MEMBER': Keyword, - 'KEY_TYPE': Keyword, - - 'LANCOMPILER': Keyword, - 'LANGUAGE': Keyword, - 'LARGE': Keyword, - 'LAST': Keyword, - 'LATERAL': Keyword, - 'LEADING': Keyword, - 'LEFT': Keyword, - 'LENGTH': Keyword, - 'LESS': Keyword, - 'LEVEL': Keyword, - 'LIKE': Keyword, - 'LIMIT': Keyword, - 'LISTEN': Keyword, - 'LOAD': Keyword, - 'LOCAL': Keyword, - 'LOCALTIME': Keyword, - 'LOCALTIMESTAMP': Keyword, - 'LOCATION': Keyword, - 'LOCATOR': Keyword, - 'LOCK': Keyword, - 'LOWER': Keyword, - - 'M': Keyword, - 'MAP': Keyword, - 'MATCH': Keyword, - 'MAX': Keyword, - 'MAXVALUE': Keyword, - 'MESSAGE_LENGTH': Keyword, - 'MESSAGE_OCTET_LENGTH': Keyword, - 'MESSAGE_TEXT': Keyword, - 'METHOD': Keyword, - 'MIN': Keyword, - 'MINUTE': Keyword, - 'MINVALUE': Keyword, - 'MOD': Keyword, - 'MODE': Keyword, - 'MODIFIES': Keyword, - 'MODIFY': Keyword, - 'MONTH': Keyword, - 'MORE': Keyword, - 'MOVE': Keyword, - 'MUMPS': Keyword, - - 'NAMES': Keyword, - 'NATIONAL': Keyword, - 'NATURAL': Keyword, - 'NCHAR': Keyword, - 'NCLOB': Keyword, - 'NEW': Keyword, - 'NEXT': Keyword, - 'NO': Keyword, - 'NOCREATEDB': Keyword, - 'NOCREATEUSER': Keyword, - 'NONE': Keyword, - 'NOT': Keyword, - 'NOTHING': Keyword, - 'NOTIFY': Keyword, - 'NOTNULL': Keyword, - 'NULL': Keyword, - 'NULLABLE': Keyword, - 'NULLIF': Keyword, - - 'OBJECT': Keyword, - 'OCTET_LENGTH': Keyword, - 'OF': Keyword, - 'OFF': Keyword, - 'OFFSET': Keyword, - 'OIDS': Keyword, - 'OLD': Keyword, - 'ON': Keyword, - 'ONLY': Keyword, - 'OPEN': Keyword, - 'OPERATION': Keyword, - 'OPERATOR': Keyword, - 'OPTION': Keyword, - 'OPTIONS': Keyword, - 'OR': Keyword, - 'ORDER': Keyword, - 'ORDINALITY': Keyword, - 'OUT': Keyword, - 'OUTER': Keyword, - 'OUTPUT': Keyword, - 'OVERLAPS': Keyword, - 'OVERLAY': Keyword, - 'OVERRIDING': Keyword, - 'OWNER': Keyword, - - 'PAD': Keyword, - 'PARAMETER': Keyword, - 'PARAMETERS': Keyword, - 'PARAMETER_MODE': Keyword, - 'PARAMATER_NAME': Keyword, - 'PARAMATER_ORDINAL_POSITION': Keyword, - 'PARAMETER_SPECIFIC_CATALOG': Keyword, - 'PARAMETER_SPECIFIC_NAME': Keyword, - 'PARAMATER_SPECIFIC_SCHEMA': Keyword, - 'PARTIAL': Keyword, - 'PASCAL': Keyword, - 'PENDANT': Keyword, - 'PLACING': Keyword, - 'PLI': Keyword, - 'POSITION': Keyword, - 'POSTFIX': Keyword, - 'PRECISION': Keyword, - 'PREFIX': Keyword, - 'PREORDER': Keyword, - 'PREPARE': Keyword, - 'PRESERVE': Keyword, - 'PRIMARY': Keyword, - 'PRIOR': Keyword, - 'PRIVILEGES': Keyword, - 'PROCEDURAL': Keyword, - 'PROCEDURE': Keyword, - 'PUBLIC': Keyword, - - 'RAISE': Keyword, - 'READ': Keyword, - 'READS': Keyword, - 'RECHECK': Keyword, - 'RECURSIVE': Keyword, - 'REF': Keyword, - 'REFERENCES': Keyword, - 'REFERENCING': Keyword, - 'REINDEX': Keyword, - 'RELATIVE': Keyword, - 'RENAME': Keyword, - 'REPEATABLE': Keyword, - 'REPLACE': Keyword, - 'RESET': Keyword, - 'RESTART': Keyword, - 'RESTRICT': Keyword, - 'RESULT': Keyword, - 'RETURN': Keyword, - 'RETURNED_LENGTH': Keyword, - 'RETURNED_OCTET_LENGTH': Keyword, - 'RETURNED_SQLSTATE': Keyword, - 'RETURNS': Keyword, - 'REVOKE': Keyword, - 'RIGHT': Keyword, - 'ROLE': Keyword, - 'ROLLBACK': Keyword, - 'ROLLUP': Keyword, - 'ROUTINE': Keyword, - 'ROUTINE_CATALOG': Keyword, - 'ROUTINE_NAME': Keyword, - 'ROUTINE_SCHEMA': Keyword, - 'ROW': Keyword, - 'ROWS': Keyword, - 'ROW_COUNT': Keyword, - 'RULE': Keyword, - - 'SAVE_POINT': Keyword, - 'SCALE': Keyword, - 'SCHEMA': Keyword, - 'SCHEMA_NAME': Keyword, - 'SCOPE': Keyword, - 'SCROLL': Keyword, - 'SEARCH': Keyword, - 'SECOND': Keyword, - 'SECURITY': Keyword, - 'SELF': Keyword, - 'SENSITIVE': Keyword, - 'SERIALIZABLE': Keyword, - 'SERVER_NAME': Keyword, - 'SESSION': Keyword, - 'SESSION_USER': Keyword, - 'SETOF': Keyword, - 'SETS': Keyword, - 'SHARE': Keyword, - 'SHOW': Keyword, - 'SIMILAR': Keyword, - 'SIMPLE': Keyword, - 'SIZE': Keyword, - 'SOME': Keyword, - 'SOURCE': Keyword, - 'SPACE': Keyword, - 'SPECIFIC': Keyword, - 'SPECIFICTYPE': Keyword, - 'SPECIFIC_NAME': Keyword, - 'SQL': Keyword, - 'SQLCODE': Keyword, - 'SQLERROR': Keyword, - 'SQLEXCEPTION': Keyword, - 'SQLSTATE': Keyword, - 'SQLWARNINIG': Keyword, - 'STABLE': Keyword, - 'START': Keyword, - 'STATE': Keyword, - 'STATEMENT': Keyword, - 'STATIC': Keyword, - 'STATISTICS': Keyword, - 'STDIN': Keyword, - 'STDOUT': Keyword, - 'STORAGE': Keyword, - 'STRICT': Keyword, - 'STRUCTURE': Keyword, - 'STYPE': Keyword, - 'SUBCLASS_ORIGIN': Keyword, - 'SUBLIST': Keyword, - 'SUBSTRING': Keyword, - 'SUM': Keyword, - 'SYMMETRIC': Keyword, - 'SYSID': Keyword, - 'SYSTEM': Keyword, - 'SYSTEM_USER': Keyword, - - 'TABLE': Keyword, - 'TABLE_NAME': Keyword, - ' TEMP': Keyword, - 'TEMPLATE': Keyword, - 'TEMPORARY': Keyword, - 'TERMINATE': Keyword, - 'THAN': Keyword, - 'THEN': Keyword, - 'TIMESTAMP': Keyword, - 'TIMEZONE_HOUR': Keyword, - 'TIMEZONE_MINUTE': Keyword, - 'TO': Keyword, - 'TOAST': Keyword, - 'TRAILING': Keyword, - 'TRANSATION': Keyword, - 'TRANSACTIONS_COMMITTED': Keyword, - 'TRANSACTIONS_ROLLED_BACK': Keyword, - 'TRANSATION_ACTIVE': Keyword, - 'TRANSFORM': Keyword, - 'TRANSFORMS': Keyword, - 'TRANSLATE': Keyword, - 'TRANSLATION': Keyword, - 'TREAT': Keyword, - 'TRIGGER': Keyword, - 'TRIGGER_CATALOG': Keyword, - 'TRIGGER_NAME': Keyword, - 'TRIGGER_SCHEMA': Keyword, - 'TRIM': Keyword, - 'TRUE': Keyword, - 'TRUNCATE': Keyword, - 'TRUSTED': Keyword, - 'TYPE': Keyword, - - 'UNCOMMITTED': Keyword, - 'UNDER': Keyword, - 'UNENCRYPTED': Keyword, - 'UNION': Keyword, - 'UNIQUE': Keyword, - 'UNKNOWN': Keyword, - 'UNLISTEN': Keyword, - 'UNNAMED': Keyword, - 'UNNEST': Keyword, - 'UNTIL': Keyword, - 'UPPER': Keyword, - 'USAGE': Keyword, - 'USER': Keyword, - 'USER_DEFINED_TYPE_CATALOG': Keyword, - 'USER_DEFINED_TYPE_NAME': Keyword, - 'USER_DEFINED_TYPE_SCHEMA': Keyword, - 'USING': Keyword, - - 'VACUUM': Keyword, - 'VALID': Keyword, - 'VALIDATOR': Keyword, - 'VALUES': Keyword, - 'VARIABLE': Keyword, - 'VERBOSE': Keyword, - 'VERSION': Keyword, - 'VIEW': Keyword, - 'VOLATILE': Keyword, - - 'WHEN': Keyword, - 'WHENEVER': Keyword, - 'WHERE': Keyword, - 'WITH': Keyword, - 'WITHOUT': Keyword, - 'WORK': Keyword, - 'WRITE': Keyword, - - 'YEAR': Keyword, - - 'ZONE': Keyword, - - - 'ARRAY': Name.Builtin, - 'BIGINT': Name.Builtin, - 'BINARY': Name.Builtin, - 'BIT': Name.Builtin, - 'BLOB': Name.Builtin, - 'BOOLEAN': Name.Builtin, - 'CHAR': Name.Builtin, - 'CHARACTER': Name.Builtin, - 'DATE': Name.Builtin, - 'DEC': Name.Builtin, - 'DECIMAL': Name.Builtin, - 'FLOAT': Name.Builtin, - 'INT': Name.Builtin, - 'INTEGER': Name.Builtin, - 'INTERVAL': Name.Builtin, - 'NUMBER': Name.Builtin, - 'NUMERIC': Name.Builtin, - 'REAL': Name.Builtin, - 'SERIAL': Name.Builtin, - 'SMALLINT': Name.Builtin, - 'VARCHAR': Name.Builtin, - 'VARYING': Name.Builtin, - 'INT8': Name.Builtin, - 'SERIAL8': Name.Builtin, - 'TEXT': Name.Builtin, + 'ABORT': tokens.Keyword, + 'ABS': tokens.Keyword, + 'ABSOLUTE': tokens.Keyword, + 'ACCESS': tokens.Keyword, + 'ADA': tokens.Keyword, + 'ADD': tokens.Keyword, + 'ADMIN': tokens.Keyword, + 'AFTER': tokens.Keyword, + 'AGGREGATE': tokens.Keyword, + 'ALIAS': tokens.Keyword, + 'ALL': tokens.Keyword, + 'ALLOCATE': tokens.Keyword, + 'ANALYSE': tokens.Keyword, + 'ANALYZE': tokens.Keyword, + 'ANY': tokens.Keyword, + 'ARE': tokens.Keyword, + 'ASC': tokens.Keyword, + 'ASENSITIVE': tokens.Keyword, + 'ASSERTION': tokens.Keyword, + 'ASSIGNMENT': tokens.Keyword, + 'ASYMMETRIC': tokens.Keyword, + 'AT': tokens.Keyword, + 'ATOMIC': tokens.Keyword, + 'AUTHORIZATION': tokens.Keyword, + 'AVG': tokens.Keyword, + + 'BACKWARD': tokens.Keyword, + 'BEFORE': tokens.Keyword, + 'BEGIN': tokens.Keyword, + 'BETWEEN': tokens.Keyword, + 'BITVAR': tokens.Keyword, + 'BIT_LENGTH': tokens.Keyword, + 'BOTH': tokens.Keyword, + 'BREADTH': tokens.Keyword, + +# 'C': tokens.Keyword, # most likely this is an alias + 'CACHE': tokens.Keyword, + 'CALL': tokens.Keyword, + 'CALLED': tokens.Keyword, + 'CARDINALITY': tokens.Keyword, + 'CASCADE': tokens.Keyword, + 'CASCADED': tokens.Keyword, + 'CAST': tokens.Keyword, + 'CATALOG': tokens.Keyword, + 'CATALOG_NAME': tokens.Keyword, + 'CHAIN': tokens.Keyword, + 'CHARACTERISTICS': tokens.Keyword, + 'CHARACTER_LENGTH': tokens.Keyword, + 'CHARACTER_SET_CATALOG': tokens.Keyword, + 'CHARACTER_SET_NAME': tokens.Keyword, + 'CHARACTER_SET_SCHEMA': tokens.Keyword, + 'CHAR_LENGTH': tokens.Keyword, + 'CHECK': tokens.Keyword, + 'CHECKED': tokens.Keyword, + 'CHECKPOINT': tokens.Keyword, + 'CLASS': tokens.Keyword, + 'CLASS_ORIGIN': tokens.Keyword, + 'CLOB': tokens.Keyword, + 'CLOSE': tokens.Keyword, + 'CLUSTER': tokens.Keyword, + 'COALSECE': tokens.Keyword, + 'COBOL': tokens.Keyword, + 'COLLATE': tokens.Keyword, + 'COLLATION': tokens.Keyword, + 'COLLATION_CATALOG': tokens.Keyword, + 'COLLATION_NAME': tokens.Keyword, + 'COLLATION_SCHEMA': tokens.Keyword, + 'COLUMN': tokens.Keyword, + 'COLUMN_NAME': tokens.Keyword, + 'COMMAND_FUNCTION': tokens.Keyword, + 'COMMAND_FUNCTION_CODE': tokens.Keyword, + 'COMMENT': tokens.Keyword, + 'COMMIT': tokens.Keyword, + 'COMMITTED': tokens.Keyword, + 'COMPLETION': tokens.Keyword, + 'CONDITION_NUMBER': tokens.Keyword, + 'CONNECT': tokens.Keyword, + 'CONNECTION': tokens.Keyword, + 'CONNECTION_NAME': tokens.Keyword, + 'CONSTRAINT': tokens.Keyword, + 'CONSTRAINTS': tokens.Keyword, + 'CONSTRAINT_CATALOG': tokens.Keyword, + 'CONSTRAINT_NAME': tokens.Keyword, + 'CONSTRAINT_SCHEMA': tokens.Keyword, + 'CONSTRUCTOR': tokens.Keyword, + 'CONTAINS': tokens.Keyword, + 'CONTINUE': tokens.Keyword, + 'CONVERSION': tokens.Keyword, + 'CONVERT': tokens.Keyword, + 'COPY': tokens.Keyword, + 'CORRESPONTING': tokens.Keyword, + 'COUNT': tokens.Keyword, + 'CREATEDB': tokens.Keyword, + 'CREATEUSER': tokens.Keyword, + 'CROSS': tokens.Keyword, + 'CUBE': tokens.Keyword, + 'CURRENT': tokens.Keyword, + 'CURRENT_DATE': tokens.Keyword, + 'CURRENT_PATH': tokens.Keyword, + 'CURRENT_ROLE': tokens.Keyword, + 'CURRENT_TIME': tokens.Keyword, + 'CURRENT_TIMESTAMP': tokens.Keyword, + 'CURRENT_USER': tokens.Keyword, + 'CURSOR': tokens.Keyword, + 'CURSOR_NAME': tokens.Keyword, + 'CYCLE': tokens.Keyword, + + 'DATA': tokens.Keyword, + 'DATABASE': tokens.Keyword, + 'DATETIME_INTERVAL_CODE': tokens.Keyword, + 'DATETIME_INTERVAL_PRECISION': tokens.Keyword, + 'DAY': tokens.Keyword, + 'DEALLOCATE': tokens.Keyword, + 'DECLARE': tokens.Keyword, + 'DEFAULT': tokens.Keyword, + 'DEFAULTS': tokens.Keyword, + 'DEFERRABLE': tokens.Keyword, + 'DEFERRED': tokens.Keyword, + 'DEFINED': tokens.Keyword, + 'DEFINER': tokens.Keyword, + 'DELIMITER': tokens.Keyword, + 'DELIMITERS': tokens.Keyword, + 'DEREF': tokens.Keyword, + 'DESC': tokens.Keyword, + 'DESCRIBE': tokens.Keyword, + 'DESCRIPTOR': tokens.Keyword, + 'DESTROY': tokens.Keyword, + 'DESTRUCTOR': tokens.Keyword, + 'DETERMINISTIC': tokens.Keyword, + 'DIAGNOSTICS': tokens.Keyword, + 'DICTIONARY': tokens.Keyword, + 'DISCONNECT': tokens.Keyword, + 'DISPATCH': tokens.Keyword, + 'DO': tokens.Keyword, + 'DOMAIN': tokens.Keyword, + 'DYNAMIC': tokens.Keyword, + 'DYNAMIC_FUNCTION': tokens.Keyword, + 'DYNAMIC_FUNCTION_CODE': tokens.Keyword, + + 'EACH': tokens.Keyword, + 'ENCODING': tokens.Keyword, + 'ENCRYPTED': tokens.Keyword, + 'END-EXEC': tokens.Keyword, + 'EQUALS': tokens.Keyword, + 'ESCAPE': tokens.Keyword, + 'EVERY': tokens.Keyword, + 'EXCEPT': tokens.Keyword, + 'ESCEPTION': tokens.Keyword, + 'EXCLUDING': tokens.Keyword, + 'EXCLUSIVE': tokens.Keyword, + 'EXEC': tokens.Keyword, + 'EXECUTE': tokens.Keyword, + 'EXISTING': tokens.Keyword, + 'EXISTS': tokens.Keyword, + 'EXTERNAL': tokens.Keyword, + 'EXTRACT': tokens.Keyword, + + 'FALSE': tokens.Keyword, + 'FETCH': tokens.Keyword, + 'FINAL': tokens.Keyword, + 'FIRST': tokens.Keyword, + 'FORCE': tokens.Keyword, + 'FOREIGN': tokens.Keyword, + 'FORTRAN': tokens.Keyword, + 'FORWARD': tokens.Keyword, + 'FOUND': tokens.Keyword, + 'FREE': tokens.Keyword, + 'FREEZE': tokens.Keyword, + 'FULL': tokens.Keyword, + 'FUNCTION': tokens.Keyword, + +# 'G': tokens.Keyword, + 'GENERAL': tokens.Keyword, + 'GENERATED': tokens.Keyword, + 'GET': tokens.Keyword, + 'GLOBAL': tokens.Keyword, + 'GO': tokens.Keyword, + 'GOTO': tokens.Keyword, + 'GRANT': tokens.Keyword, + 'GRANTED': tokens.Keyword, + 'GROUPING': tokens.Keyword, + + 'HANDLER': tokens.Keyword, + 'HAVING': tokens.Keyword, + 'HIERARCHY': tokens.Keyword, + 'HOLD': tokens.Keyword, + 'HOST': tokens.Keyword, + + 'IDENTITY': tokens.Keyword, + 'IGNORE': tokens.Keyword, + 'ILIKE': tokens.Keyword, + 'IMMEDIATE': tokens.Keyword, + 'IMMUTABLE': tokens.Keyword, + + 'IMPLEMENTATION': tokens.Keyword, + 'IMPLICIT': tokens.Keyword, + 'INCLUDING': tokens.Keyword, + 'INCREMENT': tokens.Keyword, + 'INDEX': tokens.Keyword, + + 'INDITCATOR': tokens.Keyword, + 'INFIX': tokens.Keyword, + 'INHERITS': tokens.Keyword, + 'INITIALIZE': tokens.Keyword, + 'INITIALLY': tokens.Keyword, + 'INOUT': tokens.Keyword, + 'INPUT': tokens.Keyword, + 'INSENSITIVE': tokens.Keyword, + 'INSTANTIABLE': tokens.Keyword, + 'INSTEAD': tokens.Keyword, + 'INTERSECT': tokens.Keyword, + 'INTO': tokens.Keyword, + 'INVOKER': tokens.Keyword, + 'IS': tokens.Keyword, + 'ISNULL': tokens.Keyword, + 'ISOLATION': tokens.Keyword, + 'ITERATE': tokens.Keyword, + +# 'K': tokens.Keyword, + 'KEY': tokens.Keyword, + 'KEY_MEMBER': tokens.Keyword, + 'KEY_TYPE': tokens.Keyword, + + 'LANCOMPILER': tokens.Keyword, + 'LANGUAGE': tokens.Keyword, + 'LARGE': tokens.Keyword, + 'LAST': tokens.Keyword, + 'LATERAL': tokens.Keyword, + 'LEADING': tokens.Keyword, + 'LENGTH': tokens.Keyword, + 'LESS': tokens.Keyword, + 'LEVEL': tokens.Keyword, + 'LIMIT': tokens.Keyword, + 'LISTEN': tokens.Keyword, + 'LOAD': tokens.Keyword, + 'LOCAL': tokens.Keyword, + 'LOCALTIME': tokens.Keyword, + 'LOCALTIMESTAMP': tokens.Keyword, + 'LOCATION': tokens.Keyword, + 'LOCATOR': tokens.Keyword, + 'LOCK': tokens.Keyword, + 'LOWER': tokens.Keyword, + +# 'M': tokens.Keyword, + 'MAP': tokens.Keyword, + 'MATCH': tokens.Keyword, + 'MAXVALUE': tokens.Keyword, + 'MESSAGE_LENGTH': tokens.Keyword, + 'MESSAGE_OCTET_LENGTH': tokens.Keyword, + 'MESSAGE_TEXT': tokens.Keyword, + 'METHOD': tokens.Keyword, + 'MINUTE': tokens.Keyword, + 'MINVALUE': tokens.Keyword, + 'MOD': tokens.Keyword, + 'MODE': tokens.Keyword, + 'MODIFIES': tokens.Keyword, + 'MODIFY': tokens.Keyword, + 'MONTH': tokens.Keyword, + 'MORE': tokens.Keyword, + 'MOVE': tokens.Keyword, + 'MUMPS': tokens.Keyword, + + 'NAMES': tokens.Keyword, + 'NATIONAL': tokens.Keyword, + 'NATURAL': tokens.Keyword, + 'NCHAR': tokens.Keyword, + 'NCLOB': tokens.Keyword, + 'NEW': tokens.Keyword, + 'NEXT': tokens.Keyword, + 'NO': tokens.Keyword, + 'NOCREATEDB': tokens.Keyword, + 'NOCREATEUSER': tokens.Keyword, + 'NONE': tokens.Keyword, + 'NOT': tokens.Keyword, + 'NOTHING': tokens.Keyword, + 'NOTIFY': tokens.Keyword, + 'NOTNULL': tokens.Keyword, + 'NULL': tokens.Keyword, + 'NULLABLE': tokens.Keyword, + 'NULLIF': tokens.Keyword, + + 'OBJECT': tokens.Keyword, + 'OCTET_LENGTH': tokens.Keyword, + 'OF': tokens.Keyword, + 'OFF': tokens.Keyword, + 'OFFSET': tokens.Keyword, + 'OIDS': tokens.Keyword, + 'OLD': tokens.Keyword, + 'ONLY': tokens.Keyword, + 'OPEN': tokens.Keyword, + 'OPERATION': tokens.Keyword, + 'OPERATOR': tokens.Keyword, + 'OPTION': tokens.Keyword, + 'OPTIONS': tokens.Keyword, + 'ORDINALITY': tokens.Keyword, + 'OUT': tokens.Keyword, + 'OUTPUT': tokens.Keyword, + 'OVERLAPS': tokens.Keyword, + 'OVERLAY': tokens.Keyword, + 'OVERRIDING': tokens.Keyword, + 'OWNER': tokens.Keyword, + + 'PAD': tokens.Keyword, + 'PARAMETER': tokens.Keyword, + 'PARAMETERS': tokens.Keyword, + 'PARAMETER_MODE': tokens.Keyword, + 'PARAMATER_NAME': tokens.Keyword, + 'PARAMATER_ORDINAL_POSITION': tokens.Keyword, + 'PARAMETER_SPECIFIC_CATALOG': tokens.Keyword, + 'PARAMETER_SPECIFIC_NAME': tokens.Keyword, + 'PARAMATER_SPECIFIC_SCHEMA': tokens.Keyword, + 'PARTIAL': tokens.Keyword, + 'PASCAL': tokens.Keyword, + 'PENDANT': tokens.Keyword, + 'PLACING': tokens.Keyword, + 'PLI': tokens.Keyword, + 'POSITION': tokens.Keyword, + 'POSTFIX': tokens.Keyword, + 'PRECISION': tokens.Keyword, + 'PREFIX': tokens.Keyword, + 'PREORDER': tokens.Keyword, + 'PREPARE': tokens.Keyword, + 'PRESERVE': tokens.Keyword, + 'PRIMARY': tokens.Keyword, + 'PRIOR': tokens.Keyword, + 'PRIVILEGES': tokens.Keyword, + 'PROCEDURAL': tokens.Keyword, + 'PROCEDURE': tokens.Keyword, + 'PUBLIC': tokens.Keyword, + + 'RAISE': tokens.Keyword, + 'READ': tokens.Keyword, + 'READS': tokens.Keyword, + 'RECHECK': tokens.Keyword, + 'RECURSIVE': tokens.Keyword, + 'REF': tokens.Keyword, + 'REFERENCES': tokens.Keyword, + 'REFERENCING': tokens.Keyword, + 'REINDEX': tokens.Keyword, + 'RELATIVE': tokens.Keyword, + 'RENAME': tokens.Keyword, + 'REPEATABLE': tokens.Keyword, + 'RESET': tokens.Keyword, + 'RESTART': tokens.Keyword, + 'RESTRICT': tokens.Keyword, + 'RESULT': tokens.Keyword, + 'RETURN': tokens.Keyword, + 'RETURNED_LENGTH': tokens.Keyword, + 'RETURNED_OCTET_LENGTH': tokens.Keyword, + 'RETURNED_SQLSTATE': tokens.Keyword, + 'RETURNS': tokens.Keyword, + 'REVOKE': tokens.Keyword, + 'RIGHT': tokens.Keyword, + 'ROLE': tokens.Keyword, + 'ROLLBACK': tokens.Keyword, + 'ROLLUP': tokens.Keyword, + 'ROUTINE': tokens.Keyword, + 'ROUTINE_CATALOG': tokens.Keyword, + 'ROUTINE_NAME': tokens.Keyword, + 'ROUTINE_SCHEMA': tokens.Keyword, + 'ROW': tokens.Keyword, + 'ROWS': tokens.Keyword, + 'ROW_COUNT': tokens.Keyword, + 'RULE': tokens.Keyword, + + 'SAVE_POINT': tokens.Keyword, + 'SCALE': tokens.Keyword, + 'SCHEMA': tokens.Keyword, + 'SCHEMA_NAME': tokens.Keyword, + 'SCOPE': tokens.Keyword, + 'SCROLL': tokens.Keyword, + 'SEARCH': tokens.Keyword, + 'SECOND': tokens.Keyword, + 'SECURITY': tokens.Keyword, + 'SELF': tokens.Keyword, + 'SENSITIVE': tokens.Keyword, + 'SERIALIZABLE': tokens.Keyword, + 'SERVER_NAME': tokens.Keyword, + 'SESSION': tokens.Keyword, + 'SESSION_USER': tokens.Keyword, + 'SETOF': tokens.Keyword, + 'SETS': tokens.Keyword, + 'SHARE': tokens.Keyword, + 'SHOW': tokens.Keyword, + 'SIMILAR': tokens.Keyword, + 'SIMPLE': tokens.Keyword, + 'SIZE': tokens.Keyword, + 'SOME': tokens.Keyword, + 'SOURCE': tokens.Keyword, + 'SPACE': tokens.Keyword, + 'SPECIFIC': tokens.Keyword, + 'SPECIFICTYPE': tokens.Keyword, + 'SPECIFIC_NAME': tokens.Keyword, + 'SQL': tokens.Keyword, + 'SQLCODE': tokens.Keyword, + 'SQLERROR': tokens.Keyword, + 'SQLEXCEPTION': tokens.Keyword, + 'SQLSTATE': tokens.Keyword, + 'SQLWARNING': tokens.Keyword, + 'STABLE': tokens.Keyword, + 'START': tokens.Keyword, + 'STATE': tokens.Keyword, + 'STATEMENT': tokens.Keyword, + 'STATIC': tokens.Keyword, + 'STATISTICS': tokens.Keyword, + 'STDIN': tokens.Keyword, + 'STDOUT': tokens.Keyword, + 'STORAGE': tokens.Keyword, + 'STRICT': tokens.Keyword, + 'STRUCTURE': tokens.Keyword, + 'STYPE': tokens.Keyword, + 'SUBCLASS_ORIGIN': tokens.Keyword, + 'SUBLIST': tokens.Keyword, + 'SUBSTRING': tokens.Keyword, + 'SUM': tokens.Keyword, + 'SYMMETRIC': tokens.Keyword, + 'SYSID': tokens.Keyword, + 'SYSTEM': tokens.Keyword, + 'SYSTEM_USER': tokens.Keyword, + + 'TABLE': tokens.Keyword, + 'TABLE_NAME': tokens.Keyword, + ' TEMP': tokens.Keyword, + 'TEMPLATE': tokens.Keyword, + 'TEMPORARY': tokens.Keyword, + 'TERMINATE': tokens.Keyword, + 'THAN': tokens.Keyword, + 'TIMESTAMP': tokens.Keyword, + 'TIMEZONE_HOUR': tokens.Keyword, + 'TIMEZONE_MINUTE': tokens.Keyword, + 'TO': tokens.Keyword, + 'TOAST': tokens.Keyword, + 'TRAILING': tokens.Keyword, + 'TRANSATION': tokens.Keyword, + 'TRANSACTIONS_COMMITTED': tokens.Keyword, + 'TRANSACTIONS_ROLLED_BACK': tokens.Keyword, + 'TRANSATION_ACTIVE': tokens.Keyword, + 'TRANSFORM': tokens.Keyword, + 'TRANSFORMS': tokens.Keyword, + 'TRANSLATE': tokens.Keyword, + 'TRANSLATION': tokens.Keyword, + 'TREAT': tokens.Keyword, + 'TRIGGER': tokens.Keyword, + 'TRIGGER_CATALOG': tokens.Keyword, + 'TRIGGER_NAME': tokens.Keyword, + 'TRIGGER_SCHEMA': tokens.Keyword, + 'TRIM': tokens.Keyword, + 'TRUE': tokens.Keyword, + 'TRUNCATE': tokens.Keyword, + 'TRUSTED': tokens.Keyword, + 'TYPE': tokens.Keyword, + + 'UNCOMMITTED': tokens.Keyword, + 'UNDER': tokens.Keyword, + 'UNENCRYPTED': tokens.Keyword, + 'UNION': tokens.Keyword, + 'UNIQUE': tokens.Keyword, + 'UNKNOWN': tokens.Keyword, + 'UNLISTEN': tokens.Keyword, + 'UNNAMED': tokens.Keyword, + 'UNNEST': tokens.Keyword, + 'UNTIL': tokens.Keyword, + 'UPPER': tokens.Keyword, + 'USAGE': tokens.Keyword, + 'USER': tokens.Keyword, + 'USER_DEFINED_TYPE_CATALOG': tokens.Keyword, + 'USER_DEFINED_TYPE_NAME': tokens.Keyword, + 'USER_DEFINED_TYPE_SCHEMA': tokens.Keyword, + 'USING': tokens.Keyword, + + 'VACUUM': tokens.Keyword, + 'VALID': tokens.Keyword, + 'VALIDATOR': tokens.Keyword, + 'VALUES': tokens.Keyword, + 'VARIABLE': tokens.Keyword, + 'VERBOSE': tokens.Keyword, + 'VERSION': tokens.Keyword, + 'VIEW': tokens.Keyword, + 'VOLATILE': tokens.Keyword, + + 'WHENEVER': tokens.Keyword, + 'WITH': tokens.Keyword, + 'WITHOUT': tokens.Keyword, + 'WORK': tokens.Keyword, + 'WRITE': tokens.Keyword, + + 'YEAR': tokens.Keyword, + + 'ZONE': tokens.Keyword, + + + 'ARRAY': tokens.Name.Builtin, + 'BIGINT': tokens.Name.Builtin, + 'BINARY': tokens.Name.Builtin, + 'BIT': tokens.Name.Builtin, + 'BLOB': tokens.Name.Builtin, + 'BOOLEAN': tokens.Name.Builtin, + 'CHAR': tokens.Name.Builtin, + 'CHARACTER': tokens.Name.Builtin, + 'DATE': tokens.Name.Builtin, + 'DEC': tokens.Name.Builtin, + 'DECIMAL': tokens.Name.Builtin, + 'FLOAT': tokens.Name.Builtin, + 'INT': tokens.Name.Builtin, + 'INTEGER': tokens.Name.Builtin, + 'INTERVAL': tokens.Name.Builtin, + 'LONG': tokens.Name.Builtin, + 'NUMBER': tokens.Name.Builtin, + 'NUMERIC': tokens.Name.Builtin, + 'REAL': tokens.Name.Builtin, + 'SERIAL': tokens.Name.Builtin, + 'SMALLINT': tokens.Name.Builtin, + 'VARCHAR': tokens.Name.Builtin, + 'VARCHAR2': tokens.Name.Builtin, + 'VARYING': tokens.Name.Builtin, + 'INT8': tokens.Name.Builtin, + 'SERIAL8': tokens.Name.Builtin, + 'TEXT': tokens.Name.Builtin, } KEYWORDS_COMMON = { - 'SELECT': Keyword.DML, - 'INSERT': Keyword.DML, - 'DELETE': Keyword.DML, - 'UPDATE': Keyword.DML, - 'DROP': Keyword.DDL, - 'CREATE': Keyword.DDL, - 'ALTER': Keyword.DDL, - - 'WHERE': Keyword, - 'FROM': Keyword, - 'INNER': Keyword, - 'JOIN': Keyword, - 'AND': Keyword, - 'OR': Keyword, - 'LIKE': Keyword, - 'ON': Keyword, - 'IN': Keyword, - 'SET': Keyword, - - 'BY': Keyword, - 'GROUP': Keyword, - 'ORDER': Keyword, - 'LEFT': Keyword, - 'OUTER': Keyword, - - 'IF': Keyword, - 'END': Keyword, - 'THEN': Keyword, - 'LOOP': Keyword, - 'AS': Keyword, - 'ELSE': Keyword, - 'FOR': Keyword, - - 'CASE': Keyword, - 'WHEN': Keyword, - 'MIN': Keyword, - 'MAX': Keyword, - 'DISTINCT': Keyword, - + 'SELECT': tokens.Keyword.DML, + 'INSERT': tokens.Keyword.DML, + 'DELETE': tokens.Keyword.DML, + 'UPDATE': tokens.Keyword.DML, + 'REPLACE': tokens.Keyword.DML, + 'DROP': tokens.Keyword.DDL, + 'CREATE': tokens.Keyword.DDL, + 'ALTER': tokens.Keyword.DDL, + + 'WHERE': tokens.Keyword, + 'FROM': tokens.Keyword, + 'INNER': tokens.Keyword, + 'JOIN': tokens.Keyword, + 'AND': tokens.Keyword, + 'OR': tokens.Keyword, + 'LIKE': tokens.Keyword, + 'ON': tokens.Keyword, + 'IN': tokens.Keyword, + 'SET': tokens.Keyword, + + 'BY': tokens.Keyword, + 'GROUP': tokens.Keyword, + 'ORDER': tokens.Keyword, + 'LEFT': tokens.Keyword, + 'OUTER': tokens.Keyword, + + 'IF': tokens.Keyword, + 'END': tokens.Keyword, + 'THEN': tokens.Keyword, + 'LOOP': tokens.Keyword, + 'AS': tokens.Keyword, + 'ELSE': tokens.Keyword, + 'FOR': tokens.Keyword, + + 'CASE': tokens.Keyword, + 'WHEN': tokens.Keyword, + 'MIN': tokens.Keyword, + 'MAX': tokens.Keyword, + 'DISTINCT': tokens.Keyword, } diff --git a/debug_toolbar/utils/sqlparse/lexer.py b/debug_toolbar/utils/sqlparse/lexer.py index 727a4ff..ae3fc2e 100644 --- a/debug_toolbar/utils/sqlparse/lexer.py +++ b/debug_toolbar/utils/sqlparse/lexer.py @@ -14,14 +14,14 @@ import re +from debug_toolbar.utils.sqlparse import tokens from debug_toolbar.utils.sqlparse.keywords import KEYWORDS, KEYWORDS_COMMON -from debug_toolbar.utils.sqlparse.tokens import * -from debug_toolbar.utils.sqlparse.tokens import _TokenType class include(str): pass + class combined(tuple): """Indicates a state combined from multiple states.""" @@ -32,9 +32,10 @@ class combined(tuple): # tuple.__init__ doesn't do anything pass + def is_keyword(value): test = value.upper() - return KEYWORDS_COMMON.get(test, KEYWORDS.get(test, Name)), value + return KEYWORDS_COMMON.get(test, KEYWORDS.get(test, tokens.Name)), value def apply_filters(stream, filters, lexer=None): @@ -43,9 +44,11 @@ def apply_filters(stream, filters, lexer=None): a stream. If lexer is given it's forwarded to the filter, otherwise the filter receives `None`. """ + def _apply(filter_, stream): for token in filter_.filter(lexer, stream): yield token + for filter_ in filters: stream = _apply(filter_, stream) return stream @@ -62,13 +65,14 @@ class LexerMeta(type): assert state[0] != '#', "invalid state name %r" % state if state in processed: return processed[state] - tokens = processed[state] = [] + tokenlist = processed[state] = [] rflags = cls.flags for tdef in unprocessed[state]: if isinstance(tdef, include): # it's a state reference assert tdef != state, "circular state reference %r" % state - tokens.extend(cls._process_state(unprocessed, processed, str(tdef))) + tokenlist.extend(cls._process_state( + unprocessed, processed, str(tdef))) continue assert type(tdef) is tuple, "wrong rule def %r" % tdef @@ -76,11 +80,13 @@ class LexerMeta(type): try: rex = re.compile(tdef[0], rflags).match except Exception, err: - raise ValueError("uncompilable regex %r in state %r of %r: %s" % - (tdef[0], state, cls, err)) + raise ValueError(("uncompilable regex %r in state" + " %r of %r: %s" + % (tdef[0], state, cls, err))) - assert type(tdef[1]) is _TokenType or callable(tdef[1]), \ - 'token type must be simple type or callable, not %r' % (tdef[1],) + assert type(tdef[1]) is tokens._TokenType or callable(tdef[1]), \ + ('token type must be simple type or callable, not %r' + % (tdef[1],)) if len(tdef) == 2: new_state = None @@ -104,7 +110,8 @@ class LexerMeta(type): cls._tmpname += 1 itokens = [] for istate in tdef2: - assert istate != state, 'circular state ref %r' % istate + assert istate != state, \ + 'circular state ref %r' % istate itokens.extend(cls._process_state(unprocessed, processed, istate)) processed[new_state] = itokens @@ -118,8 +125,8 @@ class LexerMeta(type): new_state = tdef2 else: assert False, 'unknown new state def %r' % tdef2 - tokens.append((rex, tdef[1], new_state)) - return tokens + tokenlist.append((rex, tdef[1], new_state)) + return tokenlist def process_tokendef(cls): cls._all_tokens = {} @@ -143,9 +150,7 @@ class LexerMeta(type): return type.__call__(cls, *args, **kwds) - - -class Lexer: +class Lexer(object): __metaclass__ = LexerMeta @@ -157,41 +162,53 @@ class Lexer: tokens = { 'root': [ - (r'--.*?(\r|\n|\r\n)', Comment.Single), - (r'(\r|\n|\r\n)', Newline), - (r'\s+', Whitespace), - (r'/\*', Comment.Multiline, 'multiline-comments'), - (r':=', Assignment), - (r'::', Punctuation), - (r'[*]', Wildcard), - (r"`(``|[^`])*`", Name), - (r"´(´´|[^´])*´", Name), - (r'@[a-zA-Z_][a-zA-Z0-9_]+', Name), - (r'[+/<>=~!@#%^&|`?^-]', Operator), - (r'[0-9]+', Number.Integer), + (r'--.*?(\r\n|\r|\n)', tokens.Comment.Single), + # $ matches *before* newline, therefore we have two patterns + # to match Comment.Single + (r'--.*?$', tokens.Comment.Single), + (r'(\r|\n|\r\n)', tokens.Newline), + (r'\s+', tokens.Whitespace), + (r'/\*', tokens.Comment.Multiline, 'multiline-comments'), + (r':=', tokens.Assignment), + (r'::', tokens.Punctuation), + (r'[*]', tokens.Wildcard), + (r'CASE\b', tokens.Keyword), # extended CASE(foo) + (r"`(``|[^`])*`", tokens.Name), + (r"´(´´|[^´])*´", tokens.Name), + (r'\$([a-zA-Z_][a-zA-Z0-9_]*)?\$', tokens.Name.Builtin), + (r'\?{1}', tokens.Name.Placeholder), + (r'[$:?%][a-zA-Z0-9_]+[^$:?%]?', tokens.Name.Placeholder), + (r'@[a-zA-Z_][a-zA-Z0-9_]+', tokens.Name), + (r'[a-zA-Z_][a-zA-Z0-9_]*(?=[.(])', tokens.Name), # see issue39 + (r'[<>=~!]+', tokens.Operator.Comparison), + (r'[+/@#%^&|`?^-]+', tokens.Operator), + (r'0x[0-9a-fA-F]+', tokens.Number.Hexadecimal), + (r'[0-9]*\.[0-9]+', tokens.Number.Float), + (r'[0-9]+', tokens.Number.Integer), # TODO: Backslash escapes? - (r"'(''|[^'])*'", String.Single), - (r'"(""|[^"])*"', String.Symbol), # not a real string literal in ANSI SQL - (r'(LEFT |RIGHT )?(INNER |OUTER )?JOIN', Keyword), - (r'END( IF| LOOP)?', Keyword), - (r'CREATE( OR REPLACE)?', Keyword.DDL), + (r"(''|'.*?[^\\]')", tokens.String.Single), + # not a real string literal in ANSI SQL: + (r'(""|".*?[^\\]")', tokens.String.Symbol), + (r'(\[.*[^\]]\])', tokens.Name), + (r'(LEFT |RIGHT )?(INNER |OUTER )?JOIN\b', tokens.Keyword), + (r'END( IF| LOOP)?\b', tokens.Keyword), + (r'NOT NULL\b', tokens.Keyword), + (r'CREATE( OR REPLACE)?\b', tokens.Keyword.DDL), (r'[a-zA-Z_][a-zA-Z0-9_]*', is_keyword), - (r'\$([a-zA-Z_][a-zA-Z0-9_]*)?\$', Name.Builtin), - (r'[;:()\[\],\.]', Punctuation), + (r'[;:()\[\],\.]', tokens.Punctuation), ], 'multiline-comments': [ - (r'/\*', Comment.Multiline, 'multiline-comments'), - (r'\*/', Comment.Multiline, '#pop'), - (r'[^/\*]+', Comment.Multiline), - (r'[/*]', Comment.Multiline) - ] - } + (r'/\*', tokens.Comment.Multiline, 'multiline-comments'), + (r'\*/', tokens.Comment.Multiline, '#pop'), + (r'[^/\*]+', tokens.Comment.Multiline), + (r'[/*]', tokens.Comment.Multiline) + ]} def __init__(self): self.filters = [] def add_filter(self, filter_, **options): - from sqlparse.filters import Filter + from debug_toolbar.utils.sqlparse.filters import Filter if not isinstance(filter_, Filter): filter_ = filter_(**options) self.filters.append(filter_) @@ -241,7 +258,6 @@ class Lexer: stream = apply_filters(stream, self.filters, self) return stream - def get_tokens_unprocessed(self, text, stack=('root',)): """ Split ``text`` into (tokentype, text) pairs. @@ -261,7 +277,7 @@ class Lexer: value = m.group() if value in known_names: yield pos, known_names[value], value - elif type(action) is _TokenType: + elif type(action) is tokens._TokenType: yield pos, action, value elif hasattr(action, '__call__'): ttype, value = action(value) @@ -297,9 +313,9 @@ class Lexer: pos += 1 statestack = ['root'] statetokens = tokendefs['root'] - yield pos, Text, u'\n' + yield pos, tokens.Text, u'\n' continue - yield pos, Error, text[pos] + yield pos, tokens.Error, text[pos] pos += 1 except IndexError: break diff --git a/debug_toolbar/utils/sqlparse/sql.py b/debug_toolbar/utils/sqlparse/sql.py index 5bbb977..55bf804 100644 --- a/debug_toolbar/utils/sqlparse/sql.py +++ b/debug_toolbar/utils/sqlparse/sql.py @@ -3,7 +3,6 @@ """This module contains classes representing syntactical elements of SQL.""" import re -import types from debug_toolbar.utils.sqlparse import tokens as T @@ -16,14 +15,15 @@ class Token(object): the type of the token. """ - __slots__ = ('value', 'ttype',) + __slots__ = ('value', 'ttype', 'parent') def __init__(self, ttype, value): self.value = value self.ttype = ttype + self.parent = None def __str__(self): - return unicode(self).encode('latin-1') + return unicode(self).encode('utf-8') def __repr__(self): short = self._get_repr_value() @@ -43,7 +43,7 @@ class Token(object): def _get_repr_value(self): raw = unicode(self) if len(raw) > 7: - short = raw[:6]+u'...' + short = raw[:6] + u'...' else: short = raw return re.sub('\s+', ' ', short) @@ -59,12 +59,12 @@ class Token(object): type. *values* is a list of possible values for this token. The values are OR'ed together so if only one of the values matches ``True`` - is returned. Except for keyword tokens the comparsion is + is returned. Except for keyword tokens the comparison is case-sensitive. For convenience it's ok to pass in a single string. If *regex* is ``True`` (default is ``False``) the given values are treated as regular expressions. """ - type_matched = self.ttype in ttype + type_matched = self.ttype is ttype if not type_matched or values is None: return type_matched if isinstance(values, basestring): @@ -79,7 +79,7 @@ class Token(object): return True return False else: - if self.ttype is T.Keyword: + if self.ttype in T.Keyword: values = set([v.upper() for v in values]) return self.value.upper() in values else: @@ -93,6 +93,32 @@ class Token(object): """Return ``True`` if this token is a whitespace token.""" return self.ttype and self.ttype in T.Whitespace + def within(self, group_cls): + """Returns ``True`` if this token is within *group_cls*. + + Use this method for example to check if an identifier is within + a function: ``t.within(sql.Function)``. + """ + parent = self.parent + while parent: + if isinstance(parent, group_cls): + return True + parent = parent.parent + return False + + def is_child_of(self, other): + """Returns ``True`` if this token is a direct child of *other*.""" + return self.parent == other + + def has_ancestor(self, other): + """Returns ``True`` if *other* is in this tokens ancestry.""" + parent = self.parent + while parent: + if parent == other: + return True + parent = parent.parent + return False + class TokenList(Token): """A group of tokens. @@ -113,24 +139,24 @@ class TokenList(Token): return ''.join(unicode(x) for x in self.flatten()) def __str__(self): - return unicode(self).encode('latin-1') + return unicode(self).encode('utf-8') def _get_repr_name(self): return self.__class__.__name__ - ## def _pprint_tree(self, max_depth=None, depth=0): - ## """Pretty-print the object tree.""" - ## indent = ' '*(depth*2) - ## for token in self.tokens: - ## if token.is_group(): - ## pre = ' | ' - ## else: - ## pre = ' | ' - ## print '%s%s%s \'%s\'' % (indent, pre, token._get_repr_name(), - ## token._get_repr_value()) - ## if (token.is_group() and max_depth is not None - ## and depth < max_depth): - ## token._pprint_tree(max_depth, depth+1) + def _pprint_tree(self, max_depth=None, depth=0): + """Pretty-print the object tree.""" + indent = ' '*(depth*2) + for idx, token in enumerate(self.tokens): + if token.is_group(): + pre = ' +-' + else: + pre = ' | ' + print '%s%s%d %s \'%s\'' % (indent, pre, idx, + token._get_repr_name(), + token._get_repr_value()) + if (token.is_group() and (max_depth is None or depth < max_depth)): + token._pprint_tree(max_depth, depth+1) def flatten(self): """Generator yielding ungrouped tokens. @@ -150,6 +176,10 @@ class TokenList(Token): def get_sublists(self): return [x for x in self.tokens if isinstance(x, TokenList)] + @property + def _groupable_tokens(self): + return self.tokens + def token_first(self, ignore_whitespace=True): """Returns the first child token. @@ -190,7 +220,7 @@ class TokenList(Token): def token_next_match(self, idx, ttype, value, regex=False): """Returns next token where it's ``match`` method returns ``True``.""" - if type(idx) != types.IntType: + if not isinstance(idx, int): idx = self.token_index(idx) for token in self.tokens[idx:]: if token.match(ttype, value, regex): @@ -202,8 +232,8 @@ class TokenList(Token): passed = False for func in funcs: if func(token): - passed = True - break + passed = True + break if not passed: return token return None @@ -241,7 +271,7 @@ class TokenList(Token): return None if not isinstance(idx, int): idx = self.token_index(idx) - while idx < len(self.tokens)-1: + while idx < len(self.tokens) - 1: idx += 1 if self.tokens[idx].is_whitespace() and skip_ws: continue @@ -257,18 +287,27 @@ class TokenList(Token): If *exclude_end* is ``True`` (default is ``False``) the end token is included too. """ + # FIXME(andi): rename exclude_end to inlcude_end if exclude_end: offset = 0 else: offset = 1 - return self.tokens[self.token_index(start):self.token_index(end)+offset] + end_idx = self.token_index(end) + offset + start_idx = self.token_index(start) + return self.tokens[start_idx:end_idx] - def group_tokens(self, grp_cls, tokens): + def group_tokens(self, grp_cls, tokens, ignore_ws=False): """Replace tokens by an instance of *grp_cls*.""" idx = self.token_index(tokens[0]) + if ignore_ws: + while tokens and tokens[-1].is_whitespace(): + tokens = tokens[:-1] for t in tokens: self.tokens.remove(t) grp = grp_cls(tokens) + for token in tokens: + token.parent = grp + grp.parent = self self.tokens.insert(idx, grp) return grp @@ -290,7 +329,11 @@ class Statement(TokenList): isn't a DML or DDL keyword "UNKNOWN" is returned. """ first_token = self.token_first() - if first_token.ttype in (T.Keyword.DML, T.Keyword.DDL): + if first_token is None: + # An "empty" statement that either has not tokens at all + # or only whitespace tokens. + return 'UNKNOWN' + elif first_token.ttype in (T.Keyword.DML, T.Keyword.DDL): return first_token.value.upper() else: return 'UNKNOWN' @@ -397,27 +440,36 @@ class Parenthesis(TokenList): """Tokens between parenthesis.""" __slots__ = ('value', 'ttype', 'tokens') + @property + def _groupable_tokens(self): + return self.tokens[1:-1] + class Assignment(TokenList): """An assignment like 'var := val;'""" __slots__ = ('value', 'ttype', 'tokens') + class If(TokenList): """An 'if' clause with possible 'else if' or 'else' parts.""" __slots__ = ('value', 'ttype', 'tokens') + class For(TokenList): """A 'FOR' loop.""" __slots__ = ('value', 'ttype', 'tokens') -class Comparsion(TokenList): - """A comparsion used for example in WHERE clauses.""" + +class Comparison(TokenList): + """A comparison used for example in WHERE clauses.""" __slots__ = ('value', 'ttype', 'tokens') + class Comment(TokenList): """A comment.""" __slots__ = ('value', 'ttype', 'tokens') + class Where(TokenList): """A WHERE clause.""" __slots__ = ('value', 'ttype', 'tokens') @@ -434,9 +486,12 @@ class Case(TokenList): If an ELSE exists condition is None. """ ret = [] - in_condition = in_value = False + in_value = False + in_condition = True for token in self.tokens: - if token.match(T.Keyword, 'WHEN'): + if token.match(T.Keyword, 'CASE'): + continue + elif token.match(T.Keyword, 'WHEN'): ret.append(([], [])) in_condition = True in_value = False @@ -450,8 +505,25 @@ class Case(TokenList): elif token.match(T.Keyword, 'END'): in_condition = False in_value = False + if (in_condition or in_value) and not ret: + # First condition withou preceding WHEN + ret.append(([], [])) if in_condition: ret[-1][0].append(token) elif in_value: ret[-1][1].append(token) return ret + + +class Function(TokenList): + """A function or procedure call.""" + + __slots__ = ('value', 'ttype', 'tokens') + + def get_parameters(self): + """Return a list of parameters.""" + parenthesis = self.tokens[-1] + for t in parenthesis.tokens: + if isinstance(t, IdentifierList): + return t.get_identifiers() + return [] diff --git a/debug_toolbar/utils/sqlparse/tokens.py b/debug_toolbar/utils/sqlparse/tokens.py index 2c63c41..01a9b89 100644 --- a/debug_toolbar/utils/sqlparse/tokens.py +++ b/debug_toolbar/utils/sqlparse/tokens.py @@ -9,11 +9,6 @@ """Tokens""" -try: - set -except NameError: - from sets import Set as set - class _TokenType(tuple): parent = None @@ -27,22 +22,14 @@ class _TokenType(tuple): buf.reverse() return buf - def __init__(self, *args): - # no need to call super.__init__ - self.subtypes = set() - def __contains__(self, val): - return self is val or ( - type(val) is self.__class__ and - val[:len(self)] == self - ) + return val is not None and (self is val or val[:len(self)] == self) def __getattr__(self, val): if not val or not val[0].isupper(): return tuple.__getattribute__(self, val) new = _TokenType(self + (val,)) setattr(self, val, new) - self.subtypes.add(new) new.parent = self return new @@ -53,30 +40,31 @@ class _TokenType(tuple): return 'Token' + (self and '.' or '') + '.'.join(self) -Token = _TokenType() +Token = _TokenType() # Special token types -Text = Token.Text -Whitespace = Text.Whitespace -Newline = Whitespace.Newline -Error = Token.Error +Text = Token.Text +Whitespace = Text.Whitespace +Newline = Whitespace.Newline +Error = Token.Error # Text that doesn't belong to this lexer (e.g. HTML in PHP) -Other = Token.Other +Other = Token.Other # Common token types for source code -Keyword = Token.Keyword -Name = Token.Name -Literal = Token.Literal -String = Literal.String -Number = Literal.Number +Keyword = Token.Keyword +Name = Token.Name +Literal = Token.Literal +String = Literal.String +Number = Literal.Number Punctuation = Token.Punctuation -Operator = Token.Operator -Wildcard = Token.Wildcard -Comment = Token.Comment -Assignment = Token.Assignement +Operator = Token.Operator +Comparison = Operator.Comparison +Wildcard = Token.Wildcard +Comment = Token.Comment +Assignment = Token.Assignement # Generic types for non-source code -Generic = Token.Generic +Generic = Token.Generic # String and some others are not direct childs of Token. # alias them: @@ -93,39 +81,3 @@ Group = Token.Group Group.Parenthesis = Token.Group.Parenthesis Group.Comment = Token.Group.Comment Group.Where = Token.Group.Where - - -def is_token_subtype(ttype, other): - """ - Return True if ``ttype`` is a subtype of ``other``. - - exists for backwards compatibility. use ``ttype in other`` now. - """ - return ttype in other - - -def string_to_tokentype(s): - """ - Convert a string into a token type:: - - >>> string_to_token('String.Double') - Token.Literal.String.Double - >>> string_to_token('Token.Literal.Number') - Token.Literal.Number - >>> string_to_token('') - Token - - Tokens that are already tokens are returned unchanged: - - >>> string_to_token(String) - Token.Literal.String - """ - if isinstance(s, _TokenType): - return s - if not s: - return Token - node = Token - for item in s.split('.'): - node = getattr(node, item) - return node - diff --git a/debug_toolbar/utils/tracking/db.py b/debug_toolbar/utils/tracking/db.py index 7ffacef..97a9241 100644 --- a/debug_toolbar/utils/tracking/db.py +++ b/debug_toolbar/utils/tracking/db.py @@ -2,6 +2,7 @@ import inspect import sys from datetime import datetime +from threading import local from django.conf import settings from django.template import Node @@ -16,7 +17,41 @@ from debug_toolbar.utils.compat.db import connections SQL_WARNING_THRESHOLD = getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}) \ .get('SQL_WARNING_THRESHOLD', 500) -class CursorWrapper(object): +class SQLQueryTriggered(Exception): + """Thrown when template panel triggers a query""" + pass + +class ThreadLocalState(local): + def __init__(self): + self.enabled = True + + @property + def Wrapper(self): + if self.enabled: + return NormalCursorWrapper + return ExceptionCursorWrapper + + def recording(self, v): + self.enabled = v + +state = ThreadLocalState() +recording = state.recording # export function + +def CursorWrapper(*args, **kwds): # behave like a class + return state.Wrapper(*args, **kwds) + +class ExceptionCursorWrapper(object): + """ + Wraps a cursor and raises an exception on any operation. + Used in Templates panel. + """ + def __init__(self, cursor, db, logger): + pass + + def __getattr__(self, attr): + raise SQLQueryTriggered() + +class NormalCursorWrapper(object): """ Wraps a cursor and logs queries. """ @@ -103,4 +138,4 @@ class CursorWrapper(object): return getattr(self.cursor, attr) def __iter__(self): - return iter(self.cursor)
\ No newline at end of file + return iter(self.cursor) |
