diff options
820 files changed, 50607 insertions, 483 deletions
diff --git a/askbot/locale/es/LC_MESSAGES/django.po b/askbot/locale/es/LC_MESSAGES/django.po index 869b3d58..2e135592 100644 --- a/askbot/locale/es/LC_MESSAGES/django.po +++ b/askbot/locale/es/LC_MESSAGES/django.po @@ -119,11 +119,11 @@ msgstr "" #: forms.py:175 const/__init__.py:219 msgid "approved" -msgstr "" +msgstr "aprobado" #: forms.py:176 const/__init__.py:220 msgid "watched" -msgstr "" +msgstr "visto" #: forms.py:177 const/__init__.py:221 #, fuzzy @@ -132,7 +132,7 @@ msgstr "actualizado" #: forms.py:178 const/__init__.py:222 msgid "blocked" -msgstr "" +msgstr "bloqueado" #: forms.py:180 const/__init__.py:218 #, fuzzy @@ -155,11 +155,11 @@ msgstr "no se puede votar por sus propias publicaciones" #: forms.py:254 msgid "Cannot turn other user to moderator" -msgstr "" +msgstr "No tiene permitido habilitar a otros usuarios como moderadores" #: forms.py:261 msgid "Cannot change status of another moderator" -msgstr "No esta permitido cambiar el estado de otro moderador" +msgstr "No tiene permitido cambiar el estado de otro moderador" #: forms.py:267 #, python-format @@ -168,7 +168,7 @@ msgstr "" #: forms.py:276 msgid "Subject line" -msgstr "" +msgstr "Sujeto" #: forms.py:283 msgid "Message text" @@ -401,12 +401,12 @@ msgstr "" #: conf/email.py:47 msgid "Require email verification before allowing to post" -msgstr "" +msgstr "Es requerida una verificación via email antes de poder publicar" #: conf/email.py:48 msgid "" "Active email verification is done by sending a verification key in email" -msgstr "" +msgstr "Se ha comenzado el proceso de verificación con una llave enviada a su correo electrónico" #: conf/email.py:57 #, fuzzy @@ -423,7 +423,7 @@ msgstr "" #: conf/email.py:76 msgid "Prefix for the email subject line" -msgstr "" +msgstr "Prefijo para el campo de correo electrónico" #: conf/external_keys.py:11 msgid "Keys to connect the site with external services like Facebook, etc." @@ -431,7 +431,7 @@ msgstr "" #: conf/external_keys.py:18 msgid "Google site verification key" -msgstr "" +msgstr "Llave de verificación de Google site" #: conf/external_keys.py:20 #, python-format @@ -442,7 +442,7 @@ msgstr "" #: conf/external_keys.py:34 msgid "Google Analytics key" -msgstr "" +msgstr "LLave de Googne Analytics" #: conf/external_keys.py:36 #, python-format @@ -453,8 +453,7 @@ msgstr "" #: conf/external_keys.py:49 msgid "Enable recaptcha (keys below are required)" -msgstr "" - +msgstr "Habilitar recaptcha (las llaves de abajo son requeridas)" #: conf/external_keys.py:58 msgid "Recaptcha public key" msgstr "Llave pública de Recaptcha" @@ -483,7 +482,7 @@ msgstr "" #: conf/external_keys.py:95 msgid "Facebook secret key" -msgstr "" +msgstr "Llave privada de Facebook" #: conf/external_keys.py:103 msgid "Twitter consumer key" @@ -530,7 +529,7 @@ msgstr "" #: conf/flatpages.py:17 msgid "Text of the Q&A forum About page (html format)" -msgstr "" +msgstr "Texto para la página de descripción del foro (formato html)" #: conf/flatpages.py:20 msgid "" @@ -540,7 +539,7 @@ msgstr "" #: conf/flatpages.py:30 msgid "Text of the Q&A forum Privacy Policy (html format)" -msgstr "" +msgstr "Texto para la página de politicas de privacidad del foro (formato html)" #: conf/flatpages.py:33 msgid "" @@ -571,7 +570,7 @@ msgstr "Tamaño máximo de un comentario, debe ser menor a %(max_len)s" #: conf/forum_data_rules.py:60 msgid "Minimum length of search term for Ajax search" -msgstr "" +msgstr "Tamaño minimo para terminos de búsqueda Ajax " #: conf/forum_data_rules.py:61 msgid "Must match the corresponding database backend setting" @@ -630,7 +629,7 @@ msgstr "" #: conf/minimum_reputation.py:11 msgid "Minimum reputation required to perform actions" -msgstr "" +msgstr "Para realizar acciones es requerido una reputación mÃnima" #: conf/minimum_reputation.py:20 #, fuzzy @@ -702,7 +701,7 @@ msgstr "ver preguntas etiquetadas" #: conf/minimum_reputation.py:146 msgid "Lock posts" -msgstr "" +msgstr "Bloquear entradas" #: conf/reputation_changes.py:12 msgid "Reputation loss and gain rules" @@ -793,7 +792,7 @@ msgstr "Acerca de" #: conf/site_settings.py:59 msgid "Short name for your Q&A forum" -msgstr "" +msgstr "Nombre corto para tu foro" #: conf/site_settings.py:69 msgid "Base URL for your Q&A forum, must start with http or https" @@ -1509,7 +1508,7 @@ msgstr "" #: deps/django_authopenid/views.py:513 msgid "Account recovery email sent" -msgstr "" +msgstr "Se envio el correo para recuperación de cuenta" #: deps/django_authopenid/views.py:516 msgid "Please add one or more login methods." diff --git a/askbot/skins/common/media/images/flags/ad.gif b/askbot/skins/common/media/images/flags/ad.gif Binary files differnew file mode 100755 index 00000000..57b49973 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ad.gif diff --git a/askbot/skins/common/media/images/flags/ae.gif b/askbot/skins/common/media/images/flags/ae.gif Binary files differnew file mode 100755 index 00000000..78d15b67 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ae.gif diff --git a/askbot/skins/common/media/images/flags/af.gif b/askbot/skins/common/media/images/flags/af.gif Binary files differnew file mode 100755 index 00000000..98894082 --- /dev/null +++ b/askbot/skins/common/media/images/flags/af.gif diff --git a/askbot/skins/common/media/images/flags/ag.gif b/askbot/skins/common/media/images/flags/ag.gif Binary files differnew file mode 100755 index 00000000..48f8e7bc --- /dev/null +++ b/askbot/skins/common/media/images/flags/ag.gif diff --git a/askbot/skins/common/media/images/flags/ai.gif b/askbot/skins/common/media/images/flags/ai.gif Binary files differnew file mode 100755 index 00000000..1cbc5795 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ai.gif diff --git a/askbot/skins/common/media/images/flags/al.gif b/askbot/skins/common/media/images/flags/al.gif Binary files differnew file mode 100755 index 00000000..c44fe0a0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/al.gif diff --git a/askbot/skins/common/media/images/flags/am.gif b/askbot/skins/common/media/images/flags/am.gif Binary files differnew file mode 100755 index 00000000..2915e30c --- /dev/null +++ b/askbot/skins/common/media/images/flags/am.gif diff --git a/askbot/skins/common/media/images/flags/an.gif b/askbot/skins/common/media/images/flags/an.gif Binary files differnew file mode 100755 index 00000000..cb570c67 --- /dev/null +++ b/askbot/skins/common/media/images/flags/an.gif diff --git a/askbot/skins/common/media/images/flags/ao.gif b/askbot/skins/common/media/images/flags/ao.gif Binary files differnew file mode 100644 index 00000000..8c854fa1 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ao.gif diff --git a/askbot/skins/common/media/images/flags/ar.gif b/askbot/skins/common/media/images/flags/ar.gif Binary files differnew file mode 100755 index 00000000..a9f71f7d --- /dev/null +++ b/askbot/skins/common/media/images/flags/ar.gif diff --git a/askbot/skins/common/media/images/flags/as.gif b/askbot/skins/common/media/images/flags/as.gif Binary files differnew file mode 100755 index 00000000..d776ec27 --- /dev/null +++ b/askbot/skins/common/media/images/flags/as.gif diff --git a/askbot/skins/common/media/images/flags/at.gif b/askbot/skins/common/media/images/flags/at.gif Binary files differnew file mode 100755 index 00000000..87e12173 --- /dev/null +++ b/askbot/skins/common/media/images/flags/at.gif diff --git a/askbot/skins/common/media/images/flags/au.gif b/askbot/skins/common/media/images/flags/au.gif Binary files differnew file mode 100755 index 00000000..5269c6a0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/au.gif diff --git a/askbot/skins/common/media/images/flags/aw.gif b/askbot/skins/common/media/images/flags/aw.gif Binary files differnew file mode 100755 index 00000000..27fdb4d1 --- /dev/null +++ b/askbot/skins/common/media/images/flags/aw.gif diff --git a/askbot/skins/common/media/images/flags/ax.gif b/askbot/skins/common/media/images/flags/ax.gif Binary files differnew file mode 100755 index 00000000..0ceb6849 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ax.gif diff --git a/askbot/skins/common/media/images/flags/az.gif b/askbot/skins/common/media/images/flags/az.gif Binary files differnew file mode 100755 index 00000000..d7716184 --- /dev/null +++ b/askbot/skins/common/media/images/flags/az.gif diff --git a/askbot/skins/common/media/images/flags/ba.gif b/askbot/skins/common/media/images/flags/ba.gif Binary files differnew file mode 100755 index 00000000..9bf5f0ac --- /dev/null +++ b/askbot/skins/common/media/images/flags/ba.gif diff --git a/askbot/skins/common/media/images/flags/bb.gif b/askbot/skins/common/media/images/flags/bb.gif Binary files differnew file mode 100755 index 00000000..b7d08e57 --- /dev/null +++ b/askbot/skins/common/media/images/flags/bb.gif diff --git a/askbot/skins/common/media/images/flags/bd.gif b/askbot/skins/common/media/images/flags/bd.gif Binary files differnew file mode 100755 index 00000000..0fd27eca --- /dev/null +++ b/askbot/skins/common/media/images/flags/bd.gif diff --git a/askbot/skins/common/media/images/flags/be.gif b/askbot/skins/common/media/images/flags/be.gif Binary files differnew file mode 100755 index 00000000..ae09bfbe --- /dev/null +++ b/askbot/skins/common/media/images/flags/be.gif diff --git a/askbot/skins/common/media/images/flags/bf.gif b/askbot/skins/common/media/images/flags/bf.gif Binary files differnew file mode 100755 index 00000000..9d6772cd --- /dev/null +++ b/askbot/skins/common/media/images/flags/bf.gif diff --git a/askbot/skins/common/media/images/flags/bg.gif b/askbot/skins/common/media/images/flags/bg.gif Binary files differnew file mode 100755 index 00000000..11cf8ff3 --- /dev/null +++ b/askbot/skins/common/media/images/flags/bg.gif diff --git a/askbot/skins/common/media/images/flags/bh.gif b/askbot/skins/common/media/images/flags/bh.gif Binary files differnew file mode 100755 index 00000000..56aa72b2 --- /dev/null +++ b/askbot/skins/common/media/images/flags/bh.gif diff --git a/askbot/skins/common/media/images/flags/bi.gif b/askbot/skins/common/media/images/flags/bi.gif Binary files differnew file mode 100755 index 00000000..6e2cbe12 --- /dev/null +++ b/askbot/skins/common/media/images/flags/bi.gif diff --git a/askbot/skins/common/media/images/flags/bj.gif b/askbot/skins/common/media/images/flags/bj.gif Binary files differnew file mode 100755 index 00000000..e676116f --- /dev/null +++ b/askbot/skins/common/media/images/flags/bj.gif diff --git a/askbot/skins/common/media/images/flags/bm.gif b/askbot/skins/common/media/images/flags/bm.gif Binary files differnew file mode 100755 index 00000000..9feb87bc --- /dev/null +++ b/askbot/skins/common/media/images/flags/bm.gif diff --git a/askbot/skins/common/media/images/flags/bn.gif b/askbot/skins/common/media/images/flags/bn.gif Binary files differnew file mode 100755 index 00000000..b7b6b0f9 --- /dev/null +++ b/askbot/skins/common/media/images/flags/bn.gif diff --git a/askbot/skins/common/media/images/flags/bo.gif b/askbot/skins/common/media/images/flags/bo.gif Binary files differnew file mode 100755 index 00000000..4844f856 --- /dev/null +++ b/askbot/skins/common/media/images/flags/bo.gif diff --git a/askbot/skins/common/media/images/flags/br.gif b/askbot/skins/common/media/images/flags/br.gif Binary files differnew file mode 100755 index 00000000..8c866162 --- /dev/null +++ b/askbot/skins/common/media/images/flags/br.gif diff --git a/askbot/skins/common/media/images/flags/bs.gif b/askbot/skins/common/media/images/flags/bs.gif Binary files differnew file mode 100755 index 00000000..c0a741e5 --- /dev/null +++ b/askbot/skins/common/media/images/flags/bs.gif diff --git a/askbot/skins/common/media/images/flags/bt.gif b/askbot/skins/common/media/images/flags/bt.gif Binary files differnew file mode 100755 index 00000000..abe2f3cc --- /dev/null +++ b/askbot/skins/common/media/images/flags/bt.gif diff --git a/askbot/skins/common/media/images/flags/bv.gif b/askbot/skins/common/media/images/flags/bv.gif Binary files differnew file mode 100755 index 00000000..6202d1f3 --- /dev/null +++ b/askbot/skins/common/media/images/flags/bv.gif diff --git a/askbot/skins/common/media/images/flags/bw.gif b/askbot/skins/common/media/images/flags/bw.gif Binary files differnew file mode 100755 index 00000000..986ab63c --- /dev/null +++ b/askbot/skins/common/media/images/flags/bw.gif diff --git a/askbot/skins/common/media/images/flags/by.gif b/askbot/skins/common/media/images/flags/by.gif Binary files differnew file mode 100755 index 00000000..43ffcd4c --- /dev/null +++ b/askbot/skins/common/media/images/flags/by.gif diff --git a/askbot/skins/common/media/images/flags/bz.gif b/askbot/skins/common/media/images/flags/bz.gif Binary files differnew file mode 100755 index 00000000..791737f0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/bz.gif diff --git a/askbot/skins/common/media/images/flags/ca.gif b/askbot/skins/common/media/images/flags/ca.gif Binary files differnew file mode 100755 index 00000000..457d9662 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ca.gif diff --git a/askbot/skins/common/media/images/flags/catalonia.gif b/askbot/skins/common/media/images/flags/catalonia.gif Binary files differnew file mode 100644 index 00000000..73df9a04 --- /dev/null +++ b/askbot/skins/common/media/images/flags/catalonia.gif diff --git a/askbot/skins/common/media/images/flags/cc.gif b/askbot/skins/common/media/images/flags/cc.gif Binary files differnew file mode 100755 index 00000000..3f783270 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cc.gif diff --git a/askbot/skins/common/media/images/flags/cd.gif b/askbot/skins/common/media/images/flags/cd.gif Binary files differnew file mode 100644 index 00000000..1df717ae --- /dev/null +++ b/askbot/skins/common/media/images/flags/cd.gif diff --git a/askbot/skins/common/media/images/flags/cf.gif b/askbot/skins/common/media/images/flags/cf.gif Binary files differnew file mode 100755 index 00000000..35787ca4 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cf.gif diff --git a/askbot/skins/common/media/images/flags/cg.gif b/askbot/skins/common/media/images/flags/cg.gif Binary files differnew file mode 100755 index 00000000..e0a62a51 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cg.gif diff --git a/askbot/skins/common/media/images/flags/ch.gif b/askbot/skins/common/media/images/flags/ch.gif Binary files differnew file mode 100755 index 00000000..d5c0e5b7 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ch.gif diff --git a/askbot/skins/common/media/images/flags/ci.gif b/askbot/skins/common/media/images/flags/ci.gif Binary files differnew file mode 100755 index 00000000..844120a5 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ci.gif diff --git a/askbot/skins/common/media/images/flags/ck.gif b/askbot/skins/common/media/images/flags/ck.gif Binary files differnew file mode 100755 index 00000000..2edb7399 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ck.gif diff --git a/askbot/skins/common/media/images/flags/cl.gif b/askbot/skins/common/media/images/flags/cl.gif Binary files differnew file mode 100755 index 00000000..cbc370e6 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cl.gif diff --git a/askbot/skins/common/media/images/flags/cm.gif b/askbot/skins/common/media/images/flags/cm.gif Binary files differnew file mode 100755 index 00000000..1fb102b2 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cm.gif diff --git a/askbot/skins/common/media/images/flags/cn.gif b/askbot/skins/common/media/images/flags/cn.gif Binary files differnew file mode 100755 index 00000000..b0525309 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cn.gif diff --git a/askbot/skins/common/media/images/flags/co.gif b/askbot/skins/common/media/images/flags/co.gif Binary files differnew file mode 100755 index 00000000..d0e15caf --- /dev/null +++ b/askbot/skins/common/media/images/flags/co.gif diff --git a/askbot/skins/common/media/images/flags/cr.gif b/askbot/skins/common/media/images/flags/cr.gif Binary files differnew file mode 100755 index 00000000..0728dd6a --- /dev/null +++ b/askbot/skins/common/media/images/flags/cr.gif diff --git a/askbot/skins/common/media/images/flags/cs.gif b/askbot/skins/common/media/images/flags/cs.gif Binary files differnew file mode 100755 index 00000000..101db649 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cs.gif diff --git a/askbot/skins/common/media/images/flags/cu.gif b/askbot/skins/common/media/images/flags/cu.gif Binary files differnew file mode 100755 index 00000000..291255ca --- /dev/null +++ b/askbot/skins/common/media/images/flags/cu.gif diff --git a/askbot/skins/common/media/images/flags/cv.gif b/askbot/skins/common/media/images/flags/cv.gif Binary files differnew file mode 100755 index 00000000..43c6c6cb --- /dev/null +++ b/askbot/skins/common/media/images/flags/cv.gif diff --git a/askbot/skins/common/media/images/flags/cx.gif b/askbot/skins/common/media/images/flags/cx.gif Binary files differnew file mode 100755 index 00000000..a5b43089 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cx.gif diff --git a/askbot/skins/common/media/images/flags/cy.gif b/askbot/skins/common/media/images/flags/cy.gif Binary files differnew file mode 100755 index 00000000..35c661e1 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cy.gif diff --git a/askbot/skins/common/media/images/flags/cz.gif b/askbot/skins/common/media/images/flags/cz.gif Binary files differnew file mode 100755 index 00000000..0a605e58 --- /dev/null +++ b/askbot/skins/common/media/images/flags/cz.gif diff --git a/askbot/skins/common/media/images/flags/de.gif b/askbot/skins/common/media/images/flags/de.gif Binary files differnew file mode 100755 index 00000000..75728ddf --- /dev/null +++ b/askbot/skins/common/media/images/flags/de.gif diff --git a/askbot/skins/common/media/images/flags/dj.gif b/askbot/skins/common/media/images/flags/dj.gif Binary files differnew file mode 100755 index 00000000..212406d9 --- /dev/null +++ b/askbot/skins/common/media/images/flags/dj.gif diff --git a/askbot/skins/common/media/images/flags/dk.gif b/askbot/skins/common/media/images/flags/dk.gif Binary files differnew file mode 100755 index 00000000..03e75bd2 --- /dev/null +++ b/askbot/skins/common/media/images/flags/dk.gif diff --git a/askbot/skins/common/media/images/flags/dm.gif b/askbot/skins/common/media/images/flags/dm.gif Binary files differnew file mode 100755 index 00000000..2f87f3ca --- /dev/null +++ b/askbot/skins/common/media/images/flags/dm.gif diff --git a/askbot/skins/common/media/images/flags/do.gif b/askbot/skins/common/media/images/flags/do.gif Binary files differnew file mode 100755 index 00000000..f7d0bad3 --- /dev/null +++ b/askbot/skins/common/media/images/flags/do.gif diff --git a/askbot/skins/common/media/images/flags/dz.gif b/askbot/skins/common/media/images/flags/dz.gif Binary files differnew file mode 100755 index 00000000..ed580a7c --- /dev/null +++ b/askbot/skins/common/media/images/flags/dz.gif diff --git a/askbot/skins/common/media/images/flags/ec.gif b/askbot/skins/common/media/images/flags/ec.gif Binary files differnew file mode 100755 index 00000000..9e41e0ec --- /dev/null +++ b/askbot/skins/common/media/images/flags/ec.gif diff --git a/askbot/skins/common/media/images/flags/ee.gif b/askbot/skins/common/media/images/flags/ee.gif Binary files differnew file mode 100755 index 00000000..9397a2d0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ee.gif diff --git a/askbot/skins/common/media/images/flags/eg.gif b/askbot/skins/common/media/images/flags/eg.gif Binary files differnew file mode 100755 index 00000000..6857c7dd --- /dev/null +++ b/askbot/skins/common/media/images/flags/eg.gif diff --git a/askbot/skins/common/media/images/flags/eh.gif b/askbot/skins/common/media/images/flags/eh.gif Binary files differnew file mode 100755 index 00000000..dd0391c2 --- /dev/null +++ b/askbot/skins/common/media/images/flags/eh.gif diff --git a/askbot/skins/common/media/images/flags/england.gif b/askbot/skins/common/media/images/flags/england.gif Binary files differnew file mode 100755 index 00000000..933a4f0b --- /dev/null +++ b/askbot/skins/common/media/images/flags/england.gif diff --git a/askbot/skins/common/media/images/flags/er.gif b/askbot/skins/common/media/images/flags/er.gif Binary files differnew file mode 100755 index 00000000..3d4d612c --- /dev/null +++ b/askbot/skins/common/media/images/flags/er.gif diff --git a/askbot/skins/common/media/images/flags/es.gif b/askbot/skins/common/media/images/flags/es.gif Binary files differnew file mode 100755 index 00000000..c27d65e5 --- /dev/null +++ b/askbot/skins/common/media/images/flags/es.gif diff --git a/askbot/skins/common/media/images/flags/et.gif b/askbot/skins/common/media/images/flags/et.gif Binary files differnew file mode 100755 index 00000000..f77995d0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/et.gif diff --git a/askbot/skins/common/media/images/flags/europeanunion.gif b/askbot/skins/common/media/images/flags/europeanunion.gif Binary files differnew file mode 100644 index 00000000..28a762a5 --- /dev/null +++ b/askbot/skins/common/media/images/flags/europeanunion.gif diff --git a/askbot/skins/common/media/images/flags/fam.gif b/askbot/skins/common/media/images/flags/fam.gif Binary files differnew file mode 100755 index 00000000..7d528852 --- /dev/null +++ b/askbot/skins/common/media/images/flags/fam.gif diff --git a/askbot/skins/common/media/images/flags/fi.gif b/askbot/skins/common/media/images/flags/fi.gif Binary files differnew file mode 100755 index 00000000..8d3a1918 --- /dev/null +++ b/askbot/skins/common/media/images/flags/fi.gif diff --git a/askbot/skins/common/media/images/flags/fj.gif b/askbot/skins/common/media/images/flags/fj.gif Binary files differnew file mode 100755 index 00000000..486151cb --- /dev/null +++ b/askbot/skins/common/media/images/flags/fj.gif diff --git a/askbot/skins/common/media/images/flags/fk.gif b/askbot/skins/common/media/images/flags/fk.gif Binary files differnew file mode 100755 index 00000000..37b5ecf3 --- /dev/null +++ b/askbot/skins/common/media/images/flags/fk.gif diff --git a/askbot/skins/common/media/images/flags/fm.gif b/askbot/skins/common/media/images/flags/fm.gif Binary files differnew file mode 100755 index 00000000..7f8723b7 --- /dev/null +++ b/askbot/skins/common/media/images/flags/fm.gif diff --git a/askbot/skins/common/media/images/flags/fo.gif b/askbot/skins/common/media/images/flags/fo.gif Binary files differnew file mode 100755 index 00000000..4a90fc04 --- /dev/null +++ b/askbot/skins/common/media/images/flags/fo.gif diff --git a/askbot/skins/common/media/images/flags/fr.gif b/askbot/skins/common/media/images/flags/fr.gif Binary files differnew file mode 100755 index 00000000..43d0b801 --- /dev/null +++ b/askbot/skins/common/media/images/flags/fr.gif diff --git a/askbot/skins/common/media/images/flags/ga.gif b/askbot/skins/common/media/images/flags/ga.gif Binary files differnew file mode 100755 index 00000000..23fd5f0d --- /dev/null +++ b/askbot/skins/common/media/images/flags/ga.gif diff --git a/askbot/skins/common/media/images/flags/gb.gif b/askbot/skins/common/media/images/flags/gb.gif Binary files differnew file mode 100644 index 00000000..3c6bce15 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gb.gif diff --git a/askbot/skins/common/media/images/flags/gd.gif b/askbot/skins/common/media/images/flags/gd.gif Binary files differnew file mode 100755 index 00000000..25ea3123 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gd.gif diff --git a/askbot/skins/common/media/images/flags/ge.gif b/askbot/skins/common/media/images/flags/ge.gif Binary files differnew file mode 100755 index 00000000..faa7f126 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ge.gif diff --git a/askbot/skins/common/media/images/flags/gf.gif b/askbot/skins/common/media/images/flags/gf.gif Binary files differnew file mode 100755 index 00000000..43d0b801 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gf.gif diff --git a/askbot/skins/common/media/images/flags/gh.gif b/askbot/skins/common/media/images/flags/gh.gif Binary files differnew file mode 100755 index 00000000..273fb7d1 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gh.gif diff --git a/askbot/skins/common/media/images/flags/gi.gif b/askbot/skins/common/media/images/flags/gi.gif Binary files differnew file mode 100755 index 00000000..7b1984bc --- /dev/null +++ b/askbot/skins/common/media/images/flags/gi.gif diff --git a/askbot/skins/common/media/images/flags/gl.gif b/askbot/skins/common/media/images/flags/gl.gif Binary files differnew file mode 100755 index 00000000..ef445be0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gl.gif diff --git a/askbot/skins/common/media/images/flags/gm.gif b/askbot/skins/common/media/images/flags/gm.gif Binary files differnew file mode 100755 index 00000000..6847c5a8 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gm.gif diff --git a/askbot/skins/common/media/images/flags/gn.gif b/askbot/skins/common/media/images/flags/gn.gif Binary files differnew file mode 100755 index 00000000..a982ac6f --- /dev/null +++ b/askbot/skins/common/media/images/flags/gn.gif diff --git a/askbot/skins/common/media/images/flags/gp.gif b/askbot/skins/common/media/images/flags/gp.gif Binary files differnew file mode 100755 index 00000000..31166db6 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gp.gif diff --git a/askbot/skins/common/media/images/flags/gq.gif b/askbot/skins/common/media/images/flags/gq.gif Binary files differnew file mode 100755 index 00000000..8b4e0cc4 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gq.gif diff --git a/askbot/skins/common/media/images/flags/gr.gif b/askbot/skins/common/media/images/flags/gr.gif Binary files differnew file mode 100755 index 00000000..b4c8c04e --- /dev/null +++ b/askbot/skins/common/media/images/flags/gr.gif diff --git a/askbot/skins/common/media/images/flags/gs.gif b/askbot/skins/common/media/images/flags/gs.gif Binary files differnew file mode 100755 index 00000000..ccc96ec0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gs.gif diff --git a/askbot/skins/common/media/images/flags/gt.gif b/askbot/skins/common/media/images/flags/gt.gif Binary files differnew file mode 100755 index 00000000..7e94d1dd --- /dev/null +++ b/askbot/skins/common/media/images/flags/gt.gif diff --git a/askbot/skins/common/media/images/flags/gu.gif b/askbot/skins/common/media/images/flags/gu.gif Binary files differnew file mode 100755 index 00000000..eafef683 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gu.gif diff --git a/askbot/skins/common/media/images/flags/gw.gif b/askbot/skins/common/media/images/flags/gw.gif Binary files differnew file mode 100755 index 00000000..55f75711 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gw.gif diff --git a/askbot/skins/common/media/images/flags/gy.gif b/askbot/skins/common/media/images/flags/gy.gif Binary files differnew file mode 100755 index 00000000..1cb4cd71 --- /dev/null +++ b/askbot/skins/common/media/images/flags/gy.gif diff --git a/askbot/skins/common/media/images/flags/hk.gif b/askbot/skins/common/media/images/flags/hk.gif Binary files differnew file mode 100755 index 00000000..798af96d --- /dev/null +++ b/askbot/skins/common/media/images/flags/hk.gif diff --git a/askbot/skins/common/media/images/flags/hm.gif b/askbot/skins/common/media/images/flags/hm.gif Binary files differnew file mode 100755 index 00000000..5269c6a0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/hm.gif diff --git a/askbot/skins/common/media/images/flags/hn.gif b/askbot/skins/common/media/images/flags/hn.gif Binary files differnew file mode 100755 index 00000000..6c4ffe8e --- /dev/null +++ b/askbot/skins/common/media/images/flags/hn.gif diff --git a/askbot/skins/common/media/images/flags/hr.gif b/askbot/skins/common/media/images/flags/hr.gif Binary files differnew file mode 100755 index 00000000..557c6602 --- /dev/null +++ b/askbot/skins/common/media/images/flags/hr.gif diff --git a/askbot/skins/common/media/images/flags/ht.gif b/askbot/skins/common/media/images/flags/ht.gif Binary files differnew file mode 100755 index 00000000..059604ab --- /dev/null +++ b/askbot/skins/common/media/images/flags/ht.gif diff --git a/askbot/skins/common/media/images/flags/hu.gif b/askbot/skins/common/media/images/flags/hu.gif Binary files differnew file mode 100755 index 00000000..6142d868 --- /dev/null +++ b/askbot/skins/common/media/images/flags/hu.gif diff --git a/askbot/skins/common/media/images/flags/id.gif b/askbot/skins/common/media/images/flags/id.gif Binary files differnew file mode 100755 index 00000000..865161b0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/id.gif diff --git a/askbot/skins/common/media/images/flags/ie.gif b/askbot/skins/common/media/images/flags/ie.gif Binary files differnew file mode 100755 index 00000000..506ad285 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ie.gif diff --git a/askbot/skins/common/media/images/flags/il.gif b/askbot/skins/common/media/images/flags/il.gif Binary files differnew file mode 100755 index 00000000..c8483ae5 --- /dev/null +++ b/askbot/skins/common/media/images/flags/il.gif diff --git a/askbot/skins/common/media/images/flags/in.gif b/askbot/skins/common/media/images/flags/in.gif Binary files differnew file mode 100755 index 00000000..1cd80272 --- /dev/null +++ b/askbot/skins/common/media/images/flags/in.gif diff --git a/askbot/skins/common/media/images/flags/io.gif b/askbot/skins/common/media/images/flags/io.gif Binary files differnew file mode 100755 index 00000000..de7e7ab3 --- /dev/null +++ b/askbot/skins/common/media/images/flags/io.gif diff --git a/askbot/skins/common/media/images/flags/iq.gif b/askbot/skins/common/media/images/flags/iq.gif Binary files differnew file mode 100755 index 00000000..c34fe3c4 --- /dev/null +++ b/askbot/skins/common/media/images/flags/iq.gif diff --git a/askbot/skins/common/media/images/flags/ir.gif b/askbot/skins/common/media/images/flags/ir.gif Binary files differnew file mode 100755 index 00000000..156040fc --- /dev/null +++ b/askbot/skins/common/media/images/flags/ir.gif diff --git a/askbot/skins/common/media/images/flags/is.gif b/askbot/skins/common/media/images/flags/is.gif Binary files differnew file mode 100755 index 00000000..b42502de --- /dev/null +++ b/askbot/skins/common/media/images/flags/is.gif diff --git a/askbot/skins/common/media/images/flags/it.gif b/askbot/skins/common/media/images/flags/it.gif Binary files differnew file mode 100755 index 00000000..d79e90e9 --- /dev/null +++ b/askbot/skins/common/media/images/flags/it.gif diff --git a/askbot/skins/common/media/images/flags/jm.gif b/askbot/skins/common/media/images/flags/jm.gif Binary files differnew file mode 100755 index 00000000..0bed67c2 --- /dev/null +++ b/askbot/skins/common/media/images/flags/jm.gif diff --git a/askbot/skins/common/media/images/flags/jo.gif b/askbot/skins/common/media/images/flags/jo.gif Binary files differnew file mode 100755 index 00000000..03daf8af --- /dev/null +++ b/askbot/skins/common/media/images/flags/jo.gif diff --git a/askbot/skins/common/media/images/flags/jp.gif b/askbot/skins/common/media/images/flags/jp.gif Binary files differnew file mode 100755 index 00000000..444c1d05 --- /dev/null +++ b/askbot/skins/common/media/images/flags/jp.gif diff --git a/askbot/skins/common/media/images/flags/ke.gif b/askbot/skins/common/media/images/flags/ke.gif Binary files differnew file mode 100755 index 00000000..c2b5d45c --- /dev/null +++ b/askbot/skins/common/media/images/flags/ke.gif diff --git a/askbot/skins/common/media/images/flags/kg.gif b/askbot/skins/common/media/images/flags/kg.gif Binary files differnew file mode 100755 index 00000000..72a4d412 --- /dev/null +++ b/askbot/skins/common/media/images/flags/kg.gif diff --git a/askbot/skins/common/media/images/flags/kh.gif b/askbot/skins/common/media/images/flags/kh.gif Binary files differnew file mode 100755 index 00000000..30a18315 --- /dev/null +++ b/askbot/skins/common/media/images/flags/kh.gif diff --git a/askbot/skins/common/media/images/flags/ki.gif b/askbot/skins/common/media/images/flags/ki.gif Binary files differnew file mode 100755 index 00000000..4a0751a2 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ki.gif diff --git a/askbot/skins/common/media/images/flags/km.gif b/askbot/skins/common/media/images/flags/km.gif Binary files differnew file mode 100755 index 00000000..5859595e --- /dev/null +++ b/askbot/skins/common/media/images/flags/km.gif diff --git a/askbot/skins/common/media/images/flags/kn.gif b/askbot/skins/common/media/images/flags/kn.gif Binary files differnew file mode 100755 index 00000000..bb9cc34a --- /dev/null +++ b/askbot/skins/common/media/images/flags/kn.gif diff --git a/askbot/skins/common/media/images/flags/kp.gif b/askbot/skins/common/media/images/flags/kp.gif Binary files differnew file mode 100755 index 00000000..6e0ca09e --- /dev/null +++ b/askbot/skins/common/media/images/flags/kp.gif diff --git a/askbot/skins/common/media/images/flags/kr.gif b/askbot/skins/common/media/images/flags/kr.gif Binary files differnew file mode 100755 index 00000000..1cddbe75 --- /dev/null +++ b/askbot/skins/common/media/images/flags/kr.gif diff --git a/askbot/skins/common/media/images/flags/kw.gif b/askbot/skins/common/media/images/flags/kw.gif Binary files differnew file mode 100755 index 00000000..1efc7347 --- /dev/null +++ b/askbot/skins/common/media/images/flags/kw.gif diff --git a/askbot/skins/common/media/images/flags/ky.gif b/askbot/skins/common/media/images/flags/ky.gif Binary files differnew file mode 100755 index 00000000..d3d02ee4 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ky.gif diff --git a/askbot/skins/common/media/images/flags/kz.gif b/askbot/skins/common/media/images/flags/kz.gif Binary files differnew file mode 100755 index 00000000..24baebe0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/kz.gif diff --git a/askbot/skins/common/media/images/flags/la.gif b/askbot/skins/common/media/images/flags/la.gif Binary files differnew file mode 100755 index 00000000..d14cf4d8 --- /dev/null +++ b/askbot/skins/common/media/images/flags/la.gif diff --git a/askbot/skins/common/media/images/flags/lb.gif b/askbot/skins/common/media/images/flags/lb.gif Binary files differnew file mode 100755 index 00000000..003d83af --- /dev/null +++ b/askbot/skins/common/media/images/flags/lb.gif diff --git a/askbot/skins/common/media/images/flags/lc.gif b/askbot/skins/common/media/images/flags/lc.gif Binary files differnew file mode 100644 index 00000000..f5fe5bff --- /dev/null +++ b/askbot/skins/common/media/images/flags/lc.gif diff --git a/askbot/skins/common/media/images/flags/li.gif b/askbot/skins/common/media/images/flags/li.gif Binary files differnew file mode 100755 index 00000000..713c58e1 --- /dev/null +++ b/askbot/skins/common/media/images/flags/li.gif diff --git a/askbot/skins/common/media/images/flags/lk.gif b/askbot/skins/common/media/images/flags/lk.gif Binary files differnew file mode 100755 index 00000000..1b3ee7f5 --- /dev/null +++ b/askbot/skins/common/media/images/flags/lk.gif diff --git a/askbot/skins/common/media/images/flags/lr.gif b/askbot/skins/common/media/images/flags/lr.gif Binary files differnew file mode 100755 index 00000000..435af9e5 --- /dev/null +++ b/askbot/skins/common/media/images/flags/lr.gif diff --git a/askbot/skins/common/media/images/flags/ls.gif b/askbot/skins/common/media/images/flags/ls.gif Binary files differnew file mode 100755 index 00000000..427ae957 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ls.gif diff --git a/askbot/skins/common/media/images/flags/lt.gif b/askbot/skins/common/media/images/flags/lt.gif Binary files differnew file mode 100755 index 00000000..dee9c601 --- /dev/null +++ b/askbot/skins/common/media/images/flags/lt.gif diff --git a/askbot/skins/common/media/images/flags/lu.gif b/askbot/skins/common/media/images/flags/lu.gif Binary files differnew file mode 100755 index 00000000..7d7293ed --- /dev/null +++ b/askbot/skins/common/media/images/flags/lu.gif diff --git a/askbot/skins/common/media/images/flags/lv.gif b/askbot/skins/common/media/images/flags/lv.gif Binary files differnew file mode 100755 index 00000000..17e71b7e --- /dev/null +++ b/askbot/skins/common/media/images/flags/lv.gif diff --git a/askbot/skins/common/media/images/flags/ly.gif b/askbot/skins/common/media/images/flags/ly.gif Binary files differnew file mode 100755 index 00000000..a654c30a --- /dev/null +++ b/askbot/skins/common/media/images/flags/ly.gif diff --git a/askbot/skins/common/media/images/flags/ma.gif b/askbot/skins/common/media/images/flags/ma.gif Binary files differnew file mode 100755 index 00000000..fc784119 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ma.gif diff --git a/askbot/skins/common/media/images/flags/mc.gif b/askbot/skins/common/media/images/flags/mc.gif Binary files differnew file mode 100755 index 00000000..02a7c8e1 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mc.gif diff --git a/askbot/skins/common/media/images/flags/md.gif b/askbot/skins/common/media/images/flags/md.gif Binary files differnew file mode 100755 index 00000000..e4b8a7e3 --- /dev/null +++ b/askbot/skins/common/media/images/flags/md.gif diff --git a/askbot/skins/common/media/images/flags/me.gif b/askbot/skins/common/media/images/flags/me.gif Binary files differnew file mode 100644 index 00000000..a260453c --- /dev/null +++ b/askbot/skins/common/media/images/flags/me.gif diff --git a/askbot/skins/common/media/images/flags/mg.gif b/askbot/skins/common/media/images/flags/mg.gif Binary files differnew file mode 100755 index 00000000..a91b577d --- /dev/null +++ b/askbot/skins/common/media/images/flags/mg.gif diff --git a/askbot/skins/common/media/images/flags/mh.gif b/askbot/skins/common/media/images/flags/mh.gif Binary files differnew file mode 100755 index 00000000..92f5f485 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mh.gif diff --git a/askbot/skins/common/media/images/flags/mk.gif b/askbot/skins/common/media/images/flags/mk.gif Binary files differnew file mode 100755 index 00000000..7aeb8311 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mk.gif diff --git a/askbot/skins/common/media/images/flags/ml.gif b/askbot/skins/common/media/images/flags/ml.gif Binary files differnew file mode 100755 index 00000000..53d6f490 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ml.gif diff --git a/askbot/skins/common/media/images/flags/mm.gif b/askbot/skins/common/media/images/flags/mm.gif Binary files differnew file mode 100755 index 00000000..9e0a2756 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mm.gif diff --git a/askbot/skins/common/media/images/flags/mn.gif b/askbot/skins/common/media/images/flags/mn.gif Binary files differnew file mode 100755 index 00000000..dff8ea5a --- /dev/null +++ b/askbot/skins/common/media/images/flags/mn.gif diff --git a/askbot/skins/common/media/images/flags/mo.gif b/askbot/skins/common/media/images/flags/mo.gif Binary files differnew file mode 100755 index 00000000..66cf5b4f --- /dev/null +++ b/askbot/skins/common/media/images/flags/mo.gif diff --git a/askbot/skins/common/media/images/flags/mp.gif b/askbot/skins/common/media/images/flags/mp.gif Binary files differnew file mode 100755 index 00000000..73b7147e --- /dev/null +++ b/askbot/skins/common/media/images/flags/mp.gif diff --git a/askbot/skins/common/media/images/flags/mq.gif b/askbot/skins/common/media/images/flags/mq.gif Binary files differnew file mode 100755 index 00000000..570bc5dd --- /dev/null +++ b/askbot/skins/common/media/images/flags/mq.gif diff --git a/askbot/skins/common/media/images/flags/mr.gif b/askbot/skins/common/media/images/flags/mr.gif Binary files differnew file mode 100755 index 00000000..f52fcf09 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mr.gif diff --git a/askbot/skins/common/media/images/flags/ms.gif b/askbot/skins/common/media/images/flags/ms.gif Binary files differnew file mode 100755 index 00000000..5e5a67aa --- /dev/null +++ b/askbot/skins/common/media/images/flags/ms.gif diff --git a/askbot/skins/common/media/images/flags/mt.gif b/askbot/skins/common/media/images/flags/mt.gif Binary files differnew file mode 100755 index 00000000..45c709f2 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mt.gif diff --git a/askbot/skins/common/media/images/flags/mu.gif b/askbot/skins/common/media/images/flags/mu.gif Binary files differnew file mode 100755 index 00000000..081ab453 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mu.gif diff --git a/askbot/skins/common/media/images/flags/mv.gif b/askbot/skins/common/media/images/flags/mv.gif Binary files differnew file mode 100755 index 00000000..46b63875 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mv.gif diff --git a/askbot/skins/common/media/images/flags/mw.gif b/askbot/skins/common/media/images/flags/mw.gif Binary files differnew file mode 100755 index 00000000..ad045a09 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mw.gif diff --git a/askbot/skins/common/media/images/flags/mx.gif b/askbot/skins/common/media/images/flags/mx.gif Binary files differnew file mode 100755 index 00000000..ddc75d04 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mx.gif diff --git a/askbot/skins/common/media/images/flags/my.gif b/askbot/skins/common/media/images/flags/my.gif Binary files differnew file mode 100755 index 00000000..fc7d5236 --- /dev/null +++ b/askbot/skins/common/media/images/flags/my.gif diff --git a/askbot/skins/common/media/images/flags/mz.gif b/askbot/skins/common/media/images/flags/mz.gif Binary files differnew file mode 100755 index 00000000..7d635082 --- /dev/null +++ b/askbot/skins/common/media/images/flags/mz.gif diff --git a/askbot/skins/common/media/images/flags/na.gif b/askbot/skins/common/media/images/flags/na.gif Binary files differnew file mode 100755 index 00000000..c0babe72 --- /dev/null +++ b/askbot/skins/common/media/images/flags/na.gif diff --git a/askbot/skins/common/media/images/flags/nc.gif b/askbot/skins/common/media/images/flags/nc.gif Binary files differnew file mode 100755 index 00000000..b1e91b9a --- /dev/null +++ b/askbot/skins/common/media/images/flags/nc.gif diff --git a/askbot/skins/common/media/images/flags/ne.gif b/askbot/skins/common/media/images/flags/ne.gif Binary files differnew file mode 100755 index 00000000..ff4eaf07 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ne.gif diff --git a/askbot/skins/common/media/images/flags/nf.gif b/askbot/skins/common/media/images/flags/nf.gif Binary files differnew file mode 100755 index 00000000..c83424c2 --- /dev/null +++ b/askbot/skins/common/media/images/flags/nf.gif diff --git a/askbot/skins/common/media/images/flags/ng.gif b/askbot/skins/common/media/images/flags/ng.gif Binary files differnew file mode 100755 index 00000000..bdde7cb3 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ng.gif diff --git a/askbot/skins/common/media/images/flags/ni.gif b/askbot/skins/common/media/images/flags/ni.gif Binary files differnew file mode 100755 index 00000000..d05894d0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ni.gif diff --git a/askbot/skins/common/media/images/flags/nl.gif b/askbot/skins/common/media/images/flags/nl.gif Binary files differnew file mode 100755 index 00000000..c1c8f46d --- /dev/null +++ b/askbot/skins/common/media/images/flags/nl.gif diff --git a/askbot/skins/common/media/images/flags/no.gif b/askbot/skins/common/media/images/flags/no.gif Binary files differnew file mode 100755 index 00000000..6202d1f3 --- /dev/null +++ b/askbot/skins/common/media/images/flags/no.gif diff --git a/askbot/skins/common/media/images/flags/np.gif b/askbot/skins/common/media/images/flags/np.gif Binary files differnew file mode 100755 index 00000000..1096893a --- /dev/null +++ b/askbot/skins/common/media/images/flags/np.gif diff --git a/askbot/skins/common/media/images/flags/nr.gif b/askbot/skins/common/media/images/flags/nr.gif Binary files differnew file mode 100755 index 00000000..2e4c0c5c --- /dev/null +++ b/askbot/skins/common/media/images/flags/nr.gif diff --git a/askbot/skins/common/media/images/flags/nu.gif b/askbot/skins/common/media/images/flags/nu.gif Binary files differnew file mode 100755 index 00000000..618210a7 --- /dev/null +++ b/askbot/skins/common/media/images/flags/nu.gif diff --git a/askbot/skins/common/media/images/flags/nz.gif b/askbot/skins/common/media/images/flags/nz.gif Binary files differnew file mode 100755 index 00000000..028a5dc6 --- /dev/null +++ b/askbot/skins/common/media/images/flags/nz.gif diff --git a/askbot/skins/common/media/images/flags/om.gif b/askbot/skins/common/media/images/flags/om.gif Binary files differnew file mode 100755 index 00000000..2b8c7750 --- /dev/null +++ b/askbot/skins/common/media/images/flags/om.gif diff --git a/askbot/skins/common/media/images/flags/pa.gif b/askbot/skins/common/media/images/flags/pa.gif Binary files differnew file mode 100755 index 00000000..d518b2f9 --- /dev/null +++ b/askbot/skins/common/media/images/flags/pa.gif diff --git a/askbot/skins/common/media/images/flags/pe.gif b/askbot/skins/common/media/images/flags/pe.gif Binary files differnew file mode 100755 index 00000000..3bc76390 --- /dev/null +++ b/askbot/skins/common/media/images/flags/pe.gif diff --git a/askbot/skins/common/media/images/flags/pf.gif b/askbot/skins/common/media/images/flags/pf.gif Binary files differnew file mode 100755 index 00000000..849297a5 --- /dev/null +++ b/askbot/skins/common/media/images/flags/pf.gif diff --git a/askbot/skins/common/media/images/flags/pg.gif b/askbot/skins/common/media/images/flags/pg.gif Binary files differnew file mode 100755 index 00000000..2d20b078 --- /dev/null +++ b/askbot/skins/common/media/images/flags/pg.gif diff --git a/askbot/skins/common/media/images/flags/ph.gif b/askbot/skins/common/media/images/flags/ph.gif Binary files differnew file mode 100755 index 00000000..12b380ac --- /dev/null +++ b/askbot/skins/common/media/images/flags/ph.gif diff --git a/askbot/skins/common/media/images/flags/pk.gif b/askbot/skins/common/media/images/flags/pk.gif Binary files differnew file mode 100755 index 00000000..f3f62c2e --- /dev/null +++ b/askbot/skins/common/media/images/flags/pk.gif diff --git a/askbot/skins/common/media/images/flags/pl.gif b/askbot/skins/common/media/images/flags/pl.gif Binary files differnew file mode 100755 index 00000000..bf106463 --- /dev/null +++ b/askbot/skins/common/media/images/flags/pl.gif diff --git a/askbot/skins/common/media/images/flags/pm.gif b/askbot/skins/common/media/images/flags/pm.gif Binary files differnew file mode 100755 index 00000000..99bf6fdb --- /dev/null +++ b/askbot/skins/common/media/images/flags/pm.gif diff --git a/askbot/skins/common/media/images/flags/pn.gif b/askbot/skins/common/media/images/flags/pn.gif Binary files differnew file mode 100755 index 00000000..4bc86a1d --- /dev/null +++ b/askbot/skins/common/media/images/flags/pn.gif diff --git a/askbot/skins/common/media/images/flags/pr.gif b/askbot/skins/common/media/images/flags/pr.gif Binary files differnew file mode 100755 index 00000000..6d5d5896 --- /dev/null +++ b/askbot/skins/common/media/images/flags/pr.gif diff --git a/askbot/skins/common/media/images/flags/ps.gif b/askbot/skins/common/media/images/flags/ps.gif Binary files differnew file mode 100755 index 00000000..6afa3b71 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ps.gif diff --git a/askbot/skins/common/media/images/flags/pt.gif b/askbot/skins/common/media/images/flags/pt.gif Binary files differnew file mode 100755 index 00000000..e735f740 --- /dev/null +++ b/askbot/skins/common/media/images/flags/pt.gif diff --git a/askbot/skins/common/media/images/flags/pw.gif b/askbot/skins/common/media/images/flags/pw.gif Binary files differnew file mode 100755 index 00000000..5854510f --- /dev/null +++ b/askbot/skins/common/media/images/flags/pw.gif diff --git a/askbot/skins/common/media/images/flags/py.gif b/askbot/skins/common/media/images/flags/py.gif Binary files differnew file mode 100755 index 00000000..f2e66af7 --- /dev/null +++ b/askbot/skins/common/media/images/flags/py.gif diff --git a/askbot/skins/common/media/images/flags/qa.gif b/askbot/skins/common/media/images/flags/qa.gif Binary files differnew file mode 100755 index 00000000..2e843ff9 --- /dev/null +++ b/askbot/skins/common/media/images/flags/qa.gif diff --git a/askbot/skins/common/media/images/flags/re.gif b/askbot/skins/common/media/images/flags/re.gif Binary files differnew file mode 100755 index 00000000..43d0b801 --- /dev/null +++ b/askbot/skins/common/media/images/flags/re.gif diff --git a/askbot/skins/common/media/images/flags/ro.gif b/askbot/skins/common/media/images/flags/ro.gif Binary files differnew file mode 100755 index 00000000..f5d5f125 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ro.gif diff --git a/askbot/skins/common/media/images/flags/rs.gif b/askbot/skins/common/media/images/flags/rs.gif Binary files differnew file mode 100644 index 00000000..3bd1fb2f --- /dev/null +++ b/askbot/skins/common/media/images/flags/rs.gif diff --git a/askbot/skins/common/media/images/flags/ru.gif b/askbot/skins/common/media/images/flags/ru.gif Binary files differnew file mode 100755 index 00000000..b525c462 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ru.gif diff --git a/askbot/skins/common/media/images/flags/rw.gif b/askbot/skins/common/media/images/flags/rw.gif Binary files differnew file mode 100755 index 00000000..0d095f7a --- /dev/null +++ b/askbot/skins/common/media/images/flags/rw.gif diff --git a/askbot/skins/common/media/images/flags/sa.gif b/askbot/skins/common/media/images/flags/sa.gif Binary files differnew file mode 100755 index 00000000..179961b6 --- /dev/null +++ b/askbot/skins/common/media/images/flags/sa.gif diff --git a/askbot/skins/common/media/images/flags/sb.gif b/askbot/skins/common/media/images/flags/sb.gif Binary files differnew file mode 100755 index 00000000..8f5ff837 --- /dev/null +++ b/askbot/skins/common/media/images/flags/sb.gif diff --git a/askbot/skins/common/media/images/flags/sc.gif b/askbot/skins/common/media/images/flags/sc.gif Binary files differnew file mode 100755 index 00000000..31b47677 --- /dev/null +++ b/askbot/skins/common/media/images/flags/sc.gif diff --git a/askbot/skins/common/media/images/flags/scotland.gif b/askbot/skins/common/media/images/flags/scotland.gif Binary files differnew file mode 100755 index 00000000..03f3f1de --- /dev/null +++ b/askbot/skins/common/media/images/flags/scotland.gif diff --git a/askbot/skins/common/media/images/flags/sd.gif b/askbot/skins/common/media/images/flags/sd.gif Binary files differnew file mode 100755 index 00000000..53ae214f --- /dev/null +++ b/askbot/skins/common/media/images/flags/sd.gif diff --git a/askbot/skins/common/media/images/flags/se.gif b/askbot/skins/common/media/images/flags/se.gif Binary files differnew file mode 100755 index 00000000..80f62852 --- /dev/null +++ b/askbot/skins/common/media/images/flags/se.gif diff --git a/askbot/skins/common/media/images/flags/sg.gif b/askbot/skins/common/media/images/flags/sg.gif Binary files differnew file mode 100755 index 00000000..5663d39f --- /dev/null +++ b/askbot/skins/common/media/images/flags/sg.gif diff --git a/askbot/skins/common/media/images/flags/sh.gif b/askbot/skins/common/media/images/flags/sh.gif Binary files differnew file mode 100755 index 00000000..dcc7f3bc --- /dev/null +++ b/askbot/skins/common/media/images/flags/sh.gif diff --git a/askbot/skins/common/media/images/flags/si.gif b/askbot/skins/common/media/images/flags/si.gif Binary files differnew file mode 100755 index 00000000..23852b50 --- /dev/null +++ b/askbot/skins/common/media/images/flags/si.gif diff --git a/askbot/skins/common/media/images/flags/sj.gif b/askbot/skins/common/media/images/flags/sj.gif Binary files differnew file mode 100755 index 00000000..6202d1f3 --- /dev/null +++ b/askbot/skins/common/media/images/flags/sj.gif diff --git a/askbot/skins/common/media/images/flags/sk.gif b/askbot/skins/common/media/images/flags/sk.gif Binary files differnew file mode 100755 index 00000000..1b3f22ba --- /dev/null +++ b/askbot/skins/common/media/images/flags/sk.gif diff --git a/askbot/skins/common/media/images/flags/sl.gif b/askbot/skins/common/media/images/flags/sl.gif Binary files differnew file mode 100755 index 00000000..f0f34923 --- /dev/null +++ b/askbot/skins/common/media/images/flags/sl.gif diff --git a/askbot/skins/common/media/images/flags/sm.gif b/askbot/skins/common/media/images/flags/sm.gif Binary files differnew file mode 100755 index 00000000..04d98de5 --- /dev/null +++ b/askbot/skins/common/media/images/flags/sm.gif diff --git a/askbot/skins/common/media/images/flags/sn.gif b/askbot/skins/common/media/images/flags/sn.gif Binary files differnew file mode 100755 index 00000000..6dac8709 --- /dev/null +++ b/askbot/skins/common/media/images/flags/sn.gif diff --git a/askbot/skins/common/media/images/flags/so.gif b/askbot/skins/common/media/images/flags/so.gif Binary files differnew file mode 100755 index 00000000..f1961694 --- /dev/null +++ b/askbot/skins/common/media/images/flags/so.gif diff --git a/askbot/skins/common/media/images/flags/sr.gif b/askbot/skins/common/media/images/flags/sr.gif Binary files differnew file mode 100755 index 00000000..0f7499ad --- /dev/null +++ b/askbot/skins/common/media/images/flags/sr.gif diff --git a/askbot/skins/common/media/images/flags/st.gif b/askbot/skins/common/media/images/flags/st.gif Binary files differnew file mode 100755 index 00000000..4f1e6e09 --- /dev/null +++ b/askbot/skins/common/media/images/flags/st.gif diff --git a/askbot/skins/common/media/images/flags/sv.gif b/askbot/skins/common/media/images/flags/sv.gif Binary files differnew file mode 100755 index 00000000..2d7b159a --- /dev/null +++ b/askbot/skins/common/media/images/flags/sv.gif diff --git a/askbot/skins/common/media/images/flags/sy.gif b/askbot/skins/common/media/images/flags/sy.gif Binary files differnew file mode 100755 index 00000000..dc8bd509 --- /dev/null +++ b/askbot/skins/common/media/images/flags/sy.gif diff --git a/askbot/skins/common/media/images/flags/sz.gif b/askbot/skins/common/media/images/flags/sz.gif Binary files differnew file mode 100755 index 00000000..f37aaf80 --- /dev/null +++ b/askbot/skins/common/media/images/flags/sz.gif diff --git a/askbot/skins/common/media/images/flags/tc.gif b/askbot/skins/common/media/images/flags/tc.gif Binary files differnew file mode 100755 index 00000000..11a8c232 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tc.gif diff --git a/askbot/skins/common/media/images/flags/td.gif b/askbot/skins/common/media/images/flags/td.gif Binary files differnew file mode 100755 index 00000000..7aa8a10d --- /dev/null +++ b/askbot/skins/common/media/images/flags/td.gif diff --git a/askbot/skins/common/media/images/flags/tf.gif b/askbot/skins/common/media/images/flags/tf.gif Binary files differnew file mode 100755 index 00000000..51a43250 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tf.gif diff --git a/askbot/skins/common/media/images/flags/tg.gif b/askbot/skins/common/media/images/flags/tg.gif Binary files differnew file mode 100755 index 00000000..ca6b4e77 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tg.gif diff --git a/askbot/skins/common/media/images/flags/th.gif b/askbot/skins/common/media/images/flags/th.gif Binary files differnew file mode 100755 index 00000000..01307924 --- /dev/null +++ b/askbot/skins/common/media/images/flags/th.gif diff --git a/askbot/skins/common/media/images/flags/tj.gif b/askbot/skins/common/media/images/flags/tj.gif Binary files differnew file mode 100755 index 00000000..2fe38d4a --- /dev/null +++ b/askbot/skins/common/media/images/flags/tj.gif diff --git a/askbot/skins/common/media/images/flags/tk.gif b/askbot/skins/common/media/images/flags/tk.gif Binary files differnew file mode 100755 index 00000000..3d3a727f --- /dev/null +++ b/askbot/skins/common/media/images/flags/tk.gif diff --git a/askbot/skins/common/media/images/flags/tl.gif b/askbot/skins/common/media/images/flags/tl.gif Binary files differnew file mode 100755 index 00000000..df22d582 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tl.gif diff --git a/askbot/skins/common/media/images/flags/tm.gif b/askbot/skins/common/media/images/flags/tm.gif Binary files differnew file mode 100755 index 00000000..36d0994f --- /dev/null +++ b/askbot/skins/common/media/images/flags/tm.gif diff --git a/askbot/skins/common/media/images/flags/tn.gif b/askbot/skins/common/media/images/flags/tn.gif Binary files differnew file mode 100755 index 00000000..917d4288 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tn.gif diff --git a/askbot/skins/common/media/images/flags/to.gif b/askbot/skins/common/media/images/flags/to.gif Binary files differnew file mode 100755 index 00000000..d7ed4d11 --- /dev/null +++ b/askbot/skins/common/media/images/flags/to.gif diff --git a/askbot/skins/common/media/images/flags/tr.gif b/askbot/skins/common/media/images/flags/tr.gif Binary files differnew file mode 100755 index 00000000..e407d553 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tr.gif diff --git a/askbot/skins/common/media/images/flags/tt.gif b/askbot/skins/common/media/images/flags/tt.gif Binary files differnew file mode 100755 index 00000000..47d3b806 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tt.gif diff --git a/askbot/skins/common/media/images/flags/tv.gif b/askbot/skins/common/media/images/flags/tv.gif Binary files differnew file mode 100755 index 00000000..3c338277 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tv.gif diff --git a/askbot/skins/common/media/images/flags/tw.gif b/askbot/skins/common/media/images/flags/tw.gif Binary files differnew file mode 100755 index 00000000..cacfd9b7 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tw.gif diff --git a/askbot/skins/common/media/images/flags/tz.gif b/askbot/skins/common/media/images/flags/tz.gif Binary files differnew file mode 100755 index 00000000..82b52ca2 --- /dev/null +++ b/askbot/skins/common/media/images/flags/tz.gif diff --git a/askbot/skins/common/media/images/flags/ua.gif b/askbot/skins/common/media/images/flags/ua.gif Binary files differnew file mode 100755 index 00000000..5d6cd83f --- /dev/null +++ b/askbot/skins/common/media/images/flags/ua.gif diff --git a/askbot/skins/common/media/images/flags/ug.gif b/askbot/skins/common/media/images/flags/ug.gif Binary files differnew file mode 100755 index 00000000..58b731ad --- /dev/null +++ b/askbot/skins/common/media/images/flags/ug.gif diff --git a/askbot/skins/common/media/images/flags/um.gif b/askbot/skins/common/media/images/flags/um.gif Binary files differnew file mode 100755 index 00000000..3b4c8483 --- /dev/null +++ b/askbot/skins/common/media/images/flags/um.gif diff --git a/askbot/skins/common/media/images/flags/us.gif b/askbot/skins/common/media/images/flags/us.gif Binary files differnew file mode 100755 index 00000000..8f198f73 --- /dev/null +++ b/askbot/skins/common/media/images/flags/us.gif diff --git a/askbot/skins/common/media/images/flags/uy.gif b/askbot/skins/common/media/images/flags/uy.gif Binary files differnew file mode 100755 index 00000000..12848c74 --- /dev/null +++ b/askbot/skins/common/media/images/flags/uy.gif diff --git a/askbot/skins/common/media/images/flags/uz.gif b/askbot/skins/common/media/images/flags/uz.gif Binary files differnew file mode 100755 index 00000000..dc9daeca --- /dev/null +++ b/askbot/skins/common/media/images/flags/uz.gif diff --git a/askbot/skins/common/media/images/flags/va.gif b/askbot/skins/common/media/images/flags/va.gif Binary files differnew file mode 100755 index 00000000..2bd74468 --- /dev/null +++ b/askbot/skins/common/media/images/flags/va.gif diff --git a/askbot/skins/common/media/images/flags/vc.gif b/askbot/skins/common/media/images/flags/vc.gif Binary files differnew file mode 100755 index 00000000..48213816 --- /dev/null +++ b/askbot/skins/common/media/images/flags/vc.gif diff --git a/askbot/skins/common/media/images/flags/ve.gif b/askbot/skins/common/media/images/flags/ve.gif Binary files differnew file mode 100755 index 00000000..19ce6c14 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ve.gif diff --git a/askbot/skins/common/media/images/flags/vg.gif b/askbot/skins/common/media/images/flags/vg.gif Binary files differnew file mode 100755 index 00000000..1fc0f96e --- /dev/null +++ b/askbot/skins/common/media/images/flags/vg.gif diff --git a/askbot/skins/common/media/images/flags/vi.gif b/askbot/skins/common/media/images/flags/vi.gif Binary files differnew file mode 100755 index 00000000..66f9e746 --- /dev/null +++ b/askbot/skins/common/media/images/flags/vi.gif diff --git a/askbot/skins/common/media/images/flags/vn.gif b/askbot/skins/common/media/images/flags/vn.gif Binary files differnew file mode 100755 index 00000000..f1e20c94 --- /dev/null +++ b/askbot/skins/common/media/images/flags/vn.gif diff --git a/askbot/skins/common/media/images/flags/vu.gif b/askbot/skins/common/media/images/flags/vu.gif Binary files differnew file mode 100755 index 00000000..8a8b2b06 --- /dev/null +++ b/askbot/skins/common/media/images/flags/vu.gif diff --git a/askbot/skins/common/media/images/flags/wales.gif b/askbot/skins/common/media/images/flags/wales.gif Binary files differnew file mode 100755 index 00000000..901d1750 --- /dev/null +++ b/askbot/skins/common/media/images/flags/wales.gif diff --git a/askbot/skins/common/media/images/flags/wf.gif b/askbot/skins/common/media/images/flags/wf.gif Binary files differnew file mode 100755 index 00000000..eaa954b1 --- /dev/null +++ b/askbot/skins/common/media/images/flags/wf.gif diff --git a/askbot/skins/common/media/images/flags/ws.gif b/askbot/skins/common/media/images/flags/ws.gif Binary files differnew file mode 100755 index 00000000..a51f939e --- /dev/null +++ b/askbot/skins/common/media/images/flags/ws.gif diff --git a/askbot/skins/common/media/images/flags/ye.gif b/askbot/skins/common/media/images/flags/ye.gif Binary files differnew file mode 100755 index 00000000..7b0183d0 --- /dev/null +++ b/askbot/skins/common/media/images/flags/ye.gif diff --git a/askbot/skins/common/media/images/flags/yt.gif b/askbot/skins/common/media/images/flags/yt.gif Binary files differnew file mode 100755 index 00000000..a2267c05 --- /dev/null +++ b/askbot/skins/common/media/images/flags/yt.gif diff --git a/askbot/skins/common/media/images/flags/za.gif b/askbot/skins/common/media/images/flags/za.gif Binary files differnew file mode 100755 index 00000000..ede52589 --- /dev/null +++ b/askbot/skins/common/media/images/flags/za.gif diff --git a/askbot/skins/common/media/images/flags/zm.gif b/askbot/skins/common/media/images/flags/zm.gif Binary files differnew file mode 100755 index 00000000..b2851d2b --- /dev/null +++ b/askbot/skins/common/media/images/flags/zm.gif diff --git a/askbot/skins/common/media/images/flags/zw.gif b/askbot/skins/common/media/images/flags/zw.gif Binary files differnew file mode 100755 index 00000000..02901f62 --- /dev/null +++ b/askbot/skins/common/media/images/flags/zw.gif diff --git a/askbot/skins/common/media/images/openid/aol.gif b/askbot/skins/common/media/images/openid/aol.gif Binary files differnew file mode 100755 index 00000000..decc4f12 --- /dev/null +++ b/askbot/skins/common/media/images/openid/aol.gif diff --git a/askbot/skins/common/media/images/openid/blogger.ico b/askbot/skins/common/media/images/openid/blogger.ico Binary files differnew file mode 100755 index 00000000..1b9730b0 --- /dev/null +++ b/askbot/skins/common/media/images/openid/blogger.ico diff --git a/askbot/skins/common/media/images/openid/claimid.ico b/askbot/skins/common/media/images/openid/claimid.ico Binary files differnew file mode 100755 index 00000000..2b80f491 --- /dev/null +++ b/askbot/skins/common/media/images/openid/claimid.ico diff --git a/askbot/skins/common/media/images/openid/facebook.gif b/askbot/skins/common/media/images/openid/facebook.gif Binary files differnew file mode 100755 index 00000000..b997b358 --- /dev/null +++ b/askbot/skins/common/media/images/openid/facebook.gif diff --git a/askbot/skins/common/media/images/openid/flickr.ico b/askbot/skins/common/media/images/openid/flickr.ico Binary files differnew file mode 100755 index 00000000..11f6e07f --- /dev/null +++ b/askbot/skins/common/media/images/openid/flickr.ico diff --git a/askbot/skins/common/media/images/openid/google.gif b/askbot/skins/common/media/images/openid/google.gif Binary files differnew file mode 100755 index 00000000..1b6cd07b --- /dev/null +++ b/askbot/skins/common/media/images/openid/google.gif diff --git a/askbot/skins/common/media/images/openid/livejournal.ico b/askbot/skins/common/media/images/openid/livejournal.ico Binary files differnew file mode 100755 index 00000000..f3d21ec5 --- /dev/null +++ b/askbot/skins/common/media/images/openid/livejournal.ico diff --git a/askbot/skins/common/media/images/openid/myopenid.ico b/askbot/skins/common/media/images/openid/myopenid.ico Binary files differnew file mode 100755 index 00000000..ceb06e6a --- /dev/null +++ b/askbot/skins/common/media/images/openid/myopenid.ico diff --git a/askbot/skins/common/media/images/openid/openid-inputicon.gif b/askbot/skins/common/media/images/openid/openid-inputicon.gif Binary files differnew file mode 100755 index 00000000..cde836c8 --- /dev/null +++ b/askbot/skins/common/media/images/openid/openid-inputicon.gif diff --git a/askbot/skins/common/media/images/openid/openid.gif b/askbot/skins/common/media/images/openid/openid.gif Binary files differnew file mode 100755 index 00000000..c718b0e6 --- /dev/null +++ b/askbot/skins/common/media/images/openid/openid.gif diff --git a/askbot/skins/common/media/images/openid/technorati.ico b/askbot/skins/common/media/images/openid/technorati.ico Binary files differnew file mode 100755 index 00000000..fa1083c1 --- /dev/null +++ b/askbot/skins/common/media/images/openid/technorati.ico diff --git a/askbot/skins/common/media/images/openid/twitter.png b/askbot/skins/common/media/images/openid/twitter.png Binary files differnew file mode 100755 index 00000000..9a6552d1 --- /dev/null +++ b/askbot/skins/common/media/images/openid/twitter.png diff --git a/askbot/skins/common/media/images/openid/verisign.ico b/askbot/skins/common/media/images/openid/verisign.ico Binary files differnew file mode 100755 index 00000000..3953af93 --- /dev/null +++ b/askbot/skins/common/media/images/openid/verisign.ico diff --git a/askbot/skins/common/media/images/openid/vidoop.ico b/askbot/skins/common/media/images/openid/vidoop.ico Binary files differnew file mode 100755 index 00000000..bbd9a0d5 --- /dev/null +++ b/askbot/skins/common/media/images/openid/vidoop.ico diff --git a/askbot/skins/common/media/images/openid/wordpress.ico b/askbot/skins/common/media/images/openid/wordpress.ico Binary files differnew file mode 100755 index 00000000..31b7d2c2 --- /dev/null +++ b/askbot/skins/common/media/images/openid/wordpress.ico diff --git a/askbot/skins/common/media/images/openid/yahoo.gif b/askbot/skins/common/media/images/openid/yahoo.gif Binary files differnew file mode 100755 index 00000000..0f0eb8ef --- /dev/null +++ b/askbot/skins/common/media/images/openid/yahoo.gif diff --git a/askbot/skins/common/media/jquery-openid/images/aol.gif b/askbot/skins/common/media/jquery-openid/images/aol.gif Binary files differnew file mode 100755 index 00000000..24d1e152 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/aol.gif diff --git a/askbot/skins/common/media/jquery-openid/images/blogger-1.png b/askbot/skins/common/media/jquery-openid/images/blogger-1.png Binary files differnew file mode 100755 index 00000000..8b360ea5 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/blogger-1.png diff --git a/askbot/skins/common/media/jquery-openid/images/blogger.ico b/askbot/skins/common/media/jquery-openid/images/blogger.ico Binary files differnew file mode 100755 index 00000000..1b9730b0 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/blogger.ico diff --git a/askbot/skins/common/media/jquery-openid/images/claimid-0.png b/askbot/skins/common/media/jquery-openid/images/claimid-0.png Binary files differnew file mode 100755 index 00000000..4a0ea1b3 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/claimid-0.png diff --git a/askbot/skins/common/media/jquery-openid/images/claimid.ico b/askbot/skins/common/media/jquery-openid/images/claimid.ico Binary files differnew file mode 100755 index 00000000..2b80f491 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/claimid.ico diff --git a/askbot/skins/common/media/jquery-openid/images/facebook.gif b/askbot/skins/common/media/jquery-openid/images/facebook.gif Binary files differnew file mode 100755 index 00000000..c5586455 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/facebook.gif diff --git a/askbot/skins/common/media/jquery-openid/images/flickr.ico b/askbot/skins/common/media/jquery-openid/images/flickr.ico Binary files differnew file mode 100755 index 00000000..11f6e07f --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/flickr.ico diff --git a/askbot/skins/common/media/jquery-openid/images/flickr.png b/askbot/skins/common/media/jquery-openid/images/flickr.png Binary files differnew file mode 100755 index 00000000..142405a6 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/flickr.png diff --git a/askbot/skins/common/media/jquery-openid/images/google.gif b/askbot/skins/common/media/jquery-openid/images/google.gif Binary files differnew file mode 100755 index 00000000..65395365 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/google.gif diff --git a/askbot/skins/common/media/jquery-openid/images/identica.png b/askbot/skins/common/media/jquery-openid/images/identica.png Binary files differnew file mode 100644 index 00000000..2b607db1 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/identica.png diff --git a/askbot/skins/common/media/jquery-openid/images/linkedin.gif b/askbot/skins/common/media/jquery-openid/images/linkedin.gif Binary files differnew file mode 100644 index 00000000..36e049ac --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/linkedin.gif diff --git a/askbot/skins/common/media/jquery-openid/images/livejournal-1.png b/askbot/skins/common/media/jquery-openid/images/livejournal-1.png Binary files differnew file mode 100755 index 00000000..e6436081 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/livejournal-1.png diff --git a/askbot/skins/common/media/jquery-openid/images/livejournal.ico b/askbot/skins/common/media/jquery-openid/images/livejournal.ico Binary files differnew file mode 100755 index 00000000..f3d21ec5 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/livejournal.ico diff --git a/askbot/skins/common/media/jquery-openid/images/myopenid-2.png b/askbot/skins/common/media/jquery-openid/images/myopenid-2.png Binary files differnew file mode 100755 index 00000000..f64fb8e8 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/myopenid-2.png diff --git a/askbot/skins/common/media/jquery-openid/images/myopenid.ico b/askbot/skins/common/media/jquery-openid/images/myopenid.ico Binary files differnew file mode 100755 index 00000000..ceb06e6a --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/myopenid.ico diff --git a/askbot/skins/common/media/jquery-openid/images/openid-inputicon.gif b/askbot/skins/common/media/jquery-openid/images/openid-inputicon.gif Binary files differnew file mode 100755 index 00000000..cde836c8 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/openid-inputicon.gif diff --git a/askbot/skins/common/media/jquery-openid/images/openid.gif b/askbot/skins/common/media/jquery-openid/images/openid.gif Binary files differnew file mode 100755 index 00000000..19eb7c6f --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/openid.gif diff --git a/askbot/skins/common/media/jquery-openid/images/openidico.png b/askbot/skins/common/media/jquery-openid/images/openidico.png Binary files differnew file mode 100755 index 00000000..ab622669 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/openidico.png diff --git a/askbot/skins/common/media/jquery-openid/images/openidico16.png b/askbot/skins/common/media/jquery-openid/images/openidico16.png Binary files differnew file mode 100755 index 00000000..ad718ac5 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/openidico16.png diff --git a/askbot/skins/common/media/jquery-openid/images/technorati-1.png b/askbot/skins/common/media/jquery-openid/images/technorati-1.png Binary files differnew file mode 100755 index 00000000..f7195240 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/technorati-1.png diff --git a/askbot/skins/common/media/jquery-openid/images/technorati.ico b/askbot/skins/common/media/jquery-openid/images/technorati.ico Binary files differnew file mode 100755 index 00000000..fa1083c1 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/technorati.ico diff --git a/askbot/skins/common/media/jquery-openid/images/twitter.gif b/askbot/skins/common/media/jquery-openid/images/twitter.gif Binary files differnew file mode 100644 index 00000000..173cace1 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/twitter.gif diff --git a/askbot/skins/common/media/jquery-openid/images/verisign-2.png b/askbot/skins/common/media/jquery-openid/images/verisign-2.png Binary files differnew file mode 100755 index 00000000..c1467008 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/verisign-2.png diff --git a/askbot/skins/common/media/jquery-openid/images/verisign.ico b/askbot/skins/common/media/jquery-openid/images/verisign.ico Binary files differnew file mode 100755 index 00000000..3953af93 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/verisign.ico diff --git a/askbot/skins/common/media/jquery-openid/images/vidoop.ico b/askbot/skins/common/media/jquery-openid/images/vidoop.ico Binary files differnew file mode 100755 index 00000000..bbd9a0d5 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/vidoop.ico diff --git a/askbot/skins/common/media/jquery-openid/images/vidoop.png b/askbot/skins/common/media/jquery-openid/images/vidoop.png Binary files differnew file mode 100755 index 00000000..032c9e98 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/vidoop.png diff --git a/askbot/skins/common/media/jquery-openid/images/wordpress.ico b/askbot/skins/common/media/jquery-openid/images/wordpress.ico Binary files differnew file mode 100755 index 00000000..31b7d2c2 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/wordpress.ico diff --git a/askbot/skins/common/media/jquery-openid/images/wordpress.png b/askbot/skins/common/media/jquery-openid/images/wordpress.png Binary files differnew file mode 100755 index 00000000..ee29f0cf --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/wordpress.png diff --git a/askbot/skins/common/media/jquery-openid/images/yahoo.gif b/askbot/skins/common/media/jquery-openid/images/yahoo.gif Binary files differnew file mode 100755 index 00000000..614910a9 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/images/yahoo.gif diff --git a/askbot/skins/common/media/jquery-openid/jquery.openid.js b/askbot/skins/common/media/jquery-openid/jquery.openid.js new file mode 100644 index 00000000..7ba9adce --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/jquery.openid.js @@ -0,0 +1,447 @@ +$.fn.authenticator = function() { + var signin_page = $(this); + var signin_form = $('#signin-form'); + var openid_login_token_input = $('input[name=openid_login_token]'); + var openid_login_token_input_fields = $('#openid-fs'); + var provider_name_input = $('input[name=login_provider_name]'); + var email_input_fields = $('#email-input-fs'); + var account_recovery_heading = $('#account-recovery-heading'); + var account_recovery_hint = $('#account-recovery-form>.hint'); + var account_recovery_link = $('#account-recovery-form>.hint>span.link'); + var account_recovery_text_span = $('#account-recovery-form>.hint>span.text'); + var password_input_fields = $('#password-fs'); + var existing_login_methods_div = $('#existing-login-methods'); + var openid_submit_button = $('input[name=openid_login_with_extra_token]'); + var existing_login_methods = {}; + + var account_recovery_question_text = account_recovery_heading.html(); + var account_recovery_prompt_text = account_recovery_text_span.html(); + + var setup_click_handler = function(elements, handler_function){ + elements.unbind('click').click(handler_function); + }; + + var setup_enter_key_handler = function(elements, handler_function){ + elements.each( + function(index, element){ + $(element).unbind('keypress').keypress( + function(e){ + if ((e.which && e.which == 13)||(e.keyCode && e.keyCode == 13)){ + if (handler_function){ + return handler_function(); + } + else { + element.click(); + return false; + } + } + } + ); + } + ); + }; + + var setup_event_handlers = function(elements, handler_function){ + setup_click_handler(elements, handler_function); + setup_enter_key_handler(elements); + }; + + var get_provider_name = function(row_el){ + var row = $(row_el); + var name_span = row.find('.ab-provider-name'); + return provider_name = $.trim(name_span.html()); + }; + + var read_existing_login_methods = function(){ + $('.ab-provider-row').each( + function(i, provider_row){ + var provider_name = get_provider_name(provider_row); + existing_login_methods[provider_name] = true; + } + ); + }; + + var setup_login_method_deleters = function(){ + $('.ab-provider-row').each( + function(i, provider_row){ + var provider_name = get_provider_name(provider_row); + var remove_button = $( + provider_row + ).find('button'); + remove_button.click( + function(){ + var message = $.i18n._( + 'Are you sure you want to remove ' + + 'your {provider} login?' + ).replace( + '{provider}', + provider_name + ); + if (confirm(message)){ + $.ajax({ + type: 'POST', + url: authUrl + 'delete_login_method/',//url!!! + data: {provider_name: provider_name}, + success: function(data, text_status, xhr){ + $(provider_row).remove(); + delete existing_login_methods[provider_name]; + provider_count -=1; + if (provider_count < 0){ + provider_count === 0; + } + if (provider_count === 0){ + $('#ab-existing-login-methods').remove(); + $('#ab-show-login-methods').remove(); + $('h1').html( + $.i18n._("Please add one or more login methods.") + ); + $('#login-intro').html( + $.i18n._("You don\'t have a method to log in right now, please add one or more by clicking any of the icons below.") + ); + existing_login_methods = null; + } + } + }); + } + } + ); + } + ); + } + + var submit_login_with_password = function(){ + var username = $('#id_username'); + var password = $('#id_password'); + + if (username.val().length < 1){ + username.focus(); + return false; + } + if (password.val().length < 1){ + password.focus(); + return false; + } + return true; + }; + + var submit_change_password = function(){ + var newpass = $('#id_new_password'); + var newpass_retyped = $('#id_new_password_retyped'); + if (newpass.val().length < 1){ + newpass.focus(); + return false + } + if (newpass_retyped.val().length < 1){ + newpass_retyped.focus(); + return false; + } + if (newpass.val() !== newpass_retyped.val()){ + newpass_retyped.after( + '<span class="error">' + + $.i18n._('passwords do not match') + + '</span>' + ); + newpass.val('').focus(); + newpass_retyped.val(''); + return false; + } + return true; + }; + + //validator, may be extended to check url for openid + var submit_with_extra_openid_token = function() { + if (openid_login_token_input.val().length < 1) { + openid_login_token_input.focus(); + return false; + } + return true; + }; + + var insert_login_list_enabler = function(){ + var enabler = $('#login-list-enabler'); + if (enabler.is('p#login-list-enabler')){ + enabler.show(); + } + else { + enabler = $( + '<p id="login-list-enabler"><a href="#">' + + $.i18n._('Show/change current login methods') + + '</a></p>'); + setup_event_handlers( + enabler, + function(){ + if (askbot['settings']['signin_always_show_local_login'] === false){ + password_input_fields.hide(); + } + openid_login_token_input_fields.hide(); + enabler.hide(); + existing_login_methods_div.show(); + } + ); + existing_login_methods_div.after(enabler); + } + }; + + var reset_password_input_fields = function(){ + if (userIsAuthenticated){ + $('#id_new_password').val(''); + $('#id_new_password_retyped').val(''); + } + else { + $('#id_username').val(''); + $('#id_password').val(''); + } + }; + + var reset_form = function(){ + openid_login_token_input_fields.hide(); + if (askbot['settings']['signin_always_show_local_login'] === false){ + password_input_fields.hide(); + } + reset_password_input_fields(); + $('.error').remove(); + if (userIsAuthenticated === false){ + email_input_fields.hide(); + account_recovery_heading.hide(); + account_recovery_link.show(); + account_recovery_hint.show(); + $('#account-recovery-form>p.hint').css('margin-top','10px'); + account_recovery_text_span.html(account_recovery_question_text).show(); + } + else { + if (existing_login_methods !== null){ + existing_login_methods_div.hide(); + insert_login_list_enabler(); + } + } + }; + + var set_provider_name = function(element){ + var provider_name = element.attr('name'); + provider_name_input.val(provider_name); + }; + + var show_openid_input_fields = function(provider_name){ + reset_form(); + var token_name = extra_token_name[provider_name] + if (userIsAuthenticated){ + var heading_text = $.i18n._( + 'Please enter your {token_name}, then proceed' + ); + $('#openid-heading').html( + heading_text.replace('{token_name}', token_name) + ); + var button_text = $.i18n._('Connect your {provider_name} account to {site}'); + button_text = button_text.replace( + '{provider_name}', provider_name + ).replace( + '{site}', siteName + ); + openid_submit_button.val(button_text); + } + else { + $('#openid-heading>span').html(token_name); + } + openid_login_token_input_fields.show(); + openid_login_token_input.focus(); + }; + + var start_simple_login = function() { + //$('#openid_form .providers td').removeClass('highlight'); + //$li.addClass('highlight'); + set_provider_name($(this)); + signin_form.submit(); + return true; + }; + + var start_login_with_extra_openid_token = function() { + show_openid_input_fields($(this).attr('name')); + set_provider_name($(this)); + + setup_enter_key_handler( + openid_login_token_input, + function(){ + openid_submit_button.click(); + return false; + } + ); + + setup_event_handlers( + openid_submit_button, + function(){ + signin_form.unbind( + 'submit' + ).submit( + submit_with_extra_openid_token + ); + } + ); + return false; + }; + + var start_facebook_login = function(){ + set_provider_name($(this)); + if (typeof FB != 'undefined'){ + FB.getLoginStatus(function(response){ + if (response.authResponse){ + signin_form.submit(); + } + else { + if (FB.getSession()){ + signin_form.submit(); + } + FB.login(); + } + }); + } + return false; + }; + + var start_password_login_or_change = function(){ + //called upon clicking on one of the password login buttons + reset_form(); + set_provider_name($(this)); + var provider_name = $(this).attr('name'); + return setup_password_login_or_change(provider_name); + }; + + var init_always_visible_password_login = function(){ + reset_form(); + //will break wordpress and ldap + provider_name_input.val('local'); + setup_password_login_or_change('local'); + }; + + var setup_password_login_or_change = function(provider_name){ + var token_name = extra_token_name[provider_name] + var password_action_input = $('input[name=password_action]'); + if (userIsAuthenticated === true){ + var password_button = $('input[name=change_password]'); + var submit_action = submit_change_password; + if (existing_login_methods && existing_login_methods[provider_name]){ + var change_pw_heading = 'Change your {provider} password'; + var password_heading_text = $.i18n._(change_pw_heading); + var password_button_text = $.i18n._('Change password'); + } + else { + var create_pw_heading = 'Create a password for {provider}'; + var password_heading_text = $.i18n._(create_pw_heading); + var password_button_text = $.i18n._('Create password'); + } + if (provider_name === 'local'){ + var provider_cleaned_name = siteName; + } + else { + var provider_cleaned_name = provider_name; + } + $('#password-heading').html( + password_heading_text.replace('{provider}', provider_cleaned_name) + ) + password_button.val(password_button_text); + password_action_input.val('change_password'); + var focus_input = $('#id_new_password'); + var submittable_input = $('#id_new_password_retyped'); + } + else{ + $('#password-heading>span').html(token_name); + var password_button = $('input[name=login_with_password]'); + var submit_action = submit_login_with_password; + var create_pw_link = $('a.create-password-account') + if (create_pw_link.length > 0){ + create_pw_link.html($.i18n._('Create a password-protected account')); + var url = create_pw_link.attr('href'); + if (url.indexOf('?') !== -1){ + url = url.replace(/\?.*$/,'?login_provider=' + provider_name); + } + else{ + url += '?login_provider=' + provider_name; + } + create_pw_link.attr('href', url); + } + password_action_input.val('login'); + var focus_input = $('#id_username'); + var submittable_input = $('#id_password'); + } + password_input_fields.show(); + focus_input.focus(); + + var submit_password_login = function(){ + signin_form.unbind('submit').submit(submit_action); + }; + + setup_enter_key_handler( + submittable_input, + function() { + password_button.click(); + return false; + } + ); + setup_event_handlers(password_button, submit_password_login); + return false; + }; + + var start_account_recovery = function(){ + reset_form(); + account_recovery_hint.hide(); + account_recovery_heading.css('margin-bottom', '0px'); + account_recovery_heading.html(account_recovery_prompt_text).show(); + email_input_fields.show(); + $('#id_email').focus(); + }; + + var clear_password_fields = function(){ + $('#id_password').val(''); + $('#id_new_password').val(''); + $('#id_new_password_retyped').val(''); + }; + + var setup_default_handlers = function(){ + setup_event_handlers( + signin_page.find('input.openid-direct'), + start_simple_login + ); + + setup_event_handlers( + signin_page.find('input.openid-username'), + start_login_with_extra_openid_token + ); + + setup_event_handlers( + signin_page.find('input.openid-generic'), + start_login_with_extra_openid_token + ); + + setup_event_handlers( + signin_page.find('input.facebook'), + start_facebook_login + ); + + setup_event_handlers( + signin_page.find('input.oauth'), + start_simple_login + ); + + setup_event_handlers( + signin_page.find('input.password'), + start_password_login_or_change + ); + setup_event_handlers( + signin_page.find('input.wordpress_site'), + start_password_login_or_change + ); + + setup_event_handlers(account_recovery_link, start_account_recovery); + + if (userIsAuthenticated){ + read_existing_login_methods(); + setup_login_method_deleters(); + } + }; + + setup_default_handlers(); + if (askbot['settings']['signin_always_show_local_login'] === true){ + init_always_visible_password_login(); + } + clear_password_fields(); + return this; +}; diff --git a/askbot/skins/common/media/jquery-openid/openid.css b/askbot/skins/common/media/jquery-openid/openid.css new file mode 100644 index 00000000..da541e45 --- /dev/null +++ b/askbot/skins/common/media/jquery-openid/openid.css @@ -0,0 +1,38 @@ +div#login-icons {margin:10px 0 0 0;padding:0} +ul.login-icons {width: 450px; margin:0;padding:0;text-align:left; list-style-type:none; display:block;} +ul.login-icons li {display:inline;} +ul.large input {height: 40px; width: 90px;border:1px solid #ccc;margin:0 5px 5px 0;} +.openid-signin h2 {margin-top:15px;} +.openid-signin h2#account-recovery-heading {margin-bottom:2px;} +#account-recovery-form p.hint a {color:blue; text-decoration: underline;} +.openid-signin fieldset { border-style:none;margin:0;padding:0;} +.openid-signin p {margin:0;padding:0}; +.openid-signin p.hint {color: #555;} +.openid-signin #password-fs label {width:100px;margin-top:5px;text-align:left;} +.openid-signin #password-fs .hint {margin-bottom:5px} +#password-fs a {padding-left:5px;} +/*#signin-form #account-recovery-form input {cursor:pointer;} +#signin-form #account-recovery-form input.text {cursor:default;}*/ + +table.login { text-align: right;} + +.openid-signin .submit-b { + cursor: pointer; /*letter-spacing:1px;*/ + margin: 0 0 2px 0; + vertical-align: middle; +} + +.openid-signin .highlight { -moz-border-radius:4px; -webkit-border-radius:4px; background-color: #FD6} + +ul.providers { + display: block; +} + +.openid-signin th { + color: #555; + font-weight: normal; +} + +.openid-signin .ab-provider-name { + font-weight: bold; +} diff --git a/askbot/skins/common/media/js/autocompleter.js b/askbot/skins/common/media/js/autocompleter.js new file mode 100644 index 00000000..a7c54315 --- /dev/null +++ b/askbot/skins/common/media/js/autocompleter.js @@ -0,0 +1,766 @@ +/** + * AutoCompleter Object, refactored closure style from + * jQuery autocomplete plugin + * @param {Object=} options Settings + * @constructor + */ +var AutoCompleter = function(options) { + + /** + * Default options for autocomplete plugin + */ + var defaults = { + autocompleteMultiple: true, + multipleSeparator: ' ',//a single character + inputClass: 'acInput', + loadingClass: 'acLoading', + resultsClass: 'acResults', + selectClass: 'acSelect', + queryParamName: 'q', + limitParamName: 'limit', + extraParams: {}, + lineSeparator: '\n', + cellSeparator: '|', + minChars: 2, + maxItemsToShow: 10, + delay: 400, + useCache: true, + maxCacheLength: 10, + matchSubset: true, + matchCase: false, + matchInside: true, + mustMatch: false, + preloadData: false, + selectFirst: false, + stopCharRegex: /\s+/, + selectOnly: false, + formatItem: null, // TBD + onItemSelect: false, + autoFill: false, + filterResults: true, + sortResults: true, + sortFunction: false, + onNoMatch: false + }; + + /** + * Options dictionary + * @type Object + * @private + */ + this.options = $.extend({}, defaults, options); + + /** + * Cached data + * @type Object + * @private + */ + this.cacheData_ = {}; + + /** + * Number of cached data items + * @type number + * @private + */ + this.cacheLength_ = 0; + + /** + * Class name to mark selected item + * @type string + * @private + */ + this.selectClass_ = 'jquery-autocomplete-selected-item'; + + /** + * Handler to activation timeout + * @type ?number + * @private + */ + this.keyTimeout_ = null; + + /** + * Last key pressed in the input field (store for behavior) + * @type ?number + * @private + */ + this.lastKeyPressed_ = null; + + /** + * Last value processed by the autocompleter + * @type ?string + * @private + */ + this.lastProcessedValue_ = null; + + /** + * Last value selected by the user + * @type ?string + * @private + */ + this.lastSelectedValue_ = null; + + /** + * Is this autocompleter active? + * @type boolean + * @private + */ + this.active_ = false; + + /** + * Is it OK to finish on blur? + * @type boolean + * @private + */ + this.finishOnBlur_ = true; + + this.options.minChars = parseInt(this.options.minChars, 10); + if (isNaN(this.options.minChars) || this.options.minChars < 1) { + this.options.minChars = 2; + } + + this.options.maxItemsToShow = parseInt(this.options.maxItemsToShow, 10); + if (isNaN(this.options.maxItemsToShow) || this.options.maxItemsToShow < 1) { + this.options.maxItemsToShow = 10; + } + + this.options.maxCacheLength = parseInt(this.options.maxCacheLength, 10); + if (isNaN(this.options.maxCacheLength) || this.options.maxCacheLength < 1) { + this.options.maxCacheLength = 10; + } + + if (this.options['preloadData'] === true){ + this.fetchRemoteData('', function(){}); + } +}; +inherits(AutoCompleter, WrappedElement); + +AutoCompleter.prototype.decorate = function(element){ + + /** + * Init DOM elements repository + */ + this._element = element; + + /** + * Switch off the native autocomplete + */ + this._element.attr('autocomplete', 'off'); + + /** + * Create DOM element to hold results + */ + this._results = $('<div></div>').hide(); + if (this.options.resultsClass) { + this._results.addClass(this.options.resultsClass); + } + this._results.css({ + position: 'absolute' + }); + $('body').append(this._results); + + this.setEventHandlers(); +}; + +AutoCompleter.prototype.setEventHandlers = function(){ + /** + * Shortcut to self + */ + var self = this; + + /** + * Attach keyboard monitoring to $elem + */ + self._element.keydown(function(e) { + self.lastKeyPressed_ = e.keyCode; + switch(self.lastKeyPressed_) { + + case 38: // up + e.preventDefault(); + if (self.active_) { + self.focusPrev(); + } else { + self.activate(); + } + return false; + break; + + case 40: // down + e.preventDefault(); + if (self.active_) { + self.focusNext(); + } else { + self.activate(); + } + return false; + break; + + case 9: // tab + case 13: // return + if (self.active_) { + e.preventDefault(); + self.selectCurrent(); + return false; + } + break; + + case 27: // escape + if (self.active_) { + e.preventDefault(); + self.finish(); + return false; + } + break; + + default: + self.activate(); + + } + }); + self._element.blur(function() { + if (self.finishOnBlur_) { + setTimeout(function() { self.finish(); }, 200); + } + }); +}; + +AutoCompleter.prototype.position = function() { + var offset = this._element.offset(); + this._results.css({ + top: offset.top + this._element.outerHeight(), + left: offset.left + }); +}; + +AutoCompleter.prototype.cacheRead = function(filter) { + var filterLength, searchLength, search, maxPos, pos; + if (this.options.useCache) { + filter = String(filter); + filterLength = filter.length; + if (this.options.matchSubset) { + searchLength = 1; + } else { + searchLength = filterLength; + } + while (searchLength <= filterLength) { + if (this.options.matchInside) { + maxPos = filterLength - searchLength; + } else { + maxPos = 0; + } + pos = 0; + while (pos <= maxPos) { + search = filter.substr(0, searchLength); + if (this.cacheData_[search] !== undefined) { + return this.cacheData_[search]; + } + pos++; + } + searchLength++; + } + } + return false; +}; + +AutoCompleter.prototype.cacheWrite = function(filter, data) { + if (this.options.useCache) { + if (this.cacheLength_ >= this.options.maxCacheLength) { + this.cacheFlush(); + } + filter = String(filter); + if (this.cacheData_[filter] !== undefined) { + this.cacheLength_++; + } + return this.cacheData_[filter] = data; + } + return false; +}; + +AutoCompleter.prototype.cacheFlush = function() { + this.cacheData_ = {}; + this.cacheLength_ = 0; +}; + +AutoCompleter.prototype.callHook = function(hook, data) { + var f = this.options[hook]; + if (f && $.isFunction(f)) { + return f(data, this); + } + return false; +}; + +AutoCompleter.prototype.activate = function() { + var self = this; + var activateNow = function() { + self.activateNow(); + }; + var delay = parseInt(this.options.delay, 10); + if (isNaN(delay) || delay <= 0) { + delay = 250; + } + if (this.keyTimeout_) { + clearTimeout(this.keyTimeout_); + } + this.keyTimeout_ = setTimeout(activateNow, delay); +}; + +AutoCompleter.prototype.activateNow = function() { + var value = this.getValue(); + if (value !== this.lastProcessedValue_ && value !== this.lastSelectedValue_) { + if (value.length >= this.options.minChars) { + this.active_ = true; + this.lastProcessedValue_ = value; + this.fetchData(value); + } + } +}; + +AutoCompleter.prototype.fetchData = function(value) { + if (this.options.data) { + this.filterAndShowResults(this.options.data, value); + } else { + var self = this; + this.fetchRemoteData(value, function(remoteData) { + self.filterAndShowResults(remoteData, value); + }); + } +}; + +AutoCompleter.prototype.fetchRemoteData = function(filter, callback) { + var data = this.cacheRead(filter); + if (data) { + callback(data); + } else { + var self = this; + if (this._element){ + this._element.addClass(this.options.loadingClass); + } + var ajaxCallback = function(data) { + var parsed = false; + if (data !== false) { + parsed = self.parseRemoteData(data); + self.options.data = parsed;//cache data forever - E.F. + self.cacheWrite(filter, parsed); + } + if (self._element){ + self._element.removeClass(self.options.loadingClass); + } + callback(parsed); + }; + $.ajax({ + url: this.makeUrl(filter), + success: ajaxCallback, + error: function() { + ajaxCallback(false); + } + }); + } +}; + +AutoCompleter.prototype.setOption = function(name, value){ + this.options[name] = value; +}; + +AutoCompleter.prototype.setExtraParam = function(name, value) { + var index = $.trim(String(name)); + if (index) { + if (!this.options.extraParams) { + this.options.extraParams = {}; + } + if (this.options.extraParams[index] !== value) { + this.options.extraParams[index] = value; + this.cacheFlush(); + } + } +}; + +AutoCompleter.prototype.makeUrl = function(param) { + var self = this; + var url = this.options.url; + var params = $.extend({}, this.options.extraParams); + // If options.queryParamName === false, append query to url + // instead of using a GET parameter + if (this.options.queryParamName === false) { + url += encodeURIComponent(param); + } else { + params[this.options.queryParamName] = param; + } + + if (this.options.limitParamName && this.options.maxItemsToShow) { + params[this.options.limitParamName] = this.options.maxItemsToShow; + } + + var urlAppend = []; + $.each(params, function(index, value) { + urlAppend.push(self.makeUrlParam(index, value)); + }); + if (urlAppend.length) { + url += url.indexOf('?') == -1 ? '?' : '&'; + url += urlAppend.join('&'); + } + return url; +}; + +AutoCompleter.prototype.makeUrlParam = function(name, value) { + return String(name) + '=' + encodeURIComponent(value); +}; + +/** + * Sanitize CR and LF, then split into lines + */ +AutoCompleter.prototype.splitText = function(text) { + return String(text).replace(/(\r\n|\r|\n)/g, '\n').split(this.options.lineSeparator); +}; + +AutoCompleter.prototype.parseRemoteData = function(remoteData) { + var value, lines, i, j, data; + var results = []; + var lines = this.splitText(remoteData); + for (i = 0; i < lines.length; i++) { + var line = lines[i].split(this.options.cellSeparator); + data = []; + for (j = 0; j < line.length; j++) { + data.push(unescape(line[j])); + } + value = data.shift(); + results.push({ value: unescape(value), data: data }); + } + return results; +}; + +AutoCompleter.prototype.filterAndShowResults = function(results, filter) { + this.showResults(this.filterResults(results, filter), filter); +}; + +AutoCompleter.prototype.filterResults = function(results, filter) { + + var filtered = []; + var value, data, i, result, type, include; + var regex, pattern, testValue; + + for (i = 0; i < results.length; i++) { + result = results[i]; + type = typeof result; + if (type === 'string') { + value = result; + data = {}; + } else if ($.isArray(result)) { + value = result[0]; + data = result.slice(1); + } else if (type === 'object') { + value = result.value; + data = result.data; + } + value = String(value); + if (value > '') { + if (typeof data !== 'object') { + data = {}; + } + if (this.options.filterResults) { + pattern = String(filter); + testValue = String(value); + if (!this.options.matchCase) { + pattern = pattern.toLowerCase(); + testValue = testValue.toLowerCase(); + } + include = testValue.indexOf(pattern); + if (this.options.matchInside) { + include = include > -1; + } else { + include = include === 0; + } + } else { + include = true; + } + if (include) { + filtered.push({ value: value, data: data }); + } + } + } + + if (this.options.sortResults) { + filtered = this.sortResults(filtered, filter); + } + + if (this.options.maxItemsToShow > 0 && this.options.maxItemsToShow < filtered.length) { + filtered.length = this.options.maxItemsToShow; + } + + return filtered; + +}; + +AutoCompleter.prototype.sortResults = function(results, filter) { + var self = this; + var sortFunction = this.options.sortFunction; + if (!$.isFunction(sortFunction)) { + sortFunction = function(a, b, f) { + return self.sortValueAlpha(a, b, f); + }; + } + results.sort(function(a, b) { + return sortFunction(a, b, filter); + }); + return results; +}; + +AutoCompleter.prototype.sortValueAlpha = function(a, b, filter) { + a = String(a.value); + b = String(b.value); + if (!this.options.matchCase) { + a = a.toLowerCase(); + b = b.toLowerCase(); + } + if (a > b) { + return 1; + } + if (a < b) { + return -1; + } + return 0; +}; + +AutoCompleter.prototype.showResults = function(results, filter) { + var self = this; + var $ul = $('<ul></ul>'); + var i, result, $li, extraWidth, first = false, $first = false; + var numResults = results.length; + for (i = 0; i < numResults; i++) { + result = results[i]; + $li = $('<li>' + this.showResult(result.value, result.data) + '</li>'); + $li.data('value', result.value); + $li.data('data', result.data); + $li.click(function() { + var $this = $(this); + self.selectItem($this); + }).mousedown(function() { + self.finishOnBlur_ = false; + }).mouseup(function() { + self.finishOnBlur_ = true; + }); + $ul.append($li); + if (first === false) { + first = String(result.value); + $first = $li; + $li.addClass(this.options.firstItemClass); + } + if (i == numResults - 1) { + $li.addClass(this.options.lastItemClass); + } + } + + // Alway recalculate position before showing since window size or + // input element location may have changed. This fixes #14 + this.position(); + + this._results.html($ul).show(); + extraWidth = this._results.outerWidth() - this._results.width(); + this._results.width(this._element.outerWidth() - extraWidth); + $('li', this._results).hover( + function() { self.focusItem(this); }, + function() { /* void */ } + ); + if (this.autoFill(first, filter)) { + this.focusItem($first); + } +}; + +AutoCompleter.prototype.showResult = function(value, data) { + if ($.isFunction(this.options.showResult)) { + return this.options.showResult(value, data); + } else { + return value; + } +}; + +AutoCompleter.prototype.autoFill = function(value, filter) { + var lcValue, lcFilter, valueLength, filterLength; + if (this.options.autoFill && this.lastKeyPressed_ != 8) { + lcValue = String(value).toLowerCase(); + lcFilter = String(filter).toLowerCase(); + valueLength = value.length; + filterLength = filter.length; + if (lcValue.substr(0, filterLength) === lcFilter) { + this._element.val(value); + this.selectRange(filterLength, valueLength); + return true; + } + } + return false; +}; + +AutoCompleter.prototype.focusNext = function() { + this.focusMove(+1); +}; + +AutoCompleter.prototype.focusPrev = function() { + this.focusMove(-1); +}; + +AutoCompleter.prototype.focusMove = function(modifier) { + var i, $items = $('li', this._results); + modifier = parseInt(modifier, 10); + for (var i = 0; i < $items.length; i++) { + if ($($items[i]).hasClass(this.selectClass_)) { + this.focusItem(i + modifier); + return; + } + } + this.focusItem(0); +}; + +AutoCompleter.prototype.focusItem = function(item) { + var $item, $items = $('li', this._results); + if ($items.length) { + $items.removeClass(this.selectClass_).removeClass(this.options.selectClass); + if (typeof item === 'number') { + item = parseInt(item, 10); + if (item < 0) { + item = 0; + } else if (item >= $items.length) { + item = $items.length - 1; + } + $item = $($items[item]); + } else { + $item = $(item); + } + if ($item) { + $item.addClass(this.selectClass_).addClass(this.options.selectClass); + } + } +}; + +AutoCompleter.prototype.selectCurrent = function() { + var $item = $('li.' + this.selectClass_, this._results); + if ($item.length == 1) { + this.selectItem($item); + } else { + this.finish(); + } +}; + +AutoCompleter.prototype.selectItem = function($li) { + var value = $li.data('value'); + var data = $li.data('data'); + var displayValue = this.displayValue(value, data); + this.lastProcessedValue_ = displayValue; + this.lastSelectedValue_ = displayValue; + + this.setValue(displayValue); + + this.setCaret(displayValue.length); + this.callHook('onItemSelect', { value: value, data: data }); + this.finish(); +}; + +/** + * @return {boolean} true if the symbol matches something that is + * considered content and false otherwise + * @param {string} symbol - a single char string + */ +AutoCompleter.prototype.isContentChar = function(symbol){ + if (symbol.match(this.options['stopCharRegex'])){ + return false; + } else if (symbol === this.options['multipleSeparator']){ + return false; + } else { + return true; + } +}; + +/** + * takes value from the input box + * and saves _selection_start and _selection_end coordinates + * respects settings autocompleteMultiple and + * multipleSeparator + * @return {string} the current word in the + * autocompletable word + */ +AutoCompleter.prototype.getValue = function(){ + var sel = this._element.getSelection(); + var text = this._element.val(); + var pos = sel.start;//estimated start + //find real start + var start = pos; + for (cpos = pos; cpos >= 0; cpos = cpos - 1){ + if (cpos === text.length){ + continue; + } + var symbol = text.charAt(cpos); + if (!this.isContentChar(symbol)){ + break; + } + start = cpos; + } + //find real end + var end = pos; + for (cpos = pos; cpos < text.length; cpos = cpos + 1){ + if (cpos === 0){ + continue; + } + var symbol = text.charAt(cpos); + if (!this.isContentChar(symbol)){ + break; + } + end = cpos; + } + this._selection_start = start; + this._selection_end = end; + return text.substring(start, end); +} + +/** + * sets value of the input box + * by replacing the previous selection + * with the value from the autocompleter + */ +AutoCompleter.prototype.setValue = function(val){ + var prefix = this._element.val().substring(0, this._selection_start); + var postfix = this._element.val().substring(this._selection_end + 1); + this._element.val(prefix + val + postfix); +}; + +AutoCompleter.prototype.displayValue = function(value, data) { + if ($.isFunction(this.options.displayValue)) { + return this.options.displayValue(value, data); + } else { + return value; + } +}; + +AutoCompleter.prototype.finish = function() { + if (this.keyTimeout_) { + clearTimeout(this.keyTimeout_); + } + if (this._element.val() !== this.lastSelectedValue_) { + if (this.options.mustMatch) { + this._element.val(''); + } + this.callHook('onNoMatch'); + } + this._results.hide(); + this.lastKeyPressed_ = null; + this.lastProcessedValue_ = null; + if (this.active_) { + this.callHook('onFinish'); + } + this.active_ = false; +}; + +AutoCompleter.prototype.selectRange = function(start, end) { + var input = this._element.get(0); + if (input.setSelectionRange) { + input.focus(); + input.setSelectionRange(start, end); + } else if (this.createTextRange) { + var range = this.createTextRange(); + range.collapse(true); + range.moveEnd('character', end); + range.moveStart('character', start); + range.select(); + } +}; + +AutoCompleter.prototype.setCaret = function(pos) { + this.selectRange(pos, pos); +}; + diff --git a/askbot/skins/common/media/js/compress.bat b/askbot/skins/common/media/js/compress.bat new file mode 100644 index 00000000..53d72588 --- /dev/null +++ b/askbot/skins/common/media/js/compress.bat @@ -0,0 +1,5 @@ +#java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 wmd\wmd.js -o wmd\wmd-min.js +#java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 wmd\showdown.js -o wmd\showdown-min.js +#java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 post.js -o post.pack.js +java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 se_hilite_src.js -o se_hilite.js +pause diff --git a/askbot/skins/common/media/js/editor.js b/askbot/skins/common/media/js/editor.js new file mode 100644 index 00000000..f5b1e2af --- /dev/null +++ b/askbot/skins/common/media/js/editor.js @@ -0,0 +1,75 @@ +/* + jQuery TextAreaResizer plugin + Created on 17th January 2008 by Ryan O'Dell + Version 1.0.4 +*/(function($){var textarea,staticOffset;var iLastMousePos=0;var iMin=32;var grip;$.fn.TextAreaResizer=function(){return this.each(function(){textarea=$(this).addClass('processed'),staticOffset=null;$(this).wrap('<div class="resizable-textarea"><span></span></div>').parent().append($('<div class="grippie"></div>').bind("mousedown",{el:this},startDrag));var grippie=$('div.grippie',$(this).parent())[0];grippie.style.marginRight=(grippie.offsetWidth-$(this)[0].offsetWidth)+'px'})};function startDrag(e){textarea=$(e.data.el);textarea.blur();iLastMousePos=mousePosition(e).y;staticOffset=textarea.height()-iLastMousePos;textarea.css('opacity',0.25);$(document).mousemove(performDrag).mouseup(endDrag);return false}function performDrag(e){var iThisMousePos=mousePosition(e).y;var iMousePos=staticOffset+iThisMousePos;if(iLastMousePos>=(iThisMousePos)){iMousePos-=5}iLastMousePos=iThisMousePos;iMousePos=Math.max(iMin,iMousePos);textarea.height(iMousePos+'px');if(iMousePos<iMin){endDrag(e)}return false}function endDrag(e){$(document).unbind('mousemove',performDrag).unbind('mouseup',endDrag);textarea.css('opacity',1);textarea.focus();textarea=null;staticOffset=null;iLastMousePos=0}function mousePosition(e){return{x:e.clientX+document.documentElement.scrollLeft,y:e.clientY+document.documentElement.scrollTop}}})(jQuery); +/* + * TypeWatch 2.0 - Original by Denny Ferrassoli / Refactored by Charles Christolini + * Copyright(c) 2007 Denny Ferrassoli - DennyDotNet.com + * Coprright(c) 2008 Charles Christolini - BinaryPie.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +*/(function(jQuery){jQuery.fn.typeWatch=function(o){var options=jQuery.extend({wait:750,callback:function(){},highlight:true,captureLength:2},o);function checkElement(timer,override){var elTxt=jQuery(timer.el).val();if((elTxt.length>options.captureLength&&elTxt.toUpperCase()!=timer.text)||(override&&elTxt.length>options.captureLength)){timer.text=elTxt.toUpperCase();timer.cb(elTxt)}};function watchElement(elem){if(elem.type.toUpperCase()=="TEXT"||elem.nodeName.toUpperCase()=="TEXTAREA"){var timer={timer:null,text:jQuery(elem).val().toUpperCase(),cb:options.callback,el:elem,wait:options.wait};if(options.highlight){jQuery(elem).focus(function(){this.select()})}var startWatch=function(evt){var timerWait=timer.wait;var overrideBool=false;if(evt.keyCode==13&&this.type.toUpperCase()=="TEXT"){timerWait=1;overrideBool=true}var timerCallbackFx=function(){checkElement(timer,overrideBool)};clearTimeout(timer.timer);timer.timer=setTimeout(timerCallbackFx,timerWait)};jQuery(elem).keydown(startWatch)}};return this.each(function(index){watchElement(this)})}})(jQuery); +/* +Ajax upload +*/jQuery.extend({createUploadIframe:function(d,b){var a="jUploadFrame"+d;if(window.ActiveXObject){var c=document.createElement('<iframe id="'+a+'" name="'+a+'" />');if(typeof b=="boolean"){c.src="javascript:false"}else{if(typeof b=="string"){c.src=b}}}else{var c=document.createElement("iframe");c.id=a;c.name=a}c.style.position="absolute";c.style.top="-1000px";c.style.left="-1000px";document.body.appendChild(c);return c},createUploadForm:function(g,b){var e="jUploadForm"+g;var a="jUploadFile"+g;var d=$('<form action="" method="POST" name="'+e+'" id="'+e+'" enctype="multipart/form-data"></form>');var c=$("#"+b);var f=$(c).clone();$(c).attr("id",a);$(c).before(f);$(c).appendTo(d);$(d).css("position","absolute");$(d).css("top","-1200px");$(d).css("left","-1200px");$(d).appendTo("body");return d},ajaxFileUpload:function(k){k=jQuery.extend({},jQuery.ajaxSettings,k);var a=new Date().getTime();var b=jQuery.createUploadForm(a,k.fileElementId);var i=jQuery.createUploadIframe(a,k.secureuri);var h="jUploadFrame"+a;var j="jUploadForm"+a;if(k.global&&!jQuery.active++){jQuery.event.trigger("ajaxStart")}var c=false;var f={};if(k.global){jQuery.event.trigger("ajaxSend",[f,k])}var d=function(l){var p=document.getElementById(h);try{if(p.contentWindow){f.responseText=p.contentWindow.document.body?p.contentWindow.document.body.innerText:null;f.responseXML=p.contentWindow.document.XMLDocument?p.contentWindow.document.XMLDocument:p.contentWindow.document}else{if(p.contentDocument){f.responseText=p.contentDocument.document.body?p.contentDocument.document.body.textContent||document.body.innerText:null;f.responseXML=p.contentDocument.document.XMLDocument?p.contentDocument.document.XMLDocument:p.contentDocument.document}}}catch(o){jQuery.handleError(k,f,null,o)}if(f||l=="timeout"){c=true;var m;try{m=l!="timeout"?"success":"error";if(m!="error"){var n=jQuery.uploadHttpData(f,k.dataType);if(k.success){k.success(n,m)}if(k.global){jQuery.event.trigger("ajaxSuccess",[f,k])}}else{jQuery.handleError(k,f,m)}}catch(o){m="error";jQuery.handleError(k,f,m,o)}if(k.global){jQuery.event.trigger("ajaxComplete",[f,k])}if(k.global&&!--jQuery.active){jQuery.event.trigger("ajaxStop")}if(k.complete){k.complete(f,m)}jQuery(p).unbind();setTimeout(function(){try{$(p).remove();$(b).remove()}catch(q){jQuery.handleError(k,f,null,q)}},100);f=null}};if(k.timeout>0){setTimeout(function(){if(!c){d("timeout")}},k.timeout)}try{var b=$("#"+j);$(b).attr("action",k.url);$(b).attr("method","POST");$(b).attr("target",h);if(b.encoding){b.encoding="multipart/form-data"}else{b.enctype="multipart/form-data"}$(b).submit()}catch(g){jQuery.handleError(k,f,null,g)}if(window.attachEvent){document.getElementById(h).attachEvent("onload",d)}else{document.getElementById(h).addEventListener("load",d,false)}return{abort:function(){}}},uploadHttpData:function(r,type){var data=!type;data=type=="xml"||data?r.responseXML:r.responseText;if(type=="script"){jQuery.globalEval(data)}if(type=="json"){eval("data = "+data)}if(type=="html"){jQuery("<div>").html(data).evalScripts()}return data}}); +/** + * Upload call. Used only once in the wmd file upload + * this is "tightly coupled" with the wmd file uploader + * @param {Object} jquery object imageUrl - where the + * uploaded url must be inserted on successful upload + * @param {Function} handler that is run upon change + * of the file upload field + */ +function ajaxFileUpload(imageUrl, startUploadHandler) +{ + $("#loading").ajaxStart(function(){ + $(this).show(); + }).ajaxComplete(function(){ + $(this).hide(); + }); + + $("#upload").ajaxStart(function(){ + $(this).hide(); + }).ajaxComplete(function(){ + $(this).show(); + }); + + $.ajaxFileUpload + ( + { + url: askbot['urls']['upload'], + secureuri:false, + fileElementId:'file-upload', + dataType: 'xml', + success: function (data, status) + { + var fileURL = $(data).find('file_url').text(); + var error = $(data).find('error').text(); + if(error != ''){ + alert(error); + if (startUploadHandler){ + /* re-install this as the upload extension + * will remove the handler to prevent double uploading */ + $('#file-upload').change(startUploadHandler); + } + }else{ + imageUrl.attr('value', fileURL); + } + + }, + error: function (data, status, e) + { + alert(e); + if (startUploadHandler){ + /* re-install this as the upload extension + * will remove the handler to prevent double uploading */ + $('#file-upload').change(startUploadHandler); + } + } + } + ) + + return false; +} diff --git a/askbot/skins/common/media/js/excanvas.min.js b/askbot/skins/common/media/js/excanvas.min.js new file mode 100644 index 00000000..12c74f7b --- /dev/null +++ b/askbot/skins/common/media/js/excanvas.min.js @@ -0,0 +1 @@ +if(!document.createElement("canvas").getContext){(function(){var z=Math;var K=z.round;var J=z.sin;var U=z.cos;var b=z.abs;var k=z.sqrt;var D=10;var F=D/2;function T(){return this.context_||(this.context_=new W(this))}var O=Array.prototype.slice;function G(i,j,m){var Z=O.call(arguments,2);return function(){return i.apply(j,Z.concat(O.call(arguments)))}}function AD(Z){return String(Z).replace(/&/g,"&").replace(/"/g,""")}function r(i){if(!i.namespaces.g_vml_){i.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML")}if(!i.namespaces.g_o_){i.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML")}if(!i.styleSheets.ex_canvas_){var Z=i.createStyleSheet();Z.owningElement.id="ex_canvas_";Z.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}r(document);var E={init:function(Z){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var i=Z||document;i.createElement("canvas");i.attachEvent("onreadystatechange",G(this.init_,this,i))}},init_:function(m){var j=m.getElementsByTagName("canvas");for(var Z=0;Z<j.length;Z++){this.initElement(j[Z])}},initElement:function(i){if(!i.getContext){i.getContext=T;r(i.ownerDocument);i.innerHTML="";i.attachEvent("onpropertychange",S);i.attachEvent("onresize",w);var Z=i.attributes;if(Z.width&&Z.width.specified){i.style.width=Z.width.nodeValue+"px"}else{i.width=i.clientWidth}if(Z.height&&Z.height.specified){i.style.height=Z.height.nodeValue+"px"}else{i.height=i.clientHeight}}return i}};function S(i){var Z=i.srcElement;switch(i.propertyName){case"width":Z.getContext().clearRect();Z.style.width=Z.attributes.width.nodeValue+"px";Z.firstChild.style.width=Z.clientWidth+"px";break;case"height":Z.getContext().clearRect();Z.style.height=Z.attributes.height.nodeValue+"px";Z.firstChild.style.height=Z.clientHeight+"px";break}}function w(i){var Z=i.srcElement;if(Z.firstChild){Z.firstChild.style.width=Z.clientWidth+"px";Z.firstChild.style.height=Z.clientHeight+"px"}}E.init();var I=[];for(var AC=0;AC<16;AC++){for(var AB=0;AB<16;AB++){I[AC*16+AB]=AC.toString(16)+AB.toString(16)}}function V(){return[[1,0,0],[0,1,0],[0,0,1]]}function d(m,j){var i=V();for(var Z=0;Z<3;Z++){for(var AF=0;AF<3;AF++){var p=0;for(var AE=0;AE<3;AE++){p+=m[Z][AE]*j[AE][AF]}i[Z][AF]=p}}return i}function Q(i,Z){Z.fillStyle=i.fillStyle;Z.lineCap=i.lineCap;Z.lineJoin=i.lineJoin;Z.lineWidth=i.lineWidth;Z.miterLimit=i.miterLimit;Z.shadowBlur=i.shadowBlur;Z.shadowColor=i.shadowColor;Z.shadowOffsetX=i.shadowOffsetX;Z.shadowOffsetY=i.shadowOffsetY;Z.strokeStyle=i.strokeStyle;Z.globalAlpha=i.globalAlpha;Z.font=i.font;Z.textAlign=i.textAlign;Z.textBaseline=i.textBaseline;Z.arcScaleX_=i.arcScaleX_;Z.arcScaleY_=i.arcScaleY_;Z.lineScale_=i.lineScale_}var B={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"};function g(i){var m=i.indexOf("(",3);var Z=i.indexOf(")",m+1);var j=i.substring(m+1,Z).split(",");if(j.length==4&&i.substr(3,1)=="a"){alpha=Number(j[3])}else{j[3]=1}return j}function C(Z){return parseFloat(Z)/100}function N(i,j,Z){return Math.min(Z,Math.max(j,i))}function c(AF){var j,i,Z;h=parseFloat(AF[0])/360%360;if(h<0){h++}s=N(C(AF[1]),0,1);l=N(C(AF[2]),0,1);if(s==0){j=i=Z=l}else{var m=l<0.5?l*(1+s):l+s-l*s;var AE=2*l-m;j=A(AE,m,h+1/3);i=A(AE,m,h);Z=A(AE,m,h-1/3)}return"#"+I[Math.floor(j*255)]+I[Math.floor(i*255)]+I[Math.floor(Z*255)]}function A(i,Z,j){if(j<0){j++}if(j>1){j--}if(6*j<1){return i+(Z-i)*6*j}else{if(2*j<1){return Z}else{if(3*j<2){return i+(Z-i)*(2/3-j)*6}else{return i}}}}function Y(Z){var AE,p=1;Z=String(Z);if(Z.charAt(0)=="#"){AE=Z}else{if(/^rgb/.test(Z)){var m=g(Z);var AE="#",AF;for(var j=0;j<3;j++){if(m[j].indexOf("%")!=-1){AF=Math.floor(C(m[j])*255)}else{AF=Number(m[j])}AE+=I[N(AF,0,255)]}p=m[3]}else{if(/^hsl/.test(Z)){var m=g(Z);AE=c(m);p=m[3]}else{AE=B[Z]||Z}}}return{color:AE,alpha:p}}var L={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};var f={};function X(Z){if(f[Z]){return f[Z]}var m=document.createElement("div");var j=m.style;try{j.font=Z}catch(i){}return f[Z]={style:j.fontStyle||L.style,variant:j.fontVariant||L.variant,weight:j.fontWeight||L.weight,size:j.fontSize||L.size,family:j.fontFamily||L.family}}function P(j,i){var Z={};for(var AF in j){Z[AF]=j[AF]}var AE=parseFloat(i.currentStyle.fontSize),m=parseFloat(j.size);if(typeof j.size=="number"){Z.size=j.size}else{if(j.size.indexOf("px")!=-1){Z.size=m}else{if(j.size.indexOf("em")!=-1){Z.size=AE*m}else{if(j.size.indexOf("%")!=-1){Z.size=(AE/100)*m}else{if(j.size.indexOf("pt")!=-1){Z.size=m/0.75}else{Z.size=AE}}}}}Z.size*=0.981;return Z}function AA(Z){return Z.style+" "+Z.variant+" "+Z.weight+" "+Z.size+"px "+Z.family}function t(Z){switch(Z){case"butt":return"flat";case"round":return"round";case"square":default:return"square"}}function W(i){this.m_=V();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=D*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=i;var Z=i.ownerDocument.createElement("div");Z.style.width=i.clientWidth+"px";Z.style.height=i.clientHeight+"px";Z.style.overflow="hidden";Z.style.position="absolute";i.appendChild(Z);this.element_=Z;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var M=W.prototype;M.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};M.beginPath=function(){this.currentPath_=[]};M.moveTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"moveTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.lineTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"lineTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.bezierCurveTo=function(j,i,AI,AH,AG,AE){var Z=this.getCoords_(AG,AE);var AF=this.getCoords_(j,i);var m=this.getCoords_(AI,AH);e(this,AF,m,Z)};function e(Z,m,j,i){Z.currentPath_.push({type:"bezierCurveTo",cp1x:m.x,cp1y:m.y,cp2x:j.x,cp2y:j.y,x:i.x,y:i.y});Z.currentX_=i.x;Z.currentY_=i.y}M.quadraticCurveTo=function(AG,j,i,Z){var AF=this.getCoords_(AG,j);var AE=this.getCoords_(i,Z);var AH={x:this.currentX_+2/3*(AF.x-this.currentX_),y:this.currentY_+2/3*(AF.y-this.currentY_)};var m={x:AH.x+(AE.x-this.currentX_)/3,y:AH.y+(AE.y-this.currentY_)/3};e(this,AH,m,AE)};M.arc=function(AJ,AH,AI,AE,i,j){AI*=D;var AN=j?"at":"wa";var AK=AJ+U(AE)*AI-F;var AM=AH+J(AE)*AI-F;var Z=AJ+U(i)*AI-F;var AL=AH+J(i)*AI-F;if(AK==Z&&!j){AK+=0.125}var m=this.getCoords_(AJ,AH);var AG=this.getCoords_(AK,AM);var AF=this.getCoords_(Z,AL);this.currentPath_.push({type:AN,x:m.x,y:m.y,radius:AI,xStart:AG.x,yStart:AG.y,xEnd:AF.x,yEnd:AF.y})};M.rect=function(j,i,Z,m){this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath()};M.strokeRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.stroke();this.currentPath_=p};M.fillRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.fill();this.currentPath_=p};M.createLinearGradient=function(i,m,Z,j){var p=new v("gradient");p.x0_=i;p.y0_=m;p.x1_=Z;p.y1_=j;return p};M.createRadialGradient=function(m,AE,j,i,p,Z){var AF=new v("gradientradial");AF.x0_=m;AF.y0_=AE;AF.r0_=j;AF.x1_=i;AF.y1_=p;AF.r1_=Z;return AF};M.drawImage=function(AO,j){var AH,AF,AJ,AV,AM,AK,AQ,AX;var AI=AO.runtimeStyle.width;var AN=AO.runtimeStyle.height;AO.runtimeStyle.width="auto";AO.runtimeStyle.height="auto";var AG=AO.width;var AT=AO.height;AO.runtimeStyle.width=AI;AO.runtimeStyle.height=AN;if(arguments.length==3){AH=arguments[1];AF=arguments[2];AM=AK=0;AQ=AJ=AG;AX=AV=AT}else{if(arguments.length==5){AH=arguments[1];AF=arguments[2];AJ=arguments[3];AV=arguments[4];AM=AK=0;AQ=AG;AX=AT}else{if(arguments.length==9){AM=arguments[1];AK=arguments[2];AQ=arguments[3];AX=arguments[4];AH=arguments[5];AF=arguments[6];AJ=arguments[7];AV=arguments[8]}else{throw Error("Invalid number of arguments")}}}var AW=this.getCoords_(AH,AF);var m=AQ/2;var i=AX/2;var AU=[];var Z=10;var AE=10;AU.push(" <g_vml_:group",' coordsize="',D*Z,",",D*AE,'"',' coordorigin="0,0"',' style="width:',Z,"px;height:",AE,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var p=[];p.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",K(AW.x/D),",","Dy=",K(AW.y/D),"");var AS=AW;var AR=this.getCoords_(AH+AJ,AF);var AP=this.getCoords_(AH,AF+AV);var AL=this.getCoords_(AH+AJ,AF+AV);AS.x=z.max(AS.x,AR.x,AP.x,AL.x);AS.y=z.max(AS.y,AR.y,AP.y,AL.y);AU.push("padding:0 ",K(AS.x/D),"px ",K(AS.y/D),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",p.join(""),", sizingmethod='clip');")}else{AU.push("top:",K(AW.y/D),"px;left:",K(AW.x/D),"px;")}AU.push(' ">','<g_vml_:image src="',AO.src,'"',' style="width:',D*AJ,"px;"," height:",D*AV,'px"',' cropleft="',AM/AG,'"',' croptop="',AK/AT,'"',' cropright="',(AG-AM-AQ)/AG,'"',' cropbottom="',(AT-AK-AX)/AT,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",AU.join(""))};M.stroke=function(AM){var m=10;var AN=10;var AE=5000;var AG={x:null,y:null};var AL={x:null,y:null};for(var AH=0;AH<this.currentPath_.length;AH+=AE){var AK=[];var AF=false;AK.push("<g_vml_:shape",' filled="',!!AM,'"',' style="position:absolute;width:',m,"px;height:",AN,'px;"',' coordorigin="0,0"',' coordsize="',D*m,",",D*AN,'"',' stroked="',!AM,'"',' path="');var AO=false;for(var AI=AH;AI<Math.min(AH+AE,this.currentPath_.length);AI++){if(AI%AE==0&&AI>0){AK.push(" m ",K(this.currentPath_[AI-1].x),",",K(this.currentPath_[AI-1].y))}var Z=this.currentPath_[AI];var AJ;switch(Z.type){case"moveTo":AJ=Z;AK.push(" m ",K(Z.x),",",K(Z.y));break;case"lineTo":AK.push(" l ",K(Z.x),",",K(Z.y));break;case"close":AK.push(" x ");Z=null;break;case"bezierCurveTo":AK.push(" c ",K(Z.cp1x),",",K(Z.cp1y),",",K(Z.cp2x),",",K(Z.cp2y),",",K(Z.x),",",K(Z.y));break;case"at":case"wa":AK.push(" ",Z.type," ",K(Z.x-this.arcScaleX_*Z.radius),",",K(Z.y-this.arcScaleY_*Z.radius)," ",K(Z.x+this.arcScaleX_*Z.radius),",",K(Z.y+this.arcScaleY_*Z.radius)," ",K(Z.xStart),",",K(Z.yStart)," ",K(Z.xEnd),",",K(Z.yEnd));break}if(Z){if(AG.x==null||Z.x<AG.x){AG.x=Z.x}if(AL.x==null||Z.x>AL.x){AL.x=Z.x}if(AG.y==null||Z.y<AG.y){AG.y=Z.y}if(AL.y==null||Z.y>AL.y){AL.y=Z.y}}}AK.push(' ">');if(!AM){R(this,AK)}else{a(this,AK,AG,AL)}AK.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",AK.join(""))}};function R(j,AE){var i=Y(j.strokeStyle);var m=i.color;var p=i.alpha*j.globalAlpha;var Z=j.lineScale_*j.lineWidth;if(Z<1){p*=Z}AE.push("<g_vml_:stroke",' opacity="',p,'"',' joinstyle="',j.lineJoin,'"',' miterlimit="',j.miterLimit,'"',' endcap="',t(j.lineCap),'"',' weight="',Z,'px"',' color="',m,'" />')}function a(AO,AG,Ah,AP){var AH=AO.fillStyle;var AY=AO.arcScaleX_;var AX=AO.arcScaleY_;var Z=AP.x-Ah.x;var m=AP.y-Ah.y;if(AH instanceof v){var AL=0;var Ac={x:0,y:0};var AU=0;var AK=1;if(AH.type_=="gradient"){var AJ=AH.x0_/AY;var j=AH.y0_/AX;var AI=AH.x1_/AY;var Aj=AH.y1_/AX;var Ag=AO.getCoords_(AJ,j);var Af=AO.getCoords_(AI,Aj);var AE=Af.x-Ag.x;var p=Af.y-Ag.y;AL=Math.atan2(AE,p)*180/Math.PI;if(AL<0){AL+=360}if(AL<0.000001){AL=0}}else{var Ag=AO.getCoords_(AH.x0_,AH.y0_);Ac={x:(Ag.x-Ah.x)/Z,y:(Ag.y-Ah.y)/m};Z/=AY*D;m/=AX*D;var Aa=z.max(Z,m);AU=2*AH.r0_/Aa;AK=2*AH.r1_/Aa-AU}var AS=AH.colors_;AS.sort(function(Ak,i){return Ak.offset-i.offset});var AN=AS.length;var AR=AS[0].color;var AQ=AS[AN-1].color;var AW=AS[0].alpha*AO.globalAlpha;var AV=AS[AN-1].alpha*AO.globalAlpha;var Ab=[];for(var Ae=0;Ae<AN;Ae++){var AM=AS[Ae];Ab.push(AM.offset*AK+AU+" "+AM.color)}AG.push('<g_vml_:fill type="',AH.type_,'"',' method="none" focus="100%"',' color="',AR,'"',' color2="',AQ,'"',' colors="',Ab.join(","),'"',' opacity="',AV,'"',' g_o_:opacity2="',AW,'"',' angle="',AL,'"',' focusposition="',Ac.x,",",Ac.y,'" />')}else{if(AH instanceof u){if(Z&&m){var AF=-Ah.x;var AZ=-Ah.y;AG.push("<g_vml_:fill",' position="',AF/Z*AY*AY,",",AZ/m*AX*AX,'"',' type="tile"',' src="',AH.src_,'" />')}}else{var Ai=Y(AO.fillStyle);var AT=Ai.color;var Ad=Ai.alpha*AO.globalAlpha;AG.push('<g_vml_:fill color="',AT,'" opacity="',Ad,'" />')}}}M.fill=function(){this.stroke(true)};M.closePath=function(){this.currentPath_.push({type:"close"})};M.getCoords_=function(j,i){var Z=this.m_;return{x:D*(j*Z[0][0]+i*Z[1][0]+Z[2][0])-F,y:D*(j*Z[0][1]+i*Z[1][1]+Z[2][1])-F}};M.save=function(){var Z={};Q(this,Z);this.aStack_.push(Z);this.mStack_.push(this.m_);this.m_=d(V(),this.m_)};M.restore=function(){if(this.aStack_.length){Q(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function H(Z){return isFinite(Z[0][0])&&isFinite(Z[0][1])&&isFinite(Z[1][0])&&isFinite(Z[1][1])&&isFinite(Z[2][0])&&isFinite(Z[2][1])}function y(i,Z,j){if(!H(Z)){return }i.m_=Z;if(j){var p=Z[0][0]*Z[1][1]-Z[0][1]*Z[1][0];i.lineScale_=k(b(p))}}M.translate=function(j,i){var Z=[[1,0,0],[0,1,0],[j,i,1]];y(this,d(Z,this.m_),false)};M.rotate=function(i){var m=U(i);var j=J(i);var Z=[[m,j,0],[-j,m,0],[0,0,1]];y(this,d(Z,this.m_),false)};M.scale=function(j,i){this.arcScaleX_*=j;this.arcScaleY_*=i;var Z=[[j,0,0],[0,i,0],[0,0,1]];y(this,d(Z,this.m_),true)};M.transform=function(p,m,AF,AE,i,Z){var j=[[p,m,0],[AF,AE,0],[i,Z,1]];y(this,d(j,this.m_),true)};M.setTransform=function(AE,p,AG,AF,j,i){var Z=[[AE,p,0],[AG,AF,0],[j,i,1]];y(this,Z,true)};M.drawText_=function(AK,AI,AH,AN,AG){var AM=this.m_,AQ=1000,i=0,AP=AQ,AF={x:0,y:0},AE=[];var Z=P(X(this.font),this.element_);var j=AA(Z);var AR=this.element_.currentStyle;var p=this.textAlign.toLowerCase();switch(p){case"left":case"center":case"right":break;case"end":p=AR.direction=="ltr"?"right":"left";break;case"start":p=AR.direction=="rtl"?"right":"left";break;default:p="left"}switch(this.textBaseline){case"hanging":case"top":AF.y=Z.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":AF.y=-Z.size/2.25;break}switch(p){case"right":i=AQ;AP=0.05;break;case"center":i=AP=AQ/2;break}var AO=this.getCoords_(AI+AF.x,AH+AF.y);AE.push('<g_vml_:line from="',-i,' 0" to="',AP,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!AG,'" stroked="',!!AG,'" style="position:absolute;width:1px;height:1px;">');if(AG){R(this,AE)}else{a(this,AE,{x:-i,y:0},{x:AP,y:Z.size})}var AL=AM[0][0].toFixed(3)+","+AM[1][0].toFixed(3)+","+AM[0][1].toFixed(3)+","+AM[1][1].toFixed(3)+",0,0";var AJ=K(AO.x/D)+","+K(AO.y/D);AE.push('<g_vml_:skew on="t" matrix="',AL,'" ',' offset="',AJ,'" origin="',i,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',AD(AK),'" style="v-text-align:',p,";font:",AD(j),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",AE.join(""))};M.fillText=function(j,Z,m,i){this.drawText_(j,Z,m,i,false)};M.strokeText=function(j,Z,m,i){this.drawText_(j,Z,m,i,true)};M.measureText=function(j){if(!this.textMeasureEl_){var Z='<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",Z);this.textMeasureEl_=this.element_.lastChild}var i=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(i.createTextNode(j));return{width:this.textMeasureEl_.offsetWidth}};M.clip=function(){};M.arcTo=function(){};M.createPattern=function(i,Z){return new u(i,Z)};function v(Z){this.type_=Z;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}v.prototype.addColorStop=function(i,Z){Z=Y(Z);this.colors_.push({offset:i,color:Z.color,alpha:Z.alpha})};function u(i,Z){q(i);switch(Z){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=Z;break;default:n("SYNTAX_ERR")}this.src_=i.src;this.width_=i.width;this.height_=i.height}function n(Z){throw new o(Z)}function q(Z){if(!Z||Z.nodeType!=1||Z.tagName!="IMG"){n("TYPE_MISMATCH_ERR")}if(Z.readyState!="complete"){n("INVALID_STATE_ERR")}}function o(Z){this.code=this[Z];this.message=Z+": DOM Exception "+this.code}var x=o.prototype=new Error;x.INDEX_SIZE_ERR=1;x.DOMSTRING_SIZE_ERR=2;x.HIERARCHY_REQUEST_ERR=3;x.WRONG_DOCUMENT_ERR=4;x.INVALID_CHARACTER_ERR=5;x.NO_DATA_ALLOWED_ERR=6;x.NO_MODIFICATION_ALLOWED_ERR=7;x.NOT_FOUND_ERR=8;x.NOT_SUPPORTED_ERR=9;x.INUSE_ATTRIBUTE_ERR=10;x.INVALID_STATE_ERR=11;x.SYNTAX_ERR=12;x.INVALID_MODIFICATION_ERR=13;x.NAMESPACE_ERR=14;x.INVALID_ACCESS_ERR=15;x.VALIDATION_ERR=16;x.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=E;CanvasRenderingContext2D=W;CanvasGradient=v;CanvasPattern=u;DOMException=o})()};
\ No newline at end of file diff --git a/askbot/skins/common/media/js/flot-build.bat b/askbot/skins/common/media/js/flot-build.bat new file mode 100644 index 00000000..f9f32cb7 --- /dev/null +++ b/askbot/skins/common/media/js/flot-build.bat @@ -0,0 +1,3 @@ +java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 jquery.flot.js -o jquery.flot.pack.js + +pause diff --git a/askbot/skins/common/media/js/i18n.js b/askbot/skins/common/media/js/i18n.js new file mode 100644 index 00000000..192d335b --- /dev/null +++ b/askbot/skins/common/media/js/i18n.js @@ -0,0 +1,469 @@ +//var i18nLang; +var i18nZh = { + 'insufficient privilege':'用户æƒé™ä¸åœ¨æ“作范围', + 'cannot pick own answer as best':'ä¸èƒ½è®¾ç½®è‡ªå·±çš„回ç”为最佳ç”案', + 'anonymous users cannot select favorite questions':'匿å用户ä¸èƒ½æ”¶è—问题,请先', + 'please login':'注册或者登录', + 'daily vote cap exhausted':'对ä¸èµ·ï¼Œæ‚¨å·²ç”¨å®Œä»Šæ—¥æ‰€æœ‰çš„投票。', + 'please confirm offensive':"确定è¦å½’类该帖为广告ã€äººèº«æ”»å‡»ã€æ¶æ„言论å—?", + 'anonymous users cannot flag offensive posts':'匿å用户ä¸èƒ½æ“作,请先', + 'cannot flag message as offensive twice':'ä¸èƒ½é‡å¤æ“作。', + 'flag offensive cap exhausted':'对ä¸èµ·ï¼Œæ‚¨å·²ç”¨å®Œä»Šæ—¥æ‰€æœ‰çš„5次‘水帖’æ“作。', + 'confirm delete':"确定è¦åˆ 除/æ’¤é”€åˆ é™¤è¯¥å¸–å—?", + 'anonymous users cannot delete/undelete':"匿å用户ä¸èƒ½åˆ é™¤æˆ–æ’¤é”€åˆ é™¤å¸–å", + 'post recovered':"æ“作æˆåŠŸï¼è¯¥å¸–å已被æ¢å¤ã€‚", + 'post deleted':"æ“作æˆåŠŸï¼è¯¥å¸–åå·²åˆ é™¤ã€‚", + 'add comment':'æ·»åŠ è¯„è®º', + 'delete this comment':'åˆ é™¤æ¤è¯„论', + 'add a comment':"æ·»åŠ è¯„è®º", + 'comments':"评论", + 'confirm delete comment':"真è¦åˆ 除æ¤è¯„论å—?", + '{0} characters left': '还å¯å†™{0}å—符', + 'click to close':'点击消æ¯æ¡†å…³é—', + 'loading...':'读å–ä¸...', + 'tags cannot be empty':'æ ‡ç¾ä¸èƒ½ä¸ºç©ºã€‚', + 'content cannot be empty':'内容ä¸èƒ½ä¸ºç©ºã€‚', + 'content minchars': '请输入至少 {0} å—符。', + 'please enter title':'è¯·è¾“å…¥æ ‡é¢˜ã€‚', + 'title minchars':"请输入至少 {0} å—符。", + 'delete':'åˆ é™¤', + 'undelete':'å–消', + 'bold':'粗体', + 'italic':'斜体', + 'link':'超链接', + 'quote':'引用', + 'preformatted text':'代ç ', + 'image':'图片', + 'numbered list':'æ•°å—ç¼–å·åˆ—表', + 'bulleted list':'项目符å·åˆ—表', + 'heading':'æ ‡é¢˜', + 'horizontal bar':'水平线', + 'undo':'撤销', + 'redo':'é‡åš', + 'enter image url':'<b>输入图片地å€</b></p><p>示例:<br />http://www.example.com/image.jpg \"我的截图\"', + 'enter url':'<b>输入Web地å€</b></p><p>示例:<br />http://www.cnprog.com/ \"我的网站\"</p>"', + 'upload image':'æˆ–è€…ä¸Šä¼ æœ¬åœ°å›¾ç‰‡ï¼š' +}; + +var i18nZhtw = { + 'insufficient privilege':'權é™ä¸è¶³', + 'cannot pick own answer as best':'ä¸èƒ½è”½æŽƒè‡ªç', + 'anonymous users cannot select favorite questions':'匿å用戶ä¸èƒ½æ”¶è—å•é¡Œ', + 'please login':'請先登錄', + 'daily vote cap exhausted':'å°ä¸èµ·ï¼Œæ‚¨å·²ç”¨å®Œä»Šæ—¥æ‰€æœ‰çš„投票。', + 'please confirm offensive':"確定è¦æ¸é¡žè©²å¸–為廣告ã€äººèº«æ”»æ“Šã€æƒ¡æ„言論嗎?", + 'anonymous users cannot flag offensive posts':'匿å用戶ä¸èƒ½æ“作', + 'cannot flag message as offensive twice':'ä¸èƒ½é‡è¤‡æ“作。', + 'flag offensive cap exhausted':'å°ä¸èµ·ï¼Œæ‚¨å·²ç”¨å®Œä»Šæ—¥æ‰€æœ‰çš„5次『水帖ã€æ“作。', + 'confirm delete':"確定刪除", + 'anonymous users cannot delete/undelete':"匿å用戶ä¸èƒ½åˆªé™¤æˆ–æ¢å¾©å¸–å", + 'post recovered':"æ“作æˆåŠŸï¼è©²å¸–å已被æ¢è¤‡ã€‚", + 'post deleted':"æ“作æˆåŠŸï¼è©²å¸–å已刪除。", + 'add comment':'æ·»åŠ è©•è«–', + 'delete this comment':'刪除æ¤è©•è«–', + 'add a comment':"æ·»åŠ è©•è«–", + 'comments':"è©•è«–", + 'confirm delete comment':"刪除評論確èª", + '{0} characters left': 'é‚„å¯å¯«{0}å—', + 'click to close':'點擊消æ¯æ¡†é—œé–‰', + 'loading...':'讀å–ä¸...', + 'tags cannot be empty':'標籤ä¸èƒ½ç‚ºç©ºç™½', + 'content cannot be empty':'內容ä¸èƒ½ç‚ºç©ºç™½', + 'content minchars': '請輸入至少 {0} å—符。', + 'please enter title':'請輸入標題。', + 'title minchars':"請輸入至少 {0} å—符。", + 'delete':'刪除', + 'undelete':'å–消', + 'bold':'ç²—é«”', + 'italic':'斜體', + 'link':'超連接', + 'quote':'引用', + 'preformatted text':'代碼', + 'image':'圖片', + 'numbered list':'數å—編號列表', + 'bulleted list':'é …ç›®ç¬¦è™Ÿåˆ—è¡¨', + 'heading':'標題', + 'horizontal bar':'水平線', + 'undo':'撤銷', + 'redo':'é‡åš', + 'enter image url':'<b>輸入圖片地å€</b></p><p>示例:<br />http://www.example.com/image.jpg \"我的截圖\"', + 'enter url':'<b>輸入Web地å€</b></p><p>示例:<br />http://www.cnprog.com/ \"我的網站\"</p>"', + 'upload image':'或者上傳本地圖片:' +}; + + +var i18nEn = { + "anonymous users cannot vote": "sorry, anonymous users cannot vote ", + 'tags cannot be empty':'please enter at least one tag', + 'anonymous users cannot select favorite questions':'sorry, anonymous users cannot select favorite questions ', + 'upload image':'Upload image:', + 'enter image url':'enter URL of the image, e.g. http://www.example.com/image.jpg or upload an image file', + 'enter url':'enter Web address, e.g. http://www.example.com \"page title\"', + 'upload file attachment':'Please choose and upload a file:', + 'daily vote cap exhausted':'sorry, you\'ve used up todays vote cap', + 'cannot pick own answer as best':'sorry, you cannot accept your own answer', + 'please confirm offensive':'are you sure this post is offensive, contains spam, advertising, malicious remarks, etc.?', + 'flag offensive cap exhausted':'sorry, you\'ve used up todays cap of flagging offensive messages ', + 'confirm delete':'are you sure you want to delete this?', + 'anonymous users cannot delete/undelete':'sorry, anonymous users cannot delete or undelete posts', + 'post recovered':'your post is now restored!', + 'post deleted':'your post has been deleted', + 'confirm delete comment':'do you really want to delete this comment?', + 'content minchars': 'please enter more than {0} characters', + 'title minchars':"please enter at least {0} characters", + 'characters':'characters left', + 'cannot flag message as offensive twice':'cannot flag message as offensive twice ', + 'edit':'edit', + 'click to edit this comment':'click to edit this comment', + 'confirm abandon comment':'Are you sure you do not want to post this comment?', + 'save comment': 'save comment', + 'enter more characters': 'please enter at least {0} more characters', + 'Follow': 'Follow', + '<b>Following</b><b class="unfollow">Unfollow</b>': '<b>Following</b><b class="unfollow">Unfollow</b>', +}; + +var i18nFi = { + "anonymous users cannot vote": "kirjaudu sisään, jotta voit käyttää tätä ominaisuutta ", + 'tags cannot be empty':'anna vähintään yksi tagi', + 'anonymous users cannot select favorite questions':'kirjaudu sisään, jotta voit käyttää tätä ominaisuutta', + 'upload image':'Lähetä kuva:', + 'enter image url':'Anna kuvan URL-osoite, esim. http://www.example.com/image.jpg \"kuvan otsikko\"', + 'enter url':'Anna URL-osoite, esim. http://www.example.com \"sivun otsikko\"', + 'daily vote cap exhausted':'olet käyttänyt tämän päivän osalta äänesi', + 'cannot pick own answer as best':'et voi hyväksyä omaa vastaustasi parhaaksi', + 'please confirm offensive':'oletko varma, että tämä on roskaposti, loukkaava tai muuta hyväksymätöntä?', + 'flag offensive cap exhausted':'olet käyttänyt tämän päivän merkkausmäärät ', + 'confirm delete':'oletko varma, että haluat poistaa tämän?', + 'anonymous users cannot delete/undelete':'kirjaudu sisään, jotta voit käyttää tätä ominaisuutta', + 'post recovered':'postauksesi on palautettu!', + 'post deleted':'postauksesi on poistettu', + 'confirm delete comment':'oletko varma, että haluat poistaa tämän kommentin?', + 'content minchars': 'syötä vähintään {0} merkkiä', + 'title minchars':"syötä vähintään {0} merkkiä", + '{0} characters left': '{0} merkkiä jäljellä', + 'cannot flag message as offensive twice':'ei voi merkata kahta kertaa ' +}; + +var i18nTr = { + "anonymous users cannot vote":"üye giriÅŸi yapmadan oy kullanamazsınız", + 'insufficient privilege':'buna yetkiniz yoktur', + 'cannot pick own answer as best':'en cevap olarak kendi cevabınızı seçemezsiniz', + 'anonymous users cannot select favorite questions':'üye giriÅŸi yapmadan favori seçemezsiniz', + 'please login':'lütfen üye giriÅŸi yapınız', + 'daily vote cap exhausted':'bugünlük oy verme kotanız doldu', + 'please confirm offensive':"ÅŸikayetinizi onaylayın", + 'anonymous users cannot flag offensive posts':'üye giriÅŸi yapmadan ÅŸikayet gönderemezsiniz', + 'cannot flag message as offensive twice':'ÅŸikayet mesajı olarak iki kez iÅŸaretlemelisiniz', + 'flag offensive cap exhausted':'ÅŸikayet kotası aşıldı', + 'confirm delete':"Bunu silmek istediÄŸinizden emin misiniz?", + 'anonymous users cannot delete/undelete':"üye giriÅŸi yapmadan yazı silemez yada geri alamazsınız", + 'post recovered':"yazı geri alındı", + 'post deleted':"yazı silindi", + 'add comment':'yorum ekle', + 'delete this comment':'bu yorumu sil', + 'add a comment':"yorum ekle", + 'comments':"yorumlar", + 'confirm delete comment':"yorumu silmek istediÄŸinizden emin misiniz?", + '{0} characters left': 'yazılabilir {0} karakter eksik', + 'click to close':'kapatmak için tıklayın', + 'loading...':'yükleniyor...', + 'tags cannot be empty':'etiketler boÅŸ olamaz', + 'content cannot be empty':'içerik boÅŸ olamaz', + 'content minchars': 'Lütfen en az (0) karakter girin', + 'please enter title':'lütfen bir baÅŸlık yazın', + 'title minchars':"Lütfen en az (0) karakter girin", + 'delete':'sil', + 'undelete':'geri al', + 'bold': 'kalın', + 'italic':'italik', + 'link':'link', + 'quote':'alıntı', + 'preformatted text':'hazır metin', + 'image':'resimler', + 'numbered list':'numaralı liste', + 'bulleted list':'iÅŸaretli liste', + 'heading':'BaÅŸlık', + 'horizontal bar':'yatay bar', + 'undo':'geri', + 'redo':'yeniden', + 'enter image url':'örnek resmin URLsini girin: <br />http://www.example.com/image.jpg \"resim baÅŸlığı\"', + 'enter url':'web adresini girin: <br />http://www.cnprog.com/ \"baÅŸlık baÄŸlantısı\"</p>"', + 'upload image':'resim yükle:' +}; + +var i18nEs = { + "anonymous users cannot vote":"usuarios anónimos no pueden votar", + 'insufficient privilege':'privilegio insuficiente', + 'cannot pick own answer as best':'no puede escoger su propia respuesta como la mejor', + 'anonymous users cannot select favorite questions':'usuarios anonimos no pueden seleccionar', + 'please login':'por favor inicie sesión', + 'daily vote cap exhausted':'cuota de votos diarios excedida', + 'please confirm offensive':"por favor confirme ofensiva", + 'anonymous users cannot flag offensive posts':'usuarios anónimos no pueden marcar publicaciones como ofensivas', + 'cannot flag message as offensive twice':'no puede marcar mensaje como ofensivo dos veces', + 'flag offensive cap exhausted':'cuota para marcar ofensivas ha sido excedida', + 'confirm delete':"¿Está seguro que desea borrar esto?", + 'anonymous users cannot delete/undelete':"usuarios anónimos no pueden borrar o recuperar publicaciones", + 'post recovered':"publicación recuperada", + 'post deleted':"publicación borrada。", + 'add comment':'agregar comentario', + 'delete this comment':'borrar este comentario', + 'add a comment':"agregar comentarios", + 'comments':"comentarios", + 'confirm delete comment':"¿Realmente desea borrar este comentario?", + '{0} characters left': '{0} caracteres faltantes', + 'click to close':'haga click para cerrar', + 'loading...':'cargando...', + 'tags cannot be empty':'las etiquetas no pueden estar vacÃas', + 'content cannot be empty':'el contenido no puede estar vacÃo', + 'content minchars': 'por favor introduzca mas de {0} caracteres', + 'please enter title':'por favor ingrese un tÃtulo', + 'title minchars':"por favor introduzca al menos {0} caracteres", + 'delete':'borrar', + 'undelete': 'recuperar', + 'bold': 'negrita', + 'italic':'cursiva', + 'link':'enlace', + 'quote':'citar', + 'preformatted text':'texto preformateado', + 'image':'imagen', + 'numbered list':'lista numerada', + 'bulleted list':'lista no numerada', + 'heading':'æ ‡é¢˜', + 'horizontal bar':'barra horizontal', + 'undo':'deshacer', + 'redo':'rehacer', + 'enter image url':'introduzca la URL de la imagen, por ejemplo:<br />http://www.example.com/image.jpg \"titulo de imagen\"', + 'enter url':'introduzca direcciones web, ejemplo:<br />http://www.cnprog.com/ \"titulo del enlace\"</p>"', + 'upload image':'cargar imagen:' +}; + +var i18nDe = { + "anonymous users cannot vote":"Gastbenutzer können nicht abstimmen ", + 'add a comment': 'Kommentar hinzufügen', + 'add comment': 'OK', + 'anonymous users cannot delete/undelete': 'Gastbenutzer können Beiträge nicht löschen oder wiederherstellen', + 'anonymous users cannot flag offensive posts': 'Gastbenutzer können Beiträge nicht melden', + 'anonymous users cannot select favorite questions': 'Gastbenutzer können keine Fragen als Favoriten markieren', + 'bold': 'Fett', + 'bulleted list': 'Liste', + '{0} characters left': '{0} characters left', + 'cannot flag message as offensive twice': 'Beiträge können nicht doppelt gemeldet werden', + 'cannot pick own answer as best': 'Eigene Antworten können nicht als die korrekte akzeptiert werden', + 'click to close': 'Schließen mit Klick', + 'comments': 'Kommentare', + 'confirm delete': 'Löschen bestätigen', + 'confirm delete comment': 'Löschen des Kommentars bestätigen', + 'content cannot be empty': 'Inhalt darf nicht leer sein', + 'content minchars': 'Bitte mindestens {0} Zeichen eingeben', + 'daily vote cap exhausted': 'Tägliches Abstimmungslimit erreicht', + 'delete': 'löschen', + 'delete this comment': 'Diesen Kommentar löschen', + 'enter image url': 'Bild-URL eingeben, zum Beispiel <br />http://www.ihredomain.de/bildname.jpg', + 'enter url': 'URL eingeben, zum Beispiel <br />http://www.askbot.org/ </p>', + 'flag offensive cap exhausted': 'Tägliches Limit zum Melden von Beiträgen erreicht', + 'heading': 'Titel', + 'horizontal bar': 'horizontaler Balken', + 'image': 'Bild', + 'insufficient privilege': 'nicht genügend Rechte', + 'italic': 'Kursiv', + 'link': 'Link', + 'loading...': 'Lade...', + 'numbered list': 'Nummerierte Liste', + 'please confirm offensive': 'Bitte beleidigenden/regelwidrigen Beitrag bestätigen', + 'please enter title': 'Bitte Titel eingeben', + 'please login': 'Bitte einloggen', + 'post deleted': 'Beitrag gelöscht', + 'post recovered': 'Beitrag wiederhergestellt', + 'preformatted text': 'Vorformatierter Text', + 'quote': 'Zitat', + 'redo': 'Wiederholen', + 'tags cannot be empty': 'Tags dürfen nicht leer sein', + 'title minchars': 'Bitte mindestens {0} Zeichen eingeben', + 'undelete': 'wiederherstellen', + 'undo': 'Rückgängig', + 'upload image': 'Bild hochladen' +}; + + +var i18nRu = { + "anonymous users cannot vote": "Извините, но Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы голоÑовать, ", + 'add a comment': 'добавить комментарий', + 'add comment': 'добавить комментарий', + 'save comment': 'Ñохранить комментарий', + 'anonymous users cannot delete/undelete': 'неавторизированные пользователи не могут воÑÑтанавливать и удалÑÑ‚ÑŒ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ', + 'anonymous users cannot flag offensive posts': 'Извините, но Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы пожаловатьÑÑ Ð½Ð° Ñообщение, ', + 'anonymous users cannot select favorite questions': 'Извините, но Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы добавть Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð² закладки, ', + 'Are you sure you want to remove your {provider} login?': 'Ð’Ñ‹ дейÑтвительно хотите удалить логин через {provider}?', + 'bold': 'жирный', + 'bulleted list': 'маркированный ÑпиÑок', + 'cancel': 'cancel', + '{0} characters left': 'оÑталоÑÑŒ меÑто Ð´Ð»Ñ {0} Ñимволов', + 'cannot flag message as offensive twice': 'Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð¼ÐµÑ‚Ð¸Ñ‚ÑŒ Ñообщение как Ñпам два раза', + 'cannot pick own answer as best': 'Извините, выбрать ÑобÑтвенный ответ в качеÑтве лучшего не разрешаетÑÑ', + 'Change password': 'Изменить пароль', + 'Change your {provider} password': 'Измените Ваш пароль Ð´Ð»Ñ {provider}', + 'click to close': 'нажмите, что бы закрыть', + 'Create a password for {provider}': 'Создать пароль Ð´Ð»Ñ {provider}', + 'Create password': 'Создать пароль', + 'Create a password-protected account': 'Создать аккаунт, защищенный паролем', + 'comments': 'комментарии', + 'confirm abandon comment': '', + 'Connect your {provider_name} account to {site}': 'Соедините {site} Ñ Ð’Ð°ÑˆÐ¸Ð¼ аккаунтом от {provider_name}', + 'confirm delete': 'Удалить?', + 'confirm delete comment': 'Удалить комментарий?', + 'content cannot be empty': 'пожалуйÑта, добавьте Ñодержание', + 'content minchars': 'Ñодержание должно быть более {0} Ñимволов', + 'daily vote cap exhausted': 'иÑчерпан доÑтупный на ÑÐµÐ³Ð¾Ð´Ð½Ñ Ð»Ð¸Ð¼Ð¸Ñ‚ голоÑований', + 'delete': 'удалить', + 'save tags': 'запомнить теги', + 'delete this comment': 'удалить Ñтот комментарий', + 'Delete this notification?': 'Удалить Ñто извещение?', + 'Delete these notifications?': 'Удалить Ñти извещениÑ?', + 'enter image url': 'введите url изображениÑ, например:<br /> http://www.domain.ru/kartinka.gif', + 'enter url': 'введите url, например:<br />http://www.domain.ru/ </p>', + 'flag offensive cap exhausted': 'иÑчерпан доÑтупный на ÑÐµÐ³Ð¾Ð´Ð½Ñ Ð»Ð¸Ð¼Ð¸Ñ‚ Ñообщений о Ñпаме', + 'file name': 'название файла', + 'heading': 'заголовок', + 'horizontal bar': 'Ð³Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ð»Ð¾Ñа', + 'image': 'изображение', + 'image description': 'опиÑание изображениÑ', + 'insufficient privilege': 'недоÑтаточно прав', + 'italic': 'курÑив', + 'link': 'ÑÑылка', + 'link text': 'текÑÑ‚ ÑÑылки', + 'loading...': 'загрузка...', + 'passwords do not match': 'пароли не Ñовпадают', + 'numbered list': 'пронумерованный ÑпиÑок', + 'Please add one or more login methods.': 'ПожалуйÑта, добавьте Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один поÑтоÑнный метод Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸.', + 'please confirm offensive': 'Ð’Ñ‹ уверены что Ñто Ñообщение неумеÑтно?', + 'please enter title': 'пожалуйÑта, введите заголовок', + 'Please enter your {token_name}, then proceed': 'Чтобы продолжить, пожалуйÑта введите {token_name}', + 'Please select at least one item': 'ПожалуйÑта, отметьте Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одно извещение', + 'enter more characters': 'недоÑтаточно Ñимволов, пожалуйÑта, добавьте ещё {0}', + 'please login': 'введите логин', + 'post deleted': 'Ñообщение удалено', + 'post recovered': 'воÑÑтановить Ñообщение', + 'preformatted text': 'форматирование текÑта', + 'quote': 'цитата', + 'redo': 'повторить', + 'see questions tagged \'{tag}\'': 'Ñмотрите вопроÑÑ‹, помеченные \'{tag}\'', + 'Show/change current login methods': 'ПроÑмотреть, изменить ÑущеÑтвующие методы авторизации.', + 'tags cannot be empty': 'введите теги', + 'title minchars': 'заголовок должен быть более {0} Ñимволов', + 'undelete': 'воÑÑтановить', + 'click to edit this comment': 'нажмите здеÑÑŒ, чтобы отредактировать Ñтот комментарий', + 'edit': 'редактировать', + 'undo': 'отменить', + 'upload image': 'загрузить изображение', + 'upload file attachment': 'загрузить файл', + 'You don\'t have a method to log in right now, please add one or more by clicking any of the icons below.': 'У Ð’Ð°Ñ ÑÐµÐ¹Ñ‡Ð°Ñ Ð½ÐµÑ‚ поÑтоÑнного метода авторизации, пожалуйÑта выберите Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один, нажав на любую из предложеных ниже кнопок.' +}; + +var i18nFr = { + "anonymous users cannot vote":"les utilisateurs anonyment ne peuvent pas voter ", + 'add a comment': 'Ajouter un commentaire', + 'add comment': 'OK', + 'anonymous users cannot delete/undelete': 'Les utilisateurs anonymes ne peuvent pas supprimer/restaurer', + 'anonymous users cannot flag offensive posts': 'Les utilisateurs anonymes ne peuvent pas signaler les messages à contenu abusif', + 'anonymous users cannot select favorite questions': 'Les utilisateurs anonymes ne peuvent pas sélectionner leurs questions favorites', + 'bold': 'gras', + 'bulleted list': 'liste', + '{0} characters left': '{0} characters left', + 'cannot flag message as offensive twice': 'Vous ne pouvez pas signaler deux fois un message à contenu abusif', + 'cannot pick own answer as best': 'Vous ne pouvez pas désigner une de vos propres réponses comme étant la meilleure réponse', + 'click to close': 'cliquez pour fermer', + 'comments': 'commentaires', + 'confirm delete': 'Confirmer la suppression', + 'confirm delete comment': 'Confirmer la suppression du commentaire', + 'content cannot be empty': 'Le contenu ne doit pas être vide', + 'content minchars': 'Veuillez saisir au moins {0} caractères', + 'daily vote cap exhausted': 'Votre quota journalier de votes est atteint', + 'delete': 'supprimer', + 'delete this comment': 'supprimer ce commentaire', + 'enter image url': 'Veuillez saisir une URL menant à une image, par exemple <br />http://www.votre-domaine.com/nom-image.jpg', + 'enter url': 'Entrez une URL, par exemple <br />http://www.askbot.org/ </p>', + 'flag offensive cap exhausted': 'Votre quota journalier de signalements de contenus abusifs a été atteint', + 'heading': 'Titre', + 'horizontal bar': 'Barre horizontale', + 'image': 'Image', + 'insufficient privilege': 'Privilèges insuffisants', + 'italic': 'italique', + 'link': 'lien', + 'loading...': 'Chargement en cours...', + 'numbered list': 'liste numérotée', + 'please confirm offensive': 'Veuillez confirmer que le contenu est abusif', + 'please enter title': 'Veuillez saisir un titre', + 'please login': 'Veuillez vous authentifier', + 'post deleted': 'Message supprimé', + 'post recovered': 'Message restauré', + 'preformatted text': 'Texte préformaté', + 'quote': 'Citer', + 'redo': 'Rétablir', + 'tags cannot be empty': 'Les mots-clés ne doivent pas être vides', + 'title minchars': 'Veuillez saisir au moins {0} caractères', + 'undelete': 'Restaurer', + 'undo': 'Annuler', + 'upload image': 'Charger une image' +}; + +var i18nIt = { + "anonymous users cannot vote":"Gli utenti anonimi non possono votare ", + 'add a comment': 'Aggiungi un commento', + 'add comment': 'OK', + 'anonymous users cannot delete/undelete': 'Gli utenti anonimi non possono cancellare/annullare la cancellazione', + 'anonymous users cannot flag offensive posts': 'Gli utenti anonimi non possono flaggare come offensivo questo post', + 'anonymous users cannot select favorite questions': 'Gli utenti anonimi non possono aggiungere domande ai preferiti', + 'bold': 'grassetto', + 'bulleted list': 'Lista', + 'cannot flag message as offensive twice': 'non è possibile flaggare come offensivo più di una volta ', + 'cannot pick own answer as best': 'non è possibile assegnare come miglior risposta ad una propria domanda una propria risposta', + '{0} characters left': '{0} caratteri rimanenti', + 'click to close': 'clicca per chiudere', + 'comments': 'commenti', + 'confirm delete': 'conferma la cancellazione', + 'confirm delete comment': 'Vuoi davvero cancellare il commento?', + 'content cannot be empty': 'il contenuto non può essere vuoto', + 'content minchars': 'per favore inserisci più di {0} caratteri', + 'daily vote cap exhausted': 'Spiacente, hai raggiunto il limite odierno massimo di voti', + 'delete': 'elimina', + 'delete this comment': 'Elimina questo commento', + 'enter image url': 'inserisci l\'URL dell\'immagine, es. http://www.example.com/immagine.jpg \"titolo immagine\"', + 'enter url': 'inserisci l\'indirizzo web, e.g. <br />http://www.askbot.org/ </p>', + 'flag offensive cap exhausted': 'spiacente, hai raggiunto il limite odierno massimo di flag offensivi ', + 'heading': 'Titolo', + 'horizontal bar': 'barra orizzontale', + 'image': 'Immagine', + 'insufficient privilege': 'privilegi non sufficienti', + 'italic': 'corsivo', + 'link': 'Link', + 'loading...': 'Caricamento...', + 'numbered list': 'Lista numerata', + 'please confirm offensive': 'sei certo che questo post sia offensivo, contenga spam, pubblicità , osservazioni poco idonee, ecc.?', + 'please enter title': 'Per favore inserisci il titolo', + 'please login': 'Per favore effettua il login', + 'post deleted': 'Post eliminato', + 'post recovered': 'Post recuperato', + 'preformatted text': 'Testo preformattato', + 'quote': 'cita', + 'redo': 'Esegui nuovamente', + 'tags cannot be empty': 'Il campo Tags non può essere vuoto', + 'title minchars': 'per favore inserisci almeno {0} caratteri', + 'undelete': 'elimina', + 'undo': 'annulla', + 'upload image': 'carica immagine' +}; + +var i18n = { + 'en':i18nEn, + 'zh-cn':i18nZh, + 'es':i18nEs, + 'tr':i18nTr, + 'de':i18nDe, + 'ru':i18nRu, + 'fr':i18nFr, + 'it':i18nIt, + 'zh-tw':i18nZhtw +}; + +var i18n_dict = i18n[i18nLang]; diff --git a/askbot/skins/common/media/js/jquery-1.4.3.js b/askbot/skins/common/media/js/jquery-1.4.3.js new file mode 100644 index 00000000..ad9a79c4 --- /dev/null +++ b/askbot/skins/common/media/js/jquery-1.4.3.js @@ -0,0 +1,6883 @@ +/*! + * jQuery JavaScript Library v1.4.3 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Oct 14 23:10:06 2010 -0400 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, + + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + rwhite = /\s/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for non-word characters + rnonword = /\W/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $("TAG") + } else if ( !context && !rnonword.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.4.3", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || jQuery(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy, copyIsArray; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + // A third-party is pushing the ready event forwards + if ( wait === true ) { + jQuery.readyWait--; + } + + // Make sure that the DOM is not already loaded + if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, i = 0; + while ( (fn = readyList[ i++ ]) ) { + fn.call( document, jQuery ); + } + + // Reset the list of functions + readyList = null; + } + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test(data.replace(rvalidescape, "@") + .replace(rvalidtokens, "]") + .replace(rvalidbraces, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type(array); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can be optionally by executed if its a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// Verify that \s matches non-breaking spaces +// (IE fails on this test) +if ( !rwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +// Expose jQuery to the global object +return (window.jQuery = window.$ = jQuery); + +})(); + + +(function() { + + jQuery.support = {}; + + var root = document.documentElement, + script = document.createElement("script"), + div = document.createElement("div"), + id = "script" + jQuery.now(); + + div.style.display = "none"; + div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0], + select = document.createElement("select"), + opt = select.appendChild( document.createElement("option") ); + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: div.getElementsByTagName("input")[0].value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Will be defined later + optDisabled: false, + checkClone: false, + scriptEval: false, + noCloneEvent: true, + boxModel: null, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableHiddenOffsets: true + }; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as diabled) + select.disabled = true; + jQuery.support.optDisabled = !opt.disabled; + + script.type = "text/javascript"; + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + jQuery.support.scriptEval = true; + delete window[ id ]; + } + + root.removeChild( script ); + + if ( div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>"; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"); + div.style.width = div.style.paddingLeft = "1px"; + + document.body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "<div style='width:4px;'></div>"; + jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; + } + + div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>"; + var tds = div.getElementsByTagName("td"); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; + + tds[0].style.display = ""; + tds[1].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; + div.innerHTML = ""; + + document.body.removeChild( div ).style.display = "none"; + div = tds = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + root = script = div = all = a = null; +})(); + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; + + + + +var windowData = {}, + rbrace = /^(?:\{.*\}|\[.*\])$/; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + expando: "jQuery" + jQuery.now(), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + data: function( elem, name, data ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var isNode = elem.nodeType, + id = isNode ? elem[ jQuery.expando ] : null, + cache = jQuery.cache, thisCache; + + if ( isNode && !id && typeof name === "string" && data === undefined ) { + return; + } + + // Get the data from the object directly + if ( !isNode ) { + cache = elem; + + // Compute a unique ID for the element + } else if ( !id ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } + + // Avoid generating a new cache unless none exists and we + // want to manipulate it. + if ( typeof name === "object" ) { + if ( isNode ) { + cache[ id ] = jQuery.extend(cache[ id ], name); + + } else { + jQuery.extend( cache, name ); + } + + } else if ( isNode && !cache[ id ] ) { + cache[ id ] = {}; + } + + thisCache = isNode ? cache[ id ] : cache; + + // Prevent overriding the named cache with undefined values + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + return typeof name === "string" ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var isNode = elem.nodeType, + id = isNode ? elem[ jQuery.expando ] : elem, + cache = jQuery.cache, + thisCache = isNode ? cache[ id ] : id; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( thisCache ) { + // Remove the section of cache data + delete thisCache[ name ]; + + // If we've removed all the data, remove the element's cache + if ( isNode && jQuery.isEmptyObject(thisCache) ) { + jQuery.removeData( elem ); + } + } + + // Otherwise, we want to remove all of the element's data + } else { + if ( isNode && jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + + // Completely remove the data cache + } else if ( isNode ) { + delete cache[ id ]; + + // Remove all fields from the object + } else { + for ( var n in elem ) { + delete elem[ n ]; + } + } + } + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + if ( typeof key === "undefined" ) { + return this.length ? jQuery.data( this[0] ) : null; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && this[0].nodeType === 1 ) { + data = this[0].getAttribute( "data-" + key ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + } else { + data = undefined; + } + } + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + + + + +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); + + + + +var rclass = /[\n\t]/g, + rspaces = /\s+/, + rreturn = /\r/g, + rspecialurl = /^(?:href|src|style)$/, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rradiocheck = /^(?:radio|checkbox)$/i; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", setClass = elem.className; + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, i = 0, self = jQuery(this), + state = stateVal, + classNames = value.split( rspaces ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery.data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( !arguments.length ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray(val) ) { + val = jQuery.map(val, function (value) { + return value == null ? "" : value + ""; + }); + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't set attributes on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + // 'in' checks fail in Blackberry 4.7 #6931 + if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + if ( value === null ) { + if ( elem.nodeType === 1 ) { + elem.removeAttribute( name ); + } + + } else { + elem[ name ] = value; + } + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + // Ensure that missing attributes return undefined + // Blackberry 4.7 returns "" from getAttribute #6938 + if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { + return undefined; + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + } +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspace = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }, + focusCounts = { focusin: 0, focusout: 0 }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery.data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + // Use a key less likely to result in collisions for plain JS objects. + // Fixes bug #7150. + var eventKey = elem.nodeType ? "events" : "__events__", + events = elemData[ eventKey ], + eventHandle = elemData.handle; + + if ( typeof events === "function" ) { + // On plain objects events is a fn that holds the the data + // which prevents this data from being JSON serialized + // the function does not need to be called, it just contains the data + eventHandle = events.handle; + events = events.events; + + } else if ( !events ) { + if ( !elem.nodeType ) { + // On plain objects, create a fn that acts as the holder + // of the values to avoid JSON serialization of event data + elemData[ eventKey ] = elemData = function(){}; + } + + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + eventKey = elem.nodeType ? "events" : "__events__", + elemData = jQuery.data( elem ), + events = elemData && elemData[ eventKey ]; + + if ( !elemData || !events ) { + return; + } + + if ( typeof events === "function" ) { + elemData = events; + events = events.events; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( typeof elemData === "function" ) { + jQuery.removeData( elem, eventKey ); + + } else if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + jQuery.each( jQuery.cache, function() { + if ( this.events && this.events[type] ) { + jQuery.event.trigger( event, data, this.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = elem.nodeType ? + jQuery.data( elem, "handle" ) : + (jQuery.data( elem, "__events__" ) || {}).handle; + + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + event.preventDefault(); + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (inlineError) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var target = event.target, old, targetType = type.replace(rnamespaces, ""), + isClick = jQuery.nodeName(target, "a") && targetType === "click", + special = jQuery.event.special[ targetType ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ targetType ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + targetType ]; + + if ( old ) { + target[ "on" + targetType ] = null; + } + + jQuery.event.triggered = true; + target[ targetType ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (triggerError) {} + + if ( old ) { + target[ "on" + targetType ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace_sort = [], namespace_re, events, args = jQuery.makeArray( arguments ); + + event = args[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace_sort = namespaces.slice(0).sort(); + namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.namespace = event.namespace || namespace_sort.join("."); + + events = jQuery.data(this, this.nodeType ? "events" : "__events__"); + + if ( typeof events === "function" ) { + events = events.events; + } + + handlers = (events || {})[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, body = document.body; + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + e.liveFired = undefined; + return trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + e.liveFired = undefined; + return trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery.data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery.data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + return jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + return testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + return testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery.data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + args[0].type = type; + return jQuery.event.handle.apply( elem, args ); +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + if ( focusCounts[fix]++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --focusCounts[fix] === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.trigger( e, null, e.target ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) || data === false ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, elems = [], selectors = [], + related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + events = jQuery.data( this, this.nodeType ? "events" : "__events__" ); + + if ( typeof events === "function" ) { + events = events.events; + } + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) + if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + +// Prevent memory leaks in IE +// Window isn't included so as not to unbind existing unload events +// More info: +// - http://isaacschlueter.com/2006/10/msie-memory-leaks/ +if ( window.attachEvent && !window.addEventListener ) { + jQuery(window).bind("unload", function() { + for ( var id in jQuery.cache ) { + if ( jQuery.cache[ id ].handle ) { + // Try/Catch is to handle iframes being unloaded, see #4280 + try { + jQuery.event.remove( jQuery.cache[ id ].handle.elem ); + } catch(e) {} + } + } + }); +} + + +/*! + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function(){ + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function(selector, context, results, seed) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, extra, prune = true, contextXML = Sizzle.isXML(context), + soFar = selector, ret, cur, pop, i; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec(""); + m = chunker.exec(soFar); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function(results){ + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[i-1] ) { + results.splice(i--, 1); + } + } + } + } + + return results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.matchesSelector = function(node, expr){ + return Sizzle(expr, null, null, [node]).length > 0; +}; + +Sizzle.find = function(expr, context, isXML){ + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && Sizzle.isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var filter = Expr.filter[ type ], found, item, left = match[1]; + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.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(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part){ + var isPartStr = typeof part === "string", + elem, i = 0, l = checkSet.length; + + if ( isPartStr && !/\W/.test(part) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck, nodeCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck, nodeCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + NAME: function(match, context){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + return match[1].toLowerCase(); + }, + CHILD: function(match){ + if ( match[1] === "nth" ) { + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + PSEUDO: function(match, curLoop, inplace, result, not){ + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return (/h\d/i).test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input: function(elem){ + return (/input|select|textarea|button/i).test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 === i; + }, + eq: function(elem, i, match){ + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function(elem, match, i, array){ + var name = match[1], filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + } else { + Sizzle.error( "Syntax error, unrecognized expression: " + name ); + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + if ( type === "first" ) { + return true; + } + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first === 0 ) { + return diff === 0; + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch(e){ + makeArray = function(array, results) { + var ret = results || [], i = 0; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; +} else { + sortOrder = function( a, b ) { + var ap = [], bp = [], aup = a.parentNode, bup = b.parentNode, + cur = aup, al, bl; + + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // If the nodes are siblings (or identical) we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(); + form.innerHTML = "<a name='" + id + "'/>"; + + // Inject it into the root element, check its status, and remove it quickly + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function(match, context){ + var results = context.getElementsByTagName(match[1]); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = "<a href='#'></a>"; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "<p class='TEST'></p>"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + if ( context.nodeType === 9 ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var old = context.id, id = context.id = "__sizzle__"; + + try { + return makeArray( context.querySelectorAll( "#" + id + " " + query ), extra ); + + } catch(pseudoError) { + } finally { + if ( old ) { + context.id = old; + + } else { + context.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, ":sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + if ( matches ) { + Sizzle.matchesSelector = function( node, expr ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) ) { + return matches.call( node, expr ); + } + } catch(e) {} + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "<div class='test e'></div><div class='test'></div>"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +Sizzle.contains = document.documentElement.contains ? function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +} : function(a, b){ + return !!(a.compareDocumentPosition(b) & 16); +}; + +Sizzle.isXML = function(elem){ + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + if ( jQuery.isArray( selectors ) ) { + var match, matches = {}, selector, level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + var pos = POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique(ret) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context || this.context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call(arguments).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], cur = elem[dir]; + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /<tbody/i, + rhtml = /<|&#?\w+;/, + rnocache = /<(?:script|object|embed|option|style)/i, + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, // checked="checked" or checked (html5) + raction = /\=([^="'>\s]+\/)>/g, + wrapMap = { + 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, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize <link> and <script> tags normally +if ( !jQuery.support.htmlSerialize ) { + wrapMap._default = [ 1, "div<div>", "</div>" ]; +} + +jQuery.fn.extend({ + text: function( text ) { + if ( jQuery.isFunction(text) ) { + return this.each(function(i) { + var self = jQuery(this); + self.text( text.call(this, i, self.text()) ); + }); + } + + if ( typeof text !== "object" && text !== undefined ) { + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + } + + return jQuery.text( this ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append(this); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + return this.each(function() { + jQuery( this ).wrapAll( html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }, + + append: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }, + + before: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this ); + }); + } else if ( arguments.length ) { + var set = jQuery(arguments[0]); + set.push.apply( set, this.toArray() ); + return this.pushStack( set, "before", arguments ); + } + }, + + after: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + } else if ( arguments.length ) { + var set = this.pushStack( this, "after", arguments ); + set.push.apply( set, jQuery(arguments[0]).toArray() ); + return set; + } + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( [ elem ] ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + return this; + }, + + clone: function( events ) { + // Do the clone + var ret = this.map(function() { + if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { + // IE copies events bound via attachEvent when + // using cloneNode. Calling detachEvent on the + // clone will also remove the events from the orignal + // In order to get around this, we use innerHTML. + // Unfortunately, this means some modifications to + // attributes in IE that are actually only stored + // as properties will not be copied (such as the + // the name attribute on an input). + var html = this.outerHTML, ownerDocument = this.ownerDocument; + if ( !html ) { + var div = ownerDocument.createElement("div"); + div.appendChild( this.cloneNode(true) ); + html = div.innerHTML; + } + + return jQuery.clean([html.replace(rinlinejQuery, "") + // Handle the case in IE 8 where action=/test/> self-closes a tag + .replace(raction, '="$1">') + .replace(rleadingWhitespace, "")], ownerDocument)[0]; + } else { + return this.cloneNode(true); + } + }); + + // Copy the events from the original to the clone + if ( events === true ) { + cloneCopyEvent( this, ret ); + cloneCopyEvent( this.find("*"), ret.find("*") ); + } + + // Return the cloned set + return ret; + }, + + html: function( value ) { + if ( value === undefined ) { + return this[0] && this[0].nodeType === 1 ? + this[0].innerHTML.replace(rinlinejQuery, "") : + null; + + // See if we can take a shortcut and just use innerHTML + } else if ( typeof value === "string" && !rnocache.test( value ) && + (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && + !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { + + value = value.replace(rxhtmlTag, "<$1></$2>"); + + try { + for ( var i = 0, l = this.length; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + if ( this[i].nodeType === 1 ) { + jQuery.cleanData( this[i].getElementsByTagName("*") ); + this[i].innerHTML = value; + } + } + + // If using innerHTML throws an exception, use the fallback method + } catch(e) { + this.empty().append( value ); + } + + } else if ( jQuery.isFunction( value ) ) { + this.each(function(i){ + var self = jQuery(this); + self.html( value.call(this, i, self.html()) ); + }); + + } else { + this.empty().append( value ); + } + + return this; + }, + + replaceWith: function( value ) { + if ( this[0] && this[0].parentNode ) { + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this), old = self.html(); + self.replaceWith( value.call( this, i, old ) ); + }); + } + + if ( typeof value !== "string" ) { + value = jQuery(value).detach(); + } + + return this.each(function() { + var next = this.nextSibling, parent = this.parentNode; + + jQuery(this).remove(); + + if ( next ) { + jQuery(next).before( value ); + } else { + jQuery(parent).append( value ); + } + }); + } else { + return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ); + } + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + var results, first, value = args[0], scripts = [], fragment, parent; + + // We can't cloneNode fragments that contain checked, in WebKit + if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { + return this.each(function() { + jQuery(this).domManip( args, table, callback, true ); + }); + } + + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + args[0] = value.call(this, i, table ? self.html() : undefined); + self.domManip( args, table, callback ); + }); + } + + if ( this[0] ) { + parent = value && value.parentNode; + + // If we're in a fragment, just use that instead of building a new one + if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { + results = { fragment: parent }; + + } else { + results = jQuery.buildFragment( args, this, scripts ); + } + + fragment = results.fragment; + + if ( fragment.childNodes.length === 1 ) { + first = fragment = fragment.firstChild; + } else { + first = fragment.firstChild; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + callback.call( + table ? + root(this[i], first) : + this[i], + i > 0 || results.cacheable || this.length > 1 ? + fragment.cloneNode(true) : + fragment + ); + } + } + + if ( scripts.length ) { + jQuery.each( scripts, evalScript ); + } + } + + return this; + } +}); + +function root( elem, cur ) { + return jQuery.nodeName(elem, "table") ? + (elem.getElementsByTagName("tbody")[0] || + elem.appendChild(elem.ownerDocument.createElement("tbody"))) : + elem; +} + +function cloneCopyEvent(orig, ret) { + var i = 0; + + ret.each(function() { + if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) { + return; + } + + var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( var type in events ) { + for ( var handler in events[ type ] ) { + jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); + } + } + } + }); +} + +jQuery.buildFragment = function( args, nodes, scripts ) { + var fragment, cacheable, cacheresults, + doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); + + // Only cache "small" (1/2 KB) strings that are associated with the main document + // Cloning options loses the selected state, so don't cache them + // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment + // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache + if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && + !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { + + cacheable = true; + cacheresults = jQuery.fragments[ args[0] ]; + if ( cacheresults ) { + if ( cacheresults !== 1 ) { + fragment = cacheresults; + } + } + } + + if ( !fragment ) { + fragment = doc.createDocumentFragment(); + jQuery.clean( args, doc, fragment, scripts ); + } + + if ( cacheable ) { + jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1; + } + + return { fragment: fragment, cacheable: cacheable }; +}; + +jQuery.fragments = {}; + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var ret = [], insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +}); + +jQuery.extend({ + clean: function( elems, context, fragment, scripts ) { + context = context || document; + + // !context.createElement fails in IE with an error but returns typeof 'object' + if ( typeof context.createElement === "undefined" ) { + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + } + + var ret = []; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( typeof elem === "number" ) { + elem += ""; + } + + if ( !elem ) { + continue; + } + + // Convert html string into DOM nodes + if ( typeof elem === "string" && !rhtml.test( elem ) ) { + elem = context.createTextNode( elem ); + + } else if ( typeof elem === "string" ) { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(rxhtmlTag, "<$1></$2>"); + + // Trim whitespace, otherwise indexOf won't work as expected + var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(), + wrap = wrapMap[ tag ] || wrapMap._default, + depth = wrap[0], + div = context.createElement("div"); + + // Go to html and back, then peel off extra wrappers + div.innerHTML = wrap[1] + elem + wrap[2]; + + // Move to the right depth + while ( depth-- ) { + div = div.lastChild; + } + + // Remove IE's autoinserted <tbody> from table fragments + if ( !jQuery.support.tbody ) { + + // String was a <table>, *may* have spurious <tbody> + var hasBody = rtbody.test(elem), + tbody = tag === "table" && !hasBody ? + div.firstChild && div.firstChild.childNodes : + + // String was a bare <thead> or <tfoot> + wrap[1] === "<table>" && !hasBody ? + div.childNodes : + []; + + for ( var j = tbody.length - 1; j >= 0 ; --j ) { + if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { + tbody[ j ].parentNode.removeChild( tbody[ j ] ); + } + } + + } + + // IE completely kills leading whitespace when innerHTML is used + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); + } + + elem = div.childNodes; + } + + if ( elem.nodeType ) { + ret.push( elem ); + } else { + ret = jQuery.merge( ret, elem ); + } + } + + if ( fragment ) { + for ( i = 0; ret[i]; i++ ) { + if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { + scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); + + } else { + if ( ret[i].nodeType === 1 ) { + ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) ); + } + fragment.appendChild( ret[i] ); + } + } + } + + return ret; + }, + + cleanData: function( elems ) { + var data, id, cache = jQuery.cache, + special = jQuery.event.special, + deleteExpando = jQuery.support.deleteExpando; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + continue; + } + + id = elem[ jQuery.expando ]; + + if ( id ) { + data = cache[ id ]; + + if ( data && data.events ) { + for ( var type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + if ( deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + delete cache[ id ]; + } + } + } +}); + +function evalScript( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } +} + + + + +var ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity=([^)]*)/, + rdashAlpha = /-([a-z])/ig, + rupper = /([A-Z])/g, + rnumpx = /^-?\d+(?:px)?$/i, + rnum = /^-?\d/, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssWidth = [ "Left", "Right" ], + cssHeight = [ "Top", "Bottom" ], + curCSS, + + // cache check for defaultView.getComputedStyle + getComputedStyle = document.defaultView && document.defaultView.getComputedStyle, + + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn.css = function( name, value ) { + // Setting 'undefined' is a no-op + if ( arguments.length === 2 && value === undefined ) { + return this; + } + + return jQuery.access( this, name, value, true, function( elem, name, value ) { + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }); +}; + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity", "opacity" ); + return ret === "" ? "1" : ret; + + } else { + return elem.style.opacity; + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "zIndex": true, + "fontWeight": true, + "opacity": true, + "zoom": true, + "lineHeight": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, origName = jQuery.camelCase( name ), + style = elem.style, hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // Check if we're setting a value + if ( value !== undefined ) { + // Make sure that NaN and null values aren't set. See: #7116 + if ( typeof value === "number" && isNaN( value ) || value == null ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra ) { + // Make sure that we're working with the right name + var ret, origName = jQuery.camelCase( name ), + hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { + return ret; + + // Otherwise, if a way to get the computed value exists, use that + } else if ( curCSS ) { + return curCSS( elem, name, origName ); + } + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}; + + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + }, + + camelCase: function( string ) { + return string.replace( rdashAlpha, fcamelCase ); + } +}); + +// DEPRECATED, Use jQuery.css() instead +jQuery.curCSS = jQuery.css; + +jQuery.each(["height", "width"], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + var val; + + if ( computed ) { + if ( elem.offsetWidth !== 0 ) { + val = getWH( elem, name, extra ); + + } else { + jQuery.swap( elem, cssShow, function() { + val = getWH( elem, name, extra ); + }); + } + + return val + "px"; + } + }, + + set: function( elem, value ) { + if ( rnumpx.test( value ) ) { + // ignore negative width and height values #1599 + value = parseFloat(value); + + if ( value >= 0 ) { + return value + "px"; + } + + } else { + return value; + } + } + }; +}); + +if ( !jQuery.support.opacity ) { + jQuery.cssHooks.opacity = { + get: function( elem, computed ) { + // IE uses filters for opacity + return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ? + (parseFloat(RegExp.$1) / 100) + "" : + computed ? "1" : ""; + }, + + set: function( elem, value ) { + var style = elem.style; + + // IE has trouble with opacity if it does not have layout + // Force it by setting the zoom level + style.zoom = 1; + + // Set the alpha filter to set the opacity + var opacity = jQuery.isNaN(value) ? + "" : + "alpha(opacity=" + value * 100 + ")", + filter = style.filter || ""; + + style.filter = ralpha.test(filter) ? + filter.replace(ralpha, opacity) : + style.filter + ' ' + opacity; + } + }; +} + +if ( getComputedStyle ) { + curCSS = function( elem, newName, name ) { + var ret, defaultView, computedStyle; + + name = name.replace( rupper, "-$1" ).toLowerCase(); + + if ( !(defaultView = elem.ownerDocument.defaultView) ) { + return undefined; + } + + if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) { + ret = computedStyle.getPropertyValue( name ); + if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) { + ret = jQuery.style( elem, name ); + } + } + + return ret; + }; + +} else if ( document.documentElement.currentStyle ) { + curCSS = function( elem, name ) { + var left, rsLeft, ret = elem.currentStyle && elem.currentStyle[ name ], style = elem.style; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !rnumpx.test( ret ) && rnum.test( ret ) ) { + // Remember the original values + left = style.left; + rsLeft = elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + elem.runtimeStyle.left = elem.currentStyle.left; + style.left = name === "fontSize" ? "1em" : (ret || 0); + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + elem.runtimeStyle.left = rsLeft; + } + + return ret; + }; +} + +function getWH( elem, name, extra ) { + var which = name === "width" ? cssWidth : cssHeight, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight; + + if ( extra === "border" ) { + return val; + } + + jQuery.each( which, function() { + if ( !extra ) { + val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0; + } + + if ( extra === "margin" ) { + val += parseFloat(jQuery.css( elem, "margin" + this )) || 0; + + } else { + val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0; + } + }); + + return val; +} + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.hidden = function( elem ) { + var width = elem.offsetWidth, height = elem.offsetHeight; + + return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none"); + }; + + jQuery.expr.filters.visible = function( elem ) { + return !jQuery.expr.filters.hidden( elem ); + }; +} + + + + +var jsc = jQuery.now(), + rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, + rselectTextarea = /^(?:select|textarea)/i, + rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, + rnoContent = /^(?:GET|HEAD|DELETE)$/, + rbracket = /\[\]$/, + jsre = /\=\?(&|$)/, + rquery = /\?/, + rts = /([?&])_=[^&]*/, + rurl = /^(\w+:)?\/\/([^\/?#]+)/, + r20 = /%20/g, + rhash = /#.*$/, + + // Keep a copy of the old load method + _load = jQuery.fn.load; + +jQuery.fn.extend({ + load: function( url, params, callback ) { + if ( typeof url !== "string" && _load ) { + return _load.apply( this, arguments ); + + // Don't do a request if no elements are being requested + } else if ( !this.length ) { + return this; + } + + var off = url.indexOf(" "); + if ( off >= 0 ) { + var selector = url.slice(off, url.length); + url = url.slice(0, off); + } + + // Default to a GET request + var type = "GET"; + + // If the second parameter was provided + if ( params ) { + // If it's a function + if ( jQuery.isFunction( params ) ) { + // We assume that it's the callback + callback = params; + params = null; + + // Otherwise, build a param string + } else if ( typeof params === "object" ) { + params = jQuery.param( params, jQuery.ajaxSettings.traditional ); + type = "POST"; + } + } + + var self = this; + + // Request the remote document + jQuery.ajax({ + url: url, + type: type, + dataType: "html", + data: params, + complete: function( res, status ) { + // If successful, inject the HTML into all the matched elements + if ( status === "success" || status === "notmodified" ) { + // See if a selector was specified + self.html( selector ? + // Create a dummy div to hold the results + jQuery("<div>") + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append(res.responseText.replace(rscript, "")) + + // Locate the specified elements + .find(selector) : + + // If not, just inject the full result + res.responseText ); + } + + if ( callback ) { + self.each( callback, [res.responseText, status, res] ); + } + } + }); + + return this; + }, + + serialize: function() { + return jQuery.param(this.serializeArray()); + }, + + serializeArray: function() { + return this.map(function() { + return this.elements ? jQuery.makeArray(this.elements) : this; + }) + .filter(function() { + return this.name && !this.disabled && + (this.checked || rselectTextarea.test(this.nodeName) || + rinput.test(this.type)); + }) + .map(function( i, elem ) { + var val = jQuery(this).val(); + + return val == null ? + null : + jQuery.isArray(val) ? + jQuery.map( val, function( val, i ) { + return { name: elem.name, value: val }; + }) : + { name: elem.name, value: val }; + }).get(); + } +}); + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) { + jQuery.fn[o] = function( f ) { + return this.bind(o, f); + }; +}); + +jQuery.extend({ + get: function( url, data, callback, type ) { + // shift arguments if data argument was omited + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = null; + } + + return jQuery.ajax({ + type: "GET", + url: url, + data: data, + success: callback, + dataType: type + }); + }, + + getScript: function( url, callback ) { + return jQuery.get(url, null, callback, "script"); + }, + + getJSON: function( url, data, callback ) { + return jQuery.get(url, data, callback, "json"); + }, + + post: function( url, data, callback, type ) { + // shift arguments if data argument was omited + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = {}; + } + + return jQuery.ajax({ + type: "POST", + url: url, + data: data, + success: callback, + dataType: type + }); + }, + + ajaxSetup: function( settings ) { + jQuery.extend( jQuery.ajaxSettings, settings ); + }, + + ajaxSettings: { + url: location.href, + global: true, + type: "GET", + contentType: "application/x-www-form-urlencoded", + processData: true, + async: true, + /* + timeout: 0, + data: null, + username: null, + password: null, + traditional: false, + */ + // This function can be overriden by calling jQuery.ajaxSetup + xhr: function() { + return new window.XMLHttpRequest(); + }, + accepts: { + xml: "application/xml, text/xml", + html: "text/html", + script: "text/javascript, application/javascript", + json: "application/json, text/javascript", + text: "text/plain", + _default: "*/*" + } + }, + + ajax: function( origSettings ) { + var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings), + jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type); + + s.url = s.url.replace( rhash, "" ); + + // Use original (not extended) context object if it was provided + s.context = origSettings && origSettings.context != null ? origSettings.context : s; + + // convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Handle JSONP Parameter Callbacks + if ( s.dataType === "jsonp" ) { + if ( type === "GET" ) { + if ( !jsre.test( s.url ) ) { + s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?"; + } + } else if ( !s.data || !jsre.test(s.data) ) { + s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; + } + s.dataType = "json"; + } + + // Build temporary JSONP function + if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) { + jsonp = s.jsonpCallback || ("jsonp" + jsc++); + + // Replace the =? sequence both in the query string and the data + if ( s.data ) { + s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); + } + + s.url = s.url.replace(jsre, "=" + jsonp + "$1"); + + // We need to make sure + // that a JSONP style response is executed properly + s.dataType = "script"; + + // Handle JSONP-style loading + var customJsonp = window[ jsonp ]; + + window[ jsonp ] = function( tmp ) { + data = tmp; + jQuery.handleSuccess( s, xhr, status, data ); + jQuery.handleComplete( s, xhr, status, data ); + + if ( jQuery.isFunction( customJsonp ) ) { + customJsonp( tmp ); + + } else { + // Garbage collect + window[ jsonp ] = undefined; + + try { + delete window[ jsonp ]; + } catch( jsonpError ) {} + } + + if ( head ) { + head.removeChild( script ); + } + }; + } + + if ( s.dataType === "script" && s.cache === null ) { + s.cache = false; + } + + if ( s.cache === false && type === "GET" ) { + var ts = jQuery.now(); + + // try replacing _= if it is there + var ret = s.url.replace(rts, "$1_=" + ts); + + // if nothing was replaced, add timestamp to the end + s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : ""); + } + + // If data is available, append data to url for get requests + if ( s.data && type === "GET" ) { + s.url += (rquery.test(s.url) ? "&" : "?") + s.data; + } + + // Watch for a new set of requests + if ( s.global && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Matches an absolute URL, and saves the domain + var parts = rurl.exec( s.url ), + remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host); + + // If we're requesting a remote document + // and trying to load JSON or Script with a GET + if ( s.dataType === "script" && type === "GET" && remote ) { + var head = document.getElementsByTagName("head")[0] || document.documentElement; + var script = document.createElement("script"); + if ( s.scriptCharset ) { + script.charset = s.scriptCharset; + } + script.src = s.url; + + // Handle Script loading + if ( !jsonp ) { + var done = false; + + // Attach handlers for all browsers + script.onload = script.onreadystatechange = function() { + if ( !done && (!this.readyState || + this.readyState === "loaded" || this.readyState === "complete") ) { + done = true; + jQuery.handleSuccess( s, xhr, status, data ); + jQuery.handleComplete( s, xhr, status, data ); + + // Handle memory leak in IE + script.onload = script.onreadystatechange = null; + if ( head && script.parentNode ) { + head.removeChild( script ); + } + } + }; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709 and #4378). + head.insertBefore( script, head.firstChild ); + + // We handle everything using the script element injection + return undefined; + } + + var requestDone = false; + + // Create the request object + var xhr = s.xhr(); + + if ( !xhr ) { + return; + } + + // Open the socket + // Passing null username, generates a login popup on Opera (#2865) + if ( s.username ) { + xhr.open(type, s.url, s.async, s.username, s.password); + } else { + xhr.open(type, s.url, s.async); + } + + // Need an extra try/catch for cross domain requests in Firefox 3 + try { + // Set content-type if data specified and content-body is valid for this type + if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) { + xhr.setRequestHeader("Content-Type", s.contentType); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[s.url] ) { + xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]); + } + + if ( jQuery.etag[s.url] ) { + xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]); + } + } + + // Set header so the called script knows that it's an XMLHttpRequest + // Only send the header if it's not a remote XHR + if ( !remote ) { + xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + } + + // Set the Accepts header for the server, depending on the dataType + xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? + s.accepts[ s.dataType ] + ", */*; q=0.01" : + s.accepts._default ); + } catch( headerError ) {} + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) { + // Handle the global AJAX counter + if ( s.global && jQuery.active-- === 1 ) { + jQuery.event.trigger( "ajaxStop" ); + } + + // close opended socket + xhr.abort(); + return false; + } + + if ( s.global ) { + jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] ); + } + + // Wait for a response to come back + var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) { + // The request was aborted + if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) { + // Opera doesn't call onreadystatechange before this point + // so we simulate the call + if ( !requestDone ) { + jQuery.handleComplete( s, xhr, status, data ); + } + + requestDone = true; + if ( xhr ) { + xhr.onreadystatechange = jQuery.noop; + } + + // The transfer is complete and the data is available, or the request timed out + } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) { + requestDone = true; + xhr.onreadystatechange = jQuery.noop; + + status = isTimeout === "timeout" ? + "timeout" : + !jQuery.httpSuccess( xhr ) ? + "error" : + s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? + "notmodified" : + "success"; + + var errMsg; + + if ( status === "success" ) { + // Watch for, and catch, XML document parse errors + try { + // process the data (runs the xml through httpData regardless of callback) + data = jQuery.httpData( xhr, s.dataType, s ); + } catch( parserError ) { + status = "parsererror"; + errMsg = parserError; + } + } + + // Make sure that the request was successful or notmodified + if ( status === "success" || status === "notmodified" ) { + // JSONP handles its own success callback + if ( !jsonp ) { + jQuery.handleSuccess( s, xhr, status, data ); + } + } else { + jQuery.handleError( s, xhr, status, errMsg ); + } + + // Fire the complete handlers + if ( !jsonp ) { + jQuery.handleComplete( s, xhr, status, data ); + } + + if ( isTimeout === "timeout" ) { + xhr.abort(); + } + + // Stop memory leaks + if ( s.async ) { + xhr = null; + } + } + }; + + // Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK) + // Opera doesn't fire onreadystatechange at all on abort + try { + var oldAbort = xhr.abort; + xhr.abort = function() { + // xhr.abort in IE7 is not a native JS function + // and does not have a call property + if ( xhr && oldAbort.call ) { + oldAbort.call( xhr ); + } + + onreadystatechange( "abort" ); + }; + } catch( abortError ) {} + + // Timeout checker + if ( s.async && s.timeout > 0 ) { + setTimeout(function() { + // Check to see if the request is still happening + if ( xhr && !requestDone ) { + onreadystatechange( "timeout" ); + } + }, s.timeout); + } + + // Send the data + try { + xhr.send( noContent || s.data == null ? null : s.data ); + + } catch( sendError ) { + jQuery.handleError( s, xhr, null, sendError ); + + // Fire the complete handlers + jQuery.handleComplete( s, xhr, status, data ); + } + + // firefox 1.5 doesn't fire statechange for sync requests + if ( !s.async ) { + onreadystatechange(); + } + + // return XMLHttpRequest to allow aborting the request etc. + return xhr; + }, + + // Serialize an array of form elements or a set of + // key/values into a query string + param: function( a, traditional ) { + var s = [], add = function( key, value ) { + // If value is a function, invoke it and return its value + value = jQuery.isFunction(value) ? value() : value; + s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value); + }; + + // Set traditional to true for jQuery <= 1.3.2 behavior. + if ( traditional === undefined ) { + traditional = jQuery.ajaxSettings.traditional; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray(a) || a.jquery ) { + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + }); + + } else { + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( var prefix in a ) { + buildParams( prefix, a[prefix], traditional, add ); + } + } + + // Return the resulting serialization + return s.join("&").replace(r20, "+"); + } +}); + +function buildParams( prefix, obj, traditional, add ) { + if ( jQuery.isArray(obj) && obj.length ) { + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + // If array item is non-scalar (array or object), encode its + // numeric index to resolve deserialization ambiguity issues. + // Note that rack (as of 1.0.0) can't currently deserialize + // nested arrays properly, and attempting to do so may cause + // a server error. Possible fixes are to modify rack's + // deserialization algorithm or to provide an option or flag + // to force array serialization to be shallow. + buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add ); + } + }); + + } else if ( !traditional && obj != null && typeof obj === "object" ) { + if ( jQuery.isEmptyObject( obj ) ) { + add( prefix, "" ); + + // Serialize object item. + } else { + jQuery.each( obj, function( k, v ) { + buildParams( prefix + "[" + k + "]", v, traditional, add ); + }); + } + + } else { + // Serialize scalar item. + add( prefix, obj ); + } +} + +// This is still on the jQuery object... for now +// Want to move this to jQuery.ajax some day +jQuery.extend({ + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + handleError: function( s, xhr, status, e ) { + // If a local callback was specified, fire it + if ( s.error ) { + s.error.call( s.context, xhr, status, e ); + } + + // Fire the global callback + if ( s.global ) { + jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] ); + } + }, + + handleSuccess: function( s, xhr, status, data ) { + // If a local callback was specified, fire it and pass it the data + if ( s.success ) { + s.success.call( s.context, data, status, xhr ); + } + + // Fire the global callback + if ( s.global ) { + jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] ); + } + }, + + handleComplete: function( s, xhr, status ) { + // Process result + if ( s.complete ) { + s.complete.call( s.context, xhr, status ); + } + + // The request was completed + if ( s.global ) { + jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] ); + } + + // Handle the global AJAX counter + if ( s.global && jQuery.active-- === 1 ) { + jQuery.event.trigger( "ajaxStop" ); + } + }, + + triggerGlobal: function( s, type, args ) { + (s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args); + }, + + // Determines if an XMLHttpRequest was successful or not + httpSuccess: function( xhr ) { + try { + // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 + return !xhr.status && location.protocol === "file:" || + xhr.status >= 200 && xhr.status < 300 || + xhr.status === 304 || xhr.status === 1223; + } catch(e) {} + + return false; + }, + + // Determines if an XMLHttpRequest returns NotModified + httpNotModified: function( xhr, url ) { + var lastModified = xhr.getResponseHeader("Last-Modified"), + etag = xhr.getResponseHeader("Etag"); + + if ( lastModified ) { + jQuery.lastModified[url] = lastModified; + } + + if ( etag ) { + jQuery.etag[url] = etag; + } + + return xhr.status === 304; + }, + + httpData: function( xhr, type, s ) { + var ct = xhr.getResponseHeader("content-type") || "", + xml = type === "xml" || !type && ct.indexOf("xml") >= 0, + data = xml ? xhr.responseXML : xhr.responseText; + + if ( xml && data.documentElement.nodeName === "parsererror" ) { + jQuery.error( "parsererror" ); + } + + // Allow a pre-filtering function to sanitize the response + // s is checked to keep backwards compatibility + if ( s && s.dataFilter ) { + data = s.dataFilter( data, type ); + } + + // The filter can actually parse the response + if ( typeof data === "string" ) { + // Get the JavaScript object, if JSON is used. + if ( type === "json" || !type && ct.indexOf("json") >= 0 ) { + data = jQuery.parseJSON( data ); + + // If the type is "script", eval it in global context + } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) { + jQuery.globalEval( data ); + } + } + + return data; + } + +}); + +/* + * Create the request object; Microsoft failed to properly + * implement the XMLHttpRequest in IE7 (can't request local files), + * so we use the ActiveXObject when it is available + * Additionally XMLHttpRequest can be disabled in IE7/IE8 so + * we need a fallback. + */ +if ( window.ActiveXObject ) { + jQuery.ajaxSettings.xhr = function() { + if ( window.location.protocol !== "file:" ) { + try { + return new window.XMLHttpRequest(); + } catch(xhrError) {} + } + + try { + return new window.ActiveXObject("Microsoft.XMLHTTP"); + } catch(activeError) {} + }; +} + +// Does this browser support XHR requests? +jQuery.support.ajax = !!jQuery.ajaxSettings.xhr(); + + + + +var elemdisplay = {}, + rfxtypes = /^(?:toggle|show|hide)$/, + rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/, + timerId, + fxAttrs = [ + // height animations + [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], + // width animations + [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], + // opacity animations + [ "opacity" ] + ]; + +jQuery.fn.extend({ + show: function( speed, easing, callback ) { + if ( speed || speed === 0 ) { + return this.animate( genFx("show", 3), speed, easing, callback); + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !jQuery.data(this[i], "olddisplay") && this[i].style.display === "none" ) { + this[i].style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( this[i].style.display === "" && jQuery.css( this[i], "display" ) === "none" ) { + jQuery.data(this[i], "olddisplay", defaultDisplay(this[i].nodeName)); + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + this[i].style.display = jQuery.data(this[i], "olddisplay") || ""; + } + + return this; + } + }, + + hide: function( speed, easing, callback ) { + if ( speed || speed === 0 ) { + return this.animate( genFx("hide", 3), speed, easing, callback); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + var display = jQuery.css( this[i], "display" ); + + if ( display !== "none" ) { + jQuery.data( this[i], "olddisplay", display ); + } + } + + // Set the display of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + this[i].style.display = "none"; + } + + return this; + } + }, + + // Save the old toggle function + _toggle: jQuery.fn.toggle, + + toggle: function( fn, fn2, callback ) { + var bool = typeof fn === "boolean"; + + if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) { + this._toggle.apply( this, arguments ); + + } else if ( fn == null || bool ) { + this.each(function() { + var state = bool ? fn : jQuery(this).is(":hidden"); + jQuery(this)[ state ? "show" : "hide" ](); + }); + + } else { + this.animate(genFx("toggle", 3), fn, fn2, callback); + } + + return this; + }, + + fadeTo: function( speed, to, easing, callback ) { + return this.filter(":hidden").css("opacity", 0).show().end() + .animate({opacity: to}, speed, easing, callback); + }, + + animate: function( prop, speed, easing, callback ) { + var optall = jQuery.speed(speed, easing, callback); + + if ( jQuery.isEmptyObject( prop ) ) { + return this.each( optall.complete ); + } + + return this[ optall.queue === false ? "each" : "queue" ](function() { + // XXX ‘this’ does not always have a nodeName when running the + // test suite + + var opt = jQuery.extend({}, optall), p, + isElement = this.nodeType === 1, + hidden = isElement && jQuery(this).is(":hidden"), + self = this; + + for ( p in prop ) { + var name = jQuery.camelCase( p ); + + if ( p !== name ) { + prop[ name ] = prop[ p ]; + delete prop[ p ]; + p = name; + } + + if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) { + return opt.complete.call(this); + } + + if ( isElement && ( p === "height" || p === "width" ) ) { + // Make sure that nothing sneaks out + // Record all 3 overflow attributes because IE does not + // change the overflow attribute when overflowX and + // overflowY are set to the same value + opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ]; + + // Set display property to inline-block for height/width + // animations on inline elements that are having width/height + // animated + if ( jQuery.css( this, "display" ) === "inline" && + jQuery.css( this, "float" ) === "none" ) { + if ( !jQuery.support.inlineBlockNeedsLayout ) { + this.style.display = "inline-block"; + + } else { + var display = defaultDisplay(this.nodeName); + + // inline-level elements accept inline-block; + // block-level elements need to be inline with layout + if ( display === "inline" ) { + this.style.display = "inline-block"; + + } else { + this.style.display = "inline"; + this.style.zoom = 1; + } + } + } + } + + if ( jQuery.isArray( prop[p] ) ) { + // Create (if needed) and add to specialEasing + (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1]; + prop[p] = prop[p][0]; + } + } + + if ( opt.overflow != null ) { + this.style.overflow = "hidden"; + } + + opt.curAnim = jQuery.extend({}, prop); + + jQuery.each( prop, function( name, val ) { + var e = new jQuery.fx( self, opt, name ); + + if ( rfxtypes.test(val) ) { + e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop ); + + } else { + var parts = rfxnum.exec(val), + start = e.cur(true) || 0; + + if ( parts ) { + var end = parseFloat( parts[2] ), + unit = parts[3] || "px"; + + // We need to compute starting value + if ( unit !== "px" ) { + jQuery.style( self, name, (end || 1) + unit); + start = ((end || 1) / e.cur(true)) * start; + jQuery.style( self, name, start + unit); + } + + // If a +=/-= token was provided, we're doing a relative animation + if ( parts[1] ) { + end = ((parts[1] === "-=" ? -1 : 1) * end) + start; + } + + e.custom( start, end, unit ); + + } else { + e.custom( start, val, "" ); + } + } + }); + + // For JS strict compliance + return true; + }); + }, + + stop: function( clearQueue, gotoEnd ) { + var timers = jQuery.timers; + + if ( clearQueue ) { + this.queue([]); + } + + this.each(function() { + // go in reverse order so anything added to the queue during the loop is ignored + for ( var i = timers.length - 1; i >= 0; i-- ) { + if ( timers[i].elem === this ) { + if (gotoEnd) { + // force the next step to be the last + timers[i](true); + } + + timers.splice(i, 1); + } + } + }); + + // start the next in the queue if the last step wasn't forced + if ( !gotoEnd ) { + this.dequeue(); + } + + return this; + } + +}); + +function genFx( type, num ) { + var obj = {}; + + jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() { + obj[ this ] = type; + }); + + return obj; +} + +// Generate shortcuts for custom animations +jQuery.each({ + slideDown: genFx("show", 1), + slideUp: genFx("hide", 1), + slideToggle: genFx("toggle", 1), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +}); + +jQuery.extend({ + speed: function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction(easing) && easing + }; + + opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : + opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default; + + // Queueing + opt.old = opt.complete; + opt.complete = function() { + if ( opt.queue !== false ) { + jQuery(this).dequeue(); + } + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + }; + + return opt; + }, + + easing: { + linear: function( p, n, firstNum, diff ) { + return firstNum + diff * p; + }, + swing: function( p, n, firstNum, diff ) { + return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; + } + }, + + timers: [], + + fx: function( elem, options, prop ) { + this.options = options; + this.elem = elem; + this.prop = prop; + + if ( !options.orig ) { + options.orig = {}; + } + } + +}); + +jQuery.fx.prototype = { + // Simple function for setting a style value + update: function() { + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); + }, + + // Get the current size + cur: function() { + if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) { + return this.elem[ this.prop ]; + } + + var r = parseFloat( jQuery.css( this.elem, this.prop ) ); + return r && r > -10000 ? r : 0; + }, + + // Start an animation from one number to another + custom: function( from, to, unit ) { + this.startTime = jQuery.now(); + this.start = from; + this.end = to; + this.unit = unit || this.unit || "px"; + this.now = this.start; + this.pos = this.state = 0; + + var self = this, fx = jQuery.fx; + function t( gotoEnd ) { + return self.step(gotoEnd); + } + + t.elem = this.elem; + + if ( t() && jQuery.timers.push(t) && !timerId ) { + timerId = setInterval(fx.tick, fx.interval); + } + }, + + // Simple 'show' function + show: function() { + // Remember where we started, so that we can go back to it later + this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); + this.options.show = true; + + // Begin the animation + // Make sure that we start at a small width/height to avoid any + // flash of content + this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur()); + + // Start by showing the element + jQuery( this.elem ).show(); + }, + + // Simple 'hide' function + hide: function() { + // Remember where we started, so that we can go back to it later + this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); + this.options.hide = true; + + // Begin the animation + this.custom(this.cur(), 0); + }, + + // Each step of an animation + step: function( gotoEnd ) { + var t = jQuery.now(), done = true; + + if ( gotoEnd || t >= this.options.duration + this.startTime ) { + this.now = this.end; + this.pos = this.state = 1; + this.update(); + + this.options.curAnim[ this.prop ] = true; + + for ( var i in this.options.curAnim ) { + if ( this.options.curAnim[i] !== true ) { + done = false; + } + } + + if ( done ) { + // Reset the overflow + if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) { + var elem = this.elem, options = this.options; + jQuery.each( [ "", "X", "Y" ], function (index, value) { + elem.style[ "overflow" + value ] = options.overflow[index]; + } ); + } + + // Hide the element if the "hide" operation was done + if ( this.options.hide ) { + jQuery(this.elem).hide(); + } + + // Reset the properties, if the item has been hidden or shown + if ( this.options.hide || this.options.show ) { + for ( var p in this.options.curAnim ) { + jQuery.style( this.elem, p, this.options.orig[p] ); + } + } + + // Execute the complete function + this.options.complete.call( this.elem ); + } + + return false; + + } else { + var n = t - this.startTime; + this.state = n / this.options.duration; + + // Perform the easing function, defaults to swing + var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop]; + var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear"); + this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration); + this.now = this.start + ((this.end - this.start) * this.pos); + + // Perform the next step of the animation + this.update(); + } + + return true; + } +}; + +jQuery.extend( jQuery.fx, { + tick: function() { + var timers = jQuery.timers; + + for ( var i = 0; i < timers.length; i++ ) { + if ( !timers[i]() ) { + timers.splice(i--, 1); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + }, + + interval: 13, + + stop: function() { + clearInterval( timerId ); + timerId = null; + }, + + speeds: { + slow: 600, + fast: 200, + // Default speed + _default: 400 + }, + + step: { + opacity: function( fx ) { + jQuery.style( fx.elem, "opacity", fx.now ); + }, + + _default: function( fx ) { + if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) { + fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit; + } else { + fx.elem[ fx.prop ] = fx.now; + } + } + } +}); + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.animated = function( elem ) { + return jQuery.grep(jQuery.timers, function( fn ) { + return elem === fn.elem; + }).length; + }; +} + +function defaultDisplay( nodeName ) { + if ( !elemdisplay[ nodeName ] ) { + var elem = jQuery("<" + nodeName + ">").appendTo("body"), + display = elem.css("display"); + + elem.remove(); + + if ( display === "none" || display === "" ) { + display = "block"; + } + + elemdisplay[ nodeName ] = display; + } + + return elemdisplay[ nodeName ]; +} + + + + +var rtable = /^t(?:able|d|h)$/i, + rroot = /^(?:body|html)$/i; + +if ( "getBoundingClientRect" in document.documentElement ) { + jQuery.fn.offset = function( options ) { + var elem = this[0], box; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + try { + box = elem.getBoundingClientRect(); + } catch(e) {} + + var doc = elem.ownerDocument, + docElem = doc.documentElement; + + // Make sure we're not dealing with a disconnected DOM node + if ( !box || !jQuery.contains( docElem, elem ) ) { + return box || { top: 0, left: 0 }; + } + + var body = doc.body, + win = getWindow(doc), + clientTop = docElem.clientTop || body.clientTop || 0, + clientLeft = docElem.clientLeft || body.clientLeft || 0, + scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ), + scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft), + top = box.top + scrollTop - clientTop, + left = box.left + scrollLeft - clientLeft; + + return { top: top, left: left }; + }; + +} else { + jQuery.fn.offset = function( options ) { + var elem = this[0]; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + jQuery.offset.initialize(); + + var offsetParent = elem.offsetParent, prevOffsetParent = elem, + doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement, + body = doc.body, defaultView = doc.defaultView, + prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle, + top = elem.offsetTop, left = elem.offsetLeft; + + while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { + if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { + break; + } + + computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle; + top -= elem.scrollTop; + left -= elem.scrollLeft; + + if ( elem === offsetParent ) { + top += elem.offsetTop; + left += elem.offsetLeft; + + if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevOffsetParent = offsetParent; + offsetParent = elem.offsetParent; + } + + if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevComputedStyle = computedStyle; + } + + if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) { + top += body.offsetTop; + left += body.offsetLeft; + } + + if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { + top += Math.max( docElem.scrollTop, body.scrollTop ); + left += Math.max( docElem.scrollLeft, body.scrollLeft ); + } + + return { top: top, left: left }; + }; +} + +jQuery.offset = { + initialize: function() { + var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0, + html = "<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>"; + + jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } ); + + container.innerHTML = html; + body.insertBefore( container, body.firstChild ); + innerDiv = container.firstChild; + checkDiv = innerDiv.firstChild; + td = innerDiv.nextSibling.firstChild.firstChild; + + this.doesNotAddBorder = (checkDiv.offsetTop !== 5); + this.doesAddBorderForTableAndCells = (td.offsetTop === 5); + + checkDiv.style.position = "fixed"; + checkDiv.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15); + checkDiv.style.position = checkDiv.style.top = ""; + + innerDiv.style.overflow = "hidden"; + innerDiv.style.position = "relative"; + + this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5); + + this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop); + + body.removeChild( container ); + body = container = innerDiv = checkDiv = table = td = null; + jQuery.offset.initialize = jQuery.noop; + }, + + bodyOffset: function( body ) { + var top = body.offsetTop, left = body.offsetLeft; + + jQuery.offset.initialize(); + + if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) { + top += parseFloat( jQuery.css(body, "marginTop") ) || 0; + left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; + } + + return { top: top, left: left }; + }, + + setOffset: function( elem, options, i ) { + var position = jQuery.css( elem, "position" ); + + // set position first, in-case top/left are set even on static elem + if ( position === "static" ) { + elem.style.position = "relative"; + } + + var curElem = jQuery( elem ), + curOffset = curElem.offset(), + curCSSTop = jQuery.css( elem, "top" ), + curCSSLeft = jQuery.css( elem, "left" ), + calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1), + props = {}, curPosition = {}, curTop, curLeft; + + // need to be able to calculate position if either top or left is auto and position is absolute + if ( calculatePosition ) { + curPosition = curElem.position(); + } + + curTop = calculatePosition ? curPosition.top : parseInt( curCSSTop, 10 ) || 0; + curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0; + + if ( jQuery.isFunction( options ) ) { + options = options.call( elem, i, curOffset ); + } + + if (options.top != null) { + props.top = (options.top - curOffset.top) + curTop; + } + if (options.left != null) { + props.left = (options.left - curOffset.left) + curLeft; + } + + if ( "using" in options ) { + options.using.call( elem, props ); + } else { + curElem.css( props ); + } + } +}; + + +jQuery.fn.extend({ + position: function() { + if ( !this[0] ) { + return null; + } + + var elem = this[0], + + // Get *real* offsetParent + offsetParent = this.offsetParent(), + + // Get correct offsets + offset = this.offset(), + parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); + + // Subtract element margins + // note: when an element has margin: auto the offsetLeft and marginLeft + // are the same in Safari causing offset.left to incorrectly be 0 + offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; + offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; + + // Add offsetParent borders + parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; + parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; + + // Subtract the two offsets + return { + top: offset.top - parentOffset.top, + left: offset.left - parentOffset.left + }; + }, + + offsetParent: function() { + return this.map(function() { + var offsetParent = this.offsetParent || document.body; + while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent; + }); + } +}); + + +// Create scrollLeft and scrollTop methods +jQuery.each( ["Left", "Top"], function( i, name ) { + var method = "scroll" + name; + + jQuery.fn[ method ] = function(val) { + var elem = this[0], win; + + if ( !elem ) { + return null; + } + + if ( val !== undefined ) { + // Set the scroll offset + return this.each(function() { + win = getWindow( this ); + + if ( win ) { + win.scrollTo( + !i ? val : jQuery(win).scrollLeft(), + i ? val : jQuery(win).scrollTop() + ); + + } else { + this[ method ] = val; + } + }); + } else { + win = getWindow( elem ); + + // Return the scroll offset + return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : + jQuery.support.boxModel && win.document.documentElement[ method ] || + win.document.body[ method ] : + elem[ method ]; + } + }; +}); + +function getWindow( elem ) { + return jQuery.isWindow( elem ) ? + elem : + elem.nodeType === 9 ? + elem.defaultView || elem.parentWindow : + false; +} + + + + +// Create innerHeight, innerWidth, outerHeight and outerWidth methods +jQuery.each([ "Height", "Width" ], function( i, name ) { + + var type = name.toLowerCase(); + + // innerHeight and innerWidth + jQuery.fn["inner" + name] = function() { + return this[0] ? + parseFloat( jQuery.css( this[0], type, "padding" ) ) : + null; + }; + + // outerHeight and outerWidth + jQuery.fn["outer" + name] = function( margin ) { + return this[0] ? + parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) : + null; + }; + + jQuery.fn[ type ] = function( size ) { + // Get window width or height + var elem = this[0]; + if ( !elem ) { + return size == null ? null : this; + } + + if ( jQuery.isFunction( size ) ) { + return this.each(function( i ) { + var self = jQuery( this ); + self[ type ]( size.call( this, i, self[ type ]() ) ); + }); + } + + return jQuery.isWindow( elem ) ? + // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode + elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] || + elem.document.body[ "client" + name ] : + + // Get document width or height + (elem.nodeType === 9) ? // is it a document + // Either scroll[Width/Height] or offset[Width/Height], whichever is greater + Math.max( + elem.documentElement["client" + name], + elem.body["scroll" + name], elem.documentElement["scroll" + name], + elem.body["offset" + name], elem.documentElement["offset" + name] + ) : + + // Get or set width or height on the element + size === undefined ? + // Get width or height on the element + parseFloat( jQuery.css( elem, type ) ) : + + // Set the width or height on the element (default to pixels if value is unitless) + this.css( type, typeof size === "string" ? size : size + "px" ); + }; + +}); + + +})(window); diff --git a/askbot/skins/common/media/js/jquery-fieldselection.js b/askbot/skins/common/media/js/jquery-fieldselection.js new file mode 100644 index 00000000..47f25a98 --- /dev/null +++ b/askbot/skins/common/media/js/jquery-fieldselection.js @@ -0,0 +1,83 @@ +/* + * jQuery plugin: fieldSelection - v0.1.0 - last change: 2006-12-16 + * (c) 2006 Alex Brem <alex@0xab.cd> - http://blog.0xab.cd + */ + +(function() { + + var fieldSelection = { + + getSelection: function() { + + var e = this.jquery ? this[0] : this; + + return ( + + /* mozilla / dom 3.0 */ + ('selectionStart' in e && function() { + var l = e.selectionEnd - e.selectionStart; + return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) }; + }) || + + /* exploder */ + (document.selection && function() { + + e.focus(); + + var r = document.selection.createRange(); + if (r == null) { + return { start: 0, end: e.value.length, length: 0 } + } + + var re = e.createTextRange(); + var rc = re.duplicate(); + re.moveToBookmark(r.getBookmark()); + rc.setEndPoint('EndToStart', re); + + return { start: rc.text.length, end: rc.text.length + r.text.length, length: r.text.length, text: r.text }; + }) || + + /* browser not supported */ + function() { + return { start: 0, end: e.value.length, length: 0 }; + } + + )(); + + }, + + replaceSelection: function() { + + var e = this.jquery ? this[0] : this; + var text = arguments[0] || ''; + + return ( + + /* mozilla / dom 3.0 */ + ('selectionStart' in e && function() { + e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length); + return this; + }) || + + /* exploder */ + (document.selection && function() { + e.focus(); + document.selection.createRange().text = text; + return this; + }) || + + /* browser not supported */ + function() { + e.value += text; + return this; + } + + )(); + + } + + }; + + jQuery.each(fieldSelection, function(i) { jQuery.fn[i] = this; }); + +})(); diff --git a/askbot/skins/common/media/js/jquery-fieldselection.min.js b/askbot/skins/common/media/js/jquery-fieldselection.min.js new file mode 100644 index 00000000..c2abde0b --- /dev/null +++ b/askbot/skins/common/media/js/jquery-fieldselection.min.js @@ -0,0 +1 @@ +(function(){var a={getSelection:function(){var b=this.jquery?this[0]:this;return(("selectionStart" in b&&function(){var c=b.selectionEnd-b.selectionStart;return{start:b.selectionStart,end:b.selectionEnd,length:c,text:b.value.substr(b.selectionStart,c)}})||(document.selection&&function(){b.focus();var d=document.selection.createRange();if(d==null){return{start:0,end:b.value.length,length:0}}var c=b.createTextRange();var e=c.duplicate();c.moveToBookmark(d.getBookmark());e.setEndPoint("EndToStart",c);return{start:e.text.length,end:e.text.length+d.text.length,length:d.text.length,text:d.text}})||function(){return{start:0,end:b.value.length,length:0}})()},replaceSelection:function(){var b=this.jquery?this[0]:this;var c=arguments[0]||"";return(("selectionStart" in b&&function(){b.value=b.value.substr(0,b.selectionStart)+c+b.value.substr(b.selectionEnd,b.value.length);return this})||(document.selection&&function(){b.focus();document.selection.createRange().text=c;return this})||function(){b.value+=c;return this})()}};jQuery.each(a,function(b){jQuery.fn[b]=this})})();
\ No newline at end of file diff --git a/askbot/skins/common/media/js/jquery.ajaxfileupload.js b/askbot/skins/common/media/js/jquery.ajaxfileupload.js new file mode 100644 index 00000000..75292776 --- /dev/null +++ b/askbot/skins/common/media/js/jquery.ajaxfileupload.js @@ -0,0 +1,195 @@ +jQuery.extend({ + createUploadIframe: function(id, uri){ + //create frame + var frameId = 'jUploadFrame' + id; + if(window.ActiveXObject) { + var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />'); + if(typeof uri== 'boolean'){ + io.src = 'javascript:false'; + } + else if(typeof uri== 'string'){ + io.src = uri; + } + } + else { + var io = document.createElement('iframe'); + io.id = frameId; + io.name = frameId; + } + io.style.position = 'absolute'; + io.style.top = '-1000px'; + io.style.left = '-1000px'; + + document.body.appendChild(io); + return io; + }, + createUploadForm: function(id, fileElementId) + { + //create form + var formId = 'jUploadForm' + id; + var fileId = 'jUploadFile' + id; + var form = $('<form action="" method="POST" name="' + formId + '" id="' + formId + + '" enctype="multipart/form-data"></form>'); + var oldElement = $('#' + fileElementId); + var newElement = $(oldElement).clone(); + $(oldElement).attr('id', fileId); + $(oldElement).before(newElement); + $(oldElement).appendTo(form); + //set attributes + $(form).css('position', 'absolute'); + $(form).css('top', '-1200px'); + $(form).css('left', '-1200px'); + $(form).appendTo('body'); + return form; + }, + + ajaxFileUpload: function(s) { + // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout + s = jQuery.extend({}, jQuery.ajaxSettings, s); + var id = new Date().getTime() + var form = jQuery.createUploadForm(id, s.fileElementId); + var io = jQuery.createUploadIframe(id, s.secureuri); + var frameId = 'jUploadFrame' + id; + var formId = 'jUploadForm' + id; + // Watch for a new set of requests + if ( s.global && ! jQuery.active++ ) + { + jQuery.event.trigger( "ajaxStart" ); + } + var requestDone = false; + // Create the request object + var xml = {} + if ( s.global ) + jQuery.event.trigger("ajaxSend", [xml, s]); + // Wait for a response to come back + var uploadCallback = function(isTimeout) + { + var io = document.getElementById(frameId); + try { + if(io.contentWindow){ + xml.responseText = io.contentWindow.document.body ? + io.contentWindow.document.body.innerText : null; + xml.responseXML = io.contentWindow.document.XMLDocument ? + io.contentWindow.document.XMLDocument : io.contentWindow.document; + + } + else if(io.contentDocument) + { + xml.responseText = io.contentDocument.document.body ? + io.contentDocument.document.body.textContent || document.body.innerText : null; + xml.responseXML = io.contentDocument.document.XMLDocument ? + io.contentDocument.document.XMLDocument : io.contentDocument.document; + } + } + catch(e) + { + jQuery.handleError(s, xml, null, e); + } + if ( xml || isTimeout == "timeout") + { + requestDone = true; + var status; + try { + status = isTimeout != "timeout" ? "success" : "error"; + // Make sure that the request was successful or notmodified + if ( status != "error" ) + { + // process the data (runs the xml through httpData regardless of callback) + var data = jQuery.uploadHttpData( xml, s.dataType ); + // If a local callback was specified, fire it and pass it the data + if ( s.success ) + s.success( data, status ); + + // Fire the global callback + if( s.global ) + jQuery.event.trigger( "ajaxSuccess", [xml, s] ); + } else + jQuery.handleError(s, xml, status); + } catch(e) + { + status = "error"; + jQuery.handleError(s, xml, status, e); + } + + // The request was completed + if( s.global ) + jQuery.event.trigger( "ajaxComplete", [xml, s] ); + + // Handle the global AJAX counter + if ( s.global && ! --jQuery.active ) + jQuery.event.trigger( "ajaxStop" ); + + // Process result + if ( s.complete ) + s.complete(xml, status); + + jQuery(io).unbind(); + + setTimeout(function() + { try + { + $(io).remove(); + $(form).remove(); + + } catch(e) { + jQuery.handleError(s, xml, null, e); + } + }, 100) + xml = null; + } + } + // Timeout checker + if ( s.timeout > 0 ) { + setTimeout(function(){ + // Check to see if the request is still happening + if( !requestDone ) uploadCallback( "timeout" ); + }, s.timeout); + } + try + { + // var io = $('#' + frameId); + var form = $('#' + formId); + $(form).attr('action', s.url); + $(form).attr('method', 'POST'); + $(form).attr('target', frameId); + if(form.encoding) + { + form.encoding = 'multipart/form-data'; + } + else + { + form.enctype = 'multipart/form-data'; + } + $(form).submit(); + + } catch(e) + { + jQuery.handleError(s, xml, null, e); + } + if(window.attachEvent){ + document.getElementById(frameId).attachEvent('onload', uploadCallback); + } + else{ + document.getElementById(frameId).addEventListener('load', uploadCallback, false); + } + return {abort: function () {}}; + + }, + + uploadHttpData: function( r, type ) { + var data = !type; + data = type == "xml" || data ? r.responseXML : r.responseText; + // If the type is "script", eval it in global context + if ( type == "script" ) + jQuery.globalEval( data ); + // Get the JavaScript object, if JSON is used. + if ( type == "json" ) + eval( "data = " + data ); + // evaluate scripts within html + if ( type == "html" ) + jQuery("<div>").html(data).evalScripts(); + //alert($('param', data).each(function(){alert($(this).attr('value'));})); + return data; + } +}) + diff --git a/askbot/skins/common/media/js/jquery.flot.js b/askbot/skins/common/media/js/jquery.flot.js new file mode 100644 index 00000000..6534a468 --- /dev/null +++ b/askbot/skins/common/media/js/jquery.flot.js @@ -0,0 +1,2119 @@ +/* Javascript plotting library for jQuery, v. 0.6. + * + * Released under the MIT license by IOLA, December 2007. + * + */ + +// first an inline dependency, jquery.colorhelpers.js, we inline it here +// for convenience + +/* Plugin for jQuery for working with colors. + * + * Version 1.0. + * + * Inspiration from jQuery color animation plugin by John Resig. + * + * Released under the MIT license by Ole Laursen, October 2009. + * + * Examples: + * + * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() + * var c = $.color.extract($("#mydiv"), 'background-color'); + * console.log(c.r, c.g, c.b, c.a); + * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" + * + * Note that .scale() and .add() work in-place instead of returning + * new objects. + */ +(function(){jQuery.color={};jQuery.color.make=function(E,D,B,C){var F={};F.r=E||0;F.g=D||0;F.b=B||0;F.a=C!=null?C:1;F.add=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]+=H}return F.normalize()};F.scale=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]*=H}return F.normalize()};F.toString=function(){if(F.a>=1){return"rgb("+[F.r,F.g,F.b].join(",")+")"}else{return"rgba("+[F.r,F.g,F.b,F.a].join(",")+")"}};F.normalize=function(){function G(I,J,H){return J<I?I:(J>H?H:J)}F.r=G(0,parseInt(F.r),255);F.g=G(0,parseInt(F.g),255);F.b=G(0,parseInt(F.b),255);F.a=G(0,F.a,1);return F};F.clone=function(){return jQuery.color.make(F.r,F.b,F.g,F.a)};return F.normalize()};jQuery.color.extract=function(C,B){var D;do{D=C.css(B).toLowerCase();if(D!=""&&D!="transparent"){break}C=C.parent()}while(!jQuery.nodeName(C.get(0),"body"));if(D=="rgba(0, 0, 0, 0)"){D="transparent"}return jQuery.color.parse(D)};jQuery.color.parse=function(E){var D,B=jQuery.color.make;if(D=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10))}if(D=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10),parseFloat(D[4]))}if(D=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55)}if(D=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55,parseFloat(D[4]))}if(D=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(E)){return B(parseInt(D[1],16),parseInt(D[2],16),parseInt(D[3],16))}if(D=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(E)){return B(parseInt(D[1]+D[1],16),parseInt(D[2]+D[2],16),parseInt(D[3]+D[3],16))}var C=jQuery.trim(E).toLowerCase();if(C=="transparent"){return B(255,255,255,0)}else{D=A[C];return B(D[0],D[1],D[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(); + +// the actual Flot code +(function($) { + function Plot(placeholder, data_, options_, plugins) { + // data is on the form: + // [ series1, series2 ... ] + // where series is either just the data as [ [x1, y1], [x2, y2], ... ] + // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... } + + var series = [], + options = { + // the color theme used for graphs + colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"], + legend: { + show: true, + noColumns: 1, // number of colums in legend table + labelFormatter: null, // fn: string -> string + labelBoxBorderColor: "#ccc", // border color for the little label boxes + container: null, // container (as jQuery object) to put legend in, null means default on top of graph + position: "ne", // position of default legend container within plot + margin: 5, // distance from grid edge to default legend container within plot + backgroundColor: null, // null means auto-detect + backgroundOpacity: 0.85 // set to 0 to avoid background + }, + xaxis: { + mode: null, // null or "time" + transform: null, // null or f: number -> number to transform axis + inverseTransform: null, // if transform is set, this should be the inverse function + min: null, // min. value to show, null means set automatically + max: null, // max. value to show, null means set automatically + autoscaleMargin: null, // margin in % to add if auto-setting min/max + ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks + tickFormatter: null, // fn: number -> string + labelWidth: null, // size of tick labels in pixels + labelHeight: null, + + // mode specific options + tickDecimals: null, // no. of decimals, null means auto + tickSize: null, // number or [number, "unit"] + minTickSize: null, // number or [number, "unit"] + monthNames: null, // list of names of months + timeformat: null, // format string to use + twelveHourClock: false // 12 or 24 time in time mode + }, + yaxis: { + autoscaleMargin: 0.02 + }, + x2axis: { + autoscaleMargin: null + }, + y2axis: { + autoscaleMargin: 0.02 + }, + series: { + points: { + show: false, + radius: 3, + lineWidth: 2, // in pixels + fill: true, + fillColor: "#ffffff" + }, + lines: { + // we don't put in show: false so we can see + // whether lines were actively disabled + lineWidth: 2, // in pixels + fill: false, + fillColor: null, + steps: false + }, + bars: { + show: false, + lineWidth: 2, // in pixels + barWidth: 1, // in units of the x axis + fill: true, + fillColor: null, + align: "left", // or "center" + horizontal: false // when horizontal, left is now top + }, + shadowSize: 3 + }, + grid: { + show: true, + aboveData: false, + color: "#545454", // primary color used for outline and labels + backgroundColor: null, // null for transparent, else color + tickColor: "rgba(0,0,0,0.15)", // color used for the ticks + labelMargin: 5, // in pixels + borderWidth: 2, // in pixels + borderColor: null, // set if different from the grid color + markings: null, // array of ranges or fn: axes -> array of ranges + markingsColor: "#f4f4f4", + markingsLineWidth: 2, + // interactive stuff + clickable: false, + hoverable: false, + autoHighlight: true, // highlight in case mouse is near + mouseActiveRadius: 10 // how far the mouse can be away to activate an item + }, + hooks: {} + }, + canvas = null, // the canvas for the plot itself + overlay = null, // canvas for interactive stuff on top of plot + eventHolder = null, // jQuery object that events should be bound to + ctx = null, octx = null, + axes = { xaxis: {}, yaxis: {}, x2axis: {}, y2axis: {} }, + plotOffset = { left: 0, right: 0, top: 0, bottom: 0}, + canvasWidth = 0, canvasHeight = 0, + plotWidth = 0, plotHeight = 0, + hooks = { + processOptions: [], + processRawData: [], + processDatapoints: [], + draw: [], + bindEvents: [], + drawOverlay: [] + }, + plot = this; + + // public functions + plot.setData = setData; + plot.setupGrid = setupGrid; + plot.draw = draw; + plot.getPlaceholder = function() { return placeholder; }; + plot.getCanvas = function() { return canvas; }; + plot.getPlotOffset = function() { return plotOffset; }; + plot.width = function () { return plotWidth; }; + plot.height = function () { return plotHeight; }; + plot.offset = function () { + var o = eventHolder.offset(); + o.left += plotOffset.left; + o.top += plotOffset.top; + return o; + }; + plot.getData = function() { return series; }; + plot.getAxes = function() { return axes; }; + plot.getOptions = function() { return options; }; + plot.highlight = highlight; + plot.unhighlight = unhighlight; + plot.triggerRedrawOverlay = triggerRedrawOverlay; + plot.pointOffset = function(point) { + return { left: parseInt(axisSpecToRealAxis(point, "xaxis").p2c(+point.x) + plotOffset.left), + top: parseInt(axisSpecToRealAxis(point, "yaxis").p2c(+point.y) + plotOffset.top) }; + }; + + + // public attributes + plot.hooks = hooks; + + // initialize + initPlugins(plot); + parseOptions(options_); + constructCanvas(); + setData(data_); + setupGrid(); + draw(); + bindEvents(); + + + function executeHooks(hook, args) { + args = [plot].concat(args); + for (var i = 0; i < hook.length; ++i) + hook[i].apply(this, args); + } + + function initPlugins() { + for (var i = 0; i < plugins.length; ++i) { + var p = plugins[i]; + p.init(plot); + if (p.options) + $.extend(true, options, p.options); + } + } + + function parseOptions(opts) { + $.extend(true, options, opts); + if (options.grid.borderColor == null) + options.grid.borderColor = options.grid.color; + // backwards compatibility, to be removed in future + if (options.xaxis.noTicks && options.xaxis.ticks == null) + options.xaxis.ticks = options.xaxis.noTicks; + if (options.yaxis.noTicks && options.yaxis.ticks == null) + options.yaxis.ticks = options.yaxis.noTicks; + if (options.grid.coloredAreas) + options.grid.markings = options.grid.coloredAreas; + if (options.grid.coloredAreasColor) + options.grid.markingsColor = options.grid.coloredAreasColor; + if (options.lines) + $.extend(true, options.series.lines, options.lines); + if (options.points) + $.extend(true, options.series.points, options.points); + if (options.bars) + $.extend(true, options.series.bars, options.bars); + if (options.shadowSize) + options.series.shadowSize = options.shadowSize; + + for (var n in hooks) + if (options.hooks[n] && options.hooks[n].length) + hooks[n] = hooks[n].concat(options.hooks[n]); + + executeHooks(hooks.processOptions, [options]); + } + + function setData(d) { + series = parseData(d); + fillInSeriesOptions(); + processData(); + } + + function parseData(d) { + var res = []; + for (var i = 0; i < d.length; ++i) { + var s = $.extend(true, {}, options.series); + + if (d[i].data) { + s.data = d[i].data; // move the data instead of deep-copy + delete d[i].data; + + $.extend(true, s, d[i]); + + d[i].data = s.data; + } + else + s.data = d[i]; + res.push(s); + } + + return res; + } + + function axisSpecToRealAxis(obj, attr) { + var a = obj[attr]; + if (!a || a == 1) + return axes[attr]; + if (typeof a == "number") + return axes[attr.charAt(0) + a + attr.slice(1)]; + return a; // assume it's OK + } + + function fillInSeriesOptions() { + var i; + + // collect what we already got of colors + var neededColors = series.length, + usedColors = [], + assignedColors = []; + for (i = 0; i < series.length; ++i) { + var sc = series[i].color; + if (sc != null) { + --neededColors; + if (typeof sc == "number") + assignedColors.push(sc); + else + usedColors.push($.color.parse(series[i].color)); + } + } + + // we might need to generate more colors if higher indices + // are assigned + for (i = 0; i < assignedColors.length; ++i) { + neededColors = Math.max(neededColors, assignedColors[i] + 1); + } + + // produce colors as needed + var colors = [], variation = 0; + i = 0; + while (colors.length < neededColors) { + var c; + if (options.colors.length == i) // check degenerate case + c = $.color.make(100, 100, 100); + else + c = $.color.parse(options.colors[i]); + + // vary color if needed + var sign = variation % 2 == 1 ? -1 : 1; + c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2) + + // FIXME: if we're getting to close to something else, + // we should probably skip this one + colors.push(c); + + ++i; + if (i >= options.colors.length) { + i = 0; + ++variation; + } + } + + // fill in the options + var colori = 0, s; + for (i = 0; i < series.length; ++i) { + s = series[i]; + + // assign colors + if (s.color == null) { + s.color = colors[colori].toString(); + ++colori; + } + else if (typeof s.color == "number") + s.color = colors[s.color].toString(); + + // turn on lines automatically in case nothing is set + if (s.lines.show == null) { + var v, show = true; + for (v in s) + if (s[v].show) { + show = false; + break; + } + if (show) + s.lines.show = true; + } + + // setup axes + s.xaxis = axisSpecToRealAxis(s, "xaxis"); + s.yaxis = axisSpecToRealAxis(s, "yaxis"); + } + } + + function processData() { + var topSentry = Number.POSITIVE_INFINITY, + bottomSentry = Number.NEGATIVE_INFINITY, + i, j, k, m, length, + s, points, ps, x, y, axis, val, f, p; + + for (axis in axes) { + axes[axis].datamin = topSentry; + axes[axis].datamax = bottomSentry; + axes[axis].used = false; + } + + function updateAxis(axis, min, max) { + if (min < axis.datamin) + axis.datamin = min; + if (max > axis.datamax) + axis.datamax = max; + } + + for (i = 0; i < series.length; ++i) { + s = series[i]; + s.datapoints = { points: [] }; + + executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]); + } + + // first pass: clean and copy data + for (i = 0; i < series.length; ++i) { + s = series[i]; + + var data = s.data, format = s.datapoints.format; + + if (!format) { + format = []; + // find out how to copy + format.push({ x: true, number: true, required: true }); + format.push({ y: true, number: true, required: true }); + + if (s.bars.show) + format.push({ y: true, number: true, required: false, defaultValue: 0 }); + + s.datapoints.format = format; + } + + if (s.datapoints.pointsize != null) + continue; // already filled in + + if (s.datapoints.pointsize == null) + s.datapoints.pointsize = format.length; + + ps = s.datapoints.pointsize; + points = s.datapoints.points; + + insertSteps = s.lines.show && s.lines.steps; + s.xaxis.used = s.yaxis.used = true; + + for (j = k = 0; j < data.length; ++j, k += ps) { + p = data[j]; + + var nullify = p == null; + if (!nullify) { + for (m = 0; m < ps; ++m) { + val = p[m]; + f = format[m]; + + if (f) { + if (f.number && val != null) { + val = +val; // convert to number + if (isNaN(val)) + val = null; + } + + if (val == null) { + if (f.required) + nullify = true; + + if (f.defaultValue != null) + val = f.defaultValue; + } + } + + points[k + m] = val; + } + } + + if (nullify) { + for (m = 0; m < ps; ++m) { + val = points[k + m]; + if (val != null) { + f = format[m]; + // extract min/max info + if (f.x) + updateAxis(s.xaxis, val, val); + if (f.y) + updateAxis(s.yaxis, val, val); + } + points[k + m] = null; + } + } + else { + // a little bit of line specific stuff that + // perhaps shouldn't be here, but lacking + // better means... + if (insertSteps && k > 0 + && points[k - ps] != null + && points[k - ps] != points[k] + && points[k - ps + 1] != points[k + 1]) { + // copy the point to make room for a middle point + for (m = 0; m < ps; ++m) + points[k + ps + m] = points[k + m]; + + // middle point has same y + points[k + 1] = points[k - ps + 1]; + + // we've added a point, better reflect that + k += ps; + } + } + } + } + + // give the hooks a chance to run + for (i = 0; i < series.length; ++i) { + s = series[i]; + + executeHooks(hooks.processDatapoints, [ s, s.datapoints]); + } + + // second pass: find datamax/datamin for auto-scaling + for (i = 0; i < series.length; ++i) { + s = series[i]; + points = s.datapoints.points, + ps = s.datapoints.pointsize; + + var xmin = topSentry, ymin = topSentry, + xmax = bottomSentry, ymax = bottomSentry; + + for (j = 0; j < points.length; j += ps) { + if (points[j] == null) + continue; + + for (m = 0; m < ps; ++m) { + val = points[j + m]; + f = format[m]; + if (!f) + continue; + + if (f.x) { + if (val < xmin) + xmin = val; + if (val > xmax) + xmax = val; + } + if (f.y) { + if (val < ymin) + ymin = val; + if (val > ymax) + ymax = val; + } + } + } + + if (s.bars.show) { + // make sure we got room for the bar on the dancing floor + var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2; + if (s.bars.horizontal) { + ymin += delta; + ymax += delta + s.bars.barWidth; + } + else { + xmin += delta; + xmax += delta + s.bars.barWidth; + } + } + + updateAxis(s.xaxis, xmin, xmax); + updateAxis(s.yaxis, ymin, ymax); + } + + for (axis in axes) { + if (axes[axis].datamin == topSentry) + axes[axis].datamin = null; + if (axes[axis].datamax == bottomSentry) + axes[axis].datamax = null; + } + } + + function constructCanvas() { + function makeCanvas(width, height) { + var c = document.createElement('canvas'); + c.width = width; + c.height = height; + if ($.browser.msie) // excanvas hack + c = window.G_vmlCanvasManager.initElement(c); + return c; + } + + canvasWidth = placeholder.width(); + canvasHeight = placeholder.height(); + placeholder.html(""); // clear placeholder + if (placeholder.css("position") == 'static') + placeholder.css("position", "relative"); // for positioning labels and overlay + + if (canvasWidth <= 0 || canvasHeight <= 0) + throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight; + + if ($.browser.msie) // excanvas hack + window.G_vmlCanvasManager.init_(document); // make sure everything is setup + + // the canvas + canvas = $(makeCanvas(canvasWidth, canvasHeight)).appendTo(placeholder).get(0); + ctx = canvas.getContext("2d"); + + // overlay canvas for interactive features + overlay = $(makeCanvas(canvasWidth, canvasHeight)).css({ position: 'absolute', left: 0, top: 0 }).appendTo(placeholder).get(0); + octx = overlay.getContext("2d"); + octx.stroke(); + } + + function bindEvents() { + // we include the canvas in the event holder too, because IE 7 + // sometimes has trouble with the stacking order + eventHolder = $([overlay, canvas]); + + // bind events + if (options.grid.hoverable) + eventHolder.mousemove(onMouseMove); + + if (options.grid.clickable) + eventHolder.click(onClick); + + executeHooks(hooks.bindEvents, [eventHolder]); + } + + function setupGrid() { + function setTransformationHelpers(axis, o) { + function identity(x) { return x; } + + var s, m, t = o.transform || identity, + it = o.inverseTransform; + + // add transformation helpers + if (axis == axes.xaxis || axis == axes.x2axis) { + // precompute how much the axis is scaling a point + // in canvas space + s = axis.scale = plotWidth / (t(axis.max) - t(axis.min)); + m = t(axis.min); + + // data point to canvas coordinate + if (t == identity) // slight optimization + axis.p2c = function (p) { return (p - m) * s; }; + else + axis.p2c = function (p) { return (t(p) - m) * s; }; + // canvas coordinate to data point + if (!it) + axis.c2p = function (c) { return m + c / s; }; + else + axis.c2p = function (c) { return it(m + c / s); }; + } + else { + s = axis.scale = plotHeight / (t(axis.max) - t(axis.min)); + m = t(axis.max); + + if (t == identity) + axis.p2c = function (p) { return (m - p) * s; }; + else + axis.p2c = function (p) { return (m - t(p)) * s; }; + if (!it) + axis.c2p = function (c) { return m - c / s; }; + else + axis.c2p = function (c) { return it(m - c / s); }; + } + } + + function measureLabels(axis, axisOptions) { + var i, labels = [], l; + + axis.labelWidth = axisOptions.labelWidth; + axis.labelHeight = axisOptions.labelHeight; + + if (axis == axes.xaxis || axis == axes.x2axis) { + // to avoid measuring the widths of the labels, we + // construct fixed-size boxes and put the labels inside + // them, we don't need the exact figures and the + // fixed-size box content is easy to center + if (axis.labelWidth == null) + axis.labelWidth = canvasWidth / (axis.ticks.length > 0 ? axis.ticks.length : 1); + + // measure x label heights + if (axis.labelHeight == null) { + labels = []; + for (i = 0; i < axis.ticks.length; ++i) { + l = axis.ticks[i].label; + if (l) + labels.push('<div class="tickLabel" style="float:left;width:' + axis.labelWidth + 'px">' + l + '</div>'); + } + + if (labels.length > 0) { + var dummyDiv = $('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">' + + labels.join("") + '<div style="clear:left"></div></div>').appendTo(placeholder); + axis.labelHeight = dummyDiv.height(); + dummyDiv.remove(); + } + } + } + else if (axis.labelWidth == null || axis.labelHeight == null) { + // calculate y label dimensions + for (i = 0; i < axis.ticks.length; ++i) { + l = axis.ticks[i].label; + if (l) + labels.push('<div class="tickLabel">' + l + '</div>'); + } + + if (labels.length > 0) { + var dummyDiv = $('<div style="position:absolute;top:-10000px;font-size:smaller">' + + labels.join("") + '</div>').appendTo(placeholder); + if (axis.labelWidth == null) + axis.labelWidth = dummyDiv.width(); + if (axis.labelHeight == null) + axis.labelHeight = dummyDiv.find("div").height(); + dummyDiv.remove(); + } + + } + + if (axis.labelWidth == null) + axis.labelWidth = 0; + if (axis.labelHeight == null) + axis.labelHeight = 0; + } + + function setGridSpacing() { + // get the most space needed around the grid for things + // that may stick out + var maxOutset = options.grid.borderWidth; + for (i = 0; i < series.length; ++i) + maxOutset = Math.max(maxOutset, 2 * (series[i].points.radius + series[i].points.lineWidth/2)); + + plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = maxOutset; + + var margin = options.grid.labelMargin + options.grid.borderWidth; + + if (axes.xaxis.labelHeight > 0) + plotOffset.bottom = Math.max(maxOutset, axes.xaxis.labelHeight + margin); + if (axes.yaxis.labelWidth > 0) + plotOffset.left = Math.max(maxOutset, axes.yaxis.labelWidth + margin); + if (axes.x2axis.labelHeight > 0) + plotOffset.top = Math.max(maxOutset, axes.x2axis.labelHeight + margin); + if (axes.y2axis.labelWidth > 0) + plotOffset.right = Math.max(maxOutset, axes.y2axis.labelWidth + margin); + + plotWidth = canvasWidth - plotOffset.left - plotOffset.right; + plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top; + } + + var axis; + for (axis in axes) + setRange(axes[axis], options[axis]); + + if (options.grid.show) { + for (axis in axes) { + prepareTickGeneration(axes[axis], options[axis]); + setTicks(axes[axis], options[axis]); + measureLabels(axes[axis], options[axis]); + } + + setGridSpacing(); + } + else { + plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0; + plotWidth = canvasWidth; + plotHeight = canvasHeight; + } + + for (axis in axes) + setTransformationHelpers(axes[axis], options[axis]); + + if (options.grid.show) + insertLabels(); + + insertLegend(); + } + + function setRange(axis, axisOptions) { + var min = +(axisOptions.min != null ? axisOptions.min : axis.datamin), + max = +(axisOptions.max != null ? axisOptions.max : axis.datamax), + delta = max - min; + + if (delta == 0.0) { + // degenerate case + var widen = max == 0 ? 1 : 0.01; + + if (axisOptions.min == null) + min -= widen; + // alway widen max if we couldn't widen min to ensure we + // don't fall into min == max which doesn't work + if (axisOptions.max == null || axisOptions.min != null) + max += widen; + } + else { + // consider autoscaling + var margin = axisOptions.autoscaleMargin; + if (margin != null) { + if (axisOptions.min == null) { + min -= delta * margin; + // make sure we don't go below zero if all values + // are positive + if (min < 0 && axis.datamin != null && axis.datamin >= 0) + min = 0; + } + if (axisOptions.max == null) { + max += delta * margin; + if (max > 0 && axis.datamax != null && axis.datamax <= 0) + max = 0; + } + } + } + axis.min = min; + axis.max = max; + } + + function prepareTickGeneration(axis, axisOptions) { + // estimate number of ticks + var noTicks; + if (typeof axisOptions.ticks == "number" && axisOptions.ticks > 0) + noTicks = axisOptions.ticks; + else if (axis == axes.xaxis || axis == axes.x2axis) + // heuristic based on the model a*sqrt(x) fitted to + // some reasonable data points + noTicks = 0.3 * Math.sqrt(canvasWidth); + else + noTicks = 0.3 * Math.sqrt(canvasHeight); + + var delta = (axis.max - axis.min) / noTicks, + size, generator, unit, formatter, i, magn, norm; + + if (axisOptions.mode == "time") { + // pretty handling of time + + // map of app. size of time units in milliseconds + var timeUnitSize = { + "second": 1000, + "minute": 60 * 1000, + "hour": 60 * 60 * 1000, + "day": 24 * 60 * 60 * 1000, + "month": 30 * 24 * 60 * 60 * 1000, + "year": 365.2425 * 24 * 60 * 60 * 1000 + }; + + + // the allowed tick sizes, after 1 year we use + // an integer algorithm + var spec = [ + [1, "second"], [2, "second"], [5, "second"], [10, "second"], + [30, "second"], + [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"], + [30, "minute"], + [1, "hour"], [2, "hour"], [4, "hour"], + [8, "hour"], [12, "hour"], + [1, "day"], [2, "day"], [3, "day"], + [0.25, "month"], [0.5, "month"], [1, "month"], + [2, "month"], [3, "month"], [6, "month"], + [1, "year"] + ]; + + var minSize = 0; + if (axisOptions.minTickSize != null) { + if (typeof axisOptions.tickSize == "number") + minSize = axisOptions.tickSize; + else + minSize = axisOptions.minTickSize[0] * timeUnitSize[axisOptions.minTickSize[1]]; + } + + for (i = 0; i < spec.length - 1; ++i) + if (delta < (spec[i][0] * timeUnitSize[spec[i][1]] + + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2 + && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) + break; + size = spec[i][0]; + unit = spec[i][1]; + + // special-case the possibility of several years + if (unit == "year") { + magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10)); + norm = (delta / timeUnitSize.year) / magn; + if (norm < 1.5) + size = 1; + else if (norm < 3) + size = 2; + else if (norm < 7.5) + size = 5; + else + size = 10; + + size *= magn; + } + + if (axisOptions.tickSize) { + size = axisOptions.tickSize[0]; + unit = axisOptions.tickSize[1]; + } + + generator = function(axis) { + var ticks = [], + tickSize = axis.tickSize[0], unit = axis.tickSize[1], + d = new Date(axis.min); + + var step = tickSize * timeUnitSize[unit]; + + if (unit == "second") + d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize)); + if (unit == "minute") + d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize)); + if (unit == "hour") + d.setUTCHours(floorInBase(d.getUTCHours(), tickSize)); + if (unit == "month") + d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize)); + if (unit == "year") + d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize)); + + // reset smaller components + d.setUTCMilliseconds(0); + if (step >= timeUnitSize.minute) + d.setUTCSeconds(0); + if (step >= timeUnitSize.hour) + d.setUTCMinutes(0); + if (step >= timeUnitSize.day) + d.setUTCHours(0); + if (step >= timeUnitSize.day * 4) + d.setUTCDate(1); + if (step >= timeUnitSize.year) + d.setUTCMonth(0); + + + var carry = 0, v = Number.NaN, prev; + do { + prev = v; + v = d.getTime(); + ticks.push({ v: v, label: axis.tickFormatter(v, axis) }); + if (unit == "month") { + if (tickSize < 1) { + // a bit complicated - we'll divide the month + // up but we need to take care of fractions + // so we don't end up in the middle of a day + d.setUTCDate(1); + var start = d.getTime(); + d.setUTCMonth(d.getUTCMonth() + 1); + var end = d.getTime(); + d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize); + carry = d.getUTCHours(); + d.setUTCHours(0); + } + else + d.setUTCMonth(d.getUTCMonth() + tickSize); + } + else if (unit == "year") { + d.setUTCFullYear(d.getUTCFullYear() + tickSize); + } + else + d.setTime(v + step); + } while (v < axis.max && v != prev); + + return ticks; + }; + + formatter = function (v, axis) { + var d = new Date(v); + + // first check global format + if (axisOptions.timeformat != null) + return $.plot.formatDate(d, axisOptions.timeformat, axisOptions.monthNames); + + var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]]; + var span = axis.max - axis.min; + var suffix = (axisOptions.twelveHourClock) ? " %p" : ""; + + if (t < timeUnitSize.minute) + fmt = "%h:%M:%S" + suffix; + else if (t < timeUnitSize.day) { + if (span < 2 * timeUnitSize.day) + fmt = "%h:%M" + suffix; + else + fmt = "%b %d %h:%M" + suffix; + } + else if (t < timeUnitSize.month) + fmt = "%b %d"; + else if (t < timeUnitSize.year) { + if (span < timeUnitSize.year) + fmt = "%b"; + else + fmt = "%b %y"; + } + else + fmt = "%y"; + + return $.plot.formatDate(d, fmt, axisOptions.monthNames); + }; + } + else { + // pretty rounding of base-10 numbers + var maxDec = axisOptions.tickDecimals; + var dec = -Math.floor(Math.log(delta) / Math.LN10); + if (maxDec != null && dec > maxDec) + dec = maxDec; + + magn = Math.pow(10, -dec); + norm = delta / magn; // norm is between 1.0 and 10.0 + + if (norm < 1.5) + size = 1; + else if (norm < 3) { + size = 2; + // special case for 2.5, requires an extra decimal + if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) { + size = 2.5; + ++dec; + } + } + else if (norm < 7.5) + size = 5; + else + size = 10; + + size *= magn; + + if (axisOptions.minTickSize != null && size < axisOptions.minTickSize) + size = axisOptions.minTickSize; + + if (axisOptions.tickSize != null) + size = axisOptions.tickSize; + + axis.tickDecimals = Math.max(0, (maxDec != null) ? maxDec : dec); + + generator = function (axis) { + var ticks = []; + + // spew out all possible ticks + var start = floorInBase(axis.min, axis.tickSize), + i = 0, v = Number.NaN, prev; + do { + prev = v; + v = start + i * axis.tickSize; + ticks.push({ v: v, label: axis.tickFormatter(v, axis) }); + ++i; + } while (v < axis.max && v != prev); + return ticks; + }; + + formatter = function (v, axis) { + return v.toFixed(axis.tickDecimals); + }; + } + + axis.tickSize = unit ? [size, unit] : size; + axis.tickGenerator = generator; + if ($.isFunction(axisOptions.tickFormatter)) + axis.tickFormatter = function (v, axis) { return "" + axisOptions.tickFormatter(v, axis); }; + else + axis.tickFormatter = formatter; + } + + function setTicks(axis, axisOptions) { + axis.ticks = []; + + if (!axis.used) + return; + + if (axisOptions.ticks == null) + axis.ticks = axis.tickGenerator(axis); + else if (typeof axisOptions.ticks == "number") { + if (axisOptions.ticks > 0) + axis.ticks = axis.tickGenerator(axis); + } + else if (axisOptions.ticks) { + var ticks = axisOptions.ticks; + + if ($.isFunction(ticks)) + // generate the ticks + ticks = ticks({ min: axis.min, max: axis.max }); + + // clean up the user-supplied ticks, copy them over + var i, v; + for (i = 0; i < ticks.length; ++i) { + var label = null; + var t = ticks[i]; + if (typeof t == "object") { + v = t[0]; + if (t.length > 1) + label = t[1]; + } + else + v = t; + if (label == null) + label = axis.tickFormatter(v, axis); + axis.ticks[i] = { v: v, label: label }; + } + } + + if (axisOptions.autoscaleMargin != null && axis.ticks.length > 0) { + // snap to ticks + if (axisOptions.min == null) + axis.min = Math.min(axis.min, axis.ticks[0].v); + if (axisOptions.max == null && axis.ticks.length > 1) + axis.max = Math.max(axis.max, axis.ticks[axis.ticks.length - 1].v); + } + } + + function draw() { + ctx.clearRect(0, 0, canvasWidth, canvasHeight); + + var grid = options.grid; + + if (grid.show && !grid.aboveData) + drawGrid(); + + for (var i = 0; i < series.length; ++i) + drawSeries(series[i]); + + executeHooks(hooks.draw, [ctx]); + + if (grid.show && grid.aboveData) + drawGrid(); + } + + function extractRange(ranges, coord) { + var firstAxis = coord + "axis", + secondaryAxis = coord + "2axis", + axis, from, to, reverse; + + if (ranges[firstAxis]) { + axis = axes[firstAxis]; + from = ranges[firstAxis].from; + to = ranges[firstAxis].to; + } + else if (ranges[secondaryAxis]) { + axis = axes[secondaryAxis]; + from = ranges[secondaryAxis].from; + to = ranges[secondaryAxis].to; + } + else { + // backwards-compat stuff - to be removed in future + axis = axes[firstAxis]; + from = ranges[coord + "1"]; + to = ranges[coord + "2"]; + } + + // auto-reverse as an added bonus + if (from != null && to != null && from > to) + return { from: to, to: from, axis: axis }; + + return { from: from, to: to, axis: axis }; + } + + function drawGrid() { + var i; + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + + // draw background, if any + if (options.grid.backgroundColor) { + ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)"); + ctx.fillRect(0, 0, plotWidth, plotHeight); + } + + // draw markings + var markings = options.grid.markings; + if (markings) { + if ($.isFunction(markings)) + // xmin etc. are backwards-compatible, to be removed in future + markings = markings({ xmin: axes.xaxis.min, xmax: axes.xaxis.max, ymin: axes.yaxis.min, ymax: axes.yaxis.max, xaxis: axes.xaxis, yaxis: axes.yaxis, x2axis: axes.x2axis, y2axis: axes.y2axis }); + + for (i = 0; i < markings.length; ++i) { + var m = markings[i], + xrange = extractRange(m, "x"), + yrange = extractRange(m, "y"); + + // fill in missing + if (xrange.from == null) + xrange.from = xrange.axis.min; + if (xrange.to == null) + xrange.to = xrange.axis.max; + if (yrange.from == null) + yrange.from = yrange.axis.min; + if (yrange.to == null) + yrange.to = yrange.axis.max; + + // clip + if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max || + yrange.to < yrange.axis.min || yrange.from > yrange.axis.max) + continue; + + xrange.from = Math.max(xrange.from, xrange.axis.min); + xrange.to = Math.min(xrange.to, xrange.axis.max); + yrange.from = Math.max(yrange.from, yrange.axis.min); + yrange.to = Math.min(yrange.to, yrange.axis.max); + + if (xrange.from == xrange.to && yrange.from == yrange.to) + continue; + + // then draw + xrange.from = xrange.axis.p2c(xrange.from); + xrange.to = xrange.axis.p2c(xrange.to); + yrange.from = yrange.axis.p2c(yrange.from); + yrange.to = yrange.axis.p2c(yrange.to); + + if (xrange.from == xrange.to || yrange.from == yrange.to) { + // draw line + ctx.beginPath(); + ctx.strokeStyle = m.color || options.grid.markingsColor; + ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth; + //ctx.moveTo(Math.floor(xrange.from), yrange.from); + //ctx.lineTo(Math.floor(xrange.to), yrange.to); + ctx.moveTo(xrange.from, yrange.from); + ctx.lineTo(xrange.to, yrange.to); + ctx.stroke(); + } + else { + // fill area + ctx.fillStyle = m.color || options.grid.markingsColor; + ctx.fillRect(xrange.from, yrange.to, + xrange.to - xrange.from, + yrange.from - yrange.to); + } + } + } + + // draw the inner grid + ctx.lineWidth = 1; + ctx.strokeStyle = options.grid.tickColor; + ctx.beginPath(); + var v, axis = axes.xaxis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axes.xaxis.max) + continue; // skip those lying on the axes + + ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 0); + ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, plotHeight); + } + + axis = axes.yaxis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axis.max) + continue; + + ctx.moveTo(0, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + ctx.lineTo(plotWidth, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + } + + axis = axes.x2axis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axis.max) + continue; + + ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, -5); + ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 5); + } + + axis = axes.y2axis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axis.max) + continue; + + ctx.moveTo(plotWidth-5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + ctx.lineTo(plotWidth+5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + } + + ctx.stroke(); + + if (options.grid.borderWidth) { + // draw border + var bw = options.grid.borderWidth; + ctx.lineWidth = bw; + ctx.strokeStyle = options.grid.borderColor; + ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw); + } + + ctx.restore(); + } + + function insertLabels() { + placeholder.find(".tickLabels").remove(); + + var html = ['<div class="tickLabels" style="font-size:smaller;color:' + options.grid.color + '">']; + + function addLabels(axis, labelGenerator) { + for (var i = 0; i < axis.ticks.length; ++i) { + var tick = axis.ticks[i]; + if (!tick.label || tick.v < axis.min || tick.v > axis.max) + continue; + html.push(labelGenerator(tick, axis)); + } + } + + var margin = options.grid.labelMargin + options.grid.borderWidth; + + addLabels(axes.xaxis, function (tick, axis) { + return '<div style="position:absolute;top:' + (plotOffset.top + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>"; + }); + + + addLabels(axes.yaxis, function (tick, axis) { + return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;right:' + (plotOffset.right + plotWidth + margin) + 'px;width:' + axis.labelWidth + 'px;text-align:right" class="tickLabel">' + tick.label + "</div>"; + }); + + addLabels(axes.x2axis, function (tick, axis) { + return '<div style="position:absolute;bottom:' + (plotOffset.bottom + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>"; + }); + + addLabels(axes.y2axis, function (tick, axis) { + return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;left:' + (plotOffset.left + plotWidth + margin) +'px;width:' + axis.labelWidth + 'px;text-align:left" class="tickLabel">' + tick.label + "</div>"; + }); + + html.push('</div>'); + + placeholder.append(html.join("")); + } + + function drawSeries(series) { + if (series.lines.show) + drawSeriesLines(series); + if (series.bars.show) + drawSeriesBars(series); + if (series.points.show) + drawSeriesPoints(series); + } + + function drawSeriesLines(series) { + function plotLine(datapoints, xoffset, yoffset, axisx, axisy) { + var points = datapoints.points, + ps = datapoints.pointsize, + prevx = null, prevy = null; + + ctx.beginPath(); + for (var i = ps; i < points.length; i += ps) { + var x1 = points[i - ps], y1 = points[i - ps + 1], + x2 = points[i], y2 = points[i + 1]; + + if (x1 == null || x2 == null) + continue; + + // clip with ymin + if (y1 <= y2 && y1 < axisy.min) { + if (y2 < axisy.min) + continue; // line segment is outside + // compute new intersection point + x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.min; + } + else if (y2 <= y1 && y2 < axisy.min) { + if (y1 < axisy.min) + continue; + x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.min; + } + + // clip with ymax + if (y1 >= y2 && y1 > axisy.max) { + if (y2 > axisy.max) + continue; + x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.max; + } + else if (y2 >= y1 && y2 > axisy.max) { + if (y1 > axisy.max) + continue; + x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.max; + } + + // clip with xmin + if (x1 <= x2 && x1 < axisx.min) { + if (x2 < axisx.min) + continue; + y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.min; + } + else if (x2 <= x1 && x2 < axisx.min) { + if (x1 < axisx.min) + continue; + y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.min; + } + + // clip with xmax + if (x1 >= x2 && x1 > axisx.max) { + if (x2 > axisx.max) + continue; + y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.max; + } + else if (x2 >= x1 && x2 > axisx.max) { + if (x1 > axisx.max) + continue; + y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.max; + } + + if (x1 != prevx || y1 != prevy) + ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset); + + prevx = x2; + prevy = y2; + ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset); + } + ctx.stroke(); + } + + function plotLineArea(datapoints, axisx, axisy) { + var points = datapoints.points, + ps = datapoints.pointsize, + bottom = Math.min(Math.max(0, axisy.min), axisy.max), + top, lastX = 0, areaOpen = false; + + for (var i = ps; i < points.length; i += ps) { + var x1 = points[i - ps], y1 = points[i - ps + 1], + x2 = points[i], y2 = points[i + 1]; + + if (areaOpen && x1 != null && x2 == null) { + // close area + ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom)); + ctx.fill(); + areaOpen = false; + continue; + } + + if (x1 == null || x2 == null) + continue; + + // clip x values + + // clip with xmin + if (x1 <= x2 && x1 < axisx.min) { + if (x2 < axisx.min) + continue; + y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.min; + } + else if (x2 <= x1 && x2 < axisx.min) { + if (x1 < axisx.min) + continue; + y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.min; + } + + // clip with xmax + if (x1 >= x2 && x1 > axisx.max) { + if (x2 > axisx.max) + continue; + y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.max; + } + else if (x2 >= x1 && x2 > axisx.max) { + if (x1 > axisx.max) + continue; + y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.max; + } + + if (!areaOpen) { + // open area + ctx.beginPath(); + ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom)); + areaOpen = true; + } + + // now first check the case where both is outside + if (y1 >= axisy.max && y2 >= axisy.max) { + ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max)); + ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max)); + lastX = x2; + continue; + } + else if (y1 <= axisy.min && y2 <= axisy.min) { + ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min)); + ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min)); + lastX = x2; + continue; + } + + // else it's a bit more complicated, there might + // be two rectangles and two triangles we need to fill + // in; to find these keep track of the current x values + var x1old = x1, x2old = x2; + + // and clip the y values, without shortcutting + + // clip with ymin + if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) { + x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.min; + } + else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) { + x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.min; + } + + // clip with ymax + if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) { + x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.max; + } + else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) { + x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.max; + } + + + // if the x value was changed we got a rectangle + // to fill + if (x1 != x1old) { + if (y1 <= axisy.min) + top = axisy.min; + else + top = axisy.max; + + ctx.lineTo(axisx.p2c(x1old), axisy.p2c(top)); + ctx.lineTo(axisx.p2c(x1), axisy.p2c(top)); + } + + // fill the triangles + ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1)); + ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2)); + + // fill the other rectangle if it's there + if (x2 != x2old) { + if (y2 <= axisy.min) + top = axisy.min; + else + top = axisy.max; + + ctx.lineTo(axisx.p2c(x2), axisy.p2c(top)); + ctx.lineTo(axisx.p2c(x2old), axisy.p2c(top)); + } + + lastX = Math.max(x2, x2old); + } + + if (areaOpen) { + ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom)); + ctx.fill(); + } + } + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + ctx.lineJoin = "round"; + + var lw = series.lines.lineWidth, + sw = series.shadowSize; + // FIXME: consider another form of shadow when filling is turned on + if (lw > 0 && sw > 0) { + // draw shadow as a thick and thin line with transparency + ctx.lineWidth = sw; + ctx.strokeStyle = "rgba(0,0,0,0.1)"; + // position shadow at angle from the mid of line + var angle = Math.PI/18; + plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis); + ctx.lineWidth = sw/2; + plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis); + } + + ctx.lineWidth = lw; + ctx.strokeStyle = series.color; + var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight); + if (fillStyle) { + ctx.fillStyle = fillStyle; + plotLineArea(series.datapoints, series.xaxis, series.yaxis); + } + + if (lw > 0) + plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis); + ctx.restore(); + } + + function drawSeriesPoints(series) { + function plotPoints(datapoints, radius, fillStyle, offset, circumference, axisx, axisy) { + var points = datapoints.points, ps = datapoints.pointsize; + + for (var i = 0; i < points.length; i += ps) { + var x = points[i], y = points[i + 1]; + if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) + continue; + + ctx.beginPath(); + ctx.arc(axisx.p2c(x), axisy.p2c(y) + offset, radius, 0, circumference, false); + if (fillStyle) { + ctx.fillStyle = fillStyle; + ctx.fill(); + } + ctx.stroke(); + } + } + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + + var lw = series.lines.lineWidth, + sw = series.shadowSize, + radius = series.points.radius; + if (lw > 0 && sw > 0) { + // draw shadow in two steps + var w = sw / 2; + ctx.lineWidth = w; + ctx.strokeStyle = "rgba(0,0,0,0.1)"; + plotPoints(series.datapoints, radius, null, w + w/2, Math.PI, + series.xaxis, series.yaxis); + + ctx.strokeStyle = "rgba(0,0,0,0.2)"; + plotPoints(series.datapoints, radius, null, w/2, Math.PI, + series.xaxis, series.yaxis); + } + + ctx.lineWidth = lw; + ctx.strokeStyle = series.color; + plotPoints(series.datapoints, radius, + getFillStyle(series.points, series.color), 0, 2 * Math.PI, + series.xaxis, series.yaxis); + ctx.restore(); + } + + function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal) { + var left, right, bottom, top, + drawLeft, drawRight, drawTop, drawBottom, + tmp; + + if (horizontal) { + drawBottom = drawRight = drawTop = true; + drawLeft = false; + left = b; + right = x; + top = y + barLeft; + bottom = y + barRight; + + // account for negative bars + if (right < left) { + tmp = right; + right = left; + left = tmp; + drawLeft = true; + drawRight = false; + } + } + else { + drawLeft = drawRight = drawTop = true; + drawBottom = false; + left = x + barLeft; + right = x + barRight; + bottom = b; + top = y; + + // account for negative bars + if (top < bottom) { + tmp = top; + top = bottom; + bottom = tmp; + drawBottom = true; + drawTop = false; + } + } + + // clip + if (right < axisx.min || left > axisx.max || + top < axisy.min || bottom > axisy.max) + return; + + if (left < axisx.min) { + left = axisx.min; + drawLeft = false; + } + + if (right > axisx.max) { + right = axisx.max; + drawRight = false; + } + + if (bottom < axisy.min) { + bottom = axisy.min; + drawBottom = false; + } + + if (top > axisy.max) { + top = axisy.max; + drawTop = false; + } + + left = axisx.p2c(left); + bottom = axisy.p2c(bottom); + right = axisx.p2c(right); + top = axisy.p2c(top); + + // fill the bar + if (fillStyleCallback) { + c.beginPath(); + c.moveTo(left, bottom); + c.lineTo(left, top); + c.lineTo(right, top); + c.lineTo(right, bottom); + c.fillStyle = fillStyleCallback(bottom, top); + c.fill(); + } + + // draw outline + if (drawLeft || drawRight || drawTop || drawBottom) { + c.beginPath(); + + // FIXME: inline moveTo is buggy with excanvas + c.moveTo(left, bottom + offset); + if (drawLeft) + c.lineTo(left, top + offset); + else + c.moveTo(left, top + offset); + if (drawTop) + c.lineTo(right, top + offset); + else + c.moveTo(right, top + offset); + if (drawRight) + c.lineTo(right, bottom + offset); + else + c.moveTo(right, bottom + offset); + if (drawBottom) + c.lineTo(left, bottom + offset); + else + c.moveTo(left, bottom + offset); + c.stroke(); + } + } + + function drawSeriesBars(series) { + function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) { + var points = datapoints.points, ps = datapoints.pointsize; + + for (var i = 0; i < points.length; i += ps) { + if (points[i] == null) + continue; + drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal); + } + } + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + + // FIXME: figure out a way to add shadows (for instance along the right edge) + ctx.lineWidth = series.bars.lineWidth; + ctx.strokeStyle = series.color; + var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; + var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null; + plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis); + ctx.restore(); + } + + function getFillStyle(filloptions, seriesColor, bottom, top) { + var fill = filloptions.fill; + if (!fill) + return null; + + if (filloptions.fillColor) + return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor); + + var c = $.color.parse(seriesColor); + c.a = typeof fill == "number" ? fill : 0.4; + c.normalize(); + return c.toString(); + } + + function insertLegend() { + placeholder.find(".legend").remove(); + + if (!options.legend.show) + return; + + var fragments = [], rowStarted = false, + lf = options.legend.labelFormatter, s, label; + for (i = 0; i < series.length; ++i) { + s = series[i]; + label = s.label; + if (!label) + continue; + + if (i % options.legend.noColumns == 0) { + if (rowStarted) + fragments.push('</tr>'); + fragments.push('<tr>'); + rowStarted = true; + } + + if (lf) + label = lf(label, s); + + fragments.push( + '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + s.color + ';overflow:hidden"></div></div></td>' + + '<td class="legendLabel">' + label + '</td>'); + } + if (rowStarted) + fragments.push('</tr>'); + + if (fragments.length == 0) + return; + + var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>'; + if (options.legend.container != null) + $(options.legend.container).html(table); + else { + var pos = "", + p = options.legend.position, + m = options.legend.margin; + if (m[0] == null) + m = [m, m]; + if (p.charAt(0) == "n") + pos += 'top:' + (m[1] + plotOffset.top) + 'px;'; + else if (p.charAt(0) == "s") + pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;'; + if (p.charAt(1) == "e") + pos += 'right:' + (m[0] + plotOffset.right) + 'px;'; + else if (p.charAt(1) == "w") + pos += 'left:' + (m[0] + plotOffset.left) + 'px;'; + var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder); + if (options.legend.backgroundOpacity != 0.0) { + // put in the transparent background + // separately to avoid blended labels and + // label boxes + var c = options.legend.backgroundColor; + if (c == null) { + c = options.grid.backgroundColor; + if (c && typeof c == "string") + c = $.color.parse(c); + else + c = $.color.extract(legend, 'background-color'); + c.a = 1; + c = c.toString(); + } + var div = legend.children(); + $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity); + } + } + } + + + // interactive features + + var highlights = [], + redrawTimeout = null; + + // returns the data item the mouse is over, or null if none is found + function findNearbyItem(mouseX, mouseY, seriesFilter) { + var maxDistance = options.grid.mouseActiveRadius, + smallestDistance = maxDistance * maxDistance + 1, + item = null, foundPoint = false, i, j; + + for (i = 0; i < series.length; ++i) { + if (!seriesFilter(series[i])) + continue; + + var s = series[i], + axisx = s.xaxis, + axisy = s.yaxis, + points = s.datapoints.points, + ps = s.datapoints.pointsize, + mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster + my = axisy.c2p(mouseY), + maxx = maxDistance / axisx.scale, + maxy = maxDistance / axisy.scale; + + if (s.lines.show || s.points.show) { + for (j = 0; j < points.length; j += ps) { + var x = points[j], y = points[j + 1]; + if (x == null) + continue; + + // For points and lines, the cursor must be within a + // certain distance to the data point + if (x - mx > maxx || x - mx < -maxx || + y - my > maxy || y - my < -maxy) + continue; + + // We have to calculate distances in pixels, not in + // data units, because the scales of the axes may be different + var dx = Math.abs(axisx.p2c(x) - mouseX), + dy = Math.abs(axisy.p2c(y) - mouseY), + dist = dx * dx + dy * dy; // we save the sqrt + + // use <= to ensure last point takes precedence + // (last generally means on top of) + if (dist <= smallestDistance) { + smallestDistance = dist; + item = [i, j / ps]; + } + } + } + + if (s.bars.show && !item) { // no other point can be nearby + var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2, + barRight = barLeft + s.bars.barWidth; + + for (j = 0; j < points.length; j += ps) { + var x = points[j], y = points[j + 1], b = points[j + 2]; + if (x == null) + continue; + + // for a bar graph, the cursor must be inside the bar + if (series[i].bars.horizontal ? + (mx <= Math.max(b, x) && mx >= Math.min(b, x) && + my >= y + barLeft && my <= y + barRight) : + (mx >= x + barLeft && mx <= x + barRight && + my >= Math.min(b, y) && my <= Math.max(b, y))) + item = [i, j / ps]; + } + } + } + + if (item) { + i = item[0]; + j = item[1]; + ps = series[i].datapoints.pointsize; + + return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps), + dataIndex: j, + series: series[i], + seriesIndex: i }; + } + + return null; + } + + function onMouseMove(e) { + if (options.grid.hoverable) + triggerClickHoverEvent("plothover", e, + function (s) { return s["hoverable"] != false; }); + } + + function onClick(e) { + triggerClickHoverEvent("plotclick", e, + function (s) { return s["clickable"] != false; }); + } + + // trigger click or hover event (they send the same parameters + // so we share their code) + function triggerClickHoverEvent(eventname, event, seriesFilter) { + var offset = eventHolder.offset(), + pos = { pageX: event.pageX, pageY: event.pageY }, + canvasX = event.pageX - offset.left - plotOffset.left, + canvasY = event.pageY - offset.top - plotOffset.top; + + if (axes.xaxis.used) + pos.x = axes.xaxis.c2p(canvasX); + if (axes.yaxis.used) + pos.y = axes.yaxis.c2p(canvasY); + if (axes.x2axis.used) + pos.x2 = axes.x2axis.c2p(canvasX); + if (axes.y2axis.used) + pos.y2 = axes.y2axis.c2p(canvasY); + + var item = findNearbyItem(canvasX, canvasY, seriesFilter); + + if (item) { + // fill in mouse pos for any listeners out there + item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left); + item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top); + } + + if (options.grid.autoHighlight) { + // clear auto-highlights + for (var i = 0; i < highlights.length; ++i) { + var h = highlights[i]; + if (h.auto == eventname && + !(item && h.series == item.series && h.point == item.datapoint)) + unhighlight(h.series, h.point); + } + + if (item) + highlight(item.series, item.datapoint, eventname); + } + + placeholder.trigger(eventname, [ pos, item ]); + } + + function triggerRedrawOverlay() { + if (!redrawTimeout) + redrawTimeout = setTimeout(drawOverlay, 30); + } + + function drawOverlay() { + redrawTimeout = null; + + // draw highlights + octx.save(); + octx.clearRect(0, 0, canvasWidth, canvasHeight); + octx.translate(plotOffset.left, plotOffset.top); + + var i, hi; + for (i = 0; i < highlights.length; ++i) { + hi = highlights[i]; + + if (hi.series.bars.show) + drawBarHighlight(hi.series, hi.point); + else + drawPointHighlight(hi.series, hi.point); + } + octx.restore(); + + executeHooks(hooks.drawOverlay, [octx]); + } + + function highlight(s, point, auto) { + if (typeof s == "number") + s = series[s]; + + if (typeof point == "number") + point = s.data[point]; + + var i = indexOfHighlight(s, point); + if (i == -1) { + highlights.push({ series: s, point: point, auto: auto }); + + triggerRedrawOverlay(); + } + else if (!auto) + highlights[i].auto = false; + } + + function unhighlight(s, point) { + if (s == null && point == null) { + highlights = []; + triggerRedrawOverlay(); + } + + if (typeof s == "number") + s = series[s]; + + if (typeof point == "number") + point = s.data[point]; + + var i = indexOfHighlight(s, point); + if (i != -1) { + highlights.splice(i, 1); + + triggerRedrawOverlay(); + } + } + + function indexOfHighlight(s, p) { + for (var i = 0; i < highlights.length; ++i) { + var h = highlights[i]; + if (h.series == s && h.point[0] == p[0] + && h.point[1] == p[1]) + return i; + } + return -1; + } + + function drawPointHighlight(series, point) { + var x = point[0], y = point[1], + axisx = series.xaxis, axisy = series.yaxis; + + if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) + return; + + var pointRadius = series.points.radius + series.points.lineWidth / 2; + octx.lineWidth = pointRadius; + octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString(); + var radius = 1.5 * pointRadius; + octx.beginPath(); + octx.arc(axisx.p2c(x), axisy.p2c(y), radius, 0, 2 * Math.PI, false); + octx.stroke(); + } + + function drawBarHighlight(series, point) { + octx.lineWidth = series.bars.lineWidth; + octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString(); + var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString(); + var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; + drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth, + 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal); + } + + function getColorOrGradient(spec, bottom, top, defaultColor) { + if (typeof spec == "string") + return spec; + else { + // assume this is a gradient spec; IE currently only + // supports a simple vertical gradient properly, so that's + // what we support too + var gradient = ctx.createLinearGradient(0, top, 0, bottom); + + for (var i = 0, l = spec.colors.length; i < l; ++i) { + var c = spec.colors[i]; + if (typeof c != "string") { + c = $.color.parse(defaultColor).scale('rgb', c.brightness); + c.a *= c.opacity; + c = c.toString(); + } + gradient.addColorStop(i / (l - 1), c); + } + + return gradient; + } + } + } + + $.plot = function(placeholder, data, options) { + var plot = new Plot($(placeholder), data, options, $.plot.plugins); + /*var t0 = new Date(); + var t1 = new Date(); + var tstr = "time used (msecs): " + (t1.getTime() - t0.getTime()) + if (window.console) + console.log(tstr); + else + alert(tstr);*/ + return plot; + }; + + $.plot.plugins = []; + + // returns a string with the date d formatted according to fmt + $.plot.formatDate = function(d, fmt, monthNames) { + var leftPad = function(n) { + n = "" + n; + return n.length == 1 ? "0" + n : n; + }; + + var r = []; + var escape = false; + var hours = d.getUTCHours(); + var isAM = hours < 12; + if (monthNames == null) + monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + + if (fmt.search(/%p|%P/) != -1) { + if (hours > 12) { + hours = hours - 12; + } else if (hours == 0) { + hours = 12; + } + } + for (var i = 0; i < fmt.length; ++i) { + var c = fmt.charAt(i); + + if (escape) { + switch (c) { + case 'h': c = "" + hours; break; + case 'H': c = leftPad(hours); break; + case 'M': c = leftPad(d.getUTCMinutes()); break; + case 'S': c = leftPad(d.getUTCSeconds()); break; + case 'd': c = "" + d.getUTCDate(); break; + case 'm': c = "" + (d.getUTCMonth() + 1); break; + case 'y': c = "" + d.getUTCFullYear(); break; + case 'b': c = "" + monthNames[d.getUTCMonth()]; break; + case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break; + case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break; + } + r.push(c); + escape = false; + } + else { + if (c == "%") + escape = true; + else + r.push(c); + } + } + return r.join(""); + }; + + // round to nearby lower multiple of base + function floorInBase(n, base) { + return base * Math.floor(n / base); + } + +})(jQuery); diff --git a/askbot/skins/common/media/js/jquery.flot.min.js b/askbot/skins/common/media/js/jquery.flot.min.js new file mode 100644 index 00000000..31f465b8 --- /dev/null +++ b/askbot/skins/common/media/js/jquery.flot.min.js @@ -0,0 +1 @@ +(function(){jQuery.color={};jQuery.color.make=function(G,H,J,I){var A={};A.r=G||0;A.g=H||0;A.b=J||0;A.a=I!=null?I:1;A.add=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]+=D}return A.normalize()};A.scale=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]*=D}return A.normalize()};A.toString=function(){if(A.a>=1){return"rgb("+[A.r,A.g,A.b].join(",")+")"}else{return"rgba("+[A.r,A.g,A.b,A.a].join(",")+")"}};A.normalize=function(){function C(E,D,F){return D<E?E:(D>F?F:D)}A.r=C(0,parseInt(A.r),255);A.g=C(0,parseInt(A.g),255);A.b=C(0,parseInt(A.b),255);A.a=C(0,A.a,1);return A};A.clone=function(){return jQuery.color.make(A.r,A.b,A.g,A.a)};return A.normalize()};jQuery.color.extract=function(E,F){var A;do{A=E.css(F).toLowerCase();if(A!=""&&A!="transparent"){break}E=E.parent()}while(!jQuery.nodeName(E.get(0),"body"));if(A=="rgba(0, 0, 0, 0)"){A="transparent"}return jQuery.color.parse(A)};jQuery.color.parse=function(A){var F,H=jQuery.color.make;if(F=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10))}if(F=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10),parseFloat(F[4]))}if(F=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55)}if(F=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55,parseFloat(F[4]))}if(F=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(A)){return H(parseInt(F[1],16),parseInt(F[2],16),parseInt(F[3],16))}if(F=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(A)){return H(parseInt(F[1]+F[1],16),parseInt(F[2]+F[2],16),parseInt(F[3]+F[3],16))}var G=jQuery.trim(A).toLowerCase();if(G=="transparent"){return H(255,255,255,0)}else{F=B[G];return H(F[0],F[1],F[2])}};var B={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();(function(C){function B(l,W,X,E){var O=[],g={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:0.85},xaxis:{mode:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,tickDecimals:null,tickSize:null,minTickSize:null,monthNames:null,timeformat:null,twelveHourClock:false},yaxis:{autoscaleMargin:0.02},x2axis:{autoscaleMargin:null},y2axis:{autoscaleMargin:0.02},series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false},shadowSize:3},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,tickColor:"rgba(0,0,0,0.15)",labelMargin:5,borderWidth:2,borderColor:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},hooks:{}},P=null,AC=null,AD=null,Y=null,AJ=null,s={xaxis:{},yaxis:{},x2axis:{},y2axis:{}},e={left:0,right:0,top:0,bottom:0},y=0,Q=0,I=0,t=0,L={processOptions:[],processRawData:[],processDatapoints:[],draw:[],bindEvents:[],drawOverlay:[]},G=this;G.setData=f;G.setupGrid=k;G.draw=AH;G.getPlaceholder=function(){return l};G.getCanvas=function(){return P};G.getPlotOffset=function(){return e};G.width=function(){return I};G.height=function(){return t};G.offset=function(){var AK=AD.offset();AK.left+=e.left;AK.top+=e.top;return AK};G.getData=function(){return O};G.getAxes=function(){return s};G.getOptions=function(){return g};G.highlight=AE;G.unhighlight=x;G.triggerRedrawOverlay=q;G.pointOffset=function(AK){return{left:parseInt(T(AK,"xaxis").p2c(+AK.x)+e.left),top:parseInt(T(AK,"yaxis").p2c(+AK.y)+e.top)}};G.hooks=L;b(G);r(X);c();f(W);k();AH();AG();function Z(AM,AK){AK=[G].concat(AK);for(var AL=0;AL<AM.length;++AL){AM[AL].apply(this,AK)}}function b(){for(var AK=0;AK<E.length;++AK){var AL=E[AK];AL.init(G);if(AL.options){C.extend(true,g,AL.options)}}}function r(AK){C.extend(true,g,AK);if(g.grid.borderColor==null){g.grid.borderColor=g.grid.color}if(g.xaxis.noTicks&&g.xaxis.ticks==null){g.xaxis.ticks=g.xaxis.noTicks}if(g.yaxis.noTicks&&g.yaxis.ticks==null){g.yaxis.ticks=g.yaxis.noTicks}if(g.grid.coloredAreas){g.grid.markings=g.grid.coloredAreas}if(g.grid.coloredAreasColor){g.grid.markingsColor=g.grid.coloredAreasColor}if(g.lines){C.extend(true,g.series.lines,g.lines)}if(g.points){C.extend(true,g.series.points,g.points)}if(g.bars){C.extend(true,g.series.bars,g.bars)}if(g.shadowSize){g.series.shadowSize=g.shadowSize}for(var AL in L){if(g.hooks[AL]&&g.hooks[AL].length){L[AL]=L[AL].concat(g.hooks[AL])}}Z(L.processOptions,[g])}function f(AK){O=M(AK);U();m()}function M(AN){var AL=[];for(var AK=0;AK<AN.length;++AK){var AM=C.extend(true,{},g.series);if(AN[AK].data){AM.data=AN[AK].data;delete AN[AK].data;C.extend(true,AM,AN[AK]);AN[AK].data=AM.data}else{AM.data=AN[AK]}AL.push(AM)}return AL}function T(AM,AK){var AL=AM[AK];if(!AL||AL==1){return s[AK]}if(typeof AL=="number"){return s[AK.charAt(0)+AL+AK.slice(1)]}return AL}function U(){var AP;var AV=O.length,AK=[],AN=[];for(AP=0;AP<O.length;++AP){var AS=O[AP].color;if(AS!=null){--AV;if(typeof AS=="number"){AN.push(AS)}else{AK.push(C.color.parse(O[AP].color))}}}for(AP=0;AP<AN.length;++AP){AV=Math.max(AV,AN[AP]+1)}var AL=[],AO=0;AP=0;while(AL.length<AV){var AR;if(g.colors.length==AP){AR=C.color.make(100,100,100)}else{AR=C.color.parse(g.colors[AP])}var AM=AO%2==1?-1:1;AR.scale("rgb",1+AM*Math.ceil(AO/2)*0.2);AL.push(AR);++AP;if(AP>=g.colors.length){AP=0;++AO}}var AQ=0,AW;for(AP=0;AP<O.length;++AP){AW=O[AP];if(AW.color==null){AW.color=AL[AQ].toString();++AQ}else{if(typeof AW.color=="number"){AW.color=AL[AW.color].toString()}}if(AW.lines.show==null){var AU,AT=true;for(AU in AW){if(AW[AU].show){AT=false;break}}if(AT){AW.lines.show=true}}AW.xaxis=T(AW,"xaxis");AW.yaxis=T(AW,"yaxis")}}function m(){var AW=Number.POSITIVE_INFINITY,AQ=Number.NEGATIVE_INFINITY,Ac,Aa,AZ,AV,AL,AR,Ab,AX,AP,AO,AK,Ai,Af,AT;for(AK in s){s[AK].datamin=AW;s[AK].datamax=AQ;s[AK].used=false}function AN(Al,Ak,Aj){if(Ak<Al.datamin){Al.datamin=Ak}if(Aj>Al.datamax){Al.datamax=Aj}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];AR.datapoints={points:[]};Z(L.processRawData,[AR,AR.data,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];var Ah=AR.data,Ae=AR.datapoints.format;if(!Ae){Ae=[];Ae.push({x:true,number:true,required:true});Ae.push({y:true,number:true,required:true});if(AR.bars.show){Ae.push({y:true,number:true,required:false,defaultValue:0})}AR.datapoints.format=Ae}if(AR.datapoints.pointsize!=null){continue}if(AR.datapoints.pointsize==null){AR.datapoints.pointsize=Ae.length}AX=AR.datapoints.pointsize;Ab=AR.datapoints.points;insertSteps=AR.lines.show&&AR.lines.steps;AR.xaxis.used=AR.yaxis.used=true;for(Aa=AZ=0;Aa<Ah.length;++Aa,AZ+=AX){AT=Ah[Aa];var AM=AT==null;if(!AM){for(AV=0;AV<AX;++AV){Ai=AT[AV];Af=Ae[AV];if(Af){if(Af.number&&Ai!=null){Ai=+Ai;if(isNaN(Ai)){Ai=null}}if(Ai==null){if(Af.required){AM=true}if(Af.defaultValue!=null){Ai=Af.defaultValue}}}Ab[AZ+AV]=Ai}}if(AM){for(AV=0;AV<AX;++AV){Ai=Ab[AZ+AV];if(Ai!=null){Af=Ae[AV];if(Af.x){AN(AR.xaxis,Ai,Ai)}if(Af.y){AN(AR.yaxis,Ai,Ai)}}Ab[AZ+AV]=null}}else{if(insertSteps&&AZ>0&&Ab[AZ-AX]!=null&&Ab[AZ-AX]!=Ab[AZ]&&Ab[AZ-AX+1]!=Ab[AZ+1]){for(AV=0;AV<AX;++AV){Ab[AZ+AX+AV]=Ab[AZ+AV]}Ab[AZ+1]=Ab[AZ-AX+1];AZ+=AX}}}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Z(L.processDatapoints,[AR,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Ab=AR.datapoints.points,AX=AR.datapoints.pointsize;var AS=AW,AY=AW,AU=AQ,Ad=AQ;for(Aa=0;Aa<Ab.length;Aa+=AX){if(Ab[Aa]==null){continue}for(AV=0;AV<AX;++AV){Ai=Ab[Aa+AV];Af=Ae[AV];if(!Af){continue}if(Af.x){if(Ai<AS){AS=Ai}if(Ai>AU){AU=Ai}}if(Af.y){if(Ai<AY){AY=Ai}if(Ai>Ad){Ad=Ai}}}}if(AR.bars.show){var Ag=AR.bars.align=="left"?0:-AR.bars.barWidth/2;if(AR.bars.horizontal){AY+=Ag;Ad+=Ag+AR.bars.barWidth}else{AS+=Ag;AU+=Ag+AR.bars.barWidth}}AN(AR.xaxis,AS,AU);AN(AR.yaxis,AY,Ad)}for(AK in s){if(s[AK].datamin==AW){s[AK].datamin=null}if(s[AK].datamax==AQ){s[AK].datamax=null}}}function c(){function AK(AM,AL){var AN=document.createElement("canvas");AN.width=AM;AN.height=AL;if(C.browser.msie){AN=window.G_vmlCanvasManager.initElement(AN)}return AN}y=l.width();Q=l.height();l.html("");if(l.css("position")=="static"){l.css("position","relative")}if(y<=0||Q<=0){throw"Invalid dimensions for plot, width = "+y+", height = "+Q}if(C.browser.msie){window.G_vmlCanvasManager.init_(document)}P=C(AK(y,Q)).appendTo(l).get(0);Y=P.getContext("2d");AC=C(AK(y,Q)).css({position:"absolute",left:0,top:0}).appendTo(l).get(0);AJ=AC.getContext("2d");AJ.stroke()}function AG(){AD=C([AC,P]);if(g.grid.hoverable){AD.mousemove(D)}if(g.grid.clickable){AD.click(d)}Z(L.bindEvents,[AD])}function k(){function AL(AT,AU){function AP(AV){return AV}var AS,AO,AQ=AU.transform||AP,AR=AU.inverseTransform;if(AT==s.xaxis||AT==s.x2axis){AS=AT.scale=I/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.min);if(AQ==AP){AT.p2c=function(AV){return(AV-AO)*AS}}else{AT.p2c=function(AV){return(AQ(AV)-AO)*AS}}if(!AR){AT.c2p=function(AV){return AO+AV/AS}}else{AT.c2p=function(AV){return AR(AO+AV/AS)}}}else{AS=AT.scale=t/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.max);if(AQ==AP){AT.p2c=function(AV){return(AO-AV)*AS}}else{AT.p2c=function(AV){return(AO-AQ(AV))*AS}}if(!AR){AT.c2p=function(AV){return AO-AV/AS}}else{AT.c2p=function(AV){return AR(AO-AV/AS)}}}}function AN(AR,AT){var AQ,AS=[],AP;AR.labelWidth=AT.labelWidth;AR.labelHeight=AT.labelHeight;if(AR==s.xaxis||AR==s.x2axis){if(AR.labelWidth==null){AR.labelWidth=y/(AR.ticks.length>0?AR.ticks.length:1)}if(AR.labelHeight==null){AS=[];for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel" style="float:left;width:'+AR.labelWidth+'px">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">'+AS.join("")+'<div style="clear:left"></div></div>').appendTo(l);AR.labelHeight=AO.height();AO.remove()}}}else{if(AR.labelWidth==null||AR.labelHeight==null){for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;font-size:smaller">'+AS.join("")+"</div>").appendTo(l);if(AR.labelWidth==null){AR.labelWidth=AO.width()}if(AR.labelHeight==null){AR.labelHeight=AO.find("div").height()}AO.remove()}}}if(AR.labelWidth==null){AR.labelWidth=0}if(AR.labelHeight==null){AR.labelHeight=0}}function AM(){var AP=g.grid.borderWidth;for(i=0;i<O.length;++i){AP=Math.max(AP,2*(O[i].points.radius+O[i].points.lineWidth/2))}e.left=e.right=e.top=e.bottom=AP;var AO=g.grid.labelMargin+g.grid.borderWidth;if(s.xaxis.labelHeight>0){e.bottom=Math.max(AP,s.xaxis.labelHeight+AO)}if(s.yaxis.labelWidth>0){e.left=Math.max(AP,s.yaxis.labelWidth+AO)}if(s.x2axis.labelHeight>0){e.top=Math.max(AP,s.x2axis.labelHeight+AO)}if(s.y2axis.labelWidth>0){e.right=Math.max(AP,s.y2axis.labelWidth+AO)}I=y-e.left-e.right;t=Q-e.bottom-e.top}var AK;for(AK in s){K(s[AK],g[AK])}if(g.grid.show){for(AK in s){F(s[AK],g[AK]);p(s[AK],g[AK]);AN(s[AK],g[AK])}AM()}else{e.left=e.right=e.top=e.bottom=0;I=y;t=Q}for(AK in s){AL(s[AK],g[AK])}if(g.grid.show){h()}AI()}function K(AN,AQ){var AM=+(AQ.min!=null?AQ.min:AN.datamin),AK=+(AQ.max!=null?AQ.max:AN.datamax),AP=AK-AM;if(AP==0){var AL=AK==0?1:0.01;if(AQ.min==null){AM-=AL}if(AQ.max==null||AQ.min!=null){AK+=AL}}else{var AO=AQ.autoscaleMargin;if(AO!=null){if(AQ.min==null){AM-=AP*AO;if(AM<0&&AN.datamin!=null&&AN.datamin>=0){AM=0}}if(AQ.max==null){AK+=AP*AO;if(AK>0&&AN.datamax!=null&&AN.datamax<=0){AK=0}}}}AN.min=AM;AN.max=AK}function F(AP,AS){var AO;if(typeof AS.ticks=="number"&&AS.ticks>0){AO=AS.ticks}else{if(AP==s.xaxis||AP==s.x2axis){AO=0.3*Math.sqrt(y)}else{AO=0.3*Math.sqrt(Q)}}var AX=(AP.max-AP.min)/AO,AZ,AT,AV,AW,AR,AM,AL;if(AS.mode=="time"){var AU={second:1000,minute:60*1000,hour:60*60*1000,day:24*60*60*1000,month:30*24*60*60*1000,year:365.2425*24*60*60*1000};var AY=[[1,"second"],[2,"second"],[5,"second"],[10,"second"],[30,"second"],[1,"minute"],[2,"minute"],[5,"minute"],[10,"minute"],[30,"minute"],[1,"hour"],[2,"hour"],[4,"hour"],[8,"hour"],[12,"hour"],[1,"day"],[2,"day"],[3,"day"],[0.25,"month"],[0.5,"month"],[1,"month"],[2,"month"],[3,"month"],[6,"month"],[1,"year"]];var AN=0;if(AS.minTickSize!=null){if(typeof AS.tickSize=="number"){AN=AS.tickSize}else{AN=AS.minTickSize[0]*AU[AS.minTickSize[1]]}}for(AR=0;AR<AY.length-1;++AR){if(AX<(AY[AR][0]*AU[AY[AR][1]]+AY[AR+1][0]*AU[AY[AR+1][1]])/2&&AY[AR][0]*AU[AY[AR][1]]>=AN){break}}AZ=AY[AR][0];AV=AY[AR][1];if(AV=="year"){AM=Math.pow(10,Math.floor(Math.log(AX/AU.year)/Math.LN10));AL=(AX/AU.year)/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM}if(AS.tickSize){AZ=AS.tickSize[0];AV=AS.tickSize[1]}AT=function(Ac){var Ah=[],Af=Ac.tickSize[0],Ai=Ac.tickSize[1],Ag=new Date(Ac.min);var Ab=Af*AU[Ai];if(Ai=="second"){Ag.setUTCSeconds(A(Ag.getUTCSeconds(),Af))}if(Ai=="minute"){Ag.setUTCMinutes(A(Ag.getUTCMinutes(),Af))}if(Ai=="hour"){Ag.setUTCHours(A(Ag.getUTCHours(),Af))}if(Ai=="month"){Ag.setUTCMonth(A(Ag.getUTCMonth(),Af))}if(Ai=="year"){Ag.setUTCFullYear(A(Ag.getUTCFullYear(),Af))}Ag.setUTCMilliseconds(0);if(Ab>=AU.minute){Ag.setUTCSeconds(0)}if(Ab>=AU.hour){Ag.setUTCMinutes(0)}if(Ab>=AU.day){Ag.setUTCHours(0)}if(Ab>=AU.day*4){Ag.setUTCDate(1)}if(Ab>=AU.year){Ag.setUTCMonth(0)}var Ak=0,Aj=Number.NaN,Ad;do{Ad=Aj;Aj=Ag.getTime();Ah.push({v:Aj,label:Ac.tickFormatter(Aj,Ac)});if(Ai=="month"){if(Af<1){Ag.setUTCDate(1);var Aa=Ag.getTime();Ag.setUTCMonth(Ag.getUTCMonth()+1);var Ae=Ag.getTime();Ag.setTime(Aj+Ak*AU.hour+(Ae-Aa)*Af);Ak=Ag.getUTCHours();Ag.setUTCHours(0)}else{Ag.setUTCMonth(Ag.getUTCMonth()+Af)}}else{if(Ai=="year"){Ag.setUTCFullYear(Ag.getUTCFullYear()+Af)}else{Ag.setTime(Aj+Ab)}}}while(Aj<Ac.max&&Aj!=Ad);return Ah};AW=function(Aa,Ad){var Af=new Date(Aa);if(AS.timeformat!=null){return C.plot.formatDate(Af,AS.timeformat,AS.monthNames)}var Ab=Ad.tickSize[0]*AU[Ad.tickSize[1]];var Ac=Ad.max-Ad.min;var Ae=(AS.twelveHourClock)?" %p":"";if(Ab<AU.minute){fmt="%h:%M:%S"+Ae}else{if(Ab<AU.day){if(Ac<2*AU.day){fmt="%h:%M"+Ae}else{fmt="%b %d %h:%M"+Ae}}else{if(Ab<AU.month){fmt="%b %d"}else{if(Ab<AU.year){if(Ac<AU.year){fmt="%b"}else{fmt="%b %y"}}else{fmt="%y"}}}}return C.plot.formatDate(Af,fmt,AS.monthNames)}}else{var AK=AS.tickDecimals;var AQ=-Math.floor(Math.log(AX)/Math.LN10);if(AK!=null&&AQ>AK){AQ=AK}AM=Math.pow(10,-AQ);AL=AX/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2;if(AL>2.25&&(AK==null||AQ+1<=AK)){AZ=2.5;++AQ}}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM;if(AS.minTickSize!=null&&AZ<AS.minTickSize){AZ=AS.minTickSize}if(AS.tickSize!=null){AZ=AS.tickSize}AP.tickDecimals=Math.max(0,(AK!=null)?AK:AQ);AT=function(Ac){var Ae=[];var Af=A(Ac.min,Ac.tickSize),Ab=0,Aa=Number.NaN,Ad;do{Ad=Aa;Aa=Af+Ab*Ac.tickSize;Ae.push({v:Aa,label:Ac.tickFormatter(Aa,Ac)});++Ab}while(Aa<Ac.max&&Aa!=Ad);return Ae};AW=function(Aa,Ab){return Aa.toFixed(Ab.tickDecimals)}}AP.tickSize=AV?[AZ,AV]:AZ;AP.tickGenerator=AT;if(C.isFunction(AS.tickFormatter)){AP.tickFormatter=function(Aa,Ab){return""+AS.tickFormatter(Aa,Ab)}}else{AP.tickFormatter=AW}}function p(AO,AQ){AO.ticks=[];if(!AO.used){return }if(AQ.ticks==null){AO.ticks=AO.tickGenerator(AO)}else{if(typeof AQ.ticks=="number"){if(AQ.ticks>0){AO.ticks=AO.tickGenerator(AO)}}else{if(AQ.ticks){var AP=AQ.ticks;if(C.isFunction(AP)){AP=AP({min:AO.min,max:AO.max})}var AN,AK;for(AN=0;AN<AP.length;++AN){var AL=null;var AM=AP[AN];if(typeof AM=="object"){AK=AM[0];if(AM.length>1){AL=AM[1]}}else{AK=AM}if(AL==null){AL=AO.tickFormatter(AK,AO)}AO.ticks[AN]={v:AK,label:AL}}}}}if(AQ.autoscaleMargin!=null&&AO.ticks.length>0){if(AQ.min==null){AO.min=Math.min(AO.min,AO.ticks[0].v)}if(AQ.max==null&&AO.ticks.length>1){AO.max=Math.max(AO.max,AO.ticks[AO.ticks.length-1].v)}}}function AH(){Y.clearRect(0,0,y,Q);var AL=g.grid;if(AL.show&&!AL.aboveData){S()}for(var AK=0;AK<O.length;++AK){AA(O[AK])}Z(L.draw,[Y]);if(AL.show&&AL.aboveData){S()}}function N(AL,AR){var AO=AR+"axis",AK=AR+"2axis",AN,AQ,AP,AM;if(AL[AO]){AN=s[AO];AQ=AL[AO].from;AP=AL[AO].to}else{if(AL[AK]){AN=s[AK];AQ=AL[AK].from;AP=AL[AK].to}else{AN=s[AO];AQ=AL[AR+"1"];AP=AL[AR+"2"]}}if(AQ!=null&&AP!=null&&AQ>AP){return{from:AP,to:AQ,axis:AN}}return{from:AQ,to:AP,axis:AN}}function S(){var AO;Y.save();Y.translate(e.left,e.top);if(g.grid.backgroundColor){Y.fillStyle=R(g.grid.backgroundColor,t,0,"rgba(255, 255, 255, 0)");Y.fillRect(0,0,I,t)}var AL=g.grid.markings;if(AL){if(C.isFunction(AL)){AL=AL({xmin:s.xaxis.min,xmax:s.xaxis.max,ymin:s.yaxis.min,ymax:s.yaxis.max,xaxis:s.xaxis,yaxis:s.yaxis,x2axis:s.x2axis,y2axis:s.y2axis})}for(AO=0;AO<AL.length;++AO){var AK=AL[AO],AQ=N(AK,"x"),AN=N(AK,"y");if(AQ.from==null){AQ.from=AQ.axis.min}if(AQ.to==null){AQ.to=AQ.axis.max}if(AN.from==null){AN.from=AN.axis.min}if(AN.to==null){AN.to=AN.axis.max}if(AQ.to<AQ.axis.min||AQ.from>AQ.axis.max||AN.to<AN.axis.min||AN.from>AN.axis.max){continue}AQ.from=Math.max(AQ.from,AQ.axis.min);AQ.to=Math.min(AQ.to,AQ.axis.max);AN.from=Math.max(AN.from,AN.axis.min);AN.to=Math.min(AN.to,AN.axis.max);if(AQ.from==AQ.to&&AN.from==AN.to){continue}AQ.from=AQ.axis.p2c(AQ.from);AQ.to=AQ.axis.p2c(AQ.to);AN.from=AN.axis.p2c(AN.from);AN.to=AN.axis.p2c(AN.to);if(AQ.from==AQ.to||AN.from==AN.to){Y.beginPath();Y.strokeStyle=AK.color||g.grid.markingsColor;Y.lineWidth=AK.lineWidth||g.grid.markingsLineWidth;Y.moveTo(AQ.from,AN.from);Y.lineTo(AQ.to,AN.to);Y.stroke()}else{Y.fillStyle=AK.color||g.grid.markingsColor;Y.fillRect(AQ.from,AN.to,AQ.to-AQ.from,AN.from-AN.to)}}}Y.lineWidth=1;Y.strokeStyle=g.grid.tickColor;Y.beginPath();var AM,AP=s.xaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=s.xaxis.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,0);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,t)}AP=s.yaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(0,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}AP=s.x2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,-5);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,5)}AP=s.y2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(I-5,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I+5,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}Y.stroke();if(g.grid.borderWidth){var AR=g.grid.borderWidth;Y.lineWidth=AR;Y.strokeStyle=g.grid.borderColor;Y.strokeRect(-AR/2,-AR/2,I+AR,t+AR)}Y.restore()}function h(){l.find(".tickLabels").remove();var AK=['<div class="tickLabels" style="font-size:smaller;color:'+g.grid.color+'">'];function AM(AP,AQ){for(var AO=0;AO<AP.ticks.length;++AO){var AN=AP.ticks[AO];if(!AN.label||AN.v<AP.min||AN.v>AP.max){continue}AK.push(AQ(AN,AP))}}var AL=g.grid.labelMargin+g.grid.borderWidth;AM(s.xaxis,function(AN,AO){return'<div style="position:absolute;top:'+(e.top+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.yaxis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;right:"+(e.right+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:right" class="tickLabel">'+AN.label+"</div>"});AM(s.x2axis,function(AN,AO){return'<div style="position:absolute;bottom:'+(e.bottom+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.y2axis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;left:"+(e.left+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:left" class="tickLabel">'+AN.label+"</div>"});AK.push("</div>");l.append(AK.join(""))}function AA(AK){if(AK.lines.show){a(AK)}if(AK.bars.show){n(AK)}if(AK.points.show){o(AK)}}function a(AN){function AM(AY,AZ,AR,Ad,Ac){var Ae=AY.points,AS=AY.pointsize,AW=null,AV=null;Y.beginPath();for(var AX=AS;AX<Ae.length;AX+=AS){var AU=Ae[AX-AS],Ab=Ae[AX-AS+1],AT=Ae[AX],Aa=Ae[AX+1];if(AU==null||AT==null){continue}if(Ab<=Aa&&Ab<Ac.min){if(Aa<Ac.min){continue}AU=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(Aa<=Ab&&Aa<Ac.min){if(Ab<Ac.min){continue}AT=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.min}}if(Ab>=Aa&&Ab>Ac.max){if(Aa>Ac.max){continue}AU=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(Aa>=Ab&&Aa>Ac.max){if(Ab>Ac.max){continue}AT=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.max}}if(AU<=AT&&AU<Ad.min){if(AT<Ad.min){continue}Ab=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.min}else{if(AT<=AU&&AT<Ad.min){if(AU<Ad.min){continue}Aa=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.min}}if(AU>=AT&&AU>Ad.max){if(AT>Ad.max){continue}Ab=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.max}else{if(AT>=AU&&AT>Ad.max){if(AU>Ad.max){continue}Aa=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.max}}if(AU!=AW||Ab!=AV){Y.moveTo(Ad.p2c(AU)+AZ,Ac.p2c(Ab)+AR)}AW=AT;AV=Aa;Y.lineTo(Ad.p2c(AT)+AZ,Ac.p2c(Aa)+AR)}Y.stroke()}function AO(AX,Ae,Ac){var Af=AX.points,AR=AX.pointsize,AS=Math.min(Math.max(0,Ac.min),Ac.max),Aa,AV=0,Ad=false;for(var AW=AR;AW<Af.length;AW+=AR){var AU=Af[AW-AR],Ab=Af[AW-AR+1],AT=Af[AW],AZ=Af[AW+1];if(Ad&&AU!=null&&AT==null){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill();Ad=false;continue}if(AU==null||AT==null){continue}if(AU<=AT&&AU<Ae.min){if(AT<Ae.min){continue}Ab=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.min}else{if(AT<=AU&&AT<Ae.min){if(AU<Ae.min){continue}AZ=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.min}}if(AU>=AT&&AU>Ae.max){if(AT>Ae.max){continue}Ab=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.max}else{if(AT>=AU&&AT>Ae.max){if(AU>Ae.max){continue}AZ=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.max}}if(!Ad){Y.beginPath();Y.moveTo(Ae.p2c(AU),Ac.p2c(AS));Ad=true}if(Ab>=Ac.max&&AZ>=Ac.max){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.max));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.max));AV=AT;continue}else{if(Ab<=Ac.min&&AZ<=Ac.min){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.min));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.min));AV=AT;continue}}var Ag=AU,AY=AT;if(Ab<=AZ&&Ab<Ac.min&&AZ>=Ac.min){AU=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(AZ<=Ab&&AZ<Ac.min&&Ab>=Ac.min){AT=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.min}}if(Ab>=AZ&&Ab>Ac.max&&AZ<=Ac.max){AU=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(AZ>=Ab&&AZ>Ac.max&&Ab<=Ac.max){AT=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.max}}if(AU!=Ag){if(Ab<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(Ag),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AU),Ac.p2c(Aa))}Y.lineTo(Ae.p2c(AU),Ac.p2c(Ab));Y.lineTo(Ae.p2c(AT),Ac.p2c(AZ));if(AT!=AY){if(AZ<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(AT),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AY),Ac.p2c(Aa))}AV=Math.max(AT,AY)}if(Ad){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill()}}Y.save();Y.translate(e.left,e.top);Y.lineJoin="round";var AP=AN.lines.lineWidth,AK=AN.shadowSize;if(AP>0&&AK>0){Y.lineWidth=AK;Y.strokeStyle="rgba(0,0,0,0.1)";var AQ=Math.PI/18;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/2),Math.cos(AQ)*(AP/2+AK/2),AN.xaxis,AN.yaxis);Y.lineWidth=AK/2;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/4),Math.cos(AQ)*(AP/2+AK/4),AN.xaxis,AN.yaxis)}Y.lineWidth=AP;Y.strokeStyle=AN.color;var AL=V(AN.lines,AN.color,0,t);if(AL){Y.fillStyle=AL;AO(AN.datapoints,AN.xaxis,AN.yaxis)}if(AP>0){AM(AN.datapoints,0,0,AN.xaxis,AN.yaxis)}Y.restore()}function o(AN){function AP(AU,AT,Ab,AR,AV,AZ,AY){var Aa=AU.points,AQ=AU.pointsize;for(var AS=0;AS<Aa.length;AS+=AQ){var AX=Aa[AS],AW=Aa[AS+1];if(AX==null||AX<AZ.min||AX>AZ.max||AW<AY.min||AW>AY.max){continue}Y.beginPath();Y.arc(AZ.p2c(AX),AY.p2c(AW)+AR,AT,0,AV,false);if(Ab){Y.fillStyle=Ab;Y.fill()}Y.stroke()}}Y.save();Y.translate(e.left,e.top);var AO=AN.lines.lineWidth,AL=AN.shadowSize,AK=AN.points.radius;if(AO>0&&AL>0){var AM=AL/2;Y.lineWidth=AM;Y.strokeStyle="rgba(0,0,0,0.1)";AP(AN.datapoints,AK,null,AM+AM/2,Math.PI,AN.xaxis,AN.yaxis);Y.strokeStyle="rgba(0,0,0,0.2)";AP(AN.datapoints,AK,null,AM/2,Math.PI,AN.xaxis,AN.yaxis)}Y.lineWidth=AO;Y.strokeStyle=AN.color;AP(AN.datapoints,AK,V(AN.points,AN.color),0,2*Math.PI,AN.xaxis,AN.yaxis);Y.restore()}function AB(AV,AU,Ad,AQ,AY,AN,AL,AT,AS,Ac,AZ){var AM,Ab,AR,AX,AO,AK,AW,AP,Aa;if(AZ){AP=AK=AW=true;AO=false;AM=Ad;Ab=AV;AX=AU+AQ;AR=AU+AY;if(Ab<AM){Aa=Ab;Ab=AM;AM=Aa;AO=true;AK=false}}else{AO=AK=AW=true;AP=false;AM=AV+AQ;Ab=AV+AY;AR=Ad;AX=AU;if(AX<AR){Aa=AX;AX=AR;AR=Aa;AP=true;AW=false}}if(Ab<AT.min||AM>AT.max||AX<AS.min||AR>AS.max){return }if(AM<AT.min){AM=AT.min;AO=false}if(Ab>AT.max){Ab=AT.max;AK=false}if(AR<AS.min){AR=AS.min;AP=false}if(AX>AS.max){AX=AS.max;AW=false}AM=AT.p2c(AM);AR=AS.p2c(AR);Ab=AT.p2c(Ab);AX=AS.p2c(AX);if(AL){Ac.beginPath();Ac.moveTo(AM,AR);Ac.lineTo(AM,AX);Ac.lineTo(Ab,AX);Ac.lineTo(Ab,AR);Ac.fillStyle=AL(AR,AX);Ac.fill()}if(AO||AK||AW||AP){Ac.beginPath();Ac.moveTo(AM,AR+AN);if(AO){Ac.lineTo(AM,AX+AN)}else{Ac.moveTo(AM,AX+AN)}if(AW){Ac.lineTo(Ab,AX+AN)}else{Ac.moveTo(Ab,AX+AN)}if(AK){Ac.lineTo(Ab,AR+AN)}else{Ac.moveTo(Ab,AR+AN)}if(AP){Ac.lineTo(AM,AR+AN)}else{Ac.moveTo(AM,AR+AN)}Ac.stroke()}}function n(AM){function AL(AS,AR,AU,AP,AT,AW,AV){var AX=AS.points,AO=AS.pointsize;for(var AQ=0;AQ<AX.length;AQ+=AO){if(AX[AQ]==null){continue}AB(AX[AQ],AX[AQ+1],AX[AQ+2],AR,AU,AP,AT,AW,AV,Y,AM.bars.horizontal)}}Y.save();Y.translate(e.left,e.top);Y.lineWidth=AM.bars.lineWidth;Y.strokeStyle=AM.color;var AK=AM.bars.align=="left"?0:-AM.bars.barWidth/2;var AN=AM.bars.fill?function(AO,AP){return V(AM.bars,AM.color,AO,AP)}:null;AL(AM.datapoints,AK,AK+AM.bars.barWidth,0,AN,AM.xaxis,AM.yaxis);Y.restore()}function V(AM,AK,AL,AO){var AN=AM.fill;if(!AN){return null}if(AM.fillColor){return R(AM.fillColor,AL,AO,AK)}var AP=C.color.parse(AK);AP.a=typeof AN=="number"?AN:0.4;AP.normalize();return AP.toString()}function AI(){l.find(".legend").remove();if(!g.legend.show){return }var AP=[],AN=false,AV=g.legend.labelFormatter,AU,AR;for(i=0;i<O.length;++i){AU=O[i];AR=AU.label;if(!AR){continue}if(i%g.legend.noColumns==0){if(AN){AP.push("</tr>")}AP.push("<tr>");AN=true}if(AV){AR=AV(AR,AU)}AP.push('<td class="legendColorBox"><div style="border:1px solid '+g.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+AU.color+';overflow:hidden"></div></div></td><td class="legendLabel">'+AR+"</td>")}if(AN){AP.push("</tr>")}if(AP.length==0){return }var AT='<table style="font-size:smaller;color:'+g.grid.color+'">'+AP.join("")+"</table>";if(g.legend.container!=null){C(g.legend.container).html(AT)}else{var AQ="",AL=g.legend.position,AM=g.legend.margin;if(AM[0]==null){AM=[AM,AM]}if(AL.charAt(0)=="n"){AQ+="top:"+(AM[1]+e.top)+"px;"}else{if(AL.charAt(0)=="s"){AQ+="bottom:"+(AM[1]+e.bottom)+"px;"}}if(AL.charAt(1)=="e"){AQ+="right:"+(AM[0]+e.right)+"px;"}else{if(AL.charAt(1)=="w"){AQ+="left:"+(AM[0]+e.left)+"px;"}}var AS=C('<div class="legend">'+AT.replace('style="','style="position:absolute;'+AQ+";")+"</div>").appendTo(l);if(g.legend.backgroundOpacity!=0){var AO=g.legend.backgroundColor;if(AO==null){AO=g.grid.backgroundColor;if(AO&&typeof AO=="string"){AO=C.color.parse(AO)}else{AO=C.color.extract(AS,"background-color")}AO.a=1;AO=AO.toString()}var AK=AS.children();C('<div style="position:absolute;width:'+AK.width()+"px;height:"+AK.height()+"px;"+AQ+"background-color:"+AO+';"> </div>').prependTo(AS).css("opacity",g.legend.backgroundOpacity)}}}var w=[],J=null;function AF(AR,AP,AM){var AX=g.grid.mouseActiveRadius,Aj=AX*AX+1,Ah=null,Aa=false,Af,Ad;for(Af=0;Af<O.length;++Af){if(!AM(O[Af])){continue}var AY=O[Af],AQ=AY.xaxis,AO=AY.yaxis,Ae=AY.datapoints.points,Ac=AY.datapoints.pointsize,AZ=AQ.c2p(AR),AW=AO.c2p(AP),AL=AX/AQ.scale,AK=AX/AO.scale;if(AY.lines.show||AY.points.show){for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1];if(AT==null){continue}if(AT-AZ>AL||AT-AZ<-AL||AS-AW>AK||AS-AW<-AK){continue}var AV=Math.abs(AQ.p2c(AT)-AR),AU=Math.abs(AO.p2c(AS)-AP),Ab=AV*AV+AU*AU;if(Ab<=Aj){Aj=Ab;Ah=[Af,Ad/Ac]}}}if(AY.bars.show&&!Ah){var AN=AY.bars.align=="left"?0:-AY.bars.barWidth/2,Ag=AN+AY.bars.barWidth;for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1],Ai=Ae[Ad+2];if(AT==null){continue}if(O[Af].bars.horizontal?(AZ<=Math.max(Ai,AT)&&AZ>=Math.min(Ai,AT)&&AW>=AS+AN&&AW<=AS+Ag):(AZ>=AT+AN&&AZ<=AT+Ag&&AW>=Math.min(Ai,AS)&&AW<=Math.max(Ai,AS))){Ah=[Af,Ad/Ac]}}}}if(Ah){Af=Ah[0];Ad=Ah[1];Ac=O[Af].datapoints.pointsize;return{datapoint:O[Af].datapoints.points.slice(Ad*Ac,(Ad+1)*Ac),dataIndex:Ad,series:O[Af],seriesIndex:Af}}return null}function D(AK){if(g.grid.hoverable){H("plothover",AK,function(AL){return AL.hoverable!=false})}}function d(AK){H("plotclick",AK,function(AL){return AL.clickable!=false})}function H(AL,AK,AM){var AN=AD.offset(),AS={pageX:AK.pageX,pageY:AK.pageY},AQ=AK.pageX-AN.left-e.left,AO=AK.pageY-AN.top-e.top;if(s.xaxis.used){AS.x=s.xaxis.c2p(AQ)}if(s.yaxis.used){AS.y=s.yaxis.c2p(AO)}if(s.x2axis.used){AS.x2=s.x2axis.c2p(AQ)}if(s.y2axis.used){AS.y2=s.y2axis.c2p(AO)}var AT=AF(AQ,AO,AM);if(AT){AT.pageX=parseInt(AT.series.xaxis.p2c(AT.datapoint[0])+AN.left+e.left);AT.pageY=parseInt(AT.series.yaxis.p2c(AT.datapoint[1])+AN.top+e.top)}if(g.grid.autoHighlight){for(var AP=0;AP<w.length;++AP){var AR=w[AP];if(AR.auto==AL&&!(AT&&AR.series==AT.series&&AR.point==AT.datapoint)){x(AR.series,AR.point)}}if(AT){AE(AT.series,AT.datapoint,AL)}}l.trigger(AL,[AS,AT])}function q(){if(!J){J=setTimeout(v,30)}}function v(){J=null;AJ.save();AJ.clearRect(0,0,y,Q);AJ.translate(e.left,e.top);var AL,AK;for(AL=0;AL<w.length;++AL){AK=w[AL];if(AK.series.bars.show){z(AK.series,AK.point)}else{u(AK.series,AK.point)}}AJ.restore();Z(L.drawOverlay,[AJ])}function AE(AM,AK,AN){if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL==-1){w.push({series:AM,point:AK,auto:AN});q()}else{if(!AN){w[AL].auto=false}}}function x(AM,AK){if(AM==null&&AK==null){w=[];q()}if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL!=-1){w.splice(AL,1);q()}}function j(AM,AN){for(var AK=0;AK<w.length;++AK){var AL=w[AK];if(AL.series==AM&&AL.point[0]==AN[0]&&AL.point[1]==AN[1]){return AK}}return -1}function u(AN,AM){var AL=AM[0],AR=AM[1],AQ=AN.xaxis,AP=AN.yaxis;if(AL<AQ.min||AL>AQ.max||AR<AP.min||AR>AP.max){return }var AO=AN.points.radius+AN.points.lineWidth/2;AJ.lineWidth=AO;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AK=1.5*AO;AJ.beginPath();AJ.arc(AQ.p2c(AL),AP.p2c(AR),AK,0,2*Math.PI,false);AJ.stroke()}function z(AN,AK){AJ.lineWidth=AN.bars.lineWidth;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AM=C.color.parse(AN.color).scale("a",0.5).toString();var AL=AN.bars.align=="left"?0:-AN.bars.barWidth/2;AB(AK[0],AK[1],AK[2]||0,AL,AL+AN.bars.barWidth,0,function(){return AM},AN.xaxis,AN.yaxis,AJ,AN.bars.horizontal)}function R(AM,AL,AQ,AO){if(typeof AM=="string"){return AM}else{var AP=Y.createLinearGradient(0,AQ,0,AL);for(var AN=0,AK=AM.colors.length;AN<AK;++AN){var AR=AM.colors[AN];if(typeof AR!="string"){AR=C.color.parse(AO).scale("rgb",AR.brightness);AR.a*=AR.opacity;AR=AR.toString()}AP.addColorStop(AN/(AK-1),AR)}return AP}}}C.plot=function(G,E,D){var F=new B(C(G),E,D,C.plot.plugins);return F};C.plot.plugins=[];C.plot.formatDate=function(H,E,G){var L=function(N){N=""+N;return N.length==1?"0"+N:N};var D=[];var M=false;var K=H.getUTCHours();var I=K<12;if(G==null){G=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}if(E.search(/%p|%P/)!=-1){if(K>12){K=K-12}else{if(K==0){K=12}}}for(var F=0;F<E.length;++F){var J=E.charAt(F);if(M){switch(J){case"h":J=""+K;break;case"H":J=L(K);break;case"M":J=L(H.getUTCMinutes());break;case"S":J=L(H.getUTCSeconds());break;case"d":J=""+H.getUTCDate();break;case"m":J=""+(H.getUTCMonth()+1);break;case"y":J=""+H.getUTCFullYear();break;case"b":J=""+G[H.getUTCMonth()];break;case"p":J=(I)?("am"):("pm");break;case"P":J=(I)?("AM"):("PM");break}D.push(J);M=false}else{if(J=="%"){M=true}else{D.push(J)}}}return D.join("")};function A(E,D){return D*Math.floor(E/D)}})(jQuery);
\ No newline at end of file diff --git a/askbot/skins/common/media/js/jquery.form.js b/askbot/skins/common/media/js/jquery.form.js new file mode 100644 index 00000000..443114fd --- /dev/null +++ b/askbot/skins/common/media/js/jquery.form.js @@ -0,0 +1,654 @@ +/* + * jQuery Form Plugin + * version: 2.33 (22-SEP-2009) + * @requires jQuery v1.2.6 or later + * + * Examples and documentation at: http://malsup.com/jquery/form/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ +;(function($) { + +/* + Usage Note: + ----------- + Do not use both ajaxSubmit and ajaxForm on the same form. These + functions are intended to be exclusive. Use ajaxSubmit if you want + to bind your own submit handler to the form. For example, + + $(document).ready(function() { + $('#myForm').bind('submit', function() { + $(this).ajaxSubmit({ + target: '#output' + }); + return false; // <-- important! + }); + }); + + Use ajaxForm when you want the plugin to manage all the event binding + for you. For example, + + $(document).ready(function() { + $('#myForm').ajaxForm({ + target: '#output' + }); + }); + + When using ajaxForm, the ajaxSubmit function will be invoked for you + at the appropriate time. +*/ + +/** + * ajaxSubmit() provides a mechanism for immediately submitting + * an HTML form using AJAX. + */ +$.fn.ajaxSubmit = function(options) { + // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) + if (!this.length) { + log('ajaxSubmit: skipping submit process - no element selected'); + return this; + } + + if (typeof options == 'function') + options = { success: options }; + + var url = $.trim(this.attr('action')); + if (url) { + // clean url (don't include hash vaue) + url = (url.match(/^([^#]+)/)||[])[1]; + } + url = url || window.location.href || ''; + + options = $.extend({ + url: url, + type: this.attr('method') || 'GET' + }, options || {}); + + // hook for manipulating the form data before it is extracted; + // convenient for use with rich editors like tinyMCE or FCKEditor + var veto = {}; + this.trigger('form-pre-serialize', [this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); + return this; + } + + // provide opportunity to alter form data before it is serialized + if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { + log('ajaxSubmit: submit aborted via beforeSerialize callback'); + return this; + } + + var a = this.formToArray(options.semantic); + if (options.data) { + options.extraData = options.data; + for (var n in options.data) { + if(options.data[n] instanceof Array) { + for (var k in options.data[n]) + a.push( { name: n, value: options.data[n][k] } ); + } + else + a.push( { name: n, value: options.data[n] } ); + } + } + + // give pre-submit callback an opportunity to abort the submit + if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { + log('ajaxSubmit: submit aborted via beforeSubmit callback'); + return this; + } + + // fire vetoable 'validate' event + this.trigger('form-submit-validate', [a, this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); + return this; + } + + var q = $.param(a); + + if (options.type.toUpperCase() == 'GET') { + options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; + options.data = null; // data is null for 'get' + } + else + options.data = q; // data is the query string for 'post' + + var $form = this, callbacks = []; + if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); + if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); + + // perform a load on the target only if dataType is not provided + if (!options.dataType && options.target) { + var oldSuccess = options.success || function(){}; + callbacks.push(function(data) { + $(options.target).html(data).each(oldSuccess, arguments); + }); + } + else if (options.success) + callbacks.push(options.success); + + options.success = function(data, status) { + for (var i=0, max=callbacks.length; i < max; i++) + callbacks[i].apply(options, [data, status, $form]); + }; + + // are there files to upload? + var files = $('input:file', this).fieldValue(); + var found = false; + for (var j=0; j < files.length; j++) + if (files[j]) + found = true; + + var multipart = false; +// var mp = 'multipart/form-data'; +// multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); + + // options.iframe allows user to force iframe mode + if (options.iframe || found || multipart) { + // hack to fix Safari hang (thanks to Tim Molendijk for this) + // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d + if (options.closeKeepAlive) + $.get(options.closeKeepAlive, fileUpload); + else + fileUpload(); + } + else{ + $.ajax(options); + } + + // fire 'notify' event + this.trigger('form-submit-notify', [this, options]); + return this; + + + // private function for handling file uploads (hat tip to YAHOO!) + function fileUpload() { + var form = $form[0]; + + if ($(':input[name=submit]', form).length) { + alert('Error: Form elements must not be named "submit".'); + return; + } + + var opts = $.extend({}, $.ajaxSettings, options); + var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts); + + var id = 'jqFormIO' + (new Date().getTime()); + var $io = $('<iframe id="' + id + '" name="' + id + '" src="about:blank" />'); + var io = $io[0]; + + $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); + + var xhr = { // mock object + aborted: 0, + responseText: null, + responseXML: null, + status: 0, + statusText: 'n/a', + getAllResponseHeaders: function() {}, + getResponseHeader: function() {}, + setRequestHeader: function() {}, + abort: function() { + this.aborted = 1; + $io.attr('src','about:blank'); // abort op in progress + } + }; + + var g = opts.global; + // trigger ajax global events so that activity/block indicators work like normal + if (g && ! $.active++) $.event.trigger("ajaxStart"); + if (g) $.event.trigger("ajaxSend", [xhr, opts]); + + if (s.beforeSend && s.beforeSend(xhr, s) === false) { + s.global && $.active--; + return; + } + if (xhr.aborted) + return; + + var cbInvoked = 0; + var timedOut = 0; + + // add submitting element to data if we know it + var sub = form.clk; + if (sub) { + var n = sub.name; + if (n && !sub.disabled) { + options.extraData = options.extraData || {}; + options.extraData[n] = sub.value; + if (sub.type == "image") { + options.extraData[name+'.x'] = form.clk_x; + options.extraData[name+'.y'] = form.clk_y; + } + } + } + + // take a breath so that pending repaints get some cpu time before the upload starts + setTimeout(function() { + // make sure form attrs are set + var t = $form.attr('target'), a = $form.attr('action'); + + // update form attrs in IE friendly way + form.setAttribute('target',id); + if (form.getAttribute('method') != 'POST') + form.setAttribute('method', 'POST'); + if (form.getAttribute('action') != opts.url) + form.setAttribute('action', opts.url); + + // ie borks in some cases when setting encoding + if (! options.skipEncodingOverride) { + $form.attr({ + encoding: 'multipart/form-data', + enctype: 'multipart/form-data' + }); + } + + // support timout + if (opts.timeout) + setTimeout(function() { timedOut = true; cb(); }, opts.timeout); + + // add "extra" data to form if provided in options + var extraInputs = []; + try { + if (options.extraData) + for (var n in options.extraData) + extraInputs.push( + $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />') + .appendTo(form)[0]); + + // add iframe to doc and submit the form + $io.appendTo('body'); + io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false); + form.submit(); + } + finally { + // reset attrs and remove "extra" input elements + form.setAttribute('action',a); + t ? form.setAttribute('target', t) : $form.removeAttr('target'); + $(extraInputs).remove(); + } + }, 10); + + var domCheckCount = 50; + + function cb() { + if (cbInvoked++) return; + + io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false); + + var ok = true; + try { + if (timedOut) throw 'timeout'; + // extract the server response from the iframe + var data, doc; + + doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document; + + var isXml = opts.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc); + log('isXml='+isXml); + if (!isXml && (doc.body == null || doc.body.innerHTML == '')) { + if (--domCheckCount) { + // in some browsers (Opera) the iframe DOM is not always traversable when + // the onload callback fires, so we loop a bit to accommodate + cbInvoked = 0; + setTimeout(cb, 100); + return; + } + log('Could not access iframe DOM after 50 tries.'); + return; + } + + xhr.responseText = doc.body ? doc.body.innerHTML : null; + xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; + xhr.getResponseHeader = function(header){ + var headers = {'content-type': opts.dataType}; + return headers[header]; + }; + + if (opts.dataType == 'json' || opts.dataType == 'script') { + // see if user embedded response in textarea + var ta = doc.getElementsByTagName('textarea')[0]; + if (ta) + xhr.responseText = ta.value; + else { + // account for browsers injecting pre around json response + var pre = doc.getElementsByTagName('pre')[0]; + if (pre) + xhr.responseText = pre.innerHTML; + } + } + else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) { + xhr.responseXML = toXml(xhr.responseText); + } + data = $.httpData(xhr, opts.dataType); + } + catch(e){ + ok = false; + $.handleError(opts, xhr, 'error', e); + } + + // ordering of these callbacks/triggers is odd, but that's how $.ajax does it + if (ok) { + opts.success(data, 'success'); + if (g) $.event.trigger("ajaxSuccess", [xhr, opts]); + } + if (g) $.event.trigger("ajaxComplete", [xhr, opts]); + if (g && ! --$.active) $.event.trigger("ajaxStop"); + if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error'); + + // clean up + setTimeout(function() { + $io.remove(); + xhr.responseXML = null; + }, 100); + }; + + function toXml(s, doc) { + if (window.ActiveXObject) { + doc = new ActiveXObject('Microsoft.XMLDOM'); + doc.async = 'false'; + doc.loadXML(s); + } + else + doc = (new DOMParser()).parseFromString(s, 'text/xml'); + return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null; + }; + }; +}; + +/** + * ajaxForm() provides a mechanism for fully automating form submission. + * + * The advantages of using this method instead of ajaxSubmit() are: + * + * 1: This method will include coordinates for <input type="image" /> elements (if the element + * is used to submit the form). + * 2. This method will include the submit element's name/value data (for the element that was + * used to submit the form). + * 3. This method binds the submit() method to the form for you. + * + * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely + * passes the options argument along after properly binding events for submit elements and + * the form itself. + */ +$.fn.ajaxForm = function(options) { + return this.ajaxFormUnbind().bind('submit.form-plugin', function() { + $(this).ajaxSubmit(options); + return false; + }).bind('click.form-plugin', function(e) { + var $el = $(e.target); + if (!($el.is(":submit,input:image"))) { + return; + } + var form = this; + form.clk = e.target; + if (e.target.type == 'image') { + if (e.offsetX != undefined) { + form.clk_x = e.offsetX; + form.clk_y = e.offsetY; + } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin + var offset = $el.offset(); + form.clk_x = e.pageX - offset.left; + form.clk_y = e.pageY - offset.top; + } else { + form.clk_x = e.pageX - e.target.offsetLeft; + form.clk_y = e.pageY - e.target.offsetTop; + } + } + // clear form vars + setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 10); + }); +}; + +// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm +$.fn.ajaxFormUnbind = function() { + return this.unbind('submit.form-plugin click.form-plugin'); +}; + +/** + * formToArray() gathers form element data into an array of objects that can + * be passed to any of the following ajax functions: $.get, $.post, or load. + * Each object in the array has both a 'name' and 'value' property. An example of + * an array for a simple login form might be: + * + * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] + * + * It is this array that is passed to pre-submit callback functions provided to the + * ajaxSubmit() and ajaxForm() methods. + */ +$.fn.formToArray = function(semantic) { + var a = []; + if (this.length == 0) return a; + + var form = this[0]; + var els = semantic ? form.getElementsByTagName('*') : form.elements; + if (!els) return a; + for(var i=0, max=els.length; i < max; i++) { + var el = els[i]; + var n = el.name; + if (!n) continue; + + if (semantic && form.clk && el.type == "image") { + // handle image inputs on the fly when semantic == true + if(!el.disabled && form.clk == el) { + a.push({name: n, value: $(el).val()}); + a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); + } + continue; + } + + var v = $.fieldValue(el, true); + if (v && v.constructor == Array) { + for(var j=0, jmax=v.length; j < jmax; j++) + a.push({name: n, value: v[j]}); + } + else if (v !== null && typeof v != 'undefined') + a.push({name: n, value: v}); + } + + if (!semantic && form.clk) { + // input type=='image' are not found in elements array! handle it here + var $input = $(form.clk), input = $input[0], n = input.name; + if (n && !input.disabled && input.type == 'image') { + a.push({name: n, value: $input.val()}); + a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); + } + } + return a; +}; + +/** + * Serializes form data into a 'submittable' string. This method will return a string + * in the format: name1=value1&name2=value2 + */ +$.fn.formSerialize = function(semantic) { + //hand off to jQuery.param for proper encoding + return $.param(this.formToArray(semantic)); +}; + +/** + * Serializes all field elements in the jQuery object into a query string. + * This method will return a string in the format: name1=value1&name2=value2 + */ +$.fn.fieldSerialize = function(successful) { + var a = []; + this.each(function() { + var n = this.name; + if (!n) return; + var v = $.fieldValue(this, successful); + if (v && v.constructor == Array) { + for (var i=0,max=v.length; i < max; i++) + a.push({name: n, value: v[i]}); + } + else if (v !== null && typeof v != 'undefined') + a.push({name: this.name, value: v}); + }); + //hand off to jQuery.param for proper encoding + return $.param(a); +}; + +/** + * Returns the value(s) of the element in the matched set. For example, consider the following form: + * + * <form><fieldset> + * <input name="A" type="text" /> + * <input name="A" type="text" /> + * <input name="B" type="checkbox" value="B1" /> + * <input name="B" type="checkbox" value="B2"/> + * <input name="C" type="radio" value="C1" /> + * <input name="C" type="radio" value="C2" /> + * </fieldset></form> + * + * var v = $(':text').fieldValue(); + * // if no values are entered into the text inputs + * v == ['',''] + * // if values entered into the text inputs are 'foo' and 'bar' + * v == ['foo','bar'] + * + * var v = $(':checkbox').fieldValue(); + * // if neither checkbox is checked + * v === undefined + * // if both checkboxes are checked + * v == ['B1', 'B2'] + * + * var v = $(':radio').fieldValue(); + * // if neither radio is checked + * v === undefined + * // if first radio is checked + * v == ['C1'] + * + * The successful argument controls whether or not the field element must be 'successful' + * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). + * The default value of the successful argument is true. If this value is false the value(s) + * for each element is returned. + * + * Note: This method *always* returns an array. If no valid value can be determined the + * array will be empty, otherwise it will contain one or more values. + */ +$.fn.fieldValue = function(successful) { + for (var val=[], i=0, max=this.length; i < max; i++) { + var el = this[i]; + var v = $.fieldValue(el, successful); + if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) + continue; + v.constructor == Array ? $.merge(val, v) : val.push(v); + } + return val; +}; + +/** + * Returns the value of the field element. + */ +$.fieldValue = function(el, successful) { + var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); + if (typeof successful == 'undefined') successful = true; + + if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || + (t == 'checkbox' || t == 'radio') && !el.checked || + (t == 'submit' || t == 'image') && el.form && el.form.clk != el || + tag == 'select' && el.selectedIndex == -1)) + return null; + + if (tag == 'select') { + var index = el.selectedIndex; + if (index < 0) return null; + var a = [], ops = el.options; + var one = (t == 'select-one'); + var max = (one ? index+1 : ops.length); + for(var i=(one ? index : 0); i < max; i++) { + var op = ops[i]; + if (op.selected) { + var v = op.value; + if (!v) // extra pain for IE... + v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value; + if (one) return v; + a.push(v); + } + } + return a; + } + return el.value; +}; + +/** + * Clears the form data. Takes the following actions on the form's input fields: + * - input text fields will have their 'value' property set to the empty string + * - select elements will have their 'selectedIndex' property set to -1 + * - checkbox and radio inputs will have their 'checked' property set to false + * - inputs of type submit, button, reset, and hidden will *not* be effected + * - button elements will *not* be effected + */ +$.fn.clearForm = function() { + return this.each(function() { + $('input,select,textarea', this).clearFields(); + }); +}; + +/** + * Clears the selected form elements. + */ +$.fn.clearFields = $.fn.clearInputs = function() { + return this.each(function() { + var t = this.type, tag = this.tagName.toLowerCase(); + if (t == 'text' || t == 'password' || tag == 'textarea') + this.value = ''; + else if (t == 'checkbox' || t == 'radio') + this.checked = false; + else if (tag == 'select') + this.selectedIndex = -1; + }); +}; + +/** + * Resets the form data. Causes all form elements to be reset to their original value. + */ +$.fn.resetForm = function() { + return this.each(function() { + // guard against an input with the name of 'reset' + // note that IE reports the reset function as an 'object' + if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) + this.reset(); + }); +}; + +/** + * Enables or disables any matching elements. + */ +$.fn.enable = function(b) { + if (b == undefined) b = true; + return this.each(function() { + this.disabled = !b; + }); +}; + +/** + * Checks/unchecks any matching checkboxes or radio buttons and + * selects/deselects and matching option elements. + */ +$.fn.selected = function(select) { + if (select == undefined) select = true; + return this.each(function() { + var t = this.type; + if (t == 'checkbox' || t == 'radio') + this.checked = select; + else if (this.tagName.toLowerCase() == 'option') { + var $sel = $(this).parent('select'); + if (select && $sel[0] && $sel[0].type == 'select-one') { + // deselect all other options + $sel.find('option').selected(false); + } + this.selected = select; + } + }); +}; + +// helper fn for console logging +// set $.fn.ajaxSubmit.debug to true to enable debug logging +function log() { + if ($.fn.ajaxSubmit.debug && window.console && window.console.log) + window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,'')); +}; + +})(jQuery); diff --git a/askbot/skins/common/media/js/jquery.i18n.js b/askbot/skins/common/media/js/jquery.i18n.js new file mode 100644 index 00000000..0a155a31 --- /dev/null +++ b/askbot/skins/common/media/js/jquery.i18n.js @@ -0,0 +1,133 @@ +/* + * jQuery i18n plugin + * @requires jQuery v1.1 or later + * + * Examples at: http://recurser.com/articles/2008/02/21/jquery-i18n-translation-plugin/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Based on 'javascript i18n that almost doesn't suck' by markos + * http://markos.gaivo.net/blog/?p=100 + * + * Revision: $Id$ + * Version: 1.0.0 Feb-10-2008 + */ + (function($) { +/** + * i18n provides a mechanism for translating strings using a jscript dictionary. + * + */ + + +/* + * i18n property list + */ +$.i18n = { + +/** + * setDictionary() + * Initialise the dictionary and translate nodes + * + * @param property_list i18n_dict : The dictionary to use for translation + */ + setDictionary: function(i18n_dict) { + i18n_dict = i18n_dict; + }, + +/** + * _() + * The actual translation function. Looks the given string up in the + * dictionary and returns the translation if one exists. If a translation + * is not found, returns the original word + * + * @param string str : The string to translate + * @param property_list params : params for using printf() on the string + * @return string : Translated word + * + */ + _: function (str, params) { + var transl = str; + if (i18n_dict&& i18n_dict[str]) { + transl = i18n_dict[str]; + } + return this.printf(transl, params); + }, + +/** + * toEntity() + * Change non-ASCII characters to entity representation + * + * @param string str : The string to transform + * @return string result : Original string with non-ASCII content converted to entities + * + */ + toEntity: function (str) { + var result = ''; + for (var i=0;i<str.length; i++) { + if (str.charCodeAt(i) > 128) + result += "&#"+str.charCodeAt(i)+";"; + else + result += str.charAt(i); + } + return result; + }, + +/** + * stripStr() + * + * @param string str : The string to strip + * @return string result : Stripped string + * + */ + stripStr: function(str) { + return str.replace(/^\s*/, "").replace(/\s*$/, ""); + }, + +/** + * stripStrML() + * + * @param string str : The multi-line string to strip + * @return string result : Stripped string + * + */ + stripStrML: function(str) { + // Split because m flag doesn't exist before JS1.5 and we need to + // strip newlines anyway + var parts = str.split('\n'); + for (var i=0; i<parts.length; i++) + parts[i] = stripStr(parts[i]); + + // Don't join with empty strings, because it "concats" words + // And strip again + return stripStr(parts.join(" ")); + }, + +/* + * printf() + * C-printf like function, which substitutes %s with parameters + * given in list. %%s is used to escape %s. + * + * Doesn't work in IE5.0 (splice) + * + * @param string S : string to perform printf on. + * @param string L : Array of arguments for printf() + */ + printf: function(S, L) { + if (!L) return S; + + var nS = ""; + var tS = S.split("%s"); + + for(var i=0; i<L.length; i++) { + if (tS[i].lastIndexOf('%') == tS[i].length-1 && i != L.length-1) + tS[i] += "s"+tS.splice(i+1,1)[0]; + nS += tS[i] + L[i]; + } + return nS + tS[tS.length-1]; + } + +}; + + +})(jQuery); diff --git a/askbot/skins/common/media/js/jquery.openid.js b/askbot/skins/common/media/js/jquery.openid.js new file mode 100644 index 00000000..af7d8cb9 --- /dev/null +++ b/askbot/skins/common/media/js/jquery.openid.js @@ -0,0 +1,176 @@ +/* +openid login boxes +*/ +var providers_large = { + google: { + name: 'Google', + url: 'https://www.google.com/accounts/o8/id' + }, + yahoo: { + name: 'Yahoo', + url: 'http://yahoo.com/' + }, + aol: { + name: 'AOL', + label: 'Enter your AOL screenname.', + url: 'http://openid.aol.com/{username}' + }, + openid: { + name: 'OpenID', + label: 'Enter your OpenID.', + url: 'http://' + } +}; +var providers_small = { + myopenid: { + name: 'MyOpenID', + label: 'Enter your MyOpenID username.', + url: 'http://{username}.myopenid.com/' + }, + livejournal: { + name: 'LiveJournal', + label: 'Enter your Livejournal username.', + url: 'http://{username}.livejournal.com/' + }, + flickr: { + name: 'Flickr', + label: 'Enter your Flickr username.', + url: 'http://flickr.com/{username}/' + }, + technorati: { + name: 'Technorati', + label: 'Enter your Technorati username.', + url: 'http://technorati.com/people/technorati/{username}/' + }, + wordpress: { + name: 'Wordpress', + label: 'Enter your Wordpress.com username.', + url: 'http://{username}.wordpress.com/' + }, + blogger: { + name: 'Blogger', + label: 'Your Blogger account', + url: 'http://{username}.blogspot.com/' + }, + verisign: { + name: 'Verisign', + label: 'Your Verisign username', + url: 'http://{username}.pip.verisignlabs.com/' + }, + vidoop: { + name: 'Vidoop', + label: 'Your Vidoop username', + url: 'http://{username}.myvidoop.com/' + }, + verisign: { + name: 'Verisign', + label: 'Your Verisign username', + url: 'http://{username}.pip.verisignlabs.com/' + }, + claimid: { + name: 'ClaimID', + label: 'Your ClaimID username', + url: 'http://claimid.com/{username}' + } +}; +var providers = $.extend({}, providers_large, providers_small); + +var openid = { + + cookie_expires: 6*30, // 6 months. + cookie_name: 'openid_provider', + cookie_path: '/', + + img_path: '/media/images/openid/', + + input_id: null, + provider_url: null, + + init: function(input_id) { + + var openid_btns = $('#openid_btns'); + this.input_id = input_id; + + $('#openid_choice').show(); + //$('#openid_input_area').empty(); + + // add box for each provider + for (id in providers_large) { + openid_btns.append(this.getBoxHTML(providers_large[id], 'large', '.gif')); + } + if (providers_small) { + openid_btns.append('<br/>'); + for (id in providers_small) { + openid_btns.append(this.getBoxHTML(providers_small[id], 'small', '.ico')); + } + } + + var box_id = this.readCookie(); + if (box_id) { + this.signin(box_id, true); + } + }, + getBoxHTML: function(provider, box_size, image_ext) { + + var box_id = provider["name"].toLowerCase(); + return '<a title="'+provider["name"]+'" href="javascript: openid.signin(\''+ box_id +'\');"' + + ' style="background: #FFF url(' + this.img_path + box_id + image_ext+') no-repeat center center" ' + 'class="' + box_id + ' openid_' + box_size + '_btn"></a>'; + + }, + /* Provider image click */ + signin: function(box_id, onload) { + var provider = providers[box_id]; + if (! provider) { + return; + } + this.highlight(box_id); + this.setCookie(box_id); + + $('#'+this.input_id).val(provider['url']); + var input = $('#'+this.input_id); + if(document.selection){ + var r = document.all.openid_url.createTextRange(); + var res = r.findText("{username}"); + if(res) + r.select(); + + } + else { + var text = input.val(); + var searchText = "{username}"; + var posStart = text.indexOf(searchText); + if(posStart > -1){ + input.focus(); + document.getElementById(this.input_id).setSelectionRange(posStart, posStart + searchText.length); + } + } + }, + + highlight: function (box_id) { + // remove previous highlight. + var highlight = $('#openid_highlight'); + if (highlight) { + highlight.replaceWith($('#openid_highlight a')[0]); + } + // add new highlight. + $('.'+box_id).wrap('<div id="openid_highlight"></div>'); + }, + + setCookie: function (value) { + var date = new Date(); + date.setTime(date.getTime()+(this.cookie_expires*24*60*60*1000)); + var expires = "; expires="+date.toGMTString(); + document.cookie = this.cookie_name+"="+value+expires+"; path=" + this.cookie_path; + }, + + readCookie: function () { + var nameEQ = this.cookie_name + "="; + var ca = document.cookie.split(';'); + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1,c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); + } + return null; + } +}; diff --git a/askbot/skins/common/media/js/jquery.validate.js b/askbot/skins/common/media/js/jquery.validate.js new file mode 100644 index 00000000..e402ea8c --- /dev/null +++ b/askbot/skins/common/media/js/jquery.validate.js @@ -0,0 +1,1146 @@ +/* + * jQuery validation plug-in 1.7 + * + * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ + * http://docs.jquery.com/Plugins/Validation + * + * Copyright (c) 2006 - 2008 Jörn Zaefferer + * + * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +(function($) { + +$.extend($.fn, { + // http://docs.jquery.com/Plugins/Validation/validate + validate: function( options ) { + + // if nothing is selected, return nothing; can't chain anyway + if (!this.length) { + options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" ); + return; + } + + // check if a validator for this form was already created + var validator = $.data(this[0], 'validator'); + if ( validator ) { + return validator; + } + + validator = new $.validator( options, this[0] ); + $.data(this[0], 'validator', validator); + + if ( validator.settings.onsubmit ) { + + // allow suppresing validation by adding a cancel class to the submit button + this.find("input, button").filter(".cancel").click(function() { + validator.cancelSubmit = true; + }); + + // when a submitHandler is used, capture the submitting button + if (validator.settings.submitHandler) { + this.find("input, button").filter(":submit").click(function() { + validator.submitButton = this; + }); + } + + // validate the form on submit + this.submit( function( event ) { + if ( validator.settings.debug ) + // prevent form submit to be able to see console output + event.preventDefault(); + + function handle() { + if ( validator.settings.submitHandler ) { + if (validator.submitButton) { + // insert a hidden input as a replacement for the missing submit button + var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); + } + validator.settings.submitHandler.call( validator, validator.currentForm ); + if (validator.submitButton) { + // and clean up afterwards; thanks to no-block-scope, hidden can be referenced + hidden.remove(); + } + return false; + } + return true; + } + + // prevent submit for invalid forms or custom submit handlers + if ( validator.cancelSubmit ) { + validator.cancelSubmit = false; + return handle(); + } + if ( validator.form() ) { + if ( validator.pendingRequest ) { + validator.formSubmitted = true; + return false; + } + return handle(); + } else { + validator.focusInvalid(); + return false; + } + }); + } + + return validator; + }, + // http://docs.jquery.com/Plugins/Validation/valid + valid: function() { + if ( $(this[0]).is('form')) { + return this.validate().form(); + } else { + var valid = true; + var validator = $(this[0].form).validate(); + this.each(function() { + valid &= validator.element(this); + }); + return valid; + } + }, + // attributes: space seperated list of attributes to retrieve and remove + removeAttrs: function(attributes) { + var result = {}, + $element = this; + $.each(attributes.split(/\s/), function(index, value) { + result[value] = $element.attr(value); + $element.removeAttr(value); + }); + return result; + }, + // http://docs.jquery.com/Plugins/Validation/rules + rules: function(command, argument) { + var element = this[0]; + + if (command) { + var settings = $.data(element.form, 'validator').settings; + var staticRules = settings.rules; + var existingRules = $.validator.staticRules(element); + switch(command) { + case "add": + $.extend(existingRules, $.validator.normalizeRule(argument)); + staticRules[element.name] = existingRules; + if (argument.messages) + settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); + break; + case "remove": + if (!argument) { + delete staticRules[element.name]; + return existingRules; + } + var filtered = {}; + $.each(argument.split(/\s/), function(index, method) { + filtered[method] = existingRules[method]; + delete existingRules[method]; + }); + return filtered; + } + } + + var data = $.validator.normalizeRules( + $.extend( + {}, + $.validator.metadataRules(element), + $.validator.classRules(element), + $.validator.attributeRules(element), + $.validator.staticRules(element) + ), element); + + // make sure required is at front + if (data.required) { + var param = data.required; + delete data.required; + data = $.extend({required: param}, data); + } + + return data; + } +}); + +// Custom selectors +$.extend($.expr[":"], { + // http://docs.jquery.com/Plugins/Validation/blank + blank: function(a) {return !$.trim("" + a.value);}, + // http://docs.jquery.com/Plugins/Validation/filled + filled: function(a) {return !!$.trim("" + a.value);}, + // http://docs.jquery.com/Plugins/Validation/unchecked + unchecked: function(a) {return !a.checked;} +}); + +// constructor for validator +$.validator = function( options, form ) { + this.settings = $.extend( true, {}, $.validator.defaults, options ); + this.currentForm = form; + this.init(); +}; + +$.validator.format = function(source, params) { + if ( arguments.length == 1 ) + return function() { + var args = $.makeArray(arguments); + args.unshift(source); + return $.validator.format.apply( this, args ); + }; + if ( arguments.length > 2 && params.constructor != Array ) { + params = $.makeArray(arguments).slice(1); + } + if ( params.constructor != Array ) { + params = [ params ]; + } + $.each(params, function(i, n) { + source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n); + }); + return source; +}; + +$.extend($.validator, { + + defaults: { + messages: {}, + groups: {}, + rules: {}, + errorClass: "error", + validClass: "valid", + errorElement: "label", + focusInvalid: true, + errorContainer: $( [] ), + errorLabelContainer: $( [] ), + onsubmit: true, + ignore: [], + ignoreTitle: false, + onfocusin: function(element) { + this.lastActive = element; + + // hide error label and remove error class on focus if enabled + if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { + this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); + this.errorsFor(element).hide(); + } + }, + onfocusout: function(element) { + if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { + this.element(element); + } + }, + onkeyup: function(element) { + if ( element.name in this.submitted || element == this.lastElement ) { + this.element(element); + } + }, + onclick: function(element) { + // click on selects, radiobuttons and checkboxes + if ( element.name in this.submitted ) + this.element(element); + // or option elements, check parent select in that case + else if (element.parentNode.name in this.submitted) + this.element(element.parentNode); + }, + highlight: function( element, errorClass, validClass ) { + $(element).addClass(errorClass).removeClass(validClass); + }, + unhighlight: function( element, errorClass, validClass ) { + $(element).removeClass(errorClass).addClass(validClass); + } + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults + setDefaults: function(settings) { + $.extend( $.validator.defaults, settings ); + }, + + messages: { + required: "This field is required.", + remote: "Please fix this field.", + email: "Please enter a valid email address.", + url: "Please enter a valid URL.", + date: "Please enter a valid date.", + dateISO: "Please enter a valid date (ISO).", + number: "Please enter a valid number.", + digits: "Please enter only digits.", + creditcard: "Please enter a valid credit card number.", + equalTo: "Please enter the same value again.", + accept: "Please enter a value with a valid extension.", + maxlength: $.validator.format("Please enter no more than {0} characters."), + minlength: $.validator.format("Please enter at least {0} characters."), + rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), + range: $.validator.format("Please enter a value between {0} and {1}."), + max: $.validator.format("Please enter a value less than or equal to {0}."), + min: $.validator.format("Please enter a value greater than or equal to {0}.") + }, + + autoCreateRanges: false, + + prototype: { + + init: function() { + this.labelContainer = $(this.settings.errorLabelContainer); + this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); + this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); + this.submitted = {}; + this.valueCache = {}; + this.pendingRequest = 0; + this.pending = {}; + this.invalid = {}; + this.reset(); + + var groups = (this.groups = {}); + $.each(this.settings.groups, function(key, value) { + $.each(value.split(/\s/), function(index, name) { + groups[name] = key; + }); + }); + var rules = this.settings.rules; + $.each(rules, function(key, value) { + rules[key] = $.validator.normalizeRule(value); + }); + + function delegate(event) { + var validator = $.data(this[0].form, "validator"), + eventType = "on" + event.type.replace(/^validate/, ""); + validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] ); + } + $(this.currentForm) + .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate) + .validateDelegate(":radio, :checkbox, select, option", "click", delegate); + + if (this.settings.invalidHandler) + $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/form + form: function() { + this.checkForm(); + $.extend(this.submitted, this.errorMap); + this.invalid = $.extend({}, this.errorMap); + if (!this.valid()) + $(this.currentForm).triggerHandler("invalid-form", [this]); + this.showErrors(); + return this.valid(); + }, + + checkForm: function() { + this.prepareForm(); + for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { + this.check( elements[i] ); + } + return this.valid(); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/element + element: function( element ) { + element = this.clean( element ); + this.lastElement = element; + this.prepareElement( element ); + this.currentElements = $(element); + var result = this.check( element ); + if ( result ) { + delete this.invalid[element.name]; + } else { + this.invalid[element.name] = true; + } + if ( !this.numberOfInvalids() ) { + // Hide error containers on last error + this.toHide = this.toHide.add( this.containers ); + } + this.showErrors(); + return result; + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/showErrors + showErrors: function(errors) { + if(errors) { + // add items to error list and map + $.extend( this.errorMap, errors ); + this.errorList = []; + for ( var name in errors ) { + this.errorList.push({ + message: errors[name], + element: this.findByName(name)[0] + }); + } + // remove items from success list + this.successList = $.grep( this.successList, function(element) { + return !(element.name in errors); + }); + } + this.settings.showErrors + ? this.settings.showErrors.call( this, this.errorMap, this.errorList ) + : this.defaultShowErrors(); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/resetForm + resetForm: function() { + if ( $.fn.resetForm ) + $( this.currentForm ).resetForm(); + this.submitted = {}; + this.prepareForm(); + this.hideErrors(); + this.elements().removeClass( this.settings.errorClass ); + }, + + numberOfInvalids: function() { + return this.objectLength(this.invalid); + }, + + objectLength: function( obj ) { + var count = 0; + for ( var i in obj ) + count++; + return count; + }, + + hideErrors: function() { + this.addWrapper( this.toHide ).hide(); + }, + + valid: function() { + return this.size() == 0; + }, + + size: function() { + return this.errorList.length; + }, + + focusInvalid: function() { + if( this.settings.focusInvalid ) { + try { + $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) + .filter(":visible") + .focus() + // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find + .trigger("focusin"); + } catch(e) { + // ignore IE throwing errors when focusing hidden elements + } + } + }, + + findLastActive: function() { + var lastActive = this.lastActive; + return lastActive && $.grep(this.errorList, function(n) { + return n.element.name == lastActive.name; + }).length == 1 && lastActive; + }, + + elements: function() { + var validator = this, + rulesCache = {}; + + // select all valid inputs inside the form (no submit or reset buttons) + // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved + return $([]).add(this.currentForm.elements) + .filter(":input") + .not(":submit, :reset, :image, [disabled]") + .not( this.settings.ignore ) + .filter(function() { + !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this); + + // select only the first element for each name, and only those with rules specified + if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) + return false; + + rulesCache[this.name] = true; + return true; + }); + }, + + clean: function( selector ) { + return $( selector )[0]; + }, + + errors: function() { + return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext ); + }, + + reset: function() { + this.successList = []; + this.errorList = []; + this.errorMap = {}; + this.toShow = $([]); + this.toHide = $([]); + this.currentElements = $([]); + }, + + prepareForm: function() { + this.reset(); + this.toHide = this.errors().add( this.containers ); + }, + + prepareElement: function( element ) { + this.reset(); + this.toHide = this.errorsFor(element); + }, + + check: function( element ) { + element = this.clean( element ); + + // if radio/checkbox, validate first element in group instead + if (this.checkable(element)) { + element = this.findByName( element.name )[0]; + } + + var rules = $(element).rules(); + var dependencyMismatch = false; + for( method in rules ) { + var rule = { method: method, parameters: rules[method] }; + try { + var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters ); + + // if a method indicates that the field is optional and therefore valid, + // don't mark it as valid when there are no other rules + if ( result == "dependency-mismatch" ) { + dependencyMismatch = true; + continue; + } + dependencyMismatch = false; + + if ( result == "pending" ) { + this.toHide = this.toHide.not( this.errorsFor(element) ); + return; + } + + if( !result ) { + this.formatAndAdd( element, rule ); + return false; + } + } catch(e) { + this.settings.debug && window.console && console.log("exception occured when checking element " + element.id + + ", check the '" + rule.method + "' method", e); + throw e; + } + } + if (dependencyMismatch) + return; + if ( this.objectLength(rules) ) + this.successList.push(element); + return true; + }, + + // return the custom message for the given element and validation method + // specified in the element's "messages" metadata + customMetaMessage: function(element, method) { + if (!$.metadata) + return; + + var meta = this.settings.meta + ? $(element).metadata()[this.settings.meta] + : $(element).metadata(); + + return meta && meta.messages && meta.messages[method]; + }, + + // return the custom message for the given element name and validation method + customMessage: function( name, method ) { + var m = this.settings.messages[name]; + return m && (m.constructor == String + ? m + : m[method]); + }, + + // return the first defined argument, allowing empty strings + findDefined: function() { + for(var i = 0; i < arguments.length; i++) { + if (arguments[i] !== undefined) + return arguments[i]; + } + return undefined; + }, + + defaultMessage: function( element, method) { + return this.findDefined( + this.customMessage( element.name, method ), + this.customMetaMessage( element, method ), + // title is never undefined, so handle empty string as undefined + !this.settings.ignoreTitle && element.title || undefined, + $.validator.messages[method], + "<strong>Warning: No message defined for " + element.name + "</strong>" + ); + }, + + formatAndAdd: function( element, rule ) { + var message = this.defaultMessage( element, rule.method ), + theregex = /\$?\{(\d+)\}/g; + if ( typeof message == "function" ) { + message = message.call(this, rule.parameters, element); + } else if (theregex.test(message)) { + message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters); + } + this.errorList.push({ + message: message, + element: element + }); + + this.errorMap[element.name] = message; + this.submitted[element.name] = message; + }, + + addWrapper: function(toToggle) { + if ( this.settings.wrapper ) + toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); + return toToggle; + }, + + defaultShowErrors: function() { + for ( var i = 0; this.errorList[i]; i++ ) { + var error = this.errorList[i]; + this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); + this.showLabel( error.element, error.message ); + } + if( this.errorList.length ) { + this.toShow = this.toShow.add( this.containers ); + } + if (this.settings.success) { + for ( var i = 0; this.successList[i]; i++ ) { + this.showLabel( this.successList[i] ); + } + } + if (this.settings.unhighlight) { + for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) { + this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); + } + } + this.toHide = this.toHide.not( this.toShow ); + this.hideErrors(); + this.addWrapper( this.toShow ).show(); + }, + + validElements: function() { + return this.currentElements.not(this.invalidElements()); + }, + + invalidElements: function() { + return $(this.errorList).map(function() { + return this.element; + }); + }, + + showLabel: function(element, message) { + var label = this.errorsFor( element ); + if ( label.length ) { + // refresh error/success class + label.removeClass().addClass( this.settings.errorClass ); + + // check if we have a generated label, replace the message then + label.attr("generated") && label.html(message); + } else { + // create label + label = $("<" + this.settings.errorElement + "/>") + .attr({"for": this.idOrName(element), generated: true}) + .addClass(this.settings.errorClass) + .html(message || ""); + if ( this.settings.wrapper ) { + // make sure the element is visible, even in IE + // actually showing the wrapped element is handled elsewhere + label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); + } + if ( !this.labelContainer.append(label).length ) + this.settings.errorPlacement + ? this.settings.errorPlacement(label, $(element) ) + : label.insertAfter(element); + } + if ( !message && this.settings.success ) { + label.text(""); + typeof this.settings.success == "string" + ? label.addClass( this.settings.success ) + : this.settings.success( label ); + } + this.toShow = this.toShow.add(label); + }, + + errorsFor: function(element) { + var name = this.idOrName(element); + return this.errors().filter(function() { + return $(this).attr('for') == name; + }); + }, + + idOrName: function(element) { + return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); + }, + + checkable: function( element ) { + return /radio|checkbox/i.test(element.type); + }, + + findByName: function( name ) { + // select by name and filter by form for performance over form.find("[name=...]") + var form = this.currentForm; + return $(document.getElementsByName(name)).map(function(index, element) { + return element.form == form && element.name == name && element || null; + }); + }, + + getLength: function(value, element) { + switch( element.nodeName.toLowerCase() ) { + case 'select': + return $("option:selected", element).length; + case 'input': + if( this.checkable( element) ) + return this.findByName(element.name).filter(':checked').length; + } + return value.length; + }, + + depend: function(param, element) { + return this.dependTypes[typeof param] + ? this.dependTypes[typeof param](param, element) + : true; + }, + + dependTypes: { + "boolean": function(param, element) { + return param; + }, + "string": function(param, element) { + return !!$(param, element.form).length; + }, + "function": function(param, element) { + return param(element); + } + }, + + optional: function(element) { + return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch"; + }, + + startRequest: function(element) { + if (!this.pending[element.name]) { + this.pendingRequest++; + this.pending[element.name] = true; + } + }, + + stopRequest: function(element, valid) { + this.pendingRequest--; + // sometimes synchronization fails, make sure pendingRequest is never < 0 + if (this.pendingRequest < 0) + this.pendingRequest = 0; + delete this.pending[element.name]; + if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) { + $(this.currentForm).submit(); + this.formSubmitted = false; + } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) { + $(this.currentForm).triggerHandler("invalid-form", [this]); + this.formSubmitted = false; + } + }, + + previousValue: function(element) { + return $.data(element, "previousValue") || $.data(element, "previousValue", { + old: null, + valid: true, + message: this.defaultMessage( element, "remote" ) + }); + } + + }, + + classRuleSettings: { + required: {required: true}, + email: {email: true}, + url: {url: true}, + date: {date: true}, + dateISO: {dateISO: true}, + dateDE: {dateDE: true}, + number: {number: true}, + numberDE: {numberDE: true}, + digits: {digits: true}, + creditcard: {creditcard: true} + }, + + addClassRules: function(className, rules) { + className.constructor == String ? + this.classRuleSettings[className] = rules : + $.extend(this.classRuleSettings, className); + }, + + classRules: function(element) { + var rules = {}; + var classes = $(element).attr('class'); + classes && $.each(classes.split(' '), function() { + if (this in $.validator.classRuleSettings) { + $.extend(rules, $.validator.classRuleSettings[this]); + } + }); + return rules; + }, + + attributeRules: function(element) { + var rules = {}; + var $element = $(element); + + for (method in $.validator.methods) { + var value = $element.attr(method); + if (value) { + rules[method] = value; + } + } + + // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs + if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { + delete rules.maxlength; + } + + return rules; + }, + + metadataRules: function(element) { + if (!$.metadata) return {}; + + var meta = $.data(element.form, 'validator').settings.meta; + return meta ? + $(element).metadata()[meta] : + $(element).metadata(); + }, + + staticRules: function(element) { + var rules = {}; + var validator = $.data(element.form, 'validator'); + if (validator.settings.rules) { + rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; + } + return rules; + }, + + normalizeRules: function(rules, element) { + // handle dependency check + $.each(rules, function(prop, val) { + // ignore rule when param is explicitly false, eg. required:false + if (val === false) { + delete rules[prop]; + return; + } + if (val.param || val.depends) { + var keepRule = true; + switch (typeof val.depends) { + case "string": + keepRule = !!$(val.depends, element.form).length; + break; + case "function": + keepRule = val.depends.call(element, element); + break; + } + if (keepRule) { + rules[prop] = val.param !== undefined ? val.param : true; + } else { + delete rules[prop]; + } + } + }); + + // evaluate parameters + $.each(rules, function(rule, parameter) { + rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; + }); + + // clean number parameters + $.each(['minlength', 'maxlength', 'min', 'max'], function() { + if (rules[this]) { + rules[this] = Number(rules[this]); + } + }); + $.each(['rangelength', 'range'], function() { + if (rules[this]) { + rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; + } + }); + + if ($.validator.autoCreateRanges) { + // auto-create ranges + if (rules.min && rules.max) { + rules.range = [rules.min, rules.max]; + delete rules.min; + delete rules.max; + } + if (rules.minlength && rules.maxlength) { + rules.rangelength = [rules.minlength, rules.maxlength]; + delete rules.minlength; + delete rules.maxlength; + } + } + + // To support custom messages in metadata ignore rule methods titled "messages" + if (rules.messages) { + delete rules.messages; + } + + return rules; + }, + + // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} + normalizeRule: function(data) { + if( typeof data == "string" ) { + var transformed = {}; + $.each(data.split(/\s/), function() { + transformed[this] = true; + }); + data = transformed; + } + return data; + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/addMethod + addMethod: function(name, method, message) { + $.validator.methods[name] = method; + $.validator.messages[name] = message != undefined ? message : $.validator.messages[name]; + if (method.length < 3) { + $.validator.addClassRules(name, $.validator.normalizeRule(name)); + } + }, + + methods: { + + // http://docs.jquery.com/Plugins/Validation/Methods/required + required: function(value, element, param) { + // check if dependency is met + if ( !this.depend(param, element) ) + return "dependency-mismatch"; + switch( element.nodeName.toLowerCase() ) { + case 'select': + // could be an array for select-multiple or a string, both are fine this way + var val = $(element).val(); + return val && val.length > 0; + case 'input': + if ( this.checkable(element) ) + return this.getLength(value, element) > 0; + default: + return $.trim(value).length > 0; + } + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/remote + remote: function(value, element, param) { + if ( this.optional(element) ) + return "dependency-mismatch"; + + var previous = this.previousValue(element); + if (!this.settings.messages[element.name] ) + this.settings.messages[element.name] = {}; + previous.originalMessage = this.settings.messages[element.name].remote; + this.settings.messages[element.name].remote = previous.message; + + param = typeof param == "string" && {url:param} || param; + + if ( previous.old !== value ) { + previous.old = value; + var validator = this; + this.startRequest(element); + var data = {}; + data[element.name] = value; + $.ajax($.extend(true, { + url: param, + mode: "abort", + port: "validate" + element.name, + dataType: "json", + data: data, + success: function(response) { + validator.settings.messages[element.name].remote = previous.originalMessage; + var valid = response === true; + if ( valid ) { + var submitted = validator.formSubmitted; + validator.prepareElement(element); + validator.formSubmitted = submitted; + validator.successList.push(element); + validator.showErrors(); + } else { + var errors = {}; + var message = (previous.message = response || validator.defaultMessage( element, "remote" )); + errors[element.name] = $.isFunction(message) ? message(value) : message; + validator.showErrors(errors); + } + previous.valid = valid; + validator.stopRequest(element, valid); + } + }, param)); + return "pending"; + } else if( this.pending[element.name] ) { + return "pending"; + } + return previous.valid; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/minlength + minlength: function(value, element, param) { + return this.optional(element) || this.getLength($.trim(value), element) >= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/maxlength + maxlength: function(value, element, param) { + return this.optional(element) || this.getLength($.trim(value), element) <= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/rangelength + rangelength: function(value, element, param) { + var length = this.getLength($.trim(value), element); + return this.optional(element) || ( length >= param[0] && length <= param[1] ); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/min + min: function( value, element, param ) { + return this.optional(element) || value >= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/max + max: function( value, element, param ) { + return this.optional(element) || value <= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/range + range: function( value, element, param ) { + return this.optional(element) || ( value >= param[0] && value <= param[1] ); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/email + email: function(value, element) { + // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ + return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/url + url: function(value, element) { + // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ + return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/date + date: function(value, element) { + return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/dateISO + dateISO: function(value, element) { + return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/number + number: function(value, element) { + return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/digits + digits: function(value, element) { + return this.optional(element) || /^\d+$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/creditcard + // based on http://en.wikipedia.org/wiki/Luhn + creditcard: function(value, element) { + if ( this.optional(element) ) + return "dependency-mismatch"; + // accept only digits and dashes + if (/[^0-9-]+/.test(value)) + return false; + var nCheck = 0, + nDigit = 0, + bEven = false; + + value = value.replace(/\D/g, ""); + + for (var n = value.length - 1; n >= 0; n--) { + var cDigit = value.charAt(n); + var nDigit = parseInt(cDigit, 10); + if (bEven) { + if ((nDigit *= 2) > 9) + nDigit -= 9; + } + nCheck += nDigit; + bEven = !bEven; + } + + return (nCheck % 10) == 0; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/accept + accept: function(value, element, param) { + param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif"; + return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/equalTo + equalTo: function(value, element, param) { + // bind to the blur event of the target in order to revalidate whenever the target field is updated + // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead + var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { + $(element).valid(); + }); + return value == target.val(); + } + + } + +}); + +// deprecated, use $.validator.format instead +$.format = $.validator.format; + +})(jQuery); + +// ajax mode: abort +// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); +// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() +;(function($) { + var ajax = $.ajax; + var pendingRequests = {}; + $.ajax = function(settings) { + // create settings for compatibility with ajaxSetup + settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings)); + var port = settings.port; + if (settings.mode == "abort") { + if ( pendingRequests[port] ) { + pendingRequests[port].abort(); + } + return (pendingRequests[port] = ajax.apply(this, arguments)); + } + return ajax.apply(this, arguments); + }; +})(jQuery); + +// provides cross-browser focusin and focusout events +// IE has native support, in other browsers, use event caputuring (neither bubbles) + +// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation +// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target +;(function($) { + // only implement if not provided by jQuery core (since 1.4) + // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs + if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) { + $.each({ + focus: 'focusin', + blur: 'focusout' + }, function( original, fix ){ + $.event.special[fix] = { + setup:function() { + this.addEventListener( original, handler, true ); + }, + teardown:function() { + this.removeEventListener( original, handler, true ); + }, + handler: function(e) { + arguments[0] = $.event.fix(e); + arguments[0].type = fix; + return $.event.handle.apply(this, arguments); + } + }; + function handler(e) { + e = $.event.fix(e); + e.type = fix; + return $.event.handle.call(this, e); + } + }); + }; + $.extend($.fn, { + validateDelegate: function(delegate, type, handler) { + return this.bind(type, function(event) { + var target = $(event.target); + if (target.is(delegate)) { + return handler.apply(target, arguments); + } + }); + } + }); +})(jQuery); diff --git a/askbot/skins/common/media/js/jquery.validate.min.js b/askbot/skins/common/media/js/jquery.validate.min.js new file mode 100644 index 00000000..6264866f --- /dev/null +++ b/askbot/skins/common/media/js/jquery.validate.min.js @@ -0,0 +1,16 @@ +/* + * jQuery validation plug-in 1.7 + * + * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ + * http://docs.jquery.com/Plugins/Validation + * + * Copyright (c) 2006 - 2008 Jörn Zaefferer + * + * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ +(function($){$.extend($.fn,{validate:function(options){if(!this.length){options&&options.debug&&window.console&&console.warn("nothing selected, can't validate, returning nothing");return;}var validator=$.data(this[0],'validator');if(validator){return validator;}validator=new $.validator(options,this[0]);$.data(this[0],'validator',validator);if(validator.settings.onsubmit){this.find("input, button").filter(".cancel").click(function(){validator.cancelSubmit=true;});if(validator.settings.submitHandler){this.find("input, button").filter(":submit").click(function(){validator.submitButton=this;});}this.submit(function(event){if(validator.settings.debug)event.preventDefault();function handle(){if(validator.settings.submitHandler){if(validator.submitButton){var hidden=$("<input type='hidden'/>").attr("name",validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);}validator.settings.submitHandler.call(validator,validator.currentForm);if(validator.submitButton){hidden.remove();}return false;}return true;}if(validator.cancelSubmit){validator.cancelSubmit=false;return handle();}if(validator.form()){if(validator.pendingRequest){validator.formSubmitted=true;return false;}return handle();}else{validator.focusInvalid();return false;}});}return validator;},valid:function(){if($(this[0]).is('form')){return this.validate().form();}else{var valid=true;var validator=$(this[0].form).validate();this.each(function(){valid&=validator.element(this);});return valid;}},removeAttrs:function(attributes){var result={},$element=this;$.each(attributes.split(/\s/),function(index,value){result[value]=$element.attr(value);$element.removeAttr(value);});return result;},rules:function(command,argument){var element=this[0];if(command){var settings=$.data(element.form,'validator').settings;var staticRules=settings.rules;var existingRules=$.validator.staticRules(element);switch(command){case"add":$.extend(existingRules,$.validator.normalizeRule(argument));staticRules[element.name]=existingRules;if(argument.messages)settings.messages[element.name]=$.extend(settings.messages[element.name],argument.messages);break;case"remove":if(!argument){delete staticRules[element.name];return existingRules;}var filtered={};$.each(argument.split(/\s/),function(index,method){filtered[method]=existingRules[method];delete existingRules[method];});return filtered;}}var data=$.validator.normalizeRules($.extend({},$.validator.metadataRules(element),$.validator.classRules(element),$.validator.attributeRules(element),$.validator.staticRules(element)),element);if(data.required){var param=data.required;delete data.required;data=$.extend({required:param},data);}return data;}});$.extend($.expr[":"],{blank:function(a){return!$.trim(""+a.value);},filled:function(a){return!!$.trim(""+a.value);},unchecked:function(a){return!a.checked;}});$.validator=function(options,form){this.settings=$.extend(true,{},$.validator.defaults,options);this.currentForm=form;this.init();};$.validator.format=function(source,params){if(arguments.length==1)return function(){var args=$.makeArray(arguments);args.unshift(source);return $.validator.format.apply(this,args);};if(arguments.length>2&¶ms.constructor!=Array){params=$.makeArray(arguments).slice(1);}if(params.constructor!=Array){params=[params];}$.each(params,function(i,n){source=source.replace(new RegExp("\\{"+i+"\\}","g"),n);});return source;};$.extend($.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:true,errorContainer:$([]),errorLabelContainer:$([]),onsubmit:true,ignore:[],ignoreTitle:false,onfocusin:function(element){this.lastActive=element;if(this.settings.focusCleanup&&!this.blockFocusCleanup){this.settings.unhighlight&&this.settings.unhighlight.call(this,element,this.settings.errorClass,this.settings.validClass);this.errorsFor(element).hide();}},onfocusout:function(element){if(!this.checkable(element)&&(element.name in this.submitted||!this.optional(element))){this.element(element);}},onkeyup:function(element){if(element.name in this.submitted||element==this.lastElement){this.element(element);}},onclick:function(element){if(element.name in this.submitted)this.element(element);else if(element.parentNode.name in this.submitted)this.element(element.parentNode);},highlight:function(element,errorClass,validClass){$(element).addClass(errorClass).removeClass(validClass);},unhighlight:function(element,errorClass,validClass){$(element).removeClass(errorClass).addClass(validClass);}},setDefaults:function(settings){$.extend($.validator.defaults,settings);},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",accept:"Please enter a value with a valid extension.",maxlength:$.validator.format("Please enter no more than {0} characters."),minlength:$.validator.format("Please enter at least {0} characters."),rangelength:$.validator.format("Please enter a value between {0} and {1} characters long."),range:$.validator.format("Please enter a value between {0} and {1}."),max:$.validator.format("Please enter a value less than or equal to {0}."),min:$.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:false,prototype:{init:function(){this.labelContainer=$(this.settings.errorLabelContainer);this.errorContext=this.labelContainer.length&&this.labelContainer||$(this.currentForm);this.containers=$(this.settings.errorContainer).add(this.settings.errorLabelContainer);this.submitted={};this.valueCache={};this.pendingRequest=0;this.pending={};this.invalid={};this.reset();var groups=(this.groups={});$.each(this.settings.groups,function(key,value){$.each(value.split(/\s/),function(index,name){groups[name]=key;});});var rules=this.settings.rules;$.each(rules,function(key,value){rules[key]=$.validator.normalizeRule(value);});function delegate(event){var validator=$.data(this[0].form,"validator"),eventType="on"+event.type.replace(/^validate/,"");validator.settings[eventType]&&validator.settings[eventType].call(validator,this[0]);}$(this.currentForm).validateDelegate(":text, :password, :file, select, textarea","focusin focusout keyup",delegate).validateDelegate(":radio, :checkbox, select, option","click",delegate);if(this.settings.invalidHandler)$(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler);},form:function(){this.checkForm();$.extend(this.submitted,this.errorMap);this.invalid=$.extend({},this.errorMap);if(!this.valid())$(this.currentForm).triggerHandler("invalid-form",[this]);this.showErrors();return this.valid();},checkForm:function(){this.prepareForm();for(var i=0,elements=(this.currentElements=this.elements());elements[i];i++){this.check(elements[i]);}return this.valid();},element:function(element){element=this.clean(element);this.lastElement=element;this.prepareElement(element);this.currentElements=$(element);var result=this.check(element);if(result){delete this.invalid[element.name];}else{this.invalid[element.name]=true;}if(!this.numberOfInvalids()){this.toHide=this.toHide.add(this.containers);}this.showErrors();return result;},showErrors:function(errors){if(errors){$.extend(this.errorMap,errors);this.errorList=[];for(var name in errors){this.errorList.push({message:errors[name],element:this.findByName(name)[0]});}this.successList=$.grep(this.successList,function(element){return!(element.name in errors);});}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors();},resetForm:function(){if($.fn.resetForm)$(this.currentForm).resetForm();this.submitted={};this.prepareForm();this.hideErrors();this.elements().removeClass(this.settings.errorClass);},numberOfInvalids:function(){return this.objectLength(this.invalid);},objectLength:function(obj){var count=0;for(var i in obj)count++;return count;},hideErrors:function(){this.addWrapper(this.toHide).hide();},valid:function(){return this.size()==0;},size:function(){return this.errorList.length;},focusInvalid:function(){if(this.settings.focusInvalid){try{$(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin");}catch(e){}}},findLastActive:function(){var lastActive=this.lastActive;return lastActive&&$.grep(this.errorList,function(n){return n.element.name==lastActive.name;}).length==1&&lastActive;},elements:function(){var validator=this,rulesCache={};return $([]).add(this.currentForm.elements).filter(":input").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){!this.name&&validator.settings.debug&&window.console&&console.error("%o has no name assigned",this);if(this.name in rulesCache||!validator.objectLength($(this).rules()))return false;rulesCache[this.name]=true;return true;});},clean:function(selector){return $(selector)[0];},errors:function(){return $(this.settings.errorElement+"."+this.settings.errorClass,this.errorContext);},reset:function(){this.successList=[];this.errorList=[];this.errorMap={};this.toShow=$([]);this.toHide=$([]);this.currentElements=$([]);},prepareForm:function(){this.reset();this.toHide=this.errors().add(this.containers);},prepareElement:function(element){this.reset();this.toHide=this.errorsFor(element);},check:function(element){element=this.clean(element);if(this.checkable(element)){element=this.findByName(element.name)[0];}var rules=$(element).rules();var dependencyMismatch=false;for(method in rules){var rule={method:method,parameters:rules[method]};try{var result=$.validator.methods[method].call(this,element.value.replace(/\r/g,""),element,rule.parameters);if(result=="dependency-mismatch"){dependencyMismatch=true;continue;}dependencyMismatch=false;if(result=="pending"){this.toHide=this.toHide.not(this.errorsFor(element));return;}if(!result){this.formatAndAdd(element,rule);return false;}}catch(e){this.settings.debug&&window.console&&console.log("exception occured when checking element "+element.id ++", check the '"+rule.method+"' method",e);throw e;}}if(dependencyMismatch)return;if(this.objectLength(rules))this.successList.push(element);return true;},customMetaMessage:function(element,method){if(!$.metadata)return;var meta=this.settings.meta?$(element).metadata()[this.settings.meta]:$(element).metadata();return meta&&meta.messages&&meta.messages[method];},customMessage:function(name,method){var m=this.settings.messages[name];return m&&(m.constructor==String?m:m[method]);},findDefined:function(){for(var i=0;i<arguments.length;i++){if(arguments[i]!==undefined)return arguments[i];}return undefined;},defaultMessage:function(element,method){return this.findDefined(this.customMessage(element.name,method),this.customMetaMessage(element,method),!this.settings.ignoreTitle&&element.title||undefined,$.validator.messages[method],"<strong>Warning: No message defined for "+element.name+"</strong>");},formatAndAdd:function(element,rule){var message=this.defaultMessage(element,rule.method),theregex=/\$?\{(\d+)\}/g;if(typeof message=="function"){message=message.call(this,rule.parameters,element);}else if(theregex.test(message)){message=jQuery.format(message.replace(theregex,'{$1}'),rule.parameters);}this.errorList.push({message:message,element:element});this.errorMap[element.name]=message;this.submitted[element.name]=message;},addWrapper:function(toToggle){if(this.settings.wrapper)toToggle=toToggle.add(toToggle.parent(this.settings.wrapper));return toToggle;},defaultShowErrors:function(){for(var i=0;this.errorList[i];i++){var error=this.errorList[i];this.settings.highlight&&this.settings.highlight.call(this,error.element,this.settings.errorClass,this.settings.validClass);this.showLabel(error.element,error.message);}if(this.errorList.length){this.toShow=this.toShow.add(this.containers);}if(this.settings.success){for(var i=0;this.successList[i];i++){this.showLabel(this.successList[i]);}}if(this.settings.unhighlight){for(var i=0,elements=this.validElements();elements[i];i++){this.settings.unhighlight.call(this,elements[i],this.settings.errorClass,this.settings.validClass);}}this.toHide=this.toHide.not(this.toShow);this.hideErrors();this.addWrapper(this.toShow).show();},validElements:function(){return this.currentElements.not(this.invalidElements());},invalidElements:function(){return $(this.errorList).map(function(){return this.element;});},showLabel:function(element,message){var label=this.errorsFor(element);if(label.length){label.removeClass().addClass(this.settings.errorClass);label.attr("generated")&&label.html(message);}else{label=$("<"+this.settings.errorElement+"/>").attr({"for":this.idOrName(element),generated:true}).addClass(this.settings.errorClass).html(message||"");if(this.settings.wrapper){label=label.hide().show().wrap("<"+this.settings.wrapper+"/>").parent();}if(!this.labelContainer.append(label).length)this.settings.errorPlacement?this.settings.errorPlacement(label,$(element)):label.insertAfter(element);}if(!message&&this.settings.success){label.text("");typeof this.settings.success=="string"?label.addClass(this.settings.success):this.settings.success(label);}this.toShow=this.toShow.add(label);},errorsFor:function(element){var name=this.idOrName(element);return this.errors().filter(function(){return $(this).attr('for')==name;});},idOrName:function(element){return this.groups[element.name]||(this.checkable(element)?element.name:element.id||element.name);},checkable:function(element){return/radio|checkbox/i.test(element.type);},findByName:function(name){var form=this.currentForm;return $(document.getElementsByName(name)).map(function(index,element){return element.form==form&&element.name==name&&element||null;});},getLength:function(value,element){switch(element.nodeName.toLowerCase()){case'select':return $("option:selected",element).length;case'input':if(this.checkable(element))return this.findByName(element.name).filter(':checked').length;}return value.length;},depend:function(param,element){return this.dependTypes[typeof param]?this.dependTypes[typeof param](param,element):true;},dependTypes:{"boolean":function(param,element){return param;},"string":function(param,element){return!!$(param,element.form).length;},"function":function(param,element){return param(element);}},optional:function(element){return!$.validator.methods.required.call(this,$.trim(element.value),element)&&"dependency-mismatch";},startRequest:function(element){if(!this.pending[element.name]){this.pendingRequest++;this.pending[element.name]=true;}},stopRequest:function(element,valid){this.pendingRequest--;if(this.pendingRequest<0)this.pendingRequest=0;delete this.pending[element.name];if(valid&&this.pendingRequest==0&&this.formSubmitted&&this.form()){$(this.currentForm).submit();this.formSubmitted=false;}else if(!valid&&this.pendingRequest==0&&this.formSubmitted){$(this.currentForm).triggerHandler("invalid-form",[this]);this.formSubmitted=false;}},previousValue:function(element){return $.data(element,"previousValue")||$.data(element,"previousValue",{old:null,valid:true,message:this.defaultMessage(element,"remote")});}},classRuleSettings:{required:{required:true},email:{email:true},url:{url:true},date:{date:true},dateISO:{dateISO:true},dateDE:{dateDE:true},number:{number:true},numberDE:{numberDE:true},digits:{digits:true},creditcard:{creditcard:true}},addClassRules:function(className,rules){className.constructor==String?this.classRuleSettings[className]=rules:$.extend(this.classRuleSettings,className);},classRules:function(element){var rules={};var classes=$(element).attr('class');classes&&$.each(classes.split(' '),function(){if(this in $.validator.classRuleSettings){$.extend(rules,$.validator.classRuleSettings[this]);}});return rules;},attributeRules:function(element){var rules={};var $element=$(element);for(method in $.validator.methods){var value=$element.attr(method);if(value){rules[method]=value;}}if(rules.maxlength&&/-1|2147483647|524288/.test(rules.maxlength)){delete rules.maxlength;}return rules;},metadataRules:function(element){if(!$.metadata)return{};var meta=$.data(element.form,'validator').settings.meta;return meta?$(element).metadata()[meta]:$(element).metadata();},staticRules:function(element){var rules={};var validator=$.data(element.form,'validator');if(validator.settings.rules){rules=$.validator.normalizeRule(validator.settings.rules[element.name])||{};}return rules;},normalizeRules:function(rules,element){$.each(rules,function(prop,val){if(val===false){delete rules[prop];return;}if(val.param||val.depends){var keepRule=true;switch(typeof val.depends){case"string":keepRule=!!$(val.depends,element.form).length;break;case"function":keepRule=val.depends.call(element,element);break;}if(keepRule){rules[prop]=val.param!==undefined?val.param:true;}else{delete rules[prop];}}});$.each(rules,function(rule,parameter){rules[rule]=$.isFunction(parameter)?parameter(element):parameter;});$.each(['minlength','maxlength','min','max'],function(){if(rules[this]){rules[this]=Number(rules[this]);}});$.each(['rangelength','range'],function(){if(rules[this]){rules[this]=[Number(rules[this][0]),Number(rules[this][1])];}});if($.validator.autoCreateRanges){if(rules.min&&rules.max){rules.range=[rules.min,rules.max];delete rules.min;delete rules.max;}if(rules.minlength&&rules.maxlength){rules.rangelength=[rules.minlength,rules.maxlength];delete rules.minlength;delete rules.maxlength;}}if(rules.messages){delete rules.messages;}return rules;},normalizeRule:function(data){if(typeof data=="string"){var transformed={};$.each(data.split(/\s/),function(){transformed[this]=true;});data=transformed;}return data;},addMethod:function(name,method,message){$.validator.methods[name]=method;$.validator.messages[name]=message!=undefined?message:$.validator.messages[name];if(method.length<3){$.validator.addClassRules(name,$.validator.normalizeRule(name));}},methods:{required:function(value,element,param){if(!this.depend(param,element))return"dependency-mismatch";switch(element.nodeName.toLowerCase()){case'select':var val=$(element).val();return val&&val.length>0;case'input':if(this.checkable(element))return this.getLength(value,element)>0;default:return $.trim(value).length>0;}},remote:function(value,element,param){if(this.optional(element))return"dependency-mismatch";var previous=this.previousValue(element);if(!this.settings.messages[element.name])this.settings.messages[element.name]={};previous.originalMessage=this.settings.messages[element.name].remote;this.settings.messages[element.name].remote=previous.message;param=typeof param=="string"&&{url:param}||param;if(previous.old!==value){previous.old=value;var validator=this;this.startRequest(element);var data={};data[element.name]=value;$.ajax($.extend(true,{url:param,mode:"abort",port:"validate"+element.name,dataType:"json",data:data,success:function(response){validator.settings.messages[element.name].remote=previous.originalMessage;var valid=response===true;if(valid){var submitted=validator.formSubmitted;validator.prepareElement(element);validator.formSubmitted=submitted;validator.successList.push(element);validator.showErrors();}else{var errors={};var message=(previous.message=response||validator.defaultMessage(element,"remote"));errors[element.name]=$.isFunction(message)?message(value):message;validator.showErrors(errors);}previous.valid=valid;validator.stopRequest(element,valid);}},param));return"pending";}else if(this.pending[element.name]){return"pending";}return previous.valid;},minlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)>=param;},maxlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)<=param;},rangelength:function(value,element,param){var length=this.getLength($.trim(value),element);return this.optional(element)||(length>=param[0]&&length<=param[1]);},min:function(value,element,param){return this.optional(element)||value>=param;},max:function(value,element,param){return this.optional(element)||value<=param;},range:function(value,element,param){return this.optional(element)||(value>=param[0]&&value<=param[1]);},email:function(value,element){return this.optional(element)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);},url:function(value,element){return this.optional(element)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);},date:function(value,element){return this.optional(element)||!/Invalid|NaN/.test(new Date(value));},dateISO:function(value,element){return this.optional(element)||/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);},number:function(value,element){return this.optional(element)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);},digits:function(value,element){return this.optional(element)||/^\d+$/.test(value);},creditcard:function(value,element){if(this.optional(element))return"dependency-mismatch";if(/[^0-9-]+/.test(value))return false;var nCheck=0,nDigit=0,bEven=false;value=value.replace(/\D/g,"");for(var n=value.length-1;n>=0;n--){var cDigit=value.charAt(n);var nDigit=parseInt(cDigit,10);if(bEven){if((nDigit*=2)>9)nDigit-=9;}nCheck+=nDigit;bEven=!bEven;}return(nCheck%10)==0;},accept:function(value,element,param){param=typeof param=="string"?param.replace(/,/g,'|'):"png|jpe?g|gif";return this.optional(element)||value.match(new RegExp(".("+param+")$","i"));},equalTo:function(value,element,param){var target=$(param).unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){$(element).valid();});return value==target.val();}}});$.format=$.validator.format;})(jQuery);;(function($){var ajax=$.ajax;var pendingRequests={};$.ajax=function(settings){settings=$.extend(settings,$.extend({},$.ajaxSettings,settings));var port=settings.port;if(settings.mode=="abort"){if(pendingRequests[port]){pendingRequests[port].abort();}return(pendingRequests[port]=ajax.apply(this,arguments));}return ajax.apply(this,arguments);};})(jQuery);;(function($){if(!jQuery.event.special.focusin&&!jQuery.event.special.focusout&&document.addEventListener){$.each({focus:'focusin',blur:'focusout'},function(original,fix){$.event.special[fix]={setup:function(){this.addEventListener(original,handler,true);},teardown:function(){this.removeEventListener(original,handler,true);},handler:function(e){arguments[0]=$.event.fix(e);arguments[0].type=fix;return $.event.handle.apply(this,arguments);}};function handler(e){e=$.event.fix(e);e.type=fix;return $.event.handle.call(this,e);}});};$.extend($.fn,{validateDelegate:function(delegate,type,handler){return this.bind(type,function(event){var target=$(event.target);if(target.is(delegate)){return handler.apply(target,arguments);}});}});})(jQuery);
\ No newline at end of file diff --git a/askbot/skins/common/media/js/jquery.validate.pack.js b/askbot/skins/common/media/js/jquery.validate.pack.js new file mode 100644 index 00000000..49134500 --- /dev/null +++ b/askbot/skins/common/media/js/jquery.validate.pack.js @@ -0,0 +1,15 @@ +/* + * jQuery validation plug-in 1.5 + * + * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ + * http://docs.jquery.com/Plugins/Validation + * + * Copyright (c) 2006 - 2008 Jörn Zaefferer + * + * $Id: jquery.validate.js 5952 2008-11-25 19:12:30Z joern.zaefferer $ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ +eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(7($){$.G($.2J,{1y:7(c){l(!6.E){c&&c.2g&&2T.1q&&1q.4Z("3r 2y, 4B\'t 1y, 6d 3r");8}p b=$.16(6[0],\'u\');l(b){8 b}b=1V $.u(c,6[0]);$.16(6[0],\'u\',b);l(b.q.3s){6.4I("1Y, 4E").1t(".4w").4p(7(){b.35=v});6.30(7(a){l(b.q.2g)a.5X();7 24(){l(b.q.3S){b.q.3S.12(b,b.V);8 H}8 v}l(b.35){b.35=H;8 24()}l(b.K()){l(b.1g){b.1v=v;8 H}8 24()}1c{b.2i();8 H}})}8 b},M:7(){l($(6[0]).2H(\'K\')){8 6.1y().K()}1c{p b=H;p a=$(6[0].K).1y();6.O(7(){b|=a.L(6)});8 b}},4L:7(a){p b={},$L=6;$.O(a.1H(/\\s/),7(){b[6]=$L.1G(6);$L.4G(6)});8 b},1b:7(h,k){p f=6[0];l(h){p i=$.16(f.K,\'u\').q;p d=i.1b;p c=$.u.2s(f);2q(h){1e"2o":$.G(c,$.u.1S(k));d[f.r]=c;l(k.J)i.J[f.r]=$.G(i.J[f.r],k.J);31;1e"63":l(!k){R d[f.r];8 c}p e={};$.O(k.1H(/\\s/),7(a,b){e[b]=c[b];R c[b]});8 e}}p g=$.u.3x($.G({},$.u.40(f),$.u.3W(f),$.u.3T(f),$.u.2s(f)),f);l(g.13){p j=g.13;R g.13;g=$.G({13:j},g)}8 g},Y:7(t){8 6.5A(6.2o(t).5w())}});$.G($.5t[":"],{5p:7(a){8!$.2b(a.T)},5m:7(a){8!!$.2b(a.T)},5i:7(a){8!a.3U}});$.1a=7(c,b){l(P.E==1)8 7(){p a=$.48(P);a.52(c);8 $.1a.1I(6,a)};l(P.E>2&&b.2m!=3A){b=$.48(P).4O(1)}l(b.2m!=3A){b=[b]}$.O(b,7(i,n){c=c.3u(1V 3t("\\\\{"+i+"\\\\}","g"),n)});8 c};$.u=7(b,a){6.q=$.G({},$.u.2D,b);6.V=a;6.3q()};$.G($.u,{2D:{J:{},21:{},1b:{},18:"3l",2B:"4H",2i:v,3k:$([]),2A:$([]),3s:v,3j:[],3h:H,4F:7(a){6.3g=a;l(6.q.4D&&!6.4C){6.q.1U&&6.q.1U.12(6,a,6.q.18);6.1E(a).2v()}},4z:7(a){l(!6.1u(a)&&(a.r Z 6.1j||!6.F(a))){6.L(a)}},4t:7(a){l(a.r Z 6.1j||a==6.4q){6.L(a)}},6n:7(a){l(a.r Z 6.1j)6.L(a)},37:7(a,b){$(a).2p(b)},1U:7(a,b){$(a).36(b)}},6g:7(a){$.G($.u.2D,a)},J:{13:"6e 4k 2H 13.",1R:"I 38 6 4k.",1F:"I N a M 1F 65.",1k:"I N a M 62.",1l:"I N a M 1l.",2a:"I N a M 1l (61).",20:"45 44 42 2E 5T¼5S 5R 2E.",1n:"I N a M 1n.",28:"45 44 42 5N 5M 2E.",1O:"I N 5G 1O",2d:"I N a M 5E 5C 1n.",3P:"I N 3O 5v T 5u.",3L:"I N a T 5q a M 5o.",15:$.1a("I N 3K 5n 2O {0} 2R."),1r:$.1a("I N 5k 5h {0} 2R."),2h:$.1a("I N a T 3E {0} 3R {1} 2R 5c."),27:$.1a("I N a T 3E {0} 3R {1}."),1m:$.1a("I N a T 5a 2O 47 43 3D {0}."),1w:$.1a("I N a T 51 2O 47 43 3D {0}.")},4f:H,4Y:{3q:7(){6.26=$(6.q.2A);6.3C=6.26.E&&6.26||$(6.V);6.2k=$(6.q.3k).2o(6.q.2A);6.1j={};6.4S={};6.1g=0;6.1d={};6.1f={};6.1J();p f=(6.21={});$.O(6.q.21,7(d,c){$.O(c.1H(/\\s/),7(a,b){f[b]=d})});p e=6.q.1b;$.O(e,7(b,a){e[b]=$.u.1S(a)});7 1p(a){p b=$.16(6[0].K,"u");b.q["3z"+a.1o]&&b.q["3z"+a.1o].12(b,6[0])}$(6.V).1p("3y 3w 4N",":2F, :4M, :4K, 23, 4J",1p).1p("4p",":3p, :3o",1p);l(6.q.3n)$(6.V).3m("1f-K.1y",6.q.3n)},K:7(){6.3v();$.G(6.1j,6.1z);6.1f=$.G({},6.1z);l(!6.M())$(6.V).2C("1f-K",[6]);6.1h();8 6.M()},3v:7(){6.2G();Q(p i=0,11=(6.1Z=6.11());11[i];i++){6.2n(11[i])}8 6.M()},L:7(a){a=6.2z(a);6.4q=a;6.2N(a);6.1Z=$(a);p b=6.2n(a);l(b){R 6.1f[a.r]}1c{6.1f[a.r]=v}l(!6.3i()){6.14.Y(6.2k)}6.1h();8 b},1h:7(b){l(b){$.G(6.1z,b);6.S=[];Q(p c Z b){6.S.Y({19:b[c],L:6.1X(c)[0]})}6.1i=$.3f(6.1i,7(a){8!(a.r Z b)})}6.q.1h?6.q.1h.12(6,6.1z,6.S):6.3e()},2x:7(){l($.2J.2x)$(6.V).2x();6.1j={};6.2G();6.2W();6.11().36(6.q.18)},3i:7(){8 6.2c(6.1f)},2c:7(a){p b=0;Q(p i Z a)b++;8 b},2W:7(){6.2w(6.14).2v()},M:7(){8 6.3d()==0},3d:7(){8 6.S.E},2i:7(){l(6.q.2i){3c{$(6.3b()||6.S.E&&6.S[0].L||[]).1t(":4A").3a()}39(e){}}},3b:7(){p a=6.3g;8 a&&$.3f(6.S,7(n){8 n.L.r==a.r}).E==1&&a},11:7(){p a=6,2u={};8 $([]).2o(6.V.11).1t(":1Y").1D(":30, :1J, :4y, [4x]").1D(6.q.3j).1t(7(){!6.r&&a.q.2g&&2T.1q&&1q.3l("%o 4v 3K r 4u",6);l(6.r Z 2u||!a.2c($(6).1b()))8 H;2u[6.r]=v;8 v})},2z:7(a){8 $(a)[0]},2t:7(){8 $(6.q.2B+"."+6.q.18,6.3C)},1J:7(){6.1i=[];6.S=[];6.1z={};6.1C=$([]);6.14=$([]);6.1v=H;6.1Z=$([])},2G:7(){6.1J();6.14=6.2t().Y(6.2k)},2N:7(a){6.1J();6.14=6.1E(a)},2n:7(d){d=6.2z(d);l(6.1u(d)){d=6.1X(d.r)[0]}p a=$(d).1b();p c=H;Q(W Z a){p b={W:W,2r:a[W]};3c{p f=$.u.1P[W].12(6,d.T,d,b.2r);l(f=="1T-1Q"){c=v;6m}c=H;l(f=="1d"){6.14=6.14.1D(6.1E(d));8}l(!f){6.4o(d,b);8 H}}39(e){6.q.2g&&2T.1q&&1q.6l("6k 6j 6i 6h L "+d.4n+", 2n 3O \'"+b.W+"\' W");6f e;}}l(c)8;l(6.2c(a))6.1i.Y(d);8 v},4l:7(a,b){l(!$.1x)8;p c=6.q.33?$(a).1x()[6.q.33]:$(a).1x();8 c&&c.J&&c.J[b]},4j:7(a,b){p m=6.q.J[a];8 m&&(m.2m==4i?m:m[b])},4h:7(){Q(p i=0;i<P.E;i++){l(P[i]!==2l)8 P[i]}8 2l},2j:7(a,b){8 6.4h(6.4j(a.r,b),6.4l(a,b),!6.q.3h&&a.6c||2l,$.u.J[b],"<4g>6b: 6a 19 68 Q "+a.r+"</4g>")},4o:7(b,a){p c=6.2j(b,a.W);l(17 c=="7")c=c.12(6,a.2r,b);6.S.Y({19:c,L:b});6.1z[b.r]=c;6.1j[b.r]=c},2w:7(a){l(6.q.1W)a.Y(a.64(6.q.1W));8 a},3e:7(){Q(p i=0;6.S[i];i++){p a=6.S[i];6.q.37&&6.q.37.12(6,a.L,6.q.18);6.2Z(a.L,a.19)}l(6.S.E){6.1C.Y(6.2k)}l(6.q.1s){Q(p i=0;6.1i[i];i++){6.2Z(6.1i[i])}}l(6.q.1U){Q(p i=0,11=6.4e();11[i];i++){6.q.1U.12(6,11[i],6.q.18)}}6.14=6.14.1D(6.1C);6.2W();6.2w(6.1C).4d()},4e:7(){8 6.1Z.1D(6.4c())},4c:7(){8 $(6.S).4b(7(){8 6.L})},2Z:7(a,c){p b=6.1E(a);l(b.E){b.36().2p(6.q.18);b.1G("4a")&&b.49(c)}1c{b=$("<"+6.q.2B+"/>").1G({"Q":6.2Y(a),4a:v}).2p(6.q.18).49(c||"");l(6.q.1W){b=b.2v().4d().60("<"+6.q.1W+">").5Z()}l(!6.26.5Y(b).E)6.q.46?6.q.46(b,$(a)):b.5W(a)}l(!c&&6.q.1s){b.2F("");17 6.q.1s=="1B"?b.2p(6.q.1s):6.q.1s(b)}6.1C.Y(b)},1E:7(a){8 6.2t().1t("[@Q=\'"+6.2Y(a)+"\']")},2Y:7(a){8 6.21[a.r]||(6.1u(a)?a.r:a.4n||a.r)},1u:7(a){8/3p|3o/i.U(a.1o)},1X:7(d){p c=6.V;8 $(5V.5U(d)).4b(7(a,b){8 b.K==c&&b.r==d&&b||41})},1K:7(a,b){2q(b.3Z.3Y()){1e\'23\':8 $("3X:2y",b).E;1e\'1Y\':l(6.1u(b))8 6.1X(b.r).1t(\':3U\').E}8 a.E},3B:7(b,a){8 6.2X[17 b]?6.2X[17 b](b,a):v},2X:{"5Q":7(b,a){8 b},"1B":7(b,a){8!!$(b,a.K).E},"7":7(b,a){8 b(a)}},F:7(a){8!$.u.1P.13.12(6,$.2b(a.T),a)&&"1T-1Q"},3V:7(a){l(!6.1d[a.r]){6.1g++;6.1d[a.r]=v}},4s:7(a,b){6.1g--;l(6.1g<0)6.1g=0;R 6.1d[a.r];l(b&&6.1g==0&&6.1v&&6.K()){$(6.V).30()}1c l(!b&&6.1g==0&&6.1v){$(6.V).2C("1f-K",[6])}},2f:7(a){8 $.16(a,"2f")||$.16(a,"2f",5O={2K:41,M:v,19:6.2j(a,"1R")})}},1M:{13:{13:v},1F:{1F:v},1k:{1k:v},1l:{1l:v},2a:{2a:v},20:{20:v},1n:{1n:v},28:{28:v},1O:{1O:v},2d:{2d:v}},3Q:7(a,b){a.2m==4i?6.1M[a]=b:$.G(6.1M,a)},3W:7(b){p a={};p c=$(b).1G(\'5K\');c&&$.O(c.1H(\' \'),7(){l(6 Z $.u.1M){$.G(a,$.u.1M[6])}});8 a},3T:7(c){p a={};p d=$(c);Q(W Z $.u.1P){p b=d.1G(W);l(b){a[W]=b}}l(a.15&&/-1|5J|5H/.U(a.15)){R a.15}8 a},40:7(a){l(!$.1x)8{};p b=$.16(a.K,\'u\').q.33;8 b?$(a).1x()[b]:$(a).1x()},2s:7(b){p a={};p c=$.16(b.K,\'u\');l(c.q.1b){a=$.u.1S(c.q.1b[b.r])||{}}8 a},3x:7(d,e){$.O(d,7(c,b){l(b===H){R d[c];8}l(b.2V||b.2e){p a=v;2q(17 b.2e){1e"1B":a=!!$(b.2e,e.K).E;31;1e"7":a=b.2e.12(e,e);31}l(a){d[c]=b.2V!==2l?b.2V:v}1c{R d[c]}}});$.O(d,7(a,b){d[a]=$.5F(b)?b(e):b});$.O([\'1r\',\'15\',\'1w\',\'1m\'],7(){l(d[6]){d[6]=2U(d[6])}});$.O([\'2h\',\'27\'],7(){l(d[6]){d[6]=[2U(d[6][0]),2U(d[6][1])]}});l($.u.4f){l(d.1w&&d.1m){d.27=[d.1w,d.1m];R d.1w;R d.1m}l(d.1r&&d.15){d.2h=[d.1r,d.15];R d.1r;R d.15}}l(d.J){R d.J}8 d},1S:7(a){l(17 a=="1B"){p b={};$.O(a.1H(/\\s/),7(){b[6]=v});a=b}8 a},5D:7(c,a,b){$.u.1P[c]=a;$.u.J[c]=b;l(a.E<3){$.u.3Q(c,$.u.1S(c))}},1P:{13:7(b,c,a){l(!6.3B(a,c))8"1T-1Q";2q(c.3Z.3Y()){1e\'23\':p d=$("3X:2y",c);8 d.E>0&&(c.1o=="23-5B"||($.2S.2Q&&!(d[0].5z[\'T\'].5y)?d[0].2F:d[0].T).E>0);1e\'1Y\':l(6.1u(c))8 6.1K(b,c)>0;5x:8 $.2b(b).E>0}},1R:7(e,h,d){l(6.F(h))8"1T-1Q";p g=6.2f(h);l(!6.q.J[h.r])6.q.J[h.r]={};6.q.J[h.r].1R=17 g.19=="7"?g.19(e):g.19;d=17 d=="1B"&&{1k:d}||d;l(g.2K!==e){g.2K=e;p i=6;6.3V(h);p f={};f[h.r]=e;$.2P($.G(v,{1k:d,3N:"2L",3M:"1y"+h.r,5s:"5r",16:f,1s:7(a){l(a){p b=i.1v;i.2N(h);i.1v=b;i.1i.Y(h);i.1h()}1c{p c={};c[h.r]=a||i.2j(h,"1R");i.1h(c)}g.M=a;i.4s(h,a)}},d));8"1d"}1c l(6.1d[h.r]){8"1d"}8 g.M},1r:7(b,c,a){8 6.F(c)||6.1K(b,c)>=a},15:7(b,c,a){8 6.F(c)||6.1K(b,c)<=a},2h:7(b,d,a){p c=6.1K(b,d);8 6.F(d)||(c>=a[0]&&c<=a[1])},1w:7(b,c,a){8 6.F(c)||b>=a},1m:7(b,c,a){8 6.F(c)||b<=a},27:7(b,c,a){8 6.F(c)||(b>=a[0]&&b<=a[1])},1F:7(a,b){8 6.F(b)||/^((([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\A-\\C\\w-\\B\\x-\\y])+(\\.([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\A-\\C\\w-\\B\\x-\\y])+)*)|((\\3J)((((\\29|\\1N)*(\\2M\\3I))?(\\29|\\1N)+)?(([\\3H-\\5l\\3G\\3F\\5j-\\5I\\4r]|\\5g|[\\5L-\\5f]|[\\5e-\\5d]|[\\A-\\C\\w-\\B\\x-\\y])|(\\\\([\\3H-\\1N\\3G\\3F\\2M-\\4r]|[\\A-\\C\\w-\\B\\x-\\y]))))*(((\\29|\\1N)*(\\2M\\3I))?(\\29|\\1N)+)?(\\3J)))@((([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])))\\.)+(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|[\\A-\\C\\w-\\B\\x-\\y])))\\.?$/i.U(a)},1k:7(a,b){8 6.F(b)||/^(5P?|5b):\\/\\/(((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])))\\.)+(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|[\\A-\\C\\w-\\B\\x-\\y])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|[\\59-\\58]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.U(a)},1l:7(a,b){8 6.F(b)||!/57|56/.U(1V 55(a))},2a:7(a,b){8 6.F(b)||/^\\d{4}[\\/-]\\d{1,2}[\\/-]\\d{1,2}$/.U(a)},20:7(a,b){8 6.F(b)||/^\\d\\d?\\.\\d\\d?\\.\\d\\d\\d?\\d?$/.U(a)},1n:7(a,b){8 6.F(b)||/^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)(?:\\.\\d+)?$/.U(a)},28:7(a,b){8 6.F(b)||/^-?(?:\\d+|\\d{1,3}(?:\\.\\d{3})+)(?:,\\d+)?$/.U(a)},1O:7(a,b){8 6.F(b)||/^\\d+$/.U(a)},2d:7(b,e){l(6.F(e))8"1T-1Q";l(/[^0-9-]+/.U(b))8 H;p a=0,d=0,22=H;b=b.3u(/\\D/g,"");Q(n=b.E-1;n>=0;n--){p c=b.54(n);p d=53(c,10);l(22){l((d*=2)>9)d-=9}a+=d;22=!22}8(a%10)==0},3L:7(b,c,a){a=17 a=="1B"?a:"66|67?g|50";8 6.F(c)||b.69(1V 3t(".("+a+")$","i"))},3P:7(b,c,a){8 b==$(a).4X()}}})})(2I);(7($){p c=$.2P;p d={};$.2P=7(a){a=$.G(a,$.G({},$.4W,a));p b=a.3M;l(a.3N=="2L"){l(d[b]){d[b].2L()}8(d[b]=c.1I(6,P))}8 c.1I(6,P)}})(2I);(7($){$.O({3a:\'3y\',4V:\'3w\'},7(b,a){$.1A.32[a]={4U:7(){l($.2S.2Q)8 H;6.4T(b,$.1A.32[a].34,v)},4R:7(){l($.2S.2Q)8 H;6.4Q(b,$.1A.32[a].34,v)},34:7(e){P[0]=$.1A.38(e);P[0].1o=a;8 $.1A.24.1I(6,P)}}});$.G($.2J,{1p:7(d,e,c){8 6.3m(d,7(a){p b=$(a.4m);l(b.2H(e)){8 c.1I(b,P)}})},4P:7(a,b){8 6.2C(a,[$.1A.38({1o:a,4m:b})])}})})(2I);',62,396,'||||||this|function|return|||||||||||||if||||var|settings|name|||validator|true|uF900|uFDF0|uFFEF||u00A0|uFDCF|uD7FF||length|optional|extend|false|Please|messages|form|element|valid|enter|each|arguments|for|delete|errorList|value|test|currentForm|method|_|push|in||elements|call|required|toHide|maxlength|data|typeof|errorClass|message|format|rules|else|pending|case|invalid|pendingRequest|showErrors|successList|submitted|url|date|max|number|type|delegate|console|minlength|success|filter|checkable|formSubmitted|min|metadata|validate|errorMap|event|string|toShow|not|errorsFor|email|attr|split|apply|reset|getLength|da|classRuleSettings|x09|digits|methods|mismatch|remote|normalizeRule|dependency|unhighlight|new|wrapper|findByName|input|currentElements|dateDE|groups|bEven|select|handle||labelContainer|range|numberDE|x20|dateISO|trim|objectLength|creditcard|depends|previousValue|debug|rangelength|focusInvalid|defaultMessage|containers|undefined|constructor|check|add|addClass|switch|parameters|staticRules|errors|rulesCache|hide|addWrapper|resetForm|selected|clean|errorLabelContainer|errorElement|triggerHandler|defaults|ein|text|prepareForm|is|jQuery|fn|old|abort|x0d|prepareElement|than|ajax|msie|characters|browser|window|Number|param|hideErrors|dependTypes|idOrName|showLabel|submit|break|special|meta|handler|cancelSubmit|removeClass|highlight|fix|catch|focus|findLastActive|try|size|defaultShowErrors|grep|lastActive|ignoreTitle|numberOfInvalids|ignore|errorContainer|error|bind|invalidHandler|checkbox|radio|init|nothing|onsubmit|RegExp|replace|checkForm|focusout|normalizeRules|focusin|on|Array|depend|errorContext|to|between|x0c|x0b|x01|x0a|x22|no|accept|port|mode|the|equalTo|addClassRules|and|submitHandler|attributeRules|checked|startRequest|classRules|option|toLowerCase|nodeName|metadataRules|null|Sie|equal|geben|Bitte|errorPlacement|or|makeArray|html|generated|map|invalidElements|show|validElements|autoCreateRanges|strong|findDefined|String|customMessage|field|customMetaMessage|target|id|formatAndAdd|click|lastElement|x7f|stopRequest|onkeyup|assigned|has|cancel|disabled|image|onfocusout|visible|can|blockFocusCleanup|focusCleanup|button|onfocusin|removeAttr|label|find|textarea|file|removeAttrs|password|keyup|slice|triggerEvent|removeEventListener|teardown|valueCache|addEventListener|setup|blur|ajaxSettings|val|prototype|warn|gif|greater|unshift|parseInt|charAt|Date|NaN|Invalid|uF8FF|uE000|less|ftp|long|x7e|x5d|x5b|x21|least|unchecked|x0e|at|x08|filled|more|extension|blank|with|json|dataType|expr|again|same|get|default|specified|attributes|setArray|multiple|card|addMethod|credit|isFunction|only|524288|x1f|2147483647|class|x23|Nummer|eine|previous|https|boolean|Datum|ltiges|gÃ|getElementsByName|document|insertAfter|preventDefault|append|parent|wrap|ISO|URL|remove|parents|address|png|jpe|defined|match|No|Warning|title|returning|This|throw|setDefaults|checking|when|occured|exception|log|continue|onclick'.split('|'),0,{}))
\ No newline at end of file diff --git a/askbot/skins/common/media/js/live_search.js b/askbot/skins/common/media/js/live_search.js new file mode 100644 index 00000000..f9f03453 --- /dev/null +++ b/askbot/skins/common/media/js/live_search.js @@ -0,0 +1,546 @@ +var prevSortMethod = sortMethod; +var liveSearch = function(){ + var query = undefined; + var prev_text = undefined; + var running = false; + var q_list_sel = 'question-list';//id of question listing div + var search_url = undefined; + var restart_query = function(){}; + var process_query = function(){}; + var render_result = function(){}; + + var refresh_x_button = function(){ + if ($.trim(query.val()).length > 0){ + if (query.attr('class') === 'searchInput'){ + query.attr('class', 'searchInputCancelable'); + x_button = $('<input class="cancelSearchBtn" type="button" name="reset_query"/>'); + //x_button.click(reset_query); + x_button.val('x'); + x_button.click( + function(){ + query.val(''); + if (sortMethod === 'relevance-desc'){ + sortMethod = prevSortMethod; + } + refresh_x_button(); + reset_query(sortMethod); + } + ); + query.after(x_button); + } + } else { + $('input[name=reset_query]').remove(); + query.attr('class', 'searchInput'); + } + }; + + var reset_sort_method = function(){ + if (sortMethod === 'relevance-desc'){ + sortMethod = prevSortMethod; + if (sortMethod === 'relevance-desc'){ + sortMethod = 'activity-desc'; + } + } else { + sortMethod = 'activity-desc'; + prevSortMethod = 'activity-desc'; + } + }; + + var eval_query = function(){ + cur_text = $.trim(query.val()); + if (cur_text !== prev_text && running === false){ + if (cur_text.length >= minSearchWordLength){ + process_query(); + running = true; + } else if (cur_text.length === 0){ + restart_query(); + } + } + }; + + var ask_page_search_listen = function(){ + running = false; + var ask_page_eval_handle; + query.keyup(function(e){ + if (running === false){ + clearTimeout(ask_page_eval_handle); + ask_page_eval_handle = setTimeout(eval_query, 400); + } + }); + }; + + var main_page_search_listen = function(){ + running = false; + refresh_x_button(); + var main_page_eval_handle; + query.keyup(function(e){ + refresh_x_button(); + if (running === false){ + clearTimeout(main_page_eval_handle); + main_page_eval_handle = setTimeout(eval_query, 400); + } + }); + }; + + var render_counter = function(count, word, counter_class, counter_subclass){ + var output = '<div class="' + counter_class + ' ' + counter_subclass + '">' + + '<span class="item-count">' + + count; + if (counter_class === 'accepted'){ + output += '✓'; + } + output += '</span>' + + '<div>' + word + '</div>' + + '</div>'; + return output; + }; + + var render_title = function(result){ + return '<h2>' + + '<a title="' + result['summary'] + '" ' + + 'href="' + + askbot['urls']['question_url_template'] + .replace('{{QuestionID}}', result['id']) + + '">' + + result['title'] + + '</a>' + + '</h2>'; + }; + + var render_user_link = function(result){ + if (result['u_id'] !== false){ + if (result['u_is_anonymous'] === true){ + return '<span class="anonymous">' + + askbot['messages']['name_of_anonymous_user'] + + '</span>'; + } else { + var u_slug = result['u_name'].toLowerCase().replace(/ +/g, '-'); + return '<a ' + + 'href="' + + askbot['urls']['user_url_template'] + .replace('{{user_id}}', result['u_id']) + .replace('{{slug}}', u_slug) + + '">' + + result['u_name'] + + '</a> '; + } + } + else { + return ''; + } + }; + + var render_badge = function(result, key){ + return '<span ' + + 'title="' + result[key + '_title'] + '"' + + '>' + + '<span ' + + 'class="' + result[key + '_css_class'] + '"' + + '>' + result[key + '_badge_symbol'] + '</span>' + + '<span class="badgecount">' + result[key] + '</span>'; + }; + + var render_user_badge_and_karma = function(result){ + var rep_title = result['u_rep'] + ' ' + result['u_rep_word']; + var html = '<span ' + + 'class="reputation-score" ' + + 'title="' + rep_title + '"' + + '>' + result['u_rep'] + '</span>'; + if (result['u_gold'] > 0){ + html += render_badge(result, 'u_gold'); + } + if (result['u_silver'] > 0){ + html += render_badge(result, 'u_silver'); + } + if (result['u_bronze'] > 0){ + html += render_badge(result, 'u_bronze'); + } + return html; + }; + + var render_user_flag = function(result){ + var country_code = result['u_country_code']; + if (country_code) { + return '<img class="flag" src="'+ + mediaUrl( + 'media/images/flags/' + + country_code.toLowerCase() + + '.gif' + ) + + '"/>'; + } else { + return ''; + } + }; + + var render_user_info = function(result){ + var user_html = + '<div class="userinfo">' + + '<span class="relativetime" ' + + 'title="' + result['timestamp'] + '"' + + '>' + + result['timesince'] + + '</span> ' + + render_user_link(result); + if (result['u_is_anonymous'] === false){ + user_html += render_user_flag(result); + //render_user_badge_and_karma(result) + + } + user_html += '</div>'; + return user_html; + }; + + var render_tag = function(tag_name, linkable, deletable){ + var tag = new Tag(); + tag.setName(tag_name); + tag.setDeletable(deletable); + tag.setLinkable(linkable); + return tag.getElement().outerHTML(); + }; + + var render_tags = function(tags, linkable, deletable){ + var tags_html = '<ul class="tags">'; + $.each(tags, function(idx, item){ + tags_html += render_tag(item, linkable, deletable); + }); + tags_html += '</ul>'; + return tags_html; + }; + + var render_question = function(question){ + var entry_html = + '<div class="short-summary">' + + '<div class="counts">' + + render_counter( + question['views'], + question['views_word'], + 'views', + question['views_class'] + ) + + render_counter( + question['answers'], + question['answers_word'], + 'answers', + question['answers_class'] + ) + + render_counter( + question['votes'], + question['votes_word'], + 'votes', + question['votes_class'] + ) + + '<div style="clear:both"></div>' + + render_user_info(question) + + '</div>' + + render_title(question) + + render_tags(question['tags'], true, false) + + '</div>'; + return entry_html; + }; + + var render_question_list = function(questions){ + var output = ''; + for (var i=0; i<questions.length; i++){ + output += render_question(questions[i]); + } + return output; + }; + + var render_faces = function(faces){ + if (faces.length === 0){ + return; + } + $('#contrib-users>a').remove(); + var html = ''; + for (var i=0; i<faces.length; i++){ + html += faces[i]; + } + $('#contrib-users').append(html); + }; + + var render_related_tags = function(tags){ + if (tags.length === 0){ + return; + } + var html = ''; + for (var i=0; i<tags.length; i++){ + html += render_tag(tags[i]['name'], true, false); + html += '<span class="tag-number">× ' + + tags[i]['used_count'] + + '</span>' + + '<br />'; + } + $('#related-tags').html(html); + }; + + var render_paginator = function(paginator){ + var pager = $('#pager'); + if (paginator === ''){ + pager.hide(); + return; + } + else { + pager.show(); + pager.html(paginator); + } + }; + + var set_question_count = function(count_html){ + $('#question-count').html(count_html); + }; + + var get_old_tags = function(container){ + var tag_elements = container.find('.tag'); + var old_tags = []; + tag_elements.each(function(idx, element){ + old_tags.push($(element).html()); + }); + return old_tags; + }; + + var render_search_tags = function(tags){ + var search_tags = $('#search-tags'); + search_tags.children().remove(); + var tags_html = ''; + $.each(tags, function(idx, tag_name){ + var tag = new Tag(); + tag.setName(tag_name); + tag.setDeletable(true); + tag.setLinkable(false); + tag.setDeleteHandler( + function(){ + remove_search_tag(tag_name); + } + ); + search_tags.append(tag.getElement()); + }); + }; + + var create_relevance_tab = function(){ + relevance_tab = $('<a></a>'); + relevance_tab.attr('href', '?sort=relevance-desc'); + relevance_tab.attr('id', 'by_relevance'); + relevance_tab.html('<span>' + sortButtonData['relevance']['label'] + '</span>'); + return relevance_tab; + } + + var set_active_sort_tab = function(sort_method){ + var tabs = $('#sort_tabs>a'); + tabs.attr('class', 'off'); + tabs.each(function(index, element){ + var tab = $(element); + var tab_name = tab.attr('id').replace(/^by_/,''); + if (tab_name in sortButtonData){ + tab.attr( + 'href', + '?sort=' + tab_name + '-desc' + ); + tab.attr( + 'title', + sortButtonData[tab_name]['desc_tooltip'] + ); + tab.html(sortButtonData[tab_name]['label']); + } + }); + var bits = sort_method.split('-', 2); + var name = bits[0]; + var sense = bits[1];//sense of sort + var antisense = (sense == 'asc' ? 'desc':'asc'); + var arrow = (sense == 'asc' ? ' ▲':' ▼'); + var active_tab = $('#by_' + name); + active_tab.attr('class', 'on'); + active_tab.attr('title', sortButtonData[name][antisense + '_tooltip']); + active_tab.html(sortButtonData[name]['label'] + arrow); + }; + + var render_relevance_sort_tab = function(){ + if (showSortByRelevance === false){ + return; + } + var relevance_tab = $('#by_relevance'); + if (prev_text && prev_text.length > 0){ + if (relevance_tab.length == 0){ + relevance_tab = create_relevance_tab(); + $('#sort_tabs>span').after(relevance_tab); + } + } + else { + if (relevance_tab.length > 0){ + relevance_tab.remove(); + } + } + }; + + var remove_search_tag = function(tag_name){ + $.ajax({ + url: askbot['urls']['questions'], + data: {remove_tag: tag_name}, + dataType: 'json', + success: render_result, + complete: try_again + }); + }; + + var activate_search_tags = function(){ + var search_tags = $('#search-tags .tag-left'); + $.each(search_tags, function(idx, element){ + var tag = new Tag(); + tag.decorate($(element)); + //todo: setDeleteHandler and setHandler + //must work after decorate & must have getName + tag.setDeleteHandler( + function(){ + remove_search_tag(tag.getName()); + } + ); + }); + }; + + var render_ask_page_result = function(data, text_status, xhr){ + var container = $('#' + q_list_sel); + container.fadeOut(200, function() { + container.children().remove(); + if (data.length > 5){ + container.css('overflow-y', 'scroll'); + container.css('height', '120px'); + } else { + container.css('height', data.length * 24 + 'px'); + container.css('overflow-y', 'hidden'); + } + $.each(data, function(idx, question){ + var url = question['url']; + var title = question['title']; + var answer_count = question['answer_count']; + var list_item = $('<h2></h2>'); + var count_element = $('<span class="item-count"></span>'); + count_element.html(answer_count); + list_item.append(count_element); + var link = $('<a></a>'); + link.attr('href', url); + list_item.append(link); + title_element = $('<span class="title"></span>'); + title_element.html(title); + link.append(title) + container.append(list_item); + }); + container.fadeIn(); + }); + }; + + var render_main_page_result = function(data, text_status, xhr){ + var old_list = $('#' + q_list_sel); + var new_list = $('<div></div>').hide(); + if (data['questions'].length > 0){ + old_list.stop(true); + + new_list.html(render_question_list(data['questions'])); + //old_list.hide(); + old_list.after(new_list); + //old_list.remove(); + //rename new div to old + render_paginator(data['paginator']); + set_question_count(data['question_counter']); + render_search_tags(data['query_data']['tags']); + render_faces(data['faces']); + render_related_tags(data['related_tags']); + render_relevance_sort_tab(); + set_active_sort_tab(sortMethod); + query.focus(); + + //show new div with a fadeIn effect + old_list.fadeOut(200, function() { + old_list.remove(); + new_list.attr('id', q_list_sel); + new_list.fadeIn(400); + }); + } + } + + var try_again = function(){ + running = false; + eval_query(); + } + + var send_query = function(query_text, sort_method){ + var post_data = {query: query_text}; + $.ajax({ + url: search_url, + data: {query: query_text, sort: sort_method}, + dataType: 'json', + success: render_result, + complete: try_again + }); + prev_text = query_text; + } + + var reset_query = function(sort_method){ + $.ajax({ + url: search_url, + data: {reset_query: true, sort: sort_method}, + dataType: 'json', + success: render_result, + complete: try_again + }); + prev_text = ''; + } + + var refresh_main_page = function(){ + $.ajax({ + url: askbot['urls']['questions'], + data: {preserve_state: true}, + dataType: 'json', + success: render_main_page_result + }); + }; + + return { + refresh: function(){ + query = $('input#keywords'); + refresh_main_page(); + }, + init: function(mode){ + if (mode === 'main_page'){ + //live search for the main page + query = $('input#keywords'); + search_url = askbot['urls']['questions']; + render_result = render_main_page_result; + + process_query = function(){ + if (prev_text.length === 0 && showSortByRelevance){ + if (sortMethod === 'activity-desc'){ + prevSortMethod = sortMethod; + sortMethod = 'relevance-desc'; + } + } + send_query(cur_text, sortMethod); + }; + restart_query = function() { + reset_sort_method(); + refresh_x_button(); + reset_query(sortMethod); + running = true; + }; + + activate_search_tags(); + main_page_search_listen(); + } else { + query = $('input#id_title.questionTitleInput'); + search_url = askbot['urls']['api_get_questions']; + render_result = render_ask_page_result; + process_query = function(){ + send_query(cur_text); + }; + restart_query = function(){ + $('#' + q_list_sel).css('height',0).children().remove(); + running = false; + prev_text = ''; + //ask_page_search_listen(); + }; + ask_page_search_listen(); + } + prev_text = $.trim(query.val()); + running = false; + } + }; + +}; diff --git a/askbot/skins/common/media/js/output-words.html b/askbot/skins/common/media/js/output-words.html new file mode 100644 index 00000000..8ea5f314 --- /dev/null +++ b/askbot/skins/common/media/js/output-words.html @@ -0,0 +1,49 @@ +<!--
+
+ @desc Word checker
+ Tests the JavaScript-side i18n translation arrays for completeness
+ and generates an empty template containing all the keys
+ for new translations.
+
+ Needs output-words.js and other JavaScript files shipped with Askbot.
+
+ @author Pekka Gaiser <post@pekkagaiser.com>
+ @package Part of the ASKBOT project <www.askbot.org>
+ @license Published with NO WARRANTY WHATSOEVER
+ under the same license as the Askbot project.
+ @version First release, May 7th 2010
+
+
+--><html>
+<head>
+
+<title>Translation check</title>
+
+<style type="text/css">
+
+ body { margin: 16px; color: navy}
+
+ table.languages td.language { width: 40px; padding-top: 4px; padding-bottom: 4px; text-align: center }
+ table.languages td.okay { background-color: lightgreen }
+ table.languages td.missing { background-color: orange }
+
+ div.column { width: 49%; float: left; padding-bottom: 64px }
+
+</style>
+
+<script type="text/javascript">i18nLang = "De";</script>
+<script type="text/javascript" src="jquery-1.2.6.js"></script>
+<script type="text/javascript" src="i18n.js"></script>
+<script type="text/javascript" src="output-words.js"></script>
+
+
+</head>
+<body>
+
+ <script type="text/javascript">
+ output();
+ </script>
+
+
+</body>
+</html>
\ No newline at end of file diff --git a/askbot/skins/common/media/js/output-words.js b/askbot/skins/common/media/js/output-words.js new file mode 100644 index 00000000..41e25651 --- /dev/null +++ b/askbot/skins/common/media/js/output-words.js @@ -0,0 +1,97 @@ +/* + + @desc Word checker + Tests the JavaScript-side i18n translation arrays for completeness + and generates an empty template containing all the keys + for new translations. + + Is included by output-words.html. + + @author Pekka Gaiser <post@pekkagaiser.com> + @package Part of the ASKBOT project <www.askbot.org> + @license Published with NO WARRANTY WHATSOEVER + under the same license as the Askbot project. + @version First release, May 7th 2010 + +*/ + + +function output() + { + + document.write("<div class='column'><h1>Translation check</h1><table class='languages'>"); + + var allKeys = new Array(); + + + for (var key in i18n) + { + if(!i18n.hasOwnProperty(key)) continue; + + for (var word in i18n[key]) + { + if(!i18n[key].hasOwnProperty(word)) continue; + + if (jQuery.inArray(word, allKeys) == -1) + allKeys.push(word); + + } + } + + + // Output all keys + for (var key in allKeys.sort()) + { + + document.write("<tr><td>"); + document.write(allKeys[key]); + document.write("</td><td>"); + + // Check word in all languages + for (var language in i18n) + { + if(!i18n.hasOwnProperty(language)) continue; + + if ((!i18n[language][allKeys[key]]) || (i18n[language][allKeys[key]] == "")) + document.write("<td class='language missing'>"+language+"</td>"); + else + document.write("<td class='language okay' title='"+escape(i18n[language][allKeys[key]])+"'>"+language+"</td>"); + + escape(i18n[language][key]) + + } + + document.write("</tr>"); + + } + + document.write("</table></div><div class='column'>"); + + // Translation template + + document.write("<h1>Template for new translation</h1>"); + document.write("<textarea style='width: 100%; height: 600px'>"); + document.write("// Note that the words ending with '/' (e.g. 'questions/') are directory names\n"); + document.write("// And need to be identical with the directory names\n"); + document.write("// in the basic server-side translation\n\n"); + + + document.write("var i18nXY = {\n"); + + // Output all words + for (var key in allKeys.sort()) + { + + document.write(" '"+allKeys[key]+"': '', \n"); + + } + + document.write(" 'delete_this': ''\n}"); // To prevent trailing comma + document.write("</textarea>"); + + document.write("</div>"); + + + } + + diff --git a/askbot/skins/common/media/js/post.js b/askbot/skins/common/media/js/post.js new file mode 100644 index 00000000..52772cc0 --- /dev/null +++ b/askbot/skins/common/media/js/post.js @@ -0,0 +1,1665 @@ +/* +Scripts for cnprog.com +Project Name: Lanai +All Rights Resevred 2008. CNPROG.COM +*/ +var lanai = +{ + /** + * Finds any <pre><code></code></pre> tags which aren't registered for + * pretty printing, adds the appropriate class name and invokes prettify. + */ + highlightSyntax: function(){ + var styled = false; + $("pre code").parent().each(function(){ + if (!$(this).hasClass('prettyprint')){ + $(this).addClass('prettyprint'); + styled = true; + } + }); + + if (styled){ + prettyPrint(); + } + } +}; + +function appendLoader(element) { + element.append('<img class="ajax-loader" ' + + 'src="' + mediaUrl("media/images/indicator.gif") + '" title="' + + $.i18n._('loading...') + + '" alt="' + + $.i18n._('loading...') + + '" />'); +} + +function removeLoader() { + $("img.ajax-loader").remove(); +} + +function setSubmitButtonDisabled(form, isDisabled) { + form.find("input[type='submit']").attr("disabled", isDisabled ? "true" : ""); +} + +function enableSubmitButton(form) { + setSubmitButtonDisabled(form, false); +} + +function disableSubmitButton(form) { + setSubmitButtonDisabled(form, true); +} + +function setupFormValidation(form, validationRules, validationMessages, onSubmitCallback) { + enableSubmitButton(form); + form.validate({ + debug: true, + rules: (validationRules ? validationRules : {}), + messages: (validationMessages ? validationMessages : {}), + errorElement: "span", + errorClass: "form-error", + errorPlacement: function(error, element) { + var span = element.next().find("span.form-error"); + if (span.length === 0) { + span = element.parent().find("span.form-error"); + if (span.length === 0){ + //for resizable textarea + var element_id = element.attr('id'); + span = $("label[for='" + element_id + "']"); + } + } + span.replaceWith(error); + }, + submitHandler: function(form_dom) { + disableSubmitButton($(form_dom)); + + if (onSubmitCallback){ + onSubmitCallback(); + } + else{ + form_dom.submit(); + } + } + }); +} + +var validateTagLength = function(value){ + var tags = getUniqueWords(value); + var are_tags_ok = true; + $.each(tags, function(index, value){ + if (value.length > askbot['settings']['maxTagLength']){ + are_tags_ok = false; + } + }); + return are_tags_ok; +}; +var validateTagCount = function(value){ + var tags = getUniqueWords(value); + return (tags.length <= askbot['settings']['maxTagsPerPost']); +}; + +$.validator.addMethod('limit_tag_count', validateTagCount); +$.validator.addMethod('limit_tag_length', validateTagLength); + +var CPValidator = function(){ + return { + getQuestionFormRules : function(){ + return { + tags: { + required: true, + maxlength: 105, + limit_tag_count: true, + limit_tag_length: true + }, + text: { + required: true, + minlength: 10 + } + /*title: { + required: true, + minlength: 10 + }*/ + }; + }, + getQuestionFormMessages: function(){ + return { + tags: { + required: " " + $.i18n._('tags cannot be empty'), + maxlength: askbot['messages']['tagLimits'], + limit_tag_count: askbot['messages']['maxTagsPerPost'], + limit_tag_length: askbot['messages']['maxTagLength'] + }, + text: { + required: " " + $.i18n._('content cannot be empty'), + minlength: $.i18n._('content minchars').replace('{0}', 10) + }, + title: { + required: " " + $.i18n._('please enter title'), + minlength: $.i18n._('title minchars').replace('{0}', 10) + } + }; + } + }; +}(); + +/** + * @constructor + * @extends {SimpleControl} + * @param {Comment} comment to upvote + */ +var CommentVoteButton = function(comment){ + SimpleControl.call(this); + /** + * @param {Comment} + */ + this._comment = comment; + /** + * @type {boolean} + */ + this._voted = false; + /** + * @type {number} + */ + this._score = 0; +}; +inherits(CommentVoteButton, SimpleControl); +/** + * @param {number} score + */ +CommentVoteButton.prototype.setScore = function(score){ + this._score = score; + if (this._element){ + this._element.html(score); + } +}; +/** + * @param {boolean} voted + */ +CommentVoteButton.prototype.setVoted = function(voted){ + this._voted = voted; + if (this._element){ + this._element.addClass('upvoted'); + } +}; + +CommentVoteButton.prototype.getVoteHandler = function(){ + var me = this; + var comment = this._comment; + return function(){ + var voted = me._voted; + var post_id = me._comment.getId(); + var data = { + cancel_vote: voted ? true:false, + post_id: post_id + }; + $.ajax({ + type: 'POST', + data: data, + dataType: 'json', + url: askbot['urls']['upvote_comment'], + cache: false, + success: function(data){ + if (data['success'] == true){ + me.setScore(data['score']); + me.setVoted(true); + } else { + showMessage(comment.getElement(), data['message'], 'after'); + } + } + }); + }; +}; + +CommentVoteButton.prototype.decorate = function(element){ + this._element = element; + this.setHandler(this.getVoteHandler()); + + var element = this._element; + var comment = this._comment; + /* can't call comment.getElement() here due + * an issue in the getElement() of comment + * so use an "illegal" access to comment._element here + */ + comment._element.mouseenter(function(){ + //outside height may not be known + //var height = comment.getElement().height(); + //element.height(height); + element.addClass('hover'); + }); + comment._element.mouseleave(function(){ + element.removeClass('hover'); + }); + +}; + +CommentVoteButton.prototype.createDom = function(){ + this._element = this.makeElement('div'); + if (this._score > 0){ + this._element.html(this._score); + } + this._element.addClass('upvote'); + if (this._voted){ + this._element.addClass('upvoted'); + } + this.decorate(this._element); +}; + +/** + * legacy Vote class + * handles all sorts of vote-like operations + */ +var Vote = function(){ + // All actions are related to a question + var questionId; + //question slug to build redirect urls + var questionSlug; + // The object we operate on actually. It can be a question or an answer. + var postId; + var questionAuthorId; + var currentUserId; + var answerContainerIdPrefix = 'answer-container-'; + var voteContainerId = 'vote-buttons'; + var imgIdPrefixAccept = 'answer-img-accept-'; + var classPrefixFollow= 'button follow'; + var classPrefixFollowed= 'button followed'; + var imgIdPrefixQuestionVoteup = 'question-img-upvote-'; + var imgIdPrefixQuestionVotedown = 'question-img-downvote-'; + var imgIdPrefixAnswerVoteup = 'answer-img-upvote-'; + var imgIdPrefixAnswerVotedown = 'answer-img-downvote-'; + var divIdFavorite = 'favorite-number'; + var commentLinkIdPrefix = 'comment-'; + var voteNumberClass = "vote-number"; + var offensiveIdPrefixQuestionFlag = 'question-offensive-flag-'; + var offensiveIdPrefixAnswerFlag = 'answer-offensive-flag-'; + var offensiveClassFlag = 'offensive-flag'; + var questionControlsId = 'question-controls'; + var removeQuestionLinkIdPrefix = 'question-delete-link-'; + var removeAnswerLinkIdPrefix = 'answer-delete-link-'; + var questionSubscribeUpdates = 'question-subscribe-updates'; + var questionSubscribeSidebar= 'question-subscribe-sidebar'; + + var acceptAnonymousMessage = $.i18n._('insufficient privilege'); + var acceptOwnAnswerMessage = $.i18n._('cannot pick own answer as best'); + + var pleaseLogin = " <a href='" + askbot['urls']['user_signin'] + + "?next=" + askbot['urls']['question_url_template'] + + "'>" + + $.i18n._('please login') + "</a>"; + + var favoriteAnonymousMessage = $.i18n._('anonymous users cannot follow questions') + pleaseLogin; + var subscribeAnonymousMessage = $.i18n._('anonymous users cannot subscribe to questions') + pleaseLogin; + var voteAnonymousMessage = $.i18n._('anonymous users cannot vote') + pleaseLogin; + //there were a couple of more messages... + var offensiveConfirmation = $.i18n._('please confirm offensive'); + var offensiveAnonymousMessage = $.i18n._('anonymous users cannot flag offensive posts') + pleaseLogin; + var removeConfirmation = $.i18n._('confirm delete'); + var removeAnonymousMessage = $.i18n._('anonymous users cannot delete/undelete') + pleaseLogin; + var recoveredMessage = $.i18n._('post recovered'); + var deletedMessage = $.i18n._('post deleted'); + + var VoteType = { + acceptAnswer : 0, + questionUpVote : 1, + questionDownVote : 2, + favorite : 4, + answerUpVote: 5, + answerDownVote:6, + offensiveQuestion : 7, + offensiveAnswer:8, + removeQuestion: 9, + removeAnswer:10, + questionSubscribeUpdates:11, + questionUnsubscribeUpdates:12 + }; + + var getFavoriteButton = function(){ + var favoriteButton = 'div.'+ voteContainerId +' a[class='+ classPrefixFollow +']'; + favoriteButton += ', div.'+ voteContainerId +' a[class='+ classPrefixFollowed +']'; + return $(favoriteButton); + }; + var getFavoriteNumber = function(){ + var favoriteNumber = '#'+ divIdFavorite ; + return $(favoriteNumber); + }; + var getQuestionVoteUpButton = function(){ + var questionVoteUpButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixQuestionVoteup +']'; + return $(questionVoteUpButton); + }; + var getQuestionVoteDownButton = function(){ + var questionVoteDownButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixQuestionVotedown +']'; + return $(questionVoteDownButton); + }; + var getAnswerVoteUpButtons = function(){ + var answerVoteUpButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAnswerVoteup +']'; + return $(answerVoteUpButton); + }; + var getAnswerVoteDownButtons = function(){ + var answerVoteDownButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAnswerVotedown +']'; + return $(answerVoteDownButton); + }; + var getAnswerVoteUpButton = function(id){ + var answerVoteUpButton = 'div.'+ voteContainerId +' img[id='+ imgIdPrefixAnswerVoteup + id + ']'; + return $(answerVoteUpButton); + }; + var getAnswerVoteDownButton = function(id){ + var answerVoteDownButton = 'div.'+ voteContainerId +' img[id='+ imgIdPrefixAnswerVotedown + id + ']'; + return $(answerVoteDownButton); + }; + + var getOffensiveQuestionFlag = function(){ + var offensiveQuestionFlag = '#question-table span[class='+ offensiveClassFlag +']'; + return $(offensiveQuestionFlag); + }; + + var getOffensiveAnswerFlags = function(){ + var offensiveQuestionFlag = 'div.answer span[class='+ offensiveClassFlag +']'; + return $(offensiveQuestionFlag); + }; + + var getremoveQuestionLink = function(){ + var removeQuestionLink = 'div#question-controls a[id^='+ removeQuestionLinkIdPrefix +']'; + return $(removeQuestionLink); + }; + + var getquestionSubscribeUpdatesCheckbox = function(){ + return $('#' + questionSubscribeUpdates); + }; + + var getquestionSubscribeSidebarCheckbox= function(){ + return $('#' + questionSubscribeSidebar); + }; + + var getremoveAnswersLinks = function(){ + var removeAnswerLinks = 'div.answer-controls a[id^='+ removeAnswerLinkIdPrefix +']'; + return $(removeAnswerLinks); + }; + + var setVoteImage = function(voteType, undo, object){ + var flag = undo ? "" : "-on"; + var arrow = (voteType == VoteType.questionUpVote || voteType == VoteType.answerUpVote) ? "up" : "down"; + object.attr("src", mediaUrl("media/images/vote-arrow-"+ arrow + flag +".png")); + + // if undo voting, then undo the pair of arrows. + if(undo){ + if(voteType == VoteType.questionUpVote || voteType == VoteType.questionDownVote){ + $(getQuestionVoteUpButton()).attr("src", mediaUrl("media/images/vote-arrow-up.png")); + $(getQuestionVoteDownButton()).attr("src", mediaUrl("media/images/vote-arrow-down.png")); + } + else{ + $(getAnswerVoteUpButton(postId)).attr("src", mediaUrl("media/images/vote-arrow-up.png")); + $(getAnswerVoteDownButton(postId)).attr("src", mediaUrl("media/images/vote-arrow-down.png")); + } + } + }; + + var setVoteNumber = function(object, number){ + var voteNumber = object.parent('div.'+ voteContainerId).find('div.'+ voteNumberClass); + $(voteNumber).text(number); + }; + + var bindEvents = function(){ + // accept answers + if(questionAuthorId == currentUserId){ + var acceptedButtons = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAccept +']'; + $(acceptedButtons).unbind('click').click(function(event){ + Vote.accept($(event.target)); + }); + } + // set favorite question + var favoriteButton = getFavoriteButton(); + favoriteButton.unbind('click').click(function(event){ + //Vote.favorite($(event.target)); + Vote.favorite(favoriteButton); + }); + + // question vote up + var questionVoteUpButton = getQuestionVoteUpButton(); + questionVoteUpButton.unbind('click').click(function(event){ + Vote.vote($(event.target), VoteType.questionUpVote); + }); + + var questionVoteDownButton = getQuestionVoteDownButton(); + questionVoteDownButton.unbind('click').click(function(event){ + Vote.vote($(event.target), VoteType.questionDownVote); + }); + + var answerVoteUpButton = getAnswerVoteUpButtons(); + answerVoteUpButton.unbind('click').click(function(event){ + Vote.vote($(event.target), VoteType.answerUpVote); + }); + + var answerVoteDownButton = getAnswerVoteDownButtons(); + answerVoteDownButton.unbind('click').click(function(event){ + Vote.vote($(event.target), VoteType.answerDownVote); + }); + + getOffensiveQuestionFlag().unbind('click').click(function(event){ + Vote.offensive(this, VoteType.offensiveQuestion); + }); + + getOffensiveAnswerFlags().unbind('click').click(function(event){ + Vote.offensive(this, VoteType.offensiveAnswer); + }); + + getremoveQuestionLink().unbind('click').click(function(event){ + Vote.remove(this, VoteType.removeQuestion); + }); + + getquestionSubscribeUpdatesCheckbox().unbind('click').click(function(event){ + //despeluchar esto + if (this.checked){ + getquestionSubscribeSidebarCheckbox().attr({'checked': true}); + Vote.vote($(event.target), VoteType.questionSubscribeUpdates); + } + else { + getquestionSubscribeSidebarCheckbox().attr({'checked': false}); + Vote.vote($(event.target), VoteType.questionUnsubscribeUpdates); + } + }); + + getquestionSubscribeSidebarCheckbox().unbind('click').click(function(event){ + if (this.checked){ + getquestionSubscribeUpdatesCheckbox().attr({'checked': true}); + Vote.vote($(event.target), VoteType.questionSubscribeUpdates); + } + else { + getquestionSubscribeUpdatesCheckbox().attr({'checked': false}); + Vote.vote($(event.target), VoteType.questionUnsubscribeUpdates); + } + }); + + getremoveAnswersLinks().unbind('click').click(function(event){ + Vote.remove(this, VoteType.removeAnswer); + }); + }; + + var submit = function(object, voteType, callback) { + //this function submits votes + $.ajax({ + type: "POST", + cache: false, + dataType: "json", + url: askbot['urls']['vote_url_template'].replace('{{QuestionID}}', questionId), + data: { "type": voteType, "postId": postId }, + error: handleFail, + success: function(data){callback(object, voteType, data);} + }); + }; + + var handleFail = function(xhr, msg){ + alert("Callback invoke error: " + msg); + }; + + // callback function for Accept Answer action + var callback_accept = function(object, voteType, data){ + if(data.allowed == "0" && data.success == "0"){ + showMessage(object, acceptAnonymousMessage); + } + else if(data.allowed == "-1"){ + showMessage(object, acceptOwnAnswerMessage); + } + else if(data.status == "1"){ + object.attr("src", mediaUrl("media/images/vote-accepted.png")); + $("#"+answerContainerIdPrefix+postId).removeClass("accepted-answer"); + $("#"+commentLinkIdPrefix+postId).removeClass("comment-link-accepted"); + } + else if(data.success == "1"){ + var acceptedButtons = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAccept +']'; + $(acceptedButtons).attr("src", mediaUrl("media/images/vote-accepted.png")); + var answers = ("div[id^="+answerContainerIdPrefix +"]"); + $(answers).removeClass("accepted-answer"); + var commentLinks = ("div[id^="+answerContainerIdPrefix +"] div[id^="+ commentLinkIdPrefix +"]"); + $(commentLinks).removeClass("comment-link-accepted"); + + object.attr("src", mediaUrl("media/images/vote-accepted-on.png")); + $("#"+answerContainerIdPrefix+postId).addClass("accepted-answer"); + $("#"+commentLinkIdPrefix+postId).addClass("comment-link-accepted"); + } + else{ + showMessage(object, data.message); + } + }; + + var callback_favorite = function(object, voteType, data){ + if(data.allowed == "0" && data.success == "0"){ + showMessage( + object, + favoriteAnonymousMessage.replace( + '{{QuestionID}}', + questionId).replace( + '{{questionSlug}}', + '' + ) + ); + } + else if(data.status == "1"){ + var follow_html = gettext('Follow'); + object.attr("class", 'button follow'); + object.html(follow_html); + var fav = getFavoriteNumber(); + fav.removeClass("my-favorite-number"); + if(data.count === 0){ + data.count = ''; + fav.text(''); + }else{ + var fmts = ngettext('%s follower', '%s followers', data.count); + fav.text(interpolate(fmts, [data.count])); + } + } + else if(data.success == "1"){ + var followed_html = gettext('<div>Following</div><div class="unfollow">Unfollow</div>'); + object.html(followed_html); + object.attr("class", 'button followed'); + var fav = getFavoriteNumber(); + var fmts = ngettext('%s follower', '%s followers', data.count); + fav.text(interpolate(fmts, [data.count])); + fav.addClass("my-favorite-number"); + } + else{ + showMessage(object, data.message); + } + }; + + var callback_vote = function(object, voteType, data){ + if (data.success == '0'){ + showMessage(object, data.message); + return; + } + else { + if (data.status == '1'){ + setVoteImage(voteType, true, object); + } + else { + setVoteImage(voteType, false, object); + } + setVoteNumber(object, data.count); + if (data.message && data.message.length > 0){ + showMessage(object, data.message); + } + return; + } + //may need to take a look at this again + if (data.status == "1"){ + setVoteImage(voteType, true, object); + setVoteNumber(object, data.count); + } + else if (data.success == "1"){ + setVoteImage(voteType, false, object); + setVoteNumber(object, data.count); + if (data.message.length > 0){ + showMessage(object, data.message); + } + } + }; + + var callback_offensive = function(object, voteType, data){ + //todo: transfer proper translations of these from i18n.js + //to django.po files + //_('anonymous users cannot flag offensive posts') + pleaseLogin; + if (data.success == "1"){ + $(object).children('span[class=darkred]').text("("+ data.count +")"); + } + else { + object = $(object); + showMessage(object, data.message) + } + }; + + var callback_remove = function(object, voteType, data){ + if (data.success == "1"){ + if (removeActionType == 'delete'){ + postNode.addClass('deleted'); + postRemoveLink.innerHTML = $.i18n._('undelete'); + showMessage(object, deletedMessage); + } + else if (removeActionType == 'undelete') { + postNode.removeClass('deleted'); + postRemoveLink.innerHTML = $.i18n._('delete'); + showMessage(object, recoveredMessage); + } + } + else { + showMessage(object, data.message) + } + }; + + return { + init : function(qId, qSlug, questionAuthor, userId){ + questionId = qId; + questionSlug = qSlug; + questionAuthorId = questionAuthor; + currentUserId = userId; + bindEvents(); + }, + + //accept answer + accept: function(object){ + postId = object.attr("id").substring(imgIdPrefixAccept.length); + submit(object, VoteType.acceptAnswer, callback_accept); + }, + //mark question as favorite + favorite: function(object){ + if (!currentUserId || currentUserId.toUpperCase() == "NONE"){ + showMessage( + object, + favoriteAnonymousMessage.replace( + "{{QuestionID}}", + questionId + ).replace( + '{{questionSlug}}', + questionSlug + ) + ); + return false; + } + submit(object, VoteType.favorite, callback_favorite); + }, + + vote: function(object, voteType){ + if (!currentUserId || currentUserId.toUpperCase() == "NONE"){ + if (voteType == VoteType.questionSubscribeUpdates || voteType == VoteType.questionUnsubscribeUpdates){ + getquestionSubscribeSidebarCheckbox().removeAttr('checked'); + getquestionSubscribeUpdatesCheckbox().removeAttr('checked'); + showMessage(object, subscribeAnonymousMessage); + }else { + showMessage( + $(object), + voteAnonymousMessage.replace( + "{{QuestionID}}", + questionId + ).replace( + '{{questionSlug}}', + questionSlug + ) + ); + } + return false; + } + // up and downvote processor + if (voteType == VoteType.answerUpVote){ + postId = object.attr("id").substring(imgIdPrefixAnswerVoteup.length); + } + else if (voteType == VoteType.answerDownVote){ + postId = object.attr("id").substring(imgIdPrefixAnswerVotedown.length); + } + + submit(object, voteType, callback_vote); + }, + //flag offensive + offensive: function(object, voteType){ + if (!currentUserId || currentUserId.toUpperCase() == "NONE"){ + showMessage( + $(object), + offensiveAnonymousMessage.replace( + "{{QuestionID}}", + questionId + ).replace( + '{{questionSlug}}', + questionSlug + ) + ); + return false; + } + if (confirm(offensiveConfirmation)){ + postId = object.id.substr(object.id.lastIndexOf('-') + 1); + submit(object, voteType, callback_offensive); + } + }, + //delete question or answer (comments are deleted separately) + remove: function(object, voteType){ + if (!currentUserId || currentUserId.toUpperCase() == "NONE"){ + showMessage( + $(object), + removeAnonymousMessage.replace( + '{{QuestionID}}', + questionId + ).replace( + '{{questionSlug}}', + questionSlug + ) + ); + return false; + } + bits = object.id.split('-'); + postId = bits.pop();/* this seems to be used within submit! */ + postType = bits.shift(); + + var do_proceed = false; + if (postType == 'answer'){ + postNode = $('#answer-container-' + postId); + } + else if (postType == 'question'){ + postNode = $('#question-table'); + } + postRemoveLink = object; + if (postNode.hasClass('deleted')){ + removeActionType = 'undelete'; + do_proceed = true; + } + else { + removeActionType = 'delete'; + do_proceed = confirm(removeConfirmation); + } + if (do_proceed) { + submit($(object), voteType, callback_remove); + } + } + }; +} (); + +var questionRetagger = function(){ + + var oldTagsHTML = ''; + var tagInput = null; + var tagsDiv = null; + var retagLink = null; + + var restoreEventHandlers = function(){ + $(document).unbind('click'); + }; + + var cancelRetag = function(){ + tagsDiv.html(oldTagsHTML); + tagsDiv.removeClass('post-retag'); + tagsDiv.addClass('post-tags'); + restoreEventHandlers(); + initRetagger(); + }; + + var render_tag = function(tag_name){ + //copy-paste from live search!!! + var tag = new Tag(); + tag.setName(tag_name); + return tag.getElement().outerHTML(); + }; + + var drawNewTags = function(new_tags){ + new_tags = new_tags.split(/\s+/); + var tags_html = '' + $.each(new_tags, function(index, name){ + tags_html += render_tag(name); + }); + tagsDiv.html(tags_html); + }; + + var doRetag = function(){ + $.ajax({ + type: "POST", + url: retagUrl, + dataType: "json", + data: { tags: getUniqueWords(tagInput.val()).join(' ') }, + success: function(json) { + if (json['success'] === true){ + new_tags = getUniqueWords(json['new_tags']); + oldTagsHtml = ''; + cancelRetag(); + drawNewTags(new_tags.join(' ')); + } + else { + cancelRetag(); + showMessage(tagsDiv, json['message']); + } + }, + error: function(xhr, textStatus, errorThrown) { + showMessage(tagsDiv, 'sorry, somethin is not right here'); + cancelRetag(); + } + }); + return false; + } + + var setupInputEventHandlers = function(input){ + input.keydown(function(e){ + if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)){ + cancelRetag(); + } + }); + $(document).unbind('click').click(cancelRetag, false); + input.click(function(){return false}); + }; + + var createRetagForm = function(old_tags_string){ + var div = $('<form method="post"></form>'); + tagInput = $('<input id="retag_tags" type="text" autocomplete="off" name="tags" size="30"/>'); + //var tagLabel = $('<label for="retag_tags" class="error"></label>'); + tagInput.val(old_tags_string); + //populate input + var tagAc = new AutoCompleter({ + url: askbot['urls']['get_tag_list'], + preloadData: true, + minChars: 1, + useCache: true, + matchInside: true, + maxCacheLength: 100, + delay: 10 + }); + tagAc.decorate(tagInput); + div.append(tagInput); + //div.append(tagLabel); + setupInputEventHandlers(tagInput); + + //button = $('<input type="submit" />'); + //button.val($.i18n._('save tags')); + //div.append(button); + //setupButtonEventHandlers(button); + div.validate({//copy-paste from utils.js + rules: { + tags: { + required: true, + maxlength: askbot['settings']['maxTagsPerPost'] * askbot['settings']['maxTagLength'], + limit_tag_count: true, + limit_tag_length: true + } + }, + messages: { + tags: { + required: $.i18n._('tags cannot be empty'), + maxlength: askbot['messages']['tagLimits'], + limit_tag_count: askbot['messages']['maxTagsPerPost'], + limit_tag_length: askbot['messages']['maxTagLength'] + } + }, + submitHandler: doRetag, + errorClass: "retag-error" + }); + + return div; + }; + + var getTagsAsString = function(tags_div){ + var links = tags_div.find('a'); + var tags_str = ''; + links.each(function(index, element){ + if (index === 0){ + tags_str = $(element).html(); + } + else { + tags_str += ' ' + $(element).html(); + } + }); + return tags_str; + }; + + var noopHandler = function(){ + tagInput.focus(); + return false; + }; + + var deactivateRetagLink = function(){ + retagLink.unbind('click').click(noopHandler); + retagLink.unbind('keypress').keypress(noopHandler); + }; + + var startRetag = function(){ + tagsDiv = $('#question-tags'); + oldTagsHTML = tagsDiv.html();//save to restore on cancel + var old_tags_string = getTagsAsString(tagsDiv); + var retag_form = createRetagForm(old_tags_string); + tagsDiv.html(''); + tagsDiv.append(retag_form); + tagsDiv.removeClass('post-tags'); + tagsDiv.addClass('post-retag'); + tagInput.focus(); + deactivateRetagLink(); + return false; + }; + + var setupClickAndEnterHandler = function(element, callback){ + element.unbind('click').click(callback); + element.unbind('keypress').keypress(function(e){ + if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)){ + callback(); + } + }); + } + + var initRetagger = function(){ + setupClickAndEnterHandler(retagLink, startRetag); + }; + + return { + init: function(){ + retagLink = $('#retag'); + initRetagger(); + } + }; +}(); + +//constructor for the form +var EditCommentForm = function(){ + WrappedElement.call(this); + this._comment = null; + this._comment_widget = null; + this._element = null; + this._text = ''; + this._id = 'edit-comment-form'; +}; +inherits(EditCommentForm, WrappedElement); + +EditCommentForm.prototype.getElement = function(){ + EditCommentForm.superClass_.getElement.call(this); + this._textarea.val(this._text); + return this._element; +}; + +EditCommentForm.prototype.attachTo = function(comment, mode){ + this._comment = comment; + this._type = mode; + this._comment_widget = comment.getContainerWidget(); + this._text = comment.getText(); + comment.getElement().after(this.getElement()); + comment.getElement().hide(); + this._comment_widget.hideButton(); + if (this._type == 'add'){ + this._submit_btn.html($.i18n._('add comment')); + } + else { + this._submit_btn.html($.i18n._('save comment')); + } + this.getElement().show(); + this.focus(); + putCursorAtEnd(this._textarea); +}; + +EditCommentForm.prototype.getCounterUpdater = function(){ + //returns event handler + var counter = this._text_counter; + var handler = function(){ + var textarea = $(this); + var length = textarea.val() ? textarea.val().length : 0; + var length1 = maxCommentLength - 100; + if (length1 < 0){ + length1 = Math.round(0.7*maxCommentLength); + } + var length2 = maxCommentLength - 30; + if (length2 < 0){ + length2 = Math.round(0.9*maxCommentLength); + } + + var color = 'maroon'; + if (length === 0){ + var feedback = $.i18n._('title minchars').replace('{0}', 10); + } + else if (length < 10){ + var feedback = $.i18n._('enter more characters').replace('{0}', 10 - length); + } + else { + color = length > length2 ? "#f00" : length > length1 ? "#f60" : "#999"; + var feedback = $.i18n._('{0} characters left') + .replace('{0}', maxCommentLength - length); + } + counter.html(feedback).css('color', color); + }; + return handler; +}; + +EditCommentForm.prototype.canCancel = function(){ + if (this._element === null){ + return true; + } + var ctext = $.trim(this._textarea.val()); + if ($.trim(ctext) == $.trim(this._text)){ + return true; + } + else if (this.confirmAbandon()){ + return true; + } + this.focus(); + return false; +}; + +EditCommentForm.prototype.getCancelHandler = function(){ + var form = this; + return function(){ + if (form.canCancel()){ + form.detach(); + } + return false; + }; +}; + +EditCommentForm.prototype.detach = function(){ + if (this._comment === null){ + return; + } + this._comment.getContainerWidget().showButton(); + if (this._comment.isBlank()){ + this._comment.dispose(); + } + else { + this._comment.getElement().show(); + } + this.reset(); + this._element = this._element.detach(); +}; + +EditCommentForm.prototype.createDom = function(){ + this._element = $('<form></form>'); + this._element.attr('class', 'post-comments'); + + var div = $('<div></div>'); + this._textarea = $('<textarea></textarea>'); + this._textarea.attr('id', this._id); + + /* + this._help_text = $('<span></span>').attr('class', 'help-text'); + this._help_text.html(gettext('Markdown is allowed in the comments')); + div.append(this._help_text); + + this._help_text = $('<div></div>').attr('class', 'clearfix'); + div.append(this._help_text); + */ + + this._element.append(div); + div.append(this._textarea); + this._text_counter = $('<span></span>').attr('class', 'counter'); + div.append(this._text_counter); + this._submit_btn = $('<button class="submit small"></button>'); + div.append(this._submit_btn); + this._cancel_btn = $('<button class="submit small"></button>'); + this._cancel_btn.html($.i18n._('cancel')); + div.append(this._cancel_btn); + + setupButtonEventHandlers(this._submit_btn, this.getSaveHandler()); + setupButtonEventHandlers(this._cancel_btn, this.getCancelHandler()); + + var update_counter = this.getCounterUpdater(); + var escape_handler = makeKeyHandler(27, this.getCancelHandler()); + this._textarea.attr('name', 'comment') + .attr('cols', 60) + .attr('rows', 5) + .attr('maxlength', maxCommentLength) + .blur(update_counter) + .focus(update_counter) + .keyup(update_counter) + .keyup(escape_handler); + if (askbot['settings']['saveCommentOnEnter']){ + var save_handler = makeKeyHandler(13, this.getSaveHandler()); + this._textarea.keydown(save_handler); + } + this._textarea.val(this._text); +}; + +EditCommentForm.prototype.enableButtons = function(){ + this._submit_btn.attr('disabled', ''); + this._cancel_btn.attr('disabled', ''); +}; + +EditCommentForm.prototype.disableButtons = function(){ + this._submit_btn.attr('disabled', 'disabled'); + this._cancel_btn.attr('disabled', 'disabled'); +}; + +EditCommentForm.prototype.reset = function(){ + this._comment = null; + this._text = ''; + this._textarea.val(''); + this.enableButtons(); +}; + +EditCommentForm.prototype.confirmAbandon = function(){ + this.focus(true); + this._textarea.addClass('highlight'); + var answer = confirm($.i18n._('confirm abandon comment')); + this._textarea.removeClass('highlight'); + return answer; +}; + +EditCommentForm.prototype.focus = function(hard){ + this._textarea.focus(); + if (hard === true){ + $(this._textarea).scrollTop(); + } +}; + +EditCommentForm.prototype.getSaveHandler = function(){ + + var me = this; + return function(){ + var text = me._textarea.val(); + if (text.length < 10){ + me.focus(); + return false; + } + + var post_data = { + comment: text + }; + + if (me._type == 'edit'){ + post_data['comment_id'] = me._comment.getId(); + post_url = askbot['urls']['editComment']; + } + else { + post_data['post_type'] = me._comment.getParentType(); + post_data['post_id'] = me._comment.getParentId(); + post_url = askbot['urls']['postComments']; + } + + me.disableButtons(); + + $.ajax({ + type: "POST", + url: post_url, + dataType: "json", + data: post_data, + success: function(json) { + if (me._type == 'add'){ + me._comment.dispose(); + me._comment.getContainerWidget().reRenderComments(json); + } + else { + me._comment.setContent(json); + me._comment.getElement().show(); + } + me.detach(); + }, + error: function(xhr, textStatus, errorThrown) { + me._comment.getElement().show(); + showMessage(me._comment.getElement(), xhr.responseText, 'after'); + me.detach(); + me.enableButtons(); + } + }); + return false; + }; +}; + +//a single instance to reuse +var editCommentForm = new EditCommentForm(); + +var Comment = function(widget, data){ + WrappedElement.call(this); + this._container_widget = widget; + this._data = data || {}; + this._blank = true;//set to false by setContent + this._element = null; + this._delete_prompt = $.i18n._('delete this comment'); + if (data && data['is_deletable']){ + this._deletable = data['is_deletable']; + } + else { + this._deletable = false; + } + if (data && data['is_editable']){ + this._editable = data['is_deletable']; + } + else { + this._editable = false; + } +}; +inherits(Comment, WrappedElement); + +Comment.prototype.decorate = function(element){ + this._element = $(element); + var parent_type = this._element.parent().parent().attr('id').split('-')[2]; + var comment_id = this._element.attr('id').replace('comment-',''); + this._data = {id: comment_id}; + var delete_img = this._element.find('span.delete-icon'); + if (delete_img.length > 0){ + this._deletable = true; + this._delete_icon = new DeleteIcon(this.deletePrompt); + this._delete_icon.setHandler(this.getDeleteHandler()); + this._delete_icon.decorate(delete_img); + } + var edit_link = this._element.find('a.edit'); + if (edit_link.length > 0){ + this._editable = true; + this._edit_link = new EditLink(); + this._edit_link.setHandler(this.getEditHandler()); + this._edit_link.decorate(edit_link); + } + + var vote = new CommentVoteButton(this); + vote.decorate(this._element.find('.comment-votes .upvote')); + + this._blank = false; +}; + +Comment.prototype.isBlank = function(){ + return this._blank; +}; + +Comment.prototype.getId = function(){ + return this._data['id']; +}; + +Comment.prototype.hasContent = function(){ + return ('id' in this._data); + //shortcut for 'user_url' 'html' 'user_display_name' 'comment_age' +}; + +Comment.prototype.hasText = function(){ + return ('text' in this._data); +} + +Comment.prototype.getContainerWidget = function(){ + return this._container_widget; +}; + +Comment.prototype.getParentType = function(){ + return this._container_widget.getPostType(); +}; + +Comment.prototype.getParentId = function(){ + return this._container_widget.getPostId(); +}; + +Comment.prototype.setContent = function(data){ + this._data = data || this._data; + this._element.html(''); + this._element.attr('class', 'comment'); + this._element.attr('id', 'comment-' + this._data['id']); + + var votes = this.makeElement('div'); + votes.addClass('comment-votes'); + + var vote = new CommentVoteButton(this); + if (this._data['upvoted_by_user']){ + vote.setVoted(true); + } + vote.setScore(this._data['score']); + votes.append(vote.getElement()); + + this._element.append(votes); + + this._comment_delete = $('<div class="comment-delete"></div>'); + if (this._deletable){ + this._delete_icon = new DeleteIcon(this._delete_prompt); + this._delete_icon.setHandler(this.getDeleteHandler()); + this._comment_delete.append(this._delete_icon.getElement()); + } + this._element.append(this._comment_delete); + + this._comment_body = $('<div class="comment-body"></div>'); + this._comment_body.html(this._data['html']); + //this._comment_body.append(' – '); + + this._user_link = $('<a></a>').attr('class', 'author'); + this._user_link.attr('href', this._data['user_url']); + this._user_link.html(this._data['user_display_name']); + this._comment_body.append(this._user_link); + + this._comment_body.append(' ('); + this._comment_age = $('<span class="age"></span>'); + this._comment_age.html(this._data['comment_age']); + this._comment_body.append(this._comment_age); + this._comment_body.append(')'); + + if (this._editable){ + this._edit_link = new EditLink(); + this._edit_link.setHandler(this.getEditHandler()) + this._comment_body.append(this._edit_link.getElement()); + } + this._element.append(this._comment_body); + + this._blank = false; +}; + +Comment.prototype.dispose = function(){ + if (this._comment_body){ + this._comment_body.remove(); + } + if (this._comment_delete){ + this._comment_delete.remove(); + } + if (this._user_link){ + this._user_link.remove(); + } + if (this._comment_age){ + this._comment_age.remove(); + } + if (this._delete_icon){ + this._delete_icon.dispose(); + } + if (this._edit_link){ + this._edit_link.dispose(); + } + this._data = null; + Comment.superClass_.dispose.call(this); +}; + +Comment.prototype.getElement = function(){ + Comment.superClass_.getElement.call(this); + if (this.isBlank() && this.hasContent()){ + this.setContent(); + if (enableMathJax === true){ + MathJax.Hub.Queue(['Typeset', MathJax.Hub]); + } + } + return this._element; +}; + +Comment.prototype.loadText = function(on_load_handler){ + var me = this; + $.ajax({ + type: "GET", + url: askbot['urls']['getComment'], + data: {id: this._data['id']}, + success: function(json){ + me._data['text'] = json['text']; + on_load_handler() + }, + error: function(xhr, textStatus, exception) { + showMessage(me.getElement(), xhr.responseText, 'after'); + } + }); +}; + +Comment.prototype.getText = function(){ + if (!this.isBlank()){ + if ('text' in this._data){ + return this._data['text']; + } + } + return ''; +} + +Comment.prototype.getEditHandler = function(){ + var comment = this; + return function(){ + if (editCommentForm.canCancel()){ + editCommentForm.detach(); + if (comment.hasText()){ + editCommentForm.attachTo(comment, 'edit'); + } + else { + comment.loadText( + function(){ + editCommentForm.attachTo(comment, 'edit'); + } + ); + } + } + }; +}; + +Comment.prototype.getDeleteHandler = function(){ + var comment = this; + var del_icon = this._delete_icon; + return function(){ + if (confirm($.i18n._('confirm delete comment'))){ + comment.getElement().hide(); + $.ajax({ + type: 'POST', + url: askbot['urls']['deleteComment'], + data: { comment_id: comment.getId() }, + success: function(json, textStatus, xhr) { + comment.dispose(); + }, + error: function(xhr, textStatus, exception) { + comment.getElement().show() + showMessage(del_icon.getElement(), xhr.responseText); + }, + dataType: "json" + }); + } + }; +}; + +var PostCommentsWidget = function(){ + WrappedElement.call(this); + this._denied = false; +}; +inherits(PostCommentsWidget, WrappedElement); + +PostCommentsWidget.prototype.decorate = function(element){ + var element = $(element); + this._element = element; + + var widget_id = element.attr('id'); + var id_bits = widget_id.split('-'); + this._post_id = id_bits[3]; + this._post_type = id_bits[2]; + this._is_truncated = askbot['data'][widget_id]['truncated']; + this._user_can_post = askbot['data'][widget_id]['can_post']; + + //see if user can comment here + var controls = element.find('.controls'); + this._activate_button = controls.find('.button'); + + if (this._user_can_post == false){ + setupButtonEventHandlers( + this._activate_button, + this.getReadOnlyLoadHandler() + ); + } + else { + setupButtonEventHandlers( + this._activate_button, + this.getActivateHandler() + ); + } + + this._cbox = element.find('.content'); + var comments = new Array(); + var me = this; + this._cbox.children().each(function(index, element){ + var comment = new Comment(me); + comments.push(comment) + comment.decorate(element); + }); + this._comments = comments; +}; + +PostCommentsWidget.prototype.getPostType = function(){ + return this._post_type; +}; + +PostCommentsWidget.prototype.getPostId = function(){ + return this._post_id; +}; + +PostCommentsWidget.prototype.hideButton = function(){ + this._activate_button.hide(); +}; + +PostCommentsWidget.prototype.showButton = function(){ + if (this._is_truncated === false){ + this._activate_button.html(askbot['messages']['addComment']); + } + this._activate_button.show(); +} + +PostCommentsWidget.prototype.startNewComment = function(){ + var comment = new Comment(this); + this._cbox.append(comment.getElement()); + editCommentForm.attachTo(comment, 'add'); +}; + +PostCommentsWidget.prototype.needToReload = function(){ + return this._is_truncated; +}; + +PostCommentsWidget.prototype.getActivateHandler = function(){ + var me = this; + return function() { + if (editCommentForm.canCancel()){ + editCommentForm.detach(); + if (me.needToReload()){ + me.reloadAllComments(function(json){ + me.reRenderComments(json); + me.startNewComment(); + }); + } + else { + me.startNewComment(); + } + } + }; +}; + +PostCommentsWidget.prototype.getReadOnlyLoadHandler = function(){ + var me = this; + return function(){ + me.reloadAllComments(function(json){ + me.reRenderComments(json); + me._activate_button.remove(); + }); + }; +}; + + +PostCommentsWidget.prototype.reloadAllComments = function(callback){ + var post_data = {post_id: this._post_id, post_type: this._post_type}; + var me = this; + $.ajax({ + type: "GET", + url: askbot['urls']['postComments'], + data: post_data, + success: function(json){ + callback(json); + me._is_truncated = false; + }, + dataType: "json" + }); +}; + +PostCommentsWidget.prototype.reRenderComments = function(json){ + $.each(this._comments, function(i, item){ + item.dispose(); + }); + this._comments = new Array(); + var me = this; + $.each(json, function(i, item){ + var comment = new Comment(me, item); + me._cbox.append(comment.getElement()); + me._comments.push(comment); + }); +}; + + +var socialSharing = function(){ + + var SERVICE_DATA = { + //url - template for the sharing service url, params are for the popup + identica: { + url: "http://identi.ca/notice/new?status_textarea={TEXT}%20{URL}", + params: "width=820, height=526,toolbar=1,status=1,resizable=1,scrollbars=1" + }, + twitter: { + url: "http://twitter.com/share?url={URL}&ref=twitbtn&text={TEXT}", + params: "width=820,height=526,toolbar=1,status=1,resizable=1,scrollbars=1" + }, + facebook: { + url: "http://www.facebook.com/sharer.php?u={URL}&ref=fbshare&t={TEXT}", + params: "width=630,height=436,toolbar=1,status=1,resizable=1,scrollbars=1" + }, + linkedin: { + url: "http://www.linkedin.com/shareArticle?mini=true&url={URL}&source={TEXT}", + params: "width=630,height=436,toolbar=1,status=1,resizable=1,scrollbars=1" + } + }; + var URL = ""; + var TEXT = ""; + + var share_page = function(service_name){ + if (SERVICE_DATA[service_name]){ + var url = SERVICE_DATA[service_name]['url']; + $.ajax({ + async: false, + url: "http://json-tinyurl.appspot.com/?&callback=?", + dataType: "json", + data: {'url':URL}, + success: function(data){ + url = url.replace('{URL}', data.tinyurl); + }, + error: function(data){ + url = url.replace('{URL}', URL); + }, + complete: function(data){ + url = url.replace('{TEXT}', TEXT); + var params = SERVICE_DATA[service_name]['params']; + if(!window.open(url, "sharing", params)){ + window.location.href=share_url; + } + } + }); + } + } + + return { + init: function(){ + URL = window.location.href; + TEXT = escape($('h1 > a').html()); + var fb = $('a.facebook-share') + var tw = $('a.twitter-share'); + var ln = $('a.linkedin-share'); + var ica = $('a.identica-share'); + copyAltToTitle(fb); + copyAltToTitle(tw); + copyAltToTitle(ln); + copyAltToTitle(ica); + setupButtonEventHandlers(fb, function(){share_page("facebook")}); + setupButtonEventHandlers(tw, function(){share_page("twitter")}); + setupButtonEventHandlers(ln, function(){share_page("linkedin")}); + setupButtonEventHandlers(ica, function(){share_page("identica")}); + } + } +}(); + +/** + * @constructor + * @extends {SimpleControl} + */ +var QASwapper = function(){ + SimpleControl.call(this); + this._ans_id = null; +}; +inherits(QASwapper, SimpleControl); + +QASwapper.prototype.decorate = function(element){ + this._element = element; + this._ans_id = parseInt(element.attr('id').split('-').pop()); + var me = this; + this.setHandler(function(){ + me.startSwapping(); + }); +}; + +QASwapper.prototype.startSwapping = function(){ + while (true){ + var title = prompt(gettext('Please enter question title (>10 characters)')); + if (title.length >= 10){ + var data = {new_title: title, answer_id: this._ans_id}; + $.ajax({ + type: "POST", + cache: false, + dataType: "json", + url: askbot['urls']['swap_question_with_answer'], + data: data, + success: function(data){ + var url_template = askbot['urls']['question_url_template']; + new_question_url = url_template.replace( + '{{QuestionID}}', + data['id'] + ).replace( + '{{questionSlug}}', + data['slug'] + ); + window.location.href = new_question_url; + } + }); + break; + } + } +}; + +$(document).ready(function() { + $('[id^="comments-for-"]').each(function(index, element){ + var comments = new PostCommentsWidget(); + comments.decorate(element); + }); + $('[id^="swap-question-with-answer-"]').each(function(idx, element){ + var swapper = new QASwapper(); + swapper.decorate($(element)); + }); + questionRetagger.init(); + socialSharing.init(); +}); + + +/* +Prettify +http://www.apache.org/licenses/LICENSE-2.0 +*/ +var PR_SHOULD_USE_CONTINUATION = true; var PR_TAB_WIDTH = 8; var PR_normalizedHtml; var PR; var prettyPrintOne; var prettyPrint; function _pr_isIE6() { var isIE6 = navigator && navigator.userAgent && /\bMSIE 6\./.test(navigator.userAgent); _pr_isIE6 = function() { return isIE6; }; return isIE6; } (function() { function wordSet(words) { words = words.split(/ /g); var set = {}; for (var i = words.length; --i >= 0; ) { var w = words[i]; if (w) { set[w] = null; } } return set; } var FLOW_CONTROL_KEYWORDS = "break continue do else for if return while "; var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " + "double enum extern float goto int long register short signed sizeof " + "static struct switch typedef union unsigned void volatile "; var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " + "new operator private protected public this throw true try "; var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " + "concept concept_map const_cast constexpr decltype " + "dynamic_cast explicit export friend inline late_check " + "mutable namespace nullptr reinterpret_cast static_assert static_cast " + "template typeid typename typeof using virtual wchar_t where "; var JAVA_KEYWORDS = COMMON_KEYWORDS + "boolean byte extends final finally implements import instanceof null " + "native package strictfp super synchronized throws transient "; var CSHARP_KEYWORDS = JAVA_KEYWORDS + "as base by checked decimal delegate descending event " + "fixed foreach from group implicit in interface internal into is lock " + "object out override orderby params readonly ref sbyte sealed " + "stackalloc string select uint ulong unchecked unsafe ushort var "; var JSCRIPT_KEYWORDS = COMMON_KEYWORDS + "debugger eval export function get null set undefined var with " + "Infinity NaN "; var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " + "goto if import last local my next no our print package redo require " + "sub undef unless until use wantarray while BEGIN END "; var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " + "elif except exec finally from global import in is lambda " + "nonlocal not or pass print raise try with yield " + "False True None "; var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" + " defined elsif end ensure false in module next nil not or redo rescue " + "retry self super then true undef unless until when yield BEGIN END "; var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " + "function in local set then until "; var ALL_KEYWORDS = (CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS + PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS); var PR_STRING = 'str'; var PR_KEYWORD = 'kwd'; var PR_COMMENT = 'com'; var PR_TYPE = 'typ'; var PR_LITERAL = 'lit'; var PR_PUNCTUATION = 'pun'; var PR_PLAIN = 'pln'; var PR_TAG = 'tag'; var PR_DECLARATION = 'dec'; var PR_SOURCE = 'src'; var PR_ATTRIB_NAME = 'atn'; var PR_ATTRIB_VALUE = 'atv'; var PR_NOCODE = 'nocode'; function isWordChar(ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); } function spliceArrayInto(inserted, container, containerPosition, countReplaced) { inserted.unshift(containerPosition, countReplaced || 0); try { container.splice.apply(container, inserted); } finally { inserted.splice(0, 2); } } var REGEXP_PRECEDER_PATTERN = function() { var preceders = ["!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=", "&=", "(", "*", "*=", "+=", ",", "-=", "->", "/", "/=", ":", "::", ";", "<", "<<", "<<=", "<=", "=", "==", "===", ">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", "^", "^=", "^^", "^^=", "{", "|", "|=", "||", "||=", "~", "break", "case", "continue", "delete", "do", "else", "finally", "instanceof", "return", "throw", "try", "typeof"]; var pattern = '(?:' + '(?:(?:^|[^0-9.])\\.{1,3})|' + '(?:(?:^|[^\\+])\\+)|' + '(?:(?:^|[^\\-])-)'; for (var i = 0; i < preceders.length; ++i) { var preceder = preceders[i]; if (isWordChar(preceder.charAt(0))) { pattern += '|\\b' + preceder; } else { pattern += '|' + preceder.replace(/([^=<>:&])/g, '\\$1'); } } pattern += '|^)\\s*$'; return new RegExp(pattern); } (); var pr_amp = /&/g; var pr_lt = /</g; var pr_gt = />/g; var pr_quot = /\"/g; function attribToHtml(str) { return str.replace(pr_amp, '&').replace(pr_lt, '<').replace(pr_gt, '>').replace(pr_quot, '"'); } function textToHtml(str) { return str.replace(pr_amp, '&').replace(pr_lt, '<').replace(pr_gt, '>'); } var pr_ltEnt = /</g; var pr_gtEnt = />/g; var pr_aposEnt = /'/g; var pr_quotEnt = /"/g; var pr_ampEnt = /&/g; var pr_nbspEnt = / /g; function htmlToText(html) { var pos = html.indexOf('&'); if (pos < 0) { return html; } for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0; ) { var end = html.indexOf(';', pos); if (end >= 0) { var num = html.substring(pos + 3, end); var radix = 10; if (num && num.charAt(0) === 'x') { num = num.substring(1); radix = 16; } var codePoint = parseInt(num, radix); if (!isNaN(codePoint)) { html = (html.substring(0, pos) + String.fromCharCode(codePoint) + html.substring(end + 1)); } } } return html.replace(pr_ltEnt, '<').replace(pr_gtEnt, '>').replace(pr_aposEnt, "'").replace(pr_quotEnt, '"').replace(pr_ampEnt, '&').replace(pr_nbspEnt, ' '); } function isRawContent(node) { return 'XMP' === node.tagName; } function normalizedHtml(node, out) { switch (node.nodeType) { case 1: var name = node.tagName.toLowerCase(); out.push('<', name); for (var i = 0; i < node.attributes.length; ++i) { var attr = node.attributes[i]; if (!attr.specified) { continue; } out.push(' '); normalizedHtml(attr, out); } out.push('>'); for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } if (node.firstChild || !/^(?:br|link|img)$/.test(name)) { out.push('<\/', name, '>'); } break; case 2: out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"'); break; case 3: case 4: out.push(textToHtml(node.nodeValue)); break; } } var PR_innerHtmlWorks = null; function getInnerHtml(node) { if (null === PR_innerHtmlWorks) { var testNode = document.createElement('PRE'); testNode.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />')); PR_innerHtmlWorks = !/</.test(testNode.innerHTML); } if (PR_innerHtmlWorks) { var content = node.innerHTML; if (isRawContent(node)) { content = textToHtml(content); } return content; } var out = []; for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } return out.join(''); } function makeTabExpander(tabWidth) { var SPACES = ' '; var charInLine = 0; return function(plainText) { var out = null; var pos = 0; for (var i = 0, n = plainText.length; i < n; ++i) { var ch = plainText.charAt(i); switch (ch) { case '\t': if (!out) { out = []; } out.push(plainText.substring(pos, i)); var nSpaces = tabWidth - (charInLine % tabWidth); charInLine += nSpaces; for (; nSpaces >= 0; nSpaces -= SPACES.length) { out.push(SPACES.substring(0, nSpaces)); } pos = i + 1; break; case '\n': charInLine = 0; break; default: ++charInLine; } } if (!out) { return plainText; } out.push(plainText.substring(pos)); return out.join(''); }; } var pr_chunkPattern = /(?:[^<]+|<!--[\s\S]*?-->|<!\[CDATA\[([\s\S]*?)\]\]>|<\/?[a-zA-Z][^>]*>|<)/g; var pr_commentPrefix = /^<!--/; var pr_cdataPrefix = /^<\[CDATA\[/; var pr_brPrefix = /^<br\b/i; var pr_tagNameRe = /^<(\/?)([a-zA-Z]+)/; function extractTags(s) { var matches = s.match(pr_chunkPattern); var sourceBuf = []; var sourceBufLen = 0; var extractedTags = []; if (matches) { for (var i = 0, n = matches.length; i < n; ++i) { var match = matches[i]; if (match.length > 1 && match.charAt(0) === '<') { if (pr_commentPrefix.test(match)) { continue; } if (pr_cdataPrefix.test(match)) { sourceBuf.push(match.substring(9, match.length - 3)); sourceBufLen += match.length - 12; } else if (pr_brPrefix.test(match)) { sourceBuf.push('\n'); ++sourceBufLen; } else { if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) { var name = match.match(pr_tagNameRe)[2]; var depth = 1; end_tag_loop: for (var j = i + 1; j < n; ++j) { var name2 = matches[j].match(pr_tagNameRe); if (name2 && name2[2] === name) { if (name2[1] === '/') { if (--depth === 0) { break end_tag_loop; } } else { ++depth; } } } if (j < n) { extractedTags.push(sourceBufLen, matches.slice(i, j + 1).join('')); i = j; } else { extractedTags.push(sourceBufLen, match); } } else { extractedTags.push(sourceBufLen, match); } } } else { var literalText = htmlToText(match); sourceBuf.push(literalText); sourceBufLen += literalText.length; } } } return { source: sourceBuf.join(''), tags: extractedTags }; } function isNoCodeTag(tag) { return !!tag.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g, ' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/); } function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) { var shortcuts = {}; (function() { var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns); for (var i = allPatterns.length; --i >= 0; ) { var patternParts = allPatterns[i]; var shortcutChars = patternParts[3]; if (shortcutChars) { for (var c = shortcutChars.length; --c >= 0; ) { shortcuts[shortcutChars.charAt(c)] = patternParts; } } } })(); var nPatterns = fallthroughStylePatterns.length; var notWs = /\S/; return function(sourceCode, opt_basePos) { opt_basePos = opt_basePos || 0; var decorations = [opt_basePos, PR_PLAIN]; var lastToken = ''; var pos = 0; var tail = sourceCode; while (tail.length) { var style; var token = null; var match; var patternParts = shortcuts[tail.charAt(0)]; if (patternParts) { match = tail.match(patternParts[1]); token = match[0]; style = patternParts[0]; } else { for (var i = 0; i < nPatterns; ++i) { patternParts = fallthroughStylePatterns[i]; var contextPattern = patternParts[2]; if (contextPattern && !contextPattern.test(lastToken)) { continue; } match = tail.match(patternParts[1]); if (match) { token = match[0]; style = patternParts[0]; break; } } if (!token) { style = PR_PLAIN; token = tail.substring(0, 1); } } decorations.push(opt_basePos + pos, style); pos += token.length; tail = tail.substring(token.length); if (style !== PR_COMMENT && notWs.test(token)) { lastToken = token; } } return decorations; }; } var PR_MARKUP_LEXER = createSimpleLexer([], [[PR_PLAIN, /^[^<]+/, null], [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/, null], [PR_COMMENT, /^<!--[\s\S]*?(?:-->|$)/, null], [PR_SOURCE, /^<\?[\s\S]*?(?:\?>|$)/, null], [PR_SOURCE, /^<%[\s\S]*?(?:%>|$)/, null], [PR_SOURCE, /^<(script|style|xmp)\b[^>]*>[\s\S]*?<\/\1\b[^>]*>/i, null], [PR_TAG, /^<\/?\w[^<>]*>/, null]]); var PR_SOURCE_CHUNK_PARTS = /^(<[^>]*>)([\s\S]*)(<\/[^>]*>)$/; function tokenizeMarkup(source) { var decorations = PR_MARKUP_LEXER(source); for (var i = 0; i < decorations.length; i += 2) { if (decorations[i + 1] === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var sourceChunk = source.substring(start, end); var match = sourceChunk.match(PR_SOURCE_CHUNK_PARTS); if (match) { decorations.splice(i, 2, start, PR_TAG, start + match[1].length, PR_SOURCE, start + match[1].length + (match[2] || '').length, PR_TAG); } } } return decorations; } var PR_TAG_LEXER = createSimpleLexer([[PR_ATTRIB_VALUE, /^\'[^\']*(?:\'|$)/, null, "'"], [PR_ATTRIB_VALUE, /^\"[^\"]*(?:\"|$)/, null, '"'], [PR_PUNCTUATION, /^[<>\/=]+/, null, '<>/=']], [[PR_TAG, /^[\w:\-]+/, /^</], [PR_ATTRIB_VALUE, /^[\w\-]+/, /^=/], [PR_ATTRIB_NAME, /^[\w:\-]+/, null], [PR_PLAIN, /^\s+/, null, ' \t\r\n']]); function splitTagAttributes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_TAG) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var chunk = source.substring(start, end); var subDecorations = PR_TAG_LEXER(chunk, start); spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function sourceDecorator(options) { var shortcutStylePatterns = [], fallthroughStylePatterns = []; if (options.tripleQuotedStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, null, '\'"']); } else if (options.multiLineStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, null, '\'"`']); } else { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, null, '"\'']); } fallthroughStylePatterns.push([PR_PLAIN, /^(?:[^\'\"\`\/\#]+)/, null, ' \r\n']); if (options.hashComments) { shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']); } if (options.cStyleComments) { fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]); fallthroughStylePatterns.push([PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); } if (options.regexLiterals) { var REGEX_LITERAL = ('^/(?=[^/*])' + '(?:[^/\\x5B\\x5C]' + '|\\x5C[\\s\\S]' + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+' + '(?:/|$)'); fallthroughStylePatterns.push([PR_STRING, new RegExp(REGEX_LITERAL), REGEXP_PRECEDER_PATTERN]); } var keywords = wordSet(options.keywords); options = null; var splitStringAndCommentTokens = createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns); var styleLiteralIdentifierPuncRecognizer = createSimpleLexer([], [[PR_PLAIN, /^\s+/, null, ' \r\n'], [PR_PLAIN, /^[a-z_$@][a-z_$@0-9]*/i, null], [PR_LITERAL, /^0x[a-f0-9]+[a-z]/i, null], [PR_LITERAL, /^(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?[a-z]*/i, null, '123456789'], [PR_PUNCTUATION, /^[^\s\w\.$@]+/, null]]); function splitNonStringNonCommentTokens(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_PLAIN) { var start, end, chunk, subDecs; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; chunk = source.substring(start, end); subDecs = styleLiteralIdentifierPuncRecognizer(chunk, start); for (var j = 0, m = subDecs.length; j < m; j += 2) { var subStyle = subDecs[j + 1]; if (subStyle === PR_PLAIN) { var subStart = subDecs[j]; var subEnd = j + 2 < m ? subDecs[j + 2] : chunk.length; var token = source.substring(subStart, subEnd); if (token === '.') { subDecs[j + 1] = PR_PUNCTUATION; } else if (token in keywords) { subDecs[j + 1] = PR_KEYWORD; } else if (/^@?[A-Z][A-Z$]*[a-z][A-Za-z$]*$/.test(token)) { subDecs[j + 1] = token.charAt(0) === '@' ? PR_LITERAL : PR_TYPE; } } } spliceArrayInto(subDecs, decorations, i, 2); i += subDecs.length - 2; } } return decorations; } return function(sourceCode) { var decorations = splitStringAndCommentTokens(sourceCode); decorations = splitNonStringNonCommentTokens(sourceCode, decorations); return decorations; }; } var decorateSource = sourceDecorator({ keywords: ALL_KEYWORDS, hashComments: true, cStyleComments: true, multiLineStrings: true, regexLiterals: true }); function splitSourceNodes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var subDecorations = decorateSource(source.substring(start, end)); for (var j = 0, m = subDecorations.length; j < m; j += 2) { subDecorations[j] += start; } spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function splitSourceAttributes(source, decorations) { var nextValueIsSource = false; for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; var start, end; if (style === PR_ATTRIB_NAME) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; nextValueIsSource = /^on|^style$/i.test(source.substring(start, end)); } else if (style === PR_ATTRIB_VALUE) { if (nextValueIsSource) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var attribValue = source.substring(start, end); var attribLen = attribValue.length; var quoted = (attribLen >= 2 && /^[\"\']/.test(attribValue) && attribValue.charAt(0) === attribValue.charAt(attribLen - 1)); var attribSource; var attribSourceStart; var attribSourceEnd; if (quoted) { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue; } else { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue.substring(1, attribValue.length - 1); } var attribSourceDecorations = decorateSource(attribSource); for (var j = 0, m = attribSourceDecorations.length; j < m; j += 2) { attribSourceDecorations[j] += attribSourceStart; } if (quoted) { attribSourceDecorations.push(attribSourceEnd, PR_ATTRIB_VALUE); spliceArrayInto(attribSourceDecorations, decorations, i + 2, 0); } else { spliceArrayInto(attribSourceDecorations, decorations, i, 2); } } nextValueIsSource = false; } } return decorations; } function decorateMarkup(sourceCode) { var decorations = tokenizeMarkup(sourceCode); decorations = splitTagAttributes(sourceCode, decorations); decorations = splitSourceNodes(sourceCode, decorations); decorations = splitSourceAttributes(sourceCode, decorations); return decorations; } function recombineTagsAndDecorations(sourceText, extractedTags, decorations) { var html = []; var outputIdx = 0; var openDecoration = null; var currentDecoration = null; var tagPos = 0; var decPos = 0; var tabExpander = makeTabExpander(PR_TAB_WIDTH); var adjacentSpaceRe = /([\r\n ]) /g; var startOrSpaceRe = /(^| ) /gm; var newlineRe = /\r\n?|\n/g; var trailingSpaceRe = /[ \r\n]$/; var lastWasSpace = true; function emitTextUpTo(sourceIdx) { if (sourceIdx > outputIdx) { if (openDecoration && openDecoration !== currentDecoration) { html.push('</span>'); openDecoration = null; } if (!openDecoration && currentDecoration) { openDecoration = currentDecoration; html.push('<span class="', openDecoration, '">'); } var htmlChunk = textToHtml(tabExpander(sourceText.substring(outputIdx, sourceIdx))).replace(lastWasSpace ? startOrSpaceRe : adjacentSpaceRe, '$1 '); lastWasSpace = trailingSpaceRe.test(htmlChunk); html.push(htmlChunk.replace(newlineRe, '<br />')); outputIdx = sourceIdx; } } while (true) { var outputTag; if (tagPos < extractedTags.length) { if (decPos < decorations.length) { outputTag = extractedTags[tagPos] <= decorations[decPos]; } else { outputTag = true; } } else { outputTag = false; } if (outputTag) { emitTextUpTo(extractedTags[tagPos]); if (openDecoration) { html.push('</span>'); openDecoration = null; } html.push(extractedTags[tagPos + 1]); tagPos += 2; } else if (decPos < decorations.length) { emitTextUpTo(decorations[decPos]); currentDecoration = decorations[decPos + 1]; decPos += 2; } else { break; } } emitTextUpTo(sourceText.length); if (openDecoration) { html.push('</span>'); } return html.join(''); } var langHandlerRegistry = {}; function registerLangHandler(handler, fileExtensions) { for (var i = fileExtensions.length; --i >= 0; ) { var ext = fileExtensions[i]; if (!langHandlerRegistry.hasOwnProperty(ext)) { langHandlerRegistry[ext] = handler; } else if ('console' in window) { console.log('cannot override language handler %s', ext); } } } registerLangHandler(decorateSource, ['default-code']); registerLangHandler(decorateMarkup, ['default-markup', 'html', 'htm', 'xhtml', 'xml', 'xsl']); registerLangHandler(sourceDecorator({ keywords: CPP_KEYWORDS, hashComments: true, cStyleComments: true }), ['c', 'cc', 'cpp', 'cs', 'cxx', 'cyc']); registerLangHandler(sourceDecorator({ keywords: JAVA_KEYWORDS, cStyleComments: true }), ['java']); registerLangHandler(sourceDecorator({ keywords: SH_KEYWORDS, hashComments: true, multiLineStrings: true }), ['bsh', 'csh', 'sh']); registerLangHandler(sourceDecorator({ keywords: PYTHON_KEYWORDS, hashComments: true, multiLineStrings: true, tripleQuotedStrings: true }), ['cv', 'py']); registerLangHandler(sourceDecorator({ keywords: PERL_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['perl', 'pl', 'pm']); registerLangHandler(sourceDecorator({ keywords: RUBY_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['rb']); registerLangHandler(sourceDecorator({ keywords: JSCRIPT_KEYWORDS, cStyleComments: true, regexLiterals: true }), ['js']); function prettyPrintOne(sourceCodeHtml, opt_langExtension) { try { var sourceAndExtractedTags = extractTags(sourceCodeHtml); var source = sourceAndExtractedTags.source; var extractedTags = sourceAndExtractedTags.tags; if (!langHandlerRegistry.hasOwnProperty(opt_langExtension)) { opt_langExtension = /^\s*</.test(source) ? 'default-markup' : 'default-code'; } var decorations = langHandlerRegistry[opt_langExtension].call({}, source); return recombineTagsAndDecorations(source, extractedTags, decorations); } catch (e) { if ('console' in window) { console.log(e); console.trace(); } return sourceCodeHtml; } } function prettyPrint(opt_whenDone) { var isIE6 = _pr_isIE6(); var codeSegments = [document.getElementsByTagName('pre'), document.getElementsByTagName('code'), document.getElementsByTagName('xmp')]; var elements = []; for (var i = 0; i < codeSegments.length; ++i) { for (var j = 0; j < codeSegments[i].length; ++j) { elements.push(codeSegments[i][j]); } } codeSegments = null; var k = 0; function doWork() { var endTime = (PR_SHOULD_USE_CONTINUATION ? new Date().getTime() + 250 : Infinity); for (; k < elements.length && new Date().getTime() < endTime; k++) { var cs = elements[k]; if (cs.className && cs.className.indexOf('prettyprint') >= 0) { var langExtension = cs.className.match(/\blang-(\w+)\b/); if (langExtension) { langExtension = langExtension[1]; } var nested = false; for (var p = cs.parentNode; p; p = p.parentNode) { if ((p.tagName === 'pre' || p.tagName === 'code' || p.tagName === 'xmp') && p.className && p.className.indexOf('prettyprint') >= 0) { nested = true; break; } } if (!nested) { var content = getInnerHtml(cs); content = content.replace(/(?:\r\n?|\n)$/, ''); var newContent = prettyPrintOne(content, langExtension); if (!isRawContent(cs)) { cs.innerHTML = newContent; } else { var pre = document.createElement('PRE'); for (var i = 0; i < cs.attributes.length; ++i) { var a = cs.attributes[i]; if (a.specified) { var aname = a.name.toLowerCase(); if (aname === 'class') { pre.className = a.value; } else { pre.setAttribute(a.name, a.value); } } } pre.innerHTML = newContent; cs.parentNode.replaceChild(pre, cs); cs = pre; } if (isIE6 && cs.tagName === 'PRE') { var lineBreaks = cs.getElementsByTagName('br'); for (var j = lineBreaks.length; --j >= 0; ) { var lineBreak = lineBreaks[j]; lineBreak.parentNode.replaceChild(document.createTextNode('\r\n'), lineBreak); } } } } } if (k < elements.length) { setTimeout(doWork, 250); } else if (opt_whenDone) { opt_whenDone(); } } doWork(); } window['PR_normalizedHtml'] = normalizedHtml; window['prettyPrintOne'] = prettyPrintOne; window['prettyPrint'] = prettyPrint; window['PR'] = { 'createSimpleLexer': createSimpleLexer, 'registerLangHandler': registerLangHandler, 'sourceDecorator': sourceDecorator, 'PR_ATTRIB_NAME': PR_ATTRIB_NAME, 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE, 'PR_COMMENT': PR_COMMENT, 'PR_DECLARATION': PR_DECLARATION, 'PR_KEYWORD': PR_KEYWORD, 'PR_LITERAL': PR_LITERAL, 'PR_NOCODE': PR_NOCODE, 'PR_PLAIN': PR_PLAIN, 'PR_PUNCTUATION': PR_PUNCTUATION, 'PR_SOURCE': PR_SOURCE, 'PR_STRING': PR_STRING, 'PR_TAG': PR_TAG, 'PR_TYPE': PR_TYPE }; })(); diff --git a/askbot/skins/common/media/js/se_hilite.js b/askbot/skins/common/media/js/se_hilite.js new file mode 100644 index 00000000..42e99c8e --- /dev/null +++ b/askbot/skins/common/media/js/se_hilite.js @@ -0,0 +1 @@ +Hilite={elementid:"content",exact:true,max_nodes:1000,onload:true,style_name:"hilite",style_name_suffix:true,debug_referrer:""};Hilite.search_engines=[["google\\.","q"],["search\\.yahoo\\.","p"],["search\\.msn\\.","q"],["search\\.live\\.","query"],["search\\.aol\\.","userQuery"],["ask\\.com","q"],["altavista\\.","q"],["feedster\\.","q"],["search\\.lycos\\.","q"],["alltheweb\\.","q"],["technorati\\.com/search/([^\\?/]+)",1],["dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)",1,true]];Hilite.decodeReferrer=function(d){var g=null;var e=new RegExp("");for(var c=0;c<Hilite.search_engines.length;c++){var f=Hilite.search_engines[c];e.compile("^http://(www\\.)?"+f[0],"i");var b=d.match(e);if(b){var a;if(isNaN(f[1])){a=Hilite.decodeReferrerQS(d,f[1])}else{a=b[f[1]+1]}if(a){a=decodeURIComponent(a);if(f.length>2&&f[2]){a=decodeURIComponent(a)}a=a.replace(/\'|"/g,"");a=a.split(/[\s,\+\.]+/);return a}break}}return null};Hilite.decodeReferrerQS=function(f,d){var b=f.indexOf("?");var c;if(b>=0){var a=new String(f.substring(b+1));b=0;c=0;while((b>=0)&&((c=a.indexOf("=",b))>=0)){var e,g;e=a.substring(b,c);b=a.indexOf("&",c)+1;if(e==d){if(b<=0){return a.substring(c+1)}else{return a.substring(c+1,b-1)}}else{if(b<=0){return null}}}}return null};Hilite.hiliteElement=function(f,e){if(!e||f.childNodes.length==0){return}var c=new Array();for(var b=0;b<e.length;b++){e[b]=e[b].toLowerCase();if(Hilite.exact){c.push("\\b"+e[b]+"\\b")}else{c.push(e[b])}}c=new RegExp(c.join("|"),"i");var a={};for(var b=0;b<e.length;b++){if(Hilite.style_name_suffix){a[e[b]]=Hilite.style_name+(b+1)}else{a[e[b]]=Hilite.style_name}}var d=function(m){var j=c.exec(m.data);if(j){var n=j[0];var i="";var h=m.splitText(j.index);var g=h.splitText(n.length);var l=m.ownerDocument.createElement("SPAN");m.parentNode.replaceChild(l,h);l.className=a[n.toLowerCase()];l.appendChild(h);return l}else{return m}};Hilite.walkElements(f.childNodes[0],1,d)};Hilite.hilite=function(){var a=Hilite.debug_referrer?Hilite.debug_referrer:document.referrer;var b=null;a=Hilite.decodeReferrer(a);if(a&&((Hilite.elementid&&(b=document.getElementById(Hilite.elementid)))||(b=document.body))){Hilite.hiliteElement(b,a)}};Hilite.walkElements=function(d,f,e){var a=/^(script|style|textarea)/i;var c=0;while(d&&f>0){c++;if(c>=Hilite.max_nodes){var b=function(){Hilite.walkElements(d,f,e)};setTimeout(b,50);return}if(d.nodeType==1){if(!a.test(d.tagName)&&d.childNodes.length>0){d=d.childNodes[0];f++;continue}}else{if(d.nodeType==3){d=e(d)}}if(d.nextSibling){d=d.nextSibling}else{while(f>0){d=d.parentNode;f--;if(d.nextSibling){d=d.nextSibling;break}}}}};if(Hilite.onload){if(window.attachEvent){window.attachEvent("onload",Hilite.hilite)}else{if(window.addEventListener){window.addEventListener("load",Hilite.hilite,false)}else{var __onload=window.onload;window.onload=function(){Hilite.hilite();__onload()}}}};
\ No newline at end of file diff --git a/askbot/skins/common/media/js/se_hilite_src.js b/askbot/skins/common/media/js/se_hilite_src.js new file mode 100644 index 00000000..b604f156 --- /dev/null +++ b/askbot/skins/common/media/js/se_hilite_src.js @@ -0,0 +1,273 @@ +/** + * Search Engine Keyword Highlight (http://fucoder.com/code/se-hilite/) + * + * This module can be imported by any HTML page, and it would analyse the + * referrer for search engine keywords, and then highlight those keywords on + * the page, by wrapping them around <span class="hilite">...</span> tags. + * Document can then define styles else where to provide visual feedbacks. + * + * Usage: + * + * In HTML. Add the following line towards the end of the document. + * + * <script type="text/javascript" src="se_hilite.js"></script> + * + * In CSS, define the following style: + * + * .hilite { background-color: #ff0; } + * + * If Hilite.style_name_suffix is true, then define the follow styles: + * + * .hilite1 { background-color: #ff0; } + * .hilite2 { background-color: #f0f; } + * .hilite3 { background-color: #0ff; } + * .hilite4 ... + * + * @author Scott Yang <http://scott.yang.id.au/> + * @version 1.5 + */ + +// Configuration: +Hilite = { + /** + * Element ID to be highlighted. If set, then only content inside this DOM + * element will be highlighted, otherwise everything inside document.body + * will be searched. + */ + elementid: 'content', + + /** + * Whether we are matching an exact word. For example, searching for + * "highlight" will only match "highlight" but not "highlighting" if exact + * is set to true. + */ + exact: true, + + /** + * Maximum number of DOM nodes to test, before handing the control back to + * the GUI thread. This prevents locking up the UI when parsing and + * replacing inside a large document. + */ + max_nodes: 1000, + + /** + * Whether to automatically hilite a section of the HTML document, by + * binding the "Hilite.hilite()" to window.onload() event. If this + * attribute is set to false, you can still manually trigger the hilite by + * calling Hilite.hilite() in Javascript after document has been fully + * loaded. + */ + onload: true, + + /** + * Name of the style to be used. Default to 'hilite'. + */ + style_name: 'hilite', + + /** + * Whether to use different style names for different search keywords by + * appending a number starting from 1, i.e. hilite1, hilite2, etc. + */ + style_name_suffix: true, + + /** + * Set it to override the document.referrer string. Used for debugging + * only. + */ + debug_referrer: '' +}; + +Hilite.search_engines = [ + ['google\\.', 'q'], // Google + ['search\\.yahoo\\.', 'p'], // Yahoo + ['search\\.msn\\.', 'q'], // MSN + ['search\\.live\\.', 'query'], // MSN Live + ['search\\.aol\\.', 'userQuery'], // AOL + ['ask\\.com', 'q'], // Ask.com + ['altavista\\.', 'q'], // AltaVista + ['feedster\\.', 'q'], // Feedster + ['search\\.lycos\\.', 'q'], // Lycos + ['alltheweb\\.', 'q'], // AllTheWeb + ['technorati\\.com/search/([^\\?/]+)', 1], // Technorati + ['dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)', 1, true] // DogPile +]; + +/** + * Decode the referrer string and return a list of search keywords. + */ +Hilite.decodeReferrer = function(referrer) { + var query = null; + var regex = new RegExp(''); + + for (var i = 0; i < Hilite.search_engines.length; i ++) { + var se = Hilite.search_engines[i]; + regex.compile('^http://(www\\.)?' + se[0], 'i'); + var match = referrer.match(regex); + if (match) { + var result; + if (isNaN(se[1])) { + result = Hilite.decodeReferrerQS(referrer, se[1]); + } else { + result = match[se[1] + 1]; + } + if (result) { + result = decodeURIComponent(result); + // XXX: DogPile's URI requires decoding twice. + if (se.length > 2 && se[2]) + result = decodeURIComponent(result); + result = result.replace(/\'|"/g, ''); + result = result.split(/[\s,\+\.]+/); + return result; + } + break; + } + } + return null; +}; + +Hilite.decodeReferrerQS = function(referrer, match) { + var idx = referrer.indexOf('?'); + var idx2; + if (idx >= 0) { + var qs = new String(referrer.substring(idx + 1)); + idx = 0; + idx2 = 0; + while ((idx >= 0) && ((idx2 = qs.indexOf('=', idx)) >= 0)) { + var key, val; + key = qs.substring(idx, idx2); + idx = qs.indexOf('&', idx2) + 1; + if (key == match) { + if (idx <= 0) { + return qs.substring(idx2+1); + } else { + return qs.substring(idx2+1, idx - 1); + } + } + else if (idx <=0) { + return null; + } + } + } + return null; +}; + +/** + * Highlight a DOM element with a list of keywords. + */ +Hilite.hiliteElement = function(elm, query) { + if (!query || elm.childNodes.length == 0) + return; + + var qre = new Array(); + for (var i = 0; i < query.length; i ++) { + query[i] = query[i].toLowerCase(); + if (Hilite.exact) + qre.push('\\b'+query[i]+'\\b'); + else + qre.push(query[i]); + } + + qre = new RegExp(qre.join("|"), "i"); + + var stylemapper = {}; + for (var i = 0; i < query.length; i ++) { + if (Hilite.style_name_suffix) + stylemapper[query[i]] = Hilite.style_name+(i+1); + else + stylemapper[query[i]] = Hilite.style_name; + } + + var textproc = function(node) { + var match = qre.exec(node.data); + if (match) { + var val = match[0]; + var k = ''; + var node2 = node.splitText(match.index); + var node3 = node2.splitText(val.length); + var span = node.ownerDocument.createElement('SPAN'); + node.parentNode.replaceChild(span, node2); + span.className = stylemapper[val.toLowerCase()]; + span.appendChild(node2); + return span; + } else { + return node; + } + }; + Hilite.walkElements(elm.childNodes[0], 1, textproc); +}; + +/** + * Highlight a HTML document using keywords extracted from document.referrer. + * This is the main function to be called to perform search engine highlight + * on a document. + * + * Currently it would check for DOM element 'content', element 'container' and + * then document.body in that order, so it only highlights appropriate section + * on WordPress and Movable Type pages. + */ +Hilite.hilite = function() { + // If 'debug_referrer' then we will use that as our referrer string + // instead. + var q = Hilite.debug_referrer ? Hilite.debug_referrer : document.referrer; + var e = null; + q = Hilite.decodeReferrer(q); + if (q && ((Hilite.elementid && + (e = document.getElementById(Hilite.elementid))) || + (e = document.body))) + { + Hilite.hiliteElement(e, q); + } +}; + +Hilite.walkElements = function(node, depth, textproc) { + var skipre = /^(script|style|textarea)/i; + var count = 0; + while (node && depth > 0) { + count ++; + if (count >= Hilite.max_nodes) { + var handler = function() { + Hilite.walkElements(node, depth, textproc); + }; + setTimeout(handler, 50); + return; + } + + if (node.nodeType == 1) { // ELEMENT_NODE + if (!skipre.test(node.tagName) && node.childNodes.length > 0) { + node = node.childNodes[0]; + depth ++; + continue; + } + } else if (node.nodeType == 3) { // TEXT_NODE + node = textproc(node); + } + + if (node.nextSibling) { + node = node.nextSibling; + } else { + while (depth > 0) { + node = node.parentNode; + depth --; + if (node.nextSibling) { + node = node.nextSibling; + break; + } + } + } + } +}; + +// Trigger the highlight using the onload handler. +if (Hilite.onload) { + if (window.attachEvent) { + window.attachEvent('onload', Hilite.hilite); + } else if (window.addEventListener) { + window.addEventListener('load', Hilite.hilite, false); + } else { + var __onload = window.onload; + window.onload = function() { + Hilite.hilite(); + __onload(); + }; + } +} diff --git a/askbot/skins/common/media/js/tag_selector.js b/askbot/skins/common/media/js/tag_selector.js new file mode 100644 index 00000000..659c157b --- /dev/null +++ b/askbot/skins/common/media/js/tag_selector.js @@ -0,0 +1,375 @@ + +var TagDetailBox = function(box_type){ + WrappedElement.call(this); + this.box_type = box_type; + this._is_blank = true; + this._tags = new Array(); + this.wildcard = undefined; +}; +inherits(TagDetailBox, WrappedElement); + +TagDetailBox.prototype.createDom = function(){ + this._element = this.makeElement('div'); + this._element.addClass('wildcard-tags'); + this._headline = this.makeElement('p'); + this._headline.html(gettext('Tag "<span></span>" matches:')); + this._element.append(this._headline); + this._tag_list_element = this.makeElement('ul'); + this._tag_list_element.addClass('tags'); + this._element.append(this._tag_list_element); + this._footer = this.makeElement('p'); + this._footer.css('clear', 'left'); + this._element.append(this._footer); + this._element.hide(); +}; + +TagDetailBox.prototype.belongsTo = function(wildcard){ + return (this.wildcard === wildcard); +}; + +TagDetailBox.prototype.isBlank = function(){ + return this._is_blank; +}; + +TagDetailBox.prototype.clear = function(){ + if (this.isBlank()){ + return; + } + this._is_blank = true; + this.getElement().hide(); + this.wildcard = null; + $.each(this._tags, function(idx, item){ + item.dispose(); + }); + this._tags = new Array(); +}; + +TagDetailBox.prototype.loadTags = function(wildcard, callback){ + var me = this; + $.ajax({ + type: 'GET', + dataType: 'json', + cache: false, + url: askbot['urls']['get_tags_by_wildcard'], + data: { wildcard: wildcard }, + success: callback, + failure: function(){ me._loading = false; } + }); +}; + +TagDetailBox.prototype.renderFor = function(wildcard){ + var me = this; + if (this._loading === true){ + return; + } + this._loading = true; + this.loadTags( + wildcard, + function(data, text_status, xhr){ + me._tag_names = data['tag_names']; + if (data['tag_count'] > 0){ + var wildcard_display = wildcard.replace(/\*$/, '✽'); + me._headline.find('span').html(wildcard_display); + $.each(me._tag_names, function(idx, name){ + var tag = new Tag(); + tag.setName(name); + //tag.setLinkable(false); + me._tags.push(tag); + me._tag_list_element.append(tag.getElement()); + }); + me._is_blank = false; + me.wildcard = wildcard; + var tag_count = data['tag_count']; + if (tag_count > 20){ + var fmts = gettext('and %s more, not shown...'); + var footer_text = interpolate(fmts, [tag_count - 20]); + me._footer.html(footer_text); + me._footer.show(); + } else { + me._footer.hide(); + } + me._element.show(); + } else { + me.clear(); + } + me._loading = false; + } + ); +} + +function pickedTags(){ + + var interestingTags = {}; + var ignoredTags = {}; + var interestingTagDetailBox = new TagDetailBox('interesting'); + var ignoredTagDetailBox = new TagDetailBox('ignored'); + + var sendAjax = function(tagnames, reason, action, callback){ + var url = ''; + if (action == 'add'){ + if (reason == 'good'){ + url = askbot['urls']['mark_interesting_tag']; + } + else { + url = askbot['urls']['mark_ignored_tag']; + } + } + else { + url = askbot['urls']['unmark_tag']; + } + + var call_settings = { + type:'POST', + url:url, + data: JSON.stringify({tagnames: tagnames}), + dataType: 'json' + }; + if (callback !== false){ + call_settings.success = callback; + } + $.ajax(call_settings); + }; + + var unpickTag = function(from_target, tagname, reason, send_ajax){ + //send ajax request to delete tag + var deleteTagLocally = function(){ + from_target[tagname].remove(); + delete from_target[tagname]; + }; + if (send_ajax){ + sendAjax( + [tagname], + reason, + 'remove', + function(){ + deleteTagLocally(); + liveSearch().refresh(); + } + ); + } + else { + deleteTagLocally(); + } + }; + + var getTagList = function(reason){ + var base_selector = '.marked-tags'; + if (reason === 'good'){ + var extra_selector = '.interesting'; + } else { + var extra_selector = '.ignored'; + } + return $(base_selector + extra_selector); + }; + + var getWildcardTagDetailBox = function(reason){ + if (reason === 'good'){ + return interestingTagDetailBox; + } else { + return ignoredTagDetailBox; + } + }; + + var handleWildcardTagClick = function(tag_name, reason){ + var detail_box = getWildcardTagDetailBox(reason); + var tag_box = getTagList(reason); + if (detail_box.isBlank()){ + detail_box.renderFor(tag_name); + } else if (detail_box.belongsTo(tag_name)){ + detail_box.clear();//toggle off + } else { + detail_box.clear();//redraw with new data + detail_box.renderFor(tag_name); + } + if (!detail_box.inDocument()){ + tag_box.after(detail_box.getElement()); + detail_box.enterDocument(); + } + }; + + var renderNewTags = function( + clean_tag_names, + reason, + to_target, + to_tag_container + ){ + $.each(clean_tag_names, function(idx, tag_name){ + var tag = new Tag(); + tag.setName(tag_name); + tag.setDeletable(true); + + if (/\*$/.test(tag_name)){ + tag.setLinkable(false); + var detail_box = getWildcardTagDetailBox(reason); + tag.setHandler(function(){ + handleWildcardTagClick(tag_name, reason); + if (detail_box.belongsTo(tag_name)){ + detail_box.clear(); + } + }); + var delete_handler = function(){ + unpickTag(to_target, tag_name, reason, true); + if (detail_box.belongsTo(tag_name)){ + detail_box.clear(); + } + } + } else { + var delete_handler = function(){ + unpickTag(to_target, tag_name, reason, true); + } + } + + tag.setDeleteHandler(delete_handler); + var tag_element = tag.getElement(); + to_tag_container.append(tag_element); + to_target[tag_name] = tag_element; + }); + }; + + var handlePickedTag = function(reason){ + var to_target = interestingTags; + var from_target = ignoredTags; + var to_tag_container; + if (reason == 'bad'){ + var input_sel = '#ignoredTagInput'; + to_target = ignoredTags; + from_target = interestingTags; + to_tag_container = $('div .tags.ignored'); + } + else if (reason == 'good'){ + var input_sel = '#interestingTagInput'; + to_tag_container = $('div .tags.interesting'); + } + else { + return; + } + + var tagnames = getUniqueWords($(input_sel).attr('value')); + + $.each(tagnames, function(idx, tagname){ + if (tagname in from_target){ + unpickTag(from_target,tagname,reason,false); + } + }); + + var clean_tagnames = []; + $.each(tagnames, function(idx, tagname){ + if (!(tagname in to_target)){ + clean_tagnames.push(tagname); + } + }); + + if (clean_tagnames.length > 0){ + //send ajax request to pick this tag + + sendAjax( + clean_tagnames, + reason, + 'add', + function(){ + renderNewTags( + clean_tagnames, + reason, + to_target, + to_tag_container + ); + $(input_sel).val(''); + liveSearch().refresh(); + } + ); + } + }; + + var collectPickedTags = function(section){ + if (section === 'interesting'){ + var reason = 'good'; + var tag_store = interestingTags; + } + else if (section === 'ignored'){ + var reason = 'bad'; + var tag_store = ignoredTags; + } + else { + return; + } + $('.' + section + '.tags.marked-tags .tag-left').each( + function(i,item){ + var tag = new Tag(); + tag.decorate($(item)); + tag.setDeleteHandler(function(){ + unpickTag( + tag_store, + tag.getName(), + reason, + true + ) + }); + if (tag.isWildcard()){ + tag.setHandler(function(){ + handleWildcardTagClick(tag.getName(), reason) + }); + } + tag_store[tag.getName()] = $(item); + } + ); + }; + + var setupTagFilterControl = function(control_type){ + $('#' + control_type + 'TagFilterControl input') + .unbind('click') + .click(function(){ + $.ajax({ + type: 'POST', + dataType: 'json', + cache: false, + url: askbot['urls']['set_tag_filter_strategy'], + data: { + filter_type: control_type, + filter_value: $(this).val() + }, + success: function(){ + liveSearch().refresh(); + } + }); + }); + }; + + var getResultCallback = function(reason){ + return function(){ + handlePickedTag(reason); + }; + }; + + return { + init: function(){ + collectPickedTags('interesting'); + collectPickedTags('ignored'); + setupTagFilterControl('display'); + var ac = new AutoCompleter({ + url: askbot['urls']['get_tag_list'], + preloadData: true, + minChars: 1, + useCache: true, + matchInside: true, + maxCacheLength: 100, + delay: 10 + }); + + + var interestingTagAc = $.extend(true, {}, ac); + interestingTagAc.decorate($('#interestingTagInput')); + interestingTagAc.setOption('onItemSelect', getResultCallback('good')); + + var ignoredTagAc = $.extend(true, {}, ac); + ignoredTagAc.decorate($('#ignoredTagInput')); + ignoredTagAc.setOption('onItemSelect', getResultCallback('bad')); + + $("#interestingTagAdd").click(getResultCallback('good')); + $("#ignoredTagAdd").click(getResultCallback('bad')); + } + }; +} + +$(document).ready( function(){ + pickedTags().init(); +}); diff --git a/askbot/skins/common/media/js/user.js b/askbot/skins/common/media/js/user.js new file mode 100644 index 00000000..438a3273 --- /dev/null +++ b/askbot/skins/common/media/js/user.js @@ -0,0 +1,185 @@ +$(document).ready(function(){ + + var getSelected = function(){ + + var id_list = new Array(); + var elements = $('#responses input:checked').parent(); + + elements.each(function(index, element){ + var id = $(element).attr('id').replace(/^re_/,''); + id_list.push(id); + }); + + if (id_list.length === 0){ + alert($.i18n._('Please select at least one item')); + } + + return {id_list: id_list, elements: elements}; + }; + + var submit = function(id_list, elements, action_type){ + if (action_type == 'delete' || action_type == 'mark_new' || action_type == 'mark_seen'){ + $.ajax({ + type: 'POST', + cache: false, + dataType: 'json', + data: JSON.stringify({memo_list: id_list, action_type: action_type}), + url: askbot['urls']['manageInbox'], + success: function(response_data){ + if (response_data['success'] === true){ + if (action_type == 'delete'){ + elements.remove(); + } + else if (action_type == 'mark_new'){ + elements.addClass('highlight'); + elements.addClass('new'); + elements.removeClass('seen'); + } + else if (action_type == 'mark_seen'){ + elements.removeClass('highlight'); + elements.addClass('seen'); + elements.removeClass('new'); + } + } + else { + showMessage($('#responses'), response_data['message']); + } + } + }); + } + }; + + var startAction = function(action_type){ + var data = getSelected(); + if (data['id_list'].length === 0){ + return; + } + if (action_type == 'delete'){ + if (data['id_list'].length === 1){ + var msg = $.i18n._('Delete this notification?') + } + else { + var msg = $.i18n._('Delete these notifications?') + } + if (confirm(msg) === false){ + return; + } + } + submit(data['id_list'], data['elements'], action_type); + }; + setupButtonEventHandlers($('#re_mark_seen'), function(){startAction('mark_seen')}); + setupButtonEventHandlers($('#re_mark_new'), function(){startAction('mark_new')}); + setupButtonEventHandlers($('#re_dismiss'), function(){startAction('delete')}); + setupButtonEventHandlers( + $('#sel_all'), + function(){ + setCheckBoxesIn('#responses .new', true); + setCheckBoxesIn('#responses .seen', true); + } + ); + setupButtonEventHandlers( + $('#sel_seen'), + function(){ + setCheckBoxesIn('#responses .seen', true); + } + ); + setupButtonEventHandlers( + $('#sel_new'), + function(){ + setCheckBoxesIn('#responses .new', true); + } + ); + setupButtonEventHandlers( + $('#sel_none'), + function(){ + setCheckBoxesIn('#responses .new', false); + setCheckBoxesIn('#responses .seen', false); + } + ); +}); + +/** + * @constructor + * allows to follow/unfollow users + */ +var FollowUser = function(){ + WrappedElement.call(this); + this._user_id = null; + this._user_name = null; +}; +inherits(FollowUser, WrappedElement); + +/** + * @param {string} user_name + */ +FollowUser.prototype.setUserName = function(user_name){ + this._user_name = user_name; +}; + +FollowUser.prototype.decorate = function(element){ + this._element = element; + this._user_id = parseInt(element.attr('id').split('-').pop()); + this._available_action = element.children().hasClass('follow') ? 'follow':'unfollow'; + var me = this; + setupButtonEventHandlers(this._element, function(){ me.go() }); +}; + +FollowUser.prototype.go = function(){ + if (askbot['data']['userIsAuthenticated'] === false){ + var message = gettext('Please <a href="%(signin_url)s">signin</a> to follow %(username)s'); + var message_data = { + signin_url: askbot['urls']['user_signin'] + '?next=' + window.location.href, + username: this._user_name + } + message = interpolate(message, message_data, true); + showMessage(this._element, message); + return; + } + var user_id = this._user_id; + if (this._available_action === 'follow'){ + var url = askbot['urls']['follow_user']; + } else { + var url = askbot['urls']['unfollow_user']; + } + var me = this; + $.ajax({ + type: 'POST', + cache: false, + dataType: 'json', + url: url.replace('{{userId}}', user_id), + success: function(){ me.toggleState() } + }); +}; + +FollowUser.prototype.toggleState = function(){ + if (this._available_action === 'follow'){ + this._available_action = 'unfollow'; + var unfollow_div = document.createElement('div'); + unfollow_div.setAttribute('class', 'unfollow'); + var red_div = document.createElement('div'); + red_div.setAttribute('class', 'unfollow-red'); + red_div.innerHTML = interpolate(gettext('unfollow %s'), [this._user_name]); + var green_div = document.createElement('div'); + green_div.setAttribute('class', 'unfollow-green'); + green_div.innerHTML = interpolate(gettext('following %s'), [this._user_name]); + unfollow_div.appendChild(red_div); + unfollow_div.appendChild(green_div); + this._element.html(unfollow_div); + } else { + var follow_div = document.createElement('div'); + follow_div.innerHTML = interpolate(gettext('follow %s'), [this._user_name]); + follow_div.setAttribute('class', 'follow'); + this._available_action = 'follow'; + this._element.html(follow_div); + } +}; + +(function(){ + var fbtn = $('.follow-toggle'); + if (fbtn.length === 1){ + var follow_user = new FollowUser(); + follow_user.decorate(fbtn); + follow_user.setUserName(askbot['data']['viewUserName']); + } +})(); + diff --git a/askbot/skins/common/media/js/utils.js b/askbot/skins/common/media/js/utils.js new file mode 100644 index 00000000..ec55e535 --- /dev/null +++ b/askbot/skins/common/media/js/utils.js @@ -0,0 +1,391 @@ +//var $, scriptUrl, askbotSkin +var mediaUrl = function(resource){ + return scriptUrl + 'm/' + askbotSkin + '/' + resource; +}; + +var cleanUrl = function(url){ + var re = new RegExp('//', 'g'); + return url.replace(re, '/'); +}; + +var copyAltToTitle = function(sel){ + sel.attr('title', sel.attr('alt')); +}; + +var getUniqueWords = function(value){ + var words = $.trim(value).split(/\s+/); + var uniques = new Object(); + var out = new Array(); + $.each(words, function(idx, item){ + if (!(item in uniques)){ + uniques[item] = 1; + out.push(item); + }; + }); + return out; +}; + +var showMessage = function(element, msg, where) { + var div = $('<div class="vote-notification"><h3>' + msg + '</h3>(' + + $.i18n._('click to close') + ')</div>'); + + div.click(function(event) { + $(".vote-notification").fadeOut("fast", function() { $(this).remove(); }); + }); + + var where = where || 'parent'; + + if (where == 'parent'){ + element.parent().append(div); + } + else { + element.after(div); + } + + div.fadeIn("fast"); +}; + +//outer html hack - https://github.com/brandonaaron/jquery-outerhtml/ +(function($){ + var div; + $.fn.outerHTML = function() { + var elem = this[0], + tmp; + return !elem ? null + : typeof ( tmp = elem.outerHTML ) === 'string' ? tmp + : ( div = div || $('<div/>') ).html( this.eq(0).clone() ).html(); + }; +})(jQuery); + +var makeKeyHandler = function(key, callback){ + return function(e){ + if ((e.which && e.which == key) || (e.keyCode && e.keyCode == key)){ + if(!e.shiftKey){ + callback(); + return false; + } + } + }; +}; + + +var setupButtonEventHandlers = function(button, callback){ + button.keydown(makeKeyHandler(13, callback)); + button.click(callback); +}; + + +var putCursorAtEnd = function(element){ + var el = element.get()[0]; + if (el.setSelectionRange){ + var len = element.val().length * 2; + el.setSelectionRange(len, len); + } + else{ + element.val(element.val()); + } + element.scrollTop = 999999; +}; + +var setCheckBoxesIn = function(selector, value){ + return $(selector + '> input[type=checkbox]').attr('checked', value); +}; + +var notify = function() { + var visible = false; + return { + show: function(html) { + if (html) { + $("body").css("margin-top", "2.2em"); + $(".notify span").html(html); + } + $(".notify").fadeIn("slow"); + visible = true; + }, + close: function(doPostback) { + if (doPostback) { + $.post( + askbot['urls']['mark_read_message'], + { formdata: "required" } + ); + } + $(".notify").fadeOut("fast"); + $("body").css("margin-top", "0"); + visible = false; + }, + isVisible: function() { return visible; } + }; +} (); + +/* some google closure-like code for the ui elements */ +var inherits = function(childCtor, parentCtor) { + /** @constructor taken from google closure */ + function tempCtor() {}; + tempCtor.prototype = parentCtor.prototype; + childCtor.superClass_ = parentCtor.prototype; + childCtor.prototype = new tempCtor(); + childCtor.prototype.constructor = childCtor; +}; + +/* wrapper around jQuery object */ +var WrappedElement = function(){ + this._element = null; + this._in_document = false; +}; +WrappedElement.prototype.setElement = function(element){ + this._element = element; +}; +WrappedElement.prototype.createDom = function(){ + this._element = $('<div></div>'); +}; +WrappedElement.prototype.getElement = function(){ + if (this._element === null){ + this.createDom(); + } + return this._element; +}; +WrappedElement.prototype.inDocument = function(){ + return this._in_document; +}; +WrappedElement.prototype.enterDocument = function(){ + return this._in_document = true; +}; +WrappedElement.prototype.hasElement = function(){ + return (this._element !== null); +}; +WrappedElement.prototype.makeElement = function(html_tag){ + //makes jQuery element with tags + return $('<' + html_tag + '></' + html_tag + '>'); +}; +WrappedElement.prototype.dispose = function(){ + this._element.remove(); + this._in_document = false; +}; + +var SimpleControl = function(){ + WrappedElement.call(this); + this._handler = null; + this._title = null; +}; +inherits(SimpleControl, WrappedElement); + +SimpleControl.prototype.setHandler = function(handler){ + this._handler = handler; + if (this.hasElement()){ + this.setHandlerInternal(); + } +}; + +SimpleControl.prototype.setHandlerInternal = function(){ + //default internal setHandler behavior + setupButtonEventHandlers(this._element, this._handler); +}; + +SimpleControl.prototype.setTitle = function(title){ + this._title = title; +}; + +var EditLink = function(){ + SimpleControl.call(this) +}; +inherits(EditLink, SimpleControl); + +EditLink.prototype.createDom = function(){ + var element = $('<a></a>'); + element.addClass('edit'); + this.decorate(element); +}; + +EditLink.prototype.decorate = function(element){ + this._element = element; + this._element.attr('title', $.i18n._('click to edit this comment')); + this._element.html($.i18n._('edit')); + this.setHandlerInternal(); +}; + +var DeleteIcon = function(title){ + SimpleControl.call(this); + this._title = title; +}; +inherits(DeleteIcon, SimpleControl); + +DeleteIcon.prototype.decorate = function(element){ + this._element = element; + this._element.attr('class', 'delete-icon'); + this._element.attr('title', this._title); + if (this._handler !== null){ + this.setHandlerInternal(); + } +}; + +DeleteIcon.prototype.setHandlerInternal = function(){ + setupButtonEventHandlers(this._element, this._handler); +}; + +DeleteIcon.prototype.createDom = function(){ + this._element = this.makeElement('span'); + this.decorate(this._element); +}; + +var Tag = function(){ + SimpleControl.call(this); + this._deletable = false; + this._delete_handler = null; + this._delete_icon_title = null; + this._tag_title = null; + this._name = null; + this._url_params = null; + this._inner_html_tag = 'a'; + this._html_tag = 'li'; +} +inherits(Tag, SimpleControl); + +Tag.prototype.setName = function(name){ + this._name = name; +}; + +Tag.prototype.getName = function(){ + return this._name; +}; + +Tag.prototype.setHtmlTag = function(html_tag){ + this._html_tag = html_tag; +}; + +Tag.prototype.setDeletable = function(is_deletable){ + this._deletable = is_deletable; +}; + +Tag.prototype.setLinkable = function(is_linkable){ + if (is_linkable === true){ + this._inner_html_tag = 'a'; + } else { + this._inner_html_tag = 'span'; + } +}; + +Tag.prototype.isLinkable = function(){ + return (this._inner_html_tag === 'a'); +}; + +Tag.prototype.isDeletable = function(){ + return this._deletable; +}; + +Tag.prototype.isWildcard = function(){ + return (this.getName().substr(-1) === '*'); +}; + +Tag.prototype.setUrlParams = function(url_params){ + this._url_params = url_params; +}; + +Tag.prototype.setHandlerInternal = function(){ + setupButtonEventHandlers(this._element.find('.tag'), this._handler); +}; + +/* delete handler will be specific to the task */ +Tag.prototype.setDeleteHandler = function(delete_handler){ + this._delete_handler = delete_handler; + if (this.hasElement() && this.isDeletable()){ + this._delete_icon.setHandler(delete_handler); + } +}; + +Tag.prototype.getDeleteHandler = function(){ + return this._delete_handler; +}; + +Tag.prototype.setDeleteIconTitle = function(title){ + this._delete_icon_title = title; +}; + +Tag.prototype.decorate = function(element){ + this._element = element; + var del = element.find('.delete-icon'); + if (del.length === 1){ + this.setDeletable(true); + this._delete_icon = new DeleteIcon(); + if (this._delete_icon_title != null){ + this._delete_icon.setTitle(this._delete_icon_title); + } + //do not set the delete handler here + this._delete_icon.decorate(del); + } + this._inner_element = this._element.find('.tag'); + this._name = this.decodeTagName($.trim(this._inner_element.html())); + if (this._title !== null){ + this._inner_element.attr('title', this._title); + } + if (this._handler !== null){ + this.setHandlerInternal(); + } +}; + +Tag.prototype.getDisplayTagName = function(){ + //replaces the trailing * symbol with the unicode asterisk + return this._name.replace(/\*$/, '✽'); +}; + +Tag.prototype.decodeTagName = function(encoded_name){ + return encoded_name.replace('\u273d', '*'); +}; + +Tag.prototype.createDom = function(){ + this._element = this.makeElement(this._html_tag); + //render the outer element + if (this._deletable){ + this._element.addClass('deletable-tag'); + } + this._element.addClass('tag-left'); + + //render the inner element + this._inner_element = this.makeElement(this._inner_html_tag); + if (this.isLinkable()){ + var url = askbot['urls']['questions']; + url += '?tags=' + escape(this.getName()); + if (this._url_params !== null){ + url += escape('&' + this._url_params); + } + this._inner_element.attr('href', url); + } + this._inner_element.addClass('tag tag-right'); + this._inner_element.attr('rel', 'tag'); + if (this._title === null){ + this.setTitle( + $.i18n._( + "see questions tagged '{tag}'" + ).replace( + '{tag}', + this.getName() + ) + ); + } + this._inner_element.attr('title', this._title); + this._inner_element.html(this.getDisplayTagName()); + + this._element.append(this._inner_element); + + if (!this.isLinkable() && this._handler !== null){ + this.setHandlerInternal(); + } + + if (this._deletable){ + this._delete_icon = new DeleteIcon(); + this._delete_icon.setHandler(this.getDeleteHandler()); + if (this._delete_icon_title !== null){ + this._delete_icon.setTitle(this._delete_icon_title); + } + this._element.append(this._delete_icon.getElement()); + } +}; + +//Search Engine Keyword Highlight with Javascript +//http://scott.yang.id.au/code/se-hilite/ +Hilite={elementid:"content",exact:true,max_nodes:1000,onload:true,style_name:"hilite",style_name_suffix:true,debug_referrer:""};Hilite.search_engines=[["local","q"],["cnprog\\.","q"],["google\\.","q"],["search\\.yahoo\\.","p"],["search\\.msn\\.","q"],["search\\.live\\.","query"],["search\\.aol\\.","userQuery"],["ask\\.com","q"],["altavista\\.","q"],["feedster\\.","q"],["search\\.lycos\\.","q"],["alltheweb\\.","q"],["technorati\\.com/search/([^\\?/]+)",1],["dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)",1,true]];Hilite.decodeReferrer=function(d){var g=null;var e=new RegExp("");for(var c=0;c<Hilite.search_engines.length;c++){var f=Hilite.search_engines[c];e.compile("^http://(www\\.)?"+f[0],"i");var b=d.match(e);if(b){var a;if(isNaN(f[1])){a=Hilite.decodeReferrerQS(d,f[1])}else{a=b[f[1]+1]}if(a){a=decodeURIComponent(a);if(f.length>2&&f[2]){a=decodeURIComponent(a)}a=a.replace(/\'|"/g,"");a=a.split(/[\s,\+\.]+/);return a}break}}return null};Hilite.decodeReferrerQS=function(f,d){var b=f.indexOf("?");var c;if(b>=0){var a=new String(f.substring(b+1));b=0;c=0;while((b>=0)&&((c=a.indexOf("=",b))>=0)){var e,g;e=a.substring(b,c);b=a.indexOf("&",c)+1;if(e==d){if(b<=0){return a.substring(c+1)}else{return a.substring(c+1,b-1)}}else{if(b<=0){return null}}}}return null};Hilite.hiliteElement=function(f,e){if(!e||f.childNodes.length==0){return}var c=new Array();for(var b=0;b<e.length;b++){e[b]=e[b].toLowerCase();if(Hilite.exact){c.push("\\b"+e[b]+"\\b")}else{c.push(e[b])}}c=new RegExp(c.join("|"),"i");var a={};for(var b=0;b<e.length;b++){if(Hilite.style_name_suffix){a[e[b]]=Hilite.style_name+(b+1)}else{a[e[b]]=Hilite.style_name}}var d=function(m){var j=c.exec(m.data);if(j){var n=j[0];var i="";var h=m.splitText(j.index);var g=h.splitText(n.length);var l=m.ownerDocument.createElement("SPAN");m.parentNode.replaceChild(l,h);l.className=a[n.toLowerCase()];l.appendChild(h);return l}else{return m}};Hilite.walkElements(f.childNodes[0],1,d)};Hilite.hilite=function(){var a=Hilite.debug_referrer?Hilite.debug_referrer:document.referrer;var b=null;a=Hilite.decodeReferrer(a);if(a&&((Hilite.elementid&&(b=document.getElementById(Hilite.elementid)))||(b=document.body))){Hilite.hiliteElement(b,a)}};Hilite.walkElements=function(d,f,e){var a=/^(script|style|textarea)/i;var c=0;while(d&&f>0){c++;if(c>=Hilite.max_nodes){var b=function(){Hilite.walkElements(d,f,e)};setTimeout(b,50);return}if(d.nodeType==1){if(!a.test(d.tagName)&&d.childNodes.length>0){d=d.childNodes[0];f++;continue}}else{if(d.nodeType==3){d=e(d)}}if(d.nextSibling){d=d.nextSibling}else{while(f>0){d=d.parentNode;f--;if(d.nextSibling){d=d.nextSibling;break}}}}};if(Hilite.onload){if(window.attachEvent){window.attachEvent("onload",Hilite.hilite)}else{if(window.addEventListener){window.addEventListener("load",Hilite.hilite,false)}else{var __onload=window.onload;window.onload=function(){Hilite.hilite();__onload()}}}}; +/* json2.js by D. Crockford */ +if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}()); +//jquery fieldselection +(function(){var a={getSelection:function(){var b=this.jquery?this[0]:this;return(("selectionStart" in b&&function(){var c=b.selectionEnd-b.selectionStart;return{start:b.selectionStart,end:b.selectionEnd,length:c,text:b.value.substr(b.selectionStart,c)}})||(document.selection&&function(){b.focus();var d=document.selection.createRange();if(d==null){return{start:0,end:b.value.length,length:0}}var c=b.createTextRange();var e=c.duplicate();c.moveToBookmark(d.getBookmark());e.setEndPoint("EndToStart",c);return{start:e.text.length,end:e.text.length+d.text.length,length:d.text.length,text:d.text}})||function(){return{start:0,end:b.value.length,length:0}})()},replaceSelection:function(){var b=this.jquery?this[0]:this;var c=arguments[0]||"";return(("selectionStart" in b&&function(){b.value=b.value.substr(0,b.selectionStart)+c+b.value.substr(b.selectionEnd,b.value.length);return this})||(document.selection&&function(){b.focus();document.selection.createRange().text=c;return this})||function(){b.value+=c;return this})()}};jQuery.each(a,function(b){jQuery.fn[b]=this})})(); +//our custom autocompleter +var AutoCompleter=function(a){var b={autocompleteMultiple:true,multipleSeparator:" ",inputClass:"acInput",loadingClass:"acLoading",resultsClass:"acResults",selectClass:"acSelect",queryParamName:"q",limitParamName:"limit",extraParams:{},lineSeparator:"\n",cellSeparator:"|",minChars:2,maxItemsToShow:10,delay:400,useCache:true,maxCacheLength:10,matchSubset:true,matchCase:false,matchInside:true,mustMatch:false,preloadData:false,selectFirst:false,stopCharRegex:/\s+/,selectOnly:false,formatItem:null,onItemSelect:false,autoFill:false,filterResults:true,sortResults:true,sortFunction:false,onNoMatch:false};this.options=$.extend({},b,a);this.cacheData_={};this.cacheLength_=0;this.selectClass_="jquery-autocomplete-selected-item";this.keyTimeout_=null;this.lastKeyPressed_=null;this.lastProcessedValue_=null;this.lastSelectedValue_=null;this.active_=false;this.finishOnBlur_=true;this.options.minChars=parseInt(this.options.minChars,10);if(isNaN(this.options.minChars)||this.options.minChars<1){this.options.minChars=2}this.options.maxItemsToShow=parseInt(this.options.maxItemsToShow,10);if(isNaN(this.options.maxItemsToShow)||this.options.maxItemsToShow<1){this.options.maxItemsToShow=10}this.options.maxCacheLength=parseInt(this.options.maxCacheLength,10);if(isNaN(this.options.maxCacheLength)||this.options.maxCacheLength<1){this.options.maxCacheLength=10}if(this.options.preloadData===true){this.fetchRemoteData("",function(){})}};inherits(AutoCompleter,WrappedElement);AutoCompleter.prototype.decorate=function(a){this._element=a;this._element.attr("autocomplete","off");this._results=$("<div></div>").hide();if(this.options.resultsClass){this._results.addClass(this.options.resultsClass)}this._results.css({position:"absolute"});$("body").append(this._results);this.setEventHandlers()};AutoCompleter.prototype.setEventHandlers=function(){var a=this;a._element.keydown(function(b){a.lastKeyPressed_=b.keyCode;switch(a.lastKeyPressed_){case 38:b.preventDefault();if(a.active_){a.focusPrev()}else{a.activate()}return false;break;case 40:b.preventDefault();if(a.active_){a.focusNext()}else{a.activate()}return false;break;case 9:case 13:if(a.active_){b.preventDefault();a.selectCurrent();return false}break;case 27:if(a.active_){b.preventDefault();a.finish();return false}break;default:a.activate()}});a._element.blur(function(){if(a.finishOnBlur_){setTimeout(function(){a.finish()},200)}})};AutoCompleter.prototype.position=function(){var a=this._element.offset();this._results.css({top:a.top+this._element.outerHeight(),left:a.left})};AutoCompleter.prototype.cacheRead=function(d){var f,c,b,a,e;if(this.options.useCache){d=String(d);f=d.length;if(this.options.matchSubset){c=1}else{c=f}while(c<=f){if(this.options.matchInside){a=f-c}else{a=0}e=0;while(e<=a){b=d.substr(0,c);if(this.cacheData_[b]!==undefined){return this.cacheData_[b]}e++}c++}}return false};AutoCompleter.prototype.cacheWrite=function(a,b){if(this.options.useCache){if(this.cacheLength_>=this.options.maxCacheLength){this.cacheFlush()}a=String(a);if(this.cacheData_[a]!==undefined){this.cacheLength_++}return this.cacheData_[a]=b}return false};AutoCompleter.prototype.cacheFlush=function(){this.cacheData_={};this.cacheLength_=0};AutoCompleter.prototype.callHook=function(c,b){var a=this.options[c];if(a&&$.isFunction(a)){return a(b,this)}return false};AutoCompleter.prototype.activate=function(){var b=this;var a=function(){b.activateNow()};var c=parseInt(this.options.delay,10);if(isNaN(c)||c<=0){c=250}if(this.keyTimeout_){clearTimeout(this.keyTimeout_)}this.keyTimeout_=setTimeout(a,c)};AutoCompleter.prototype.activateNow=function(){var a=this.getValue();if(a!==this.lastProcessedValue_&&a!==this.lastSelectedValue_){if(a.length>=this.options.minChars){this.active_=true;this.lastProcessedValue_=a;this.fetchData(a)}}};AutoCompleter.prototype.fetchData=function(b){if(this.options.data){this.filterAndShowResults(this.options.data,b)}else{var a=this;this.fetchRemoteData(b,function(c){a.filterAndShowResults(c,b)})}};AutoCompleter.prototype.fetchRemoteData=function(c,e){var d=this.cacheRead(c);if(d){e(d)}else{var a=this;if(this._element){this._element.addClass(this.options.loadingClass)}var b=function(g){var f=false;if(g!==false){f=a.parseRemoteData(g);a.options.data=f;a.cacheWrite(c,f)}if(a._element){a._element.removeClass(a.options.loadingClass)}e(f)};$.ajax({url:this.makeUrl(c),success:b,error:function(){b(false)}})}};AutoCompleter.prototype.setOption=function(a,b){this.options[a]=b};AutoCompleter.prototype.setExtraParam=function(b,c){var a=$.trim(String(b));if(a){if(!this.options.extraParams){this.options.extraParams={}}if(this.options.extraParams[a]!==c){this.options.extraParams[a]=c;this.cacheFlush()}}};AutoCompleter.prototype.makeUrl=function(e){var a=this;var b=this.options.url;var d=$.extend({},this.options.extraParams);if(this.options.queryParamName===false){b+=encodeURIComponent(e)}else{d[this.options.queryParamName]=e}if(this.options.limitParamName&&this.options.maxItemsToShow){d[this.options.limitParamName]=this.options.maxItemsToShow}var c=[];$.each(d,function(f,g){c.push(a.makeUrlParam(f,g))});if(c.length){b+=b.indexOf("?")==-1?"?":"&";b+=c.join("&")}return b};AutoCompleter.prototype.makeUrlParam=function(a,b){return String(a)+"="+encodeURIComponent(b)};AutoCompleter.prototype.splitText=function(a){return String(a).replace(/(\r\n|\r|\n)/g,"\n").split(this.options.lineSeparator)};AutoCompleter.prototype.parseRemoteData=function(c){var h,b,f,d,g;var e=[];var b=this.splitText(c);for(f=0;f<b.length;f++){var a=b[f].split(this.options.cellSeparator);g=[];for(d=0;d<a.length;d++){g.push(unescape(a[d]))}h=g.shift();e.push({value:unescape(h),data:g})}return e};AutoCompleter.prototype.filterAndShowResults=function(a,b){this.showResults(this.filterResults(a,b),b)};AutoCompleter.prototype.filterResults=function(d,b){var f=[];var l,c,e,m,j,a;var k,h,g;for(e=0;e<d.length;e++){m=d[e];j=typeof m;if(j==="string"){l=m;c={}}else{if($.isArray(m)){l=m[0];c=m.slice(1)}else{if(j==="object"){l=m.value;c=m.data}}}l=String(l);if(l>""){if(typeof c!=="object"){c={}}if(this.options.filterResults){h=String(b);g=String(l);if(!this.options.matchCase){h=h.toLowerCase();g=g.toLowerCase()}a=g.indexOf(h);if(this.options.matchInside){a=a>-1}else{a=a===0}}else{a=true}if(a){f.push({value:l,data:c})}}}if(this.options.sortResults){f=this.sortResults(f,b)}if(this.options.maxItemsToShow>0&&this.options.maxItemsToShow<f.length){f.length=this.options.maxItemsToShow}return f};AutoCompleter.prototype.sortResults=function(c,d){var b=this;var a=this.options.sortFunction;if(!$.isFunction(a)){a=function(g,e,h){return b.sortValueAlpha(g,e,h)}}c.sort(function(f,e){return a(f,e,d)});return c};AutoCompleter.prototype.sortValueAlpha=function(d,c,e){d=String(d.value);c=String(c.value);if(!this.options.matchCase){d=d.toLowerCase();c=c.toLowerCase()}if(d>c){return 1}if(d<c){return -1}return 0};AutoCompleter.prototype.showResults=function(e,b){var k=this;var g=$("<ul></ul>");var f,l,j,a,h=false,d=false;var c=e.length;for(f=0;f<c;f++){l=e[f];j=$("<li>"+this.showResult(l.value,l.data)+"</li>");j.data("value",l.value);j.data("data",l.data);j.click(function(){var i=$(this);k.selectItem(i)}).mousedown(function(){k.finishOnBlur_=false}).mouseup(function(){k.finishOnBlur_=true});g.append(j);if(h===false){h=String(l.value);d=j;j.addClass(this.options.firstItemClass)}if(f==c-1){j.addClass(this.options.lastItemClass)}}this.position();this._results.html(g).show();a=this._results.outerWidth()-this._results.width();this._results.width(this._element.outerWidth()-a);$("li",this._results).hover(function(){k.focusItem(this)},function(){});if(this.autoFill(h,b)){this.focusItem(d)}};AutoCompleter.prototype.showResult=function(b,a){if($.isFunction(this.options.showResult)){return this.options.showResult(b,a)}else{return b}};AutoCompleter.prototype.autoFill=function(e,c){var b,a,d,f;if(this.options.autoFill&&this.lastKeyPressed_!=8){b=String(e).toLowerCase();a=String(c).toLowerCase();d=e.length;f=c.length;if(b.substr(0,f)===a){this._element.val(e);this.selectRange(f,d);return true}}return false};AutoCompleter.prototype.focusNext=function(){this.focusMove(+1)};AutoCompleter.prototype.focusPrev=function(){this.focusMove(-1)};AutoCompleter.prototype.focusMove=function(a){var b,c=$("li",this._results);a=parseInt(a,10);for(var b=0;b<c.length;b++){if($(c[b]).hasClass(this.selectClass_)){this.focusItem(b+a);return}}this.focusItem(0)};AutoCompleter.prototype.focusItem=function(b){var a,c=$("li",this._results);if(c.length){c.removeClass(this.selectClass_).removeClass(this.options.selectClass);if(typeof b==="number"){b=parseInt(b,10);if(b<0){b=0}else{if(b>=c.length){b=c.length-1}}a=$(c[b])}else{a=$(b)}if(a){a.addClass(this.selectClass_).addClass(this.options.selectClass)}}};AutoCompleter.prototype.selectCurrent=function(){var a=$("li."+this.selectClass_,this._results);if(a.length==1){this.selectItem(a)}else{this.finish()}};AutoCompleter.prototype.selectItem=function(d){var c=d.data("value");var b=d.data("data");var a=this.displayValue(c,b);this.lastProcessedValue_=a;this.lastSelectedValue_=a;this.setValue(a);this.setCaret(a.length);this.callHook("onItemSelect",{value:c,data:b});this.finish()};AutoCompleter.prototype.isContentChar=function(a){if(a.match(this.options.stopCharRegex)){return false}else{if(a===this.options.multipleSeparator){return false}else{return true}}};AutoCompleter.prototype.getValue=function(){var c=this._element.getSelection();var d=this._element.val();var f=c.start;var e=f;for(cpos=f;cpos>=0;cpos=cpos-1){if(cpos===d.length){continue}var b=d.charAt(cpos);if(!this.isContentChar(b)){break}e=cpos}var a=f;for(cpos=f;cpos<d.length;cpos=cpos+1){if(cpos===0){continue}var b=d.charAt(cpos);if(!this.isContentChar(b)){break}a=cpos}this._selection_start=e;this._selection_end=a;return d.substring(e,a)};AutoCompleter.prototype.setValue=function(b){var a=this._element.val().substring(0,this._selection_start);var c=this._element.val().substring(this._selection_end+1);this._element.val(a+b+c)};AutoCompleter.prototype.displayValue=function(b,a){if($.isFunction(this.options.displayValue)){return this.options.displayValue(b,a)}else{return b}};AutoCompleter.prototype.finish=function(){if(this.keyTimeout_){clearTimeout(this.keyTimeout_)}if(this._element.val()!==this.lastSelectedValue_){if(this.options.mustMatch){this._element.val("")}this.callHook("onNoMatch")}this._results.hide();this.lastKeyPressed_=null;this.lastProcessedValue_=null;if(this.active_){this.callHook("onFinish")}this.active_=false};AutoCompleter.prototype.selectRange=function(d,a){var c=this._element.get(0);if(c.setSelectionRange){c.focus();c.setSelectionRange(d,a)}else{if(this.createTextRange){var b=this.createTextRange();b.collapse(true);b.moveEnd("character",a);b.moveStart("character",d);b.select()}}};AutoCompleter.prototype.setCaret=function(a){this.selectRange(a,a)}; diff --git a/askbot/skins/common/media/js/wmd/images/wmd-buttons.png b/askbot/skins/common/media/js/wmd/images/wmd-buttons.png Binary files differnew file mode 100755 index 00000000..3013a4ad --- /dev/null +++ b/askbot/skins/common/media/js/wmd/images/wmd-buttons.png diff --git a/askbot/skins/common/media/js/wmd/showdown-min.js b/askbot/skins/common/media/js/wmd/showdown-min.js new file mode 100644 index 00000000..073613b1 --- /dev/null +++ b/askbot/skins/common/media/js/wmd/showdown-min.js @@ -0,0 +1 @@ +var Attacklab=Attacklab||{};Attacklab.showdown=Attacklab.showdown||{};Attacklab.showdown.converter=function(){var a;var j;var A;var i=0;this.makeHtml=function(H){a=new Array();j=new Array();A=new Array();H=H.replace(/~/g,"~T");H=H.replace(/\$/g,"~D");H=H.replace(/\r\n/g,"\n");H=H.replace(/\r/g,"\n");H="\n\n"+H+"\n\n";H=z(H);H=H.replace(/^[ \t]+$/mg,"");H=m(H);H=d(H);H=G(H);H=q(H);H=H.replace(/~D/g,"$$");H=H.replace(/~T/g,"~");return H};var d=function(H){var H=H.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,function(K,M,L,J,I){M=M.toLowerCase();a[M]=h(L);if(J){return J+I}else{if(I){j[M]=I.replace(/"/g,""")}}return""});return H};var m=function(J){J=J.replace(/\n/g,"\n\n");var I="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del";var H="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math";J=J.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,x);J=J.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,x);J=J.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,x);J=J.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,x);J=J.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,x);J=J.replace(/\n\n/g,"\n");return J};var x=function(H,I){var J=I;J=J.replace(/\n\n/g,"\n");J=J.replace(/^\n/,"");J=J.replace(/\n+$/g,"");J="\n\n~K"+(A.push(J)-1)+"K\n\n";return J};var G=function(I){I=f(I);var H=o("<hr />");I=I.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,H);I=I.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm,H);I=I.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm,H);I=E(I);I=b(I);I=u(I);I=m(I);I=g(I);return I};var r=function(H){H=C(H);H=l(H);H=e(H);H=F(H);H=y(H);H=n(H);H=h(H);H=c(H);H=H.replace(/ +\n/g," <br />\n");return H};var l=function(I){var H=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;I=I.replace(H,function(K){var J=K.replace(/(.)<\/?code>(?=.)/g,"$1`");J=w(J,"\\`*_");return J});return I};var y=function(H){H=H.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,D);H=H.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,D);H=H.replace(/(\[([^\[\]]+)\])()()()()()/g,D);return H};var D=function(N,T,S,R,Q,P,M,L){if(L==undefined){L=""}var K=T;var I=S;var J=R.toLowerCase();var H=Q;var O=L;if(H==""){if(J==""){J=I.toLowerCase().replace(/ ?\n/g," ")}H="#"+J;if(a[J]!=undefined){H=a[J];if(j[J]!=undefined){O=j[J]}}else{if(K.search(/\(\s*\)$/m)>-1){H=""}else{return K}}}H=w(H,"*_");var U='<a href="'+H+'"';if(O!=""){O=O.replace(/"/g,""");O=w(O,"*_");U+=' title="'+O+'"'}U+=">"+I+"</a>";return U};var F=function(H){H=H.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,t);H=H.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,t);return H};var t=function(N,T,S,R,Q,P,M,L){var K=T;var J=S;var I=R.toLowerCase();var H=Q;var O=L;if(!O){O=""}if(H==""){if(I==""){I=J.toLowerCase().replace(/ ?\n/g," ")}H="#"+I;if(a[I]!=undefined){H=a[I];if(j[I]!=undefined){O=j[I]}}else{return K}}J=J.replace(/"/g,""");H=w(H,"*_");var U='<img src="'+H+'" alt="'+J+'"';O=O.replace(/"/g,""");O=w(O,"*_");U+=' title="'+O+'"';U+=" />";return U};var f=function(H){H=H.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(I,J){return o("<h1>"+r(J)+"</h1>")});H=H.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(J,I){return o("<h2>"+r(I)+"</h2>")});H=H.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(I,L,K){var J=L.length;return o("<h"+J+">"+r(K)+"</h"+J+">")});return H};var p;var E=function(I){I+="~0";var H=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;if(i){I=I.replace(H,function(K,N,M){var O=N;var L=(M.search(/[*+-]/g)>-1)?"ul":"ol";O=O.replace(/\n{2,}/g,"\n\n\n");var J=p(O);J=J.replace(/\s+$/,"");J="<"+L+">"+J+"</"+L+">\n";return J})}else{H=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;I=I.replace(H,function(L,P,N,K){var O=P;var Q=N;var M=(K.search(/[*+-]/g)>-1)?"ul":"ol";var Q=Q.replace(/\n{2,}/g,"\n\n\n");var J=p(Q);J=O+"<"+M+">\n"+J+"</"+M+">\n";return J})}I=I.replace(/~0/,"");return I};p=function(H){i++;H=H.replace(/\n{2,}$/,"\n");H+="~0";H=H.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(K,M,L,J,I){var O=I;var N=M;var P=L;if(N||(O.search(/\n{2,}/)>-1)){O=G(s(O))}else{O=E(s(O));O=O.replace(/\n$/,"");O=r(O)}return"<li>"+O+"</li>\n"});H=H.replace(/~0/g,"");i--;return H};var b=function(H){H+="~0";H=H.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(I,K,J){var L=K;var M=J;L=v(s(L));L=z(L);L=L.replace(/^\n+/g,"");L=L.replace(/\n+$/g,"");L="<pre><code>"+L+"\n</code></pre>";return o(L)+M});H=H.replace(/~0/,"");return H};var o=function(H){H=H.replace(/(^\n+|\n+$)/g,"");return"\n\n~K"+(A.push(H)-1)+"K\n\n"};var C=function(H){H=H.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(K,M,L,J,I){var N=J;N=N.replace(/^([ \t]*)/g,"");N=N.replace(/[ \t]*$/g,"");N=v(N);return M+"<code>"+N+"</code>"});return H};var v=function(H){H=H.replace(/&/g,"&");H=H.replace(/</g,"<");H=H.replace(/>/g,">");H=w(H,"*_{}[]\\",false);return H};var c=function(H){H=H.replace(/(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\1/g,"<strong>$2</strong>");H=H.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"<em>$2</em>");return H};var u=function(H){H=H.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(I,J){var K=J;K=K.replace(/^[ \t]*>[ \t]?/gm,"~0");K=K.replace(/~0/g,"");K=K.replace(/^[ \t]+$/gm,"");K=G(K);K=K.replace(/(^|\n)/g,"$1 ");K=K.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(L,M){var N=M;N=N.replace(/^ /mg,"~0");N=N.replace(/~0/g,"");return N});return o("<blockquote>\n"+K+"\n</blockquote>")});return H};var g=function(N){N=N.replace(/^\n+/g,"");N=N.replace(/\n+$/g,"");var M=N.split(/\n{2,}/g);var J=new Array();var H=M.length;for(var I=0;I<H;I++){var L=M[I];if(L.search(/~K(\d+)K/g)>=0){J.push(L)}else{if(L.search(/\S/)>=0){L=r(L);L=L.replace(/^([ \t]*)/g,"<p>");L+="</p>";J.push(L)}}}H=J.length;for(var I=0;I<H;I++){while(J[I].search(/~K(\d+)K/)>=0){var K=A[RegExp.$1];K=K.replace(/\$/g,"$$$$");J[I]=J[I].replace(/~K\d+K/,K)}}return J.join("\n\n")};var h=function(H){H=H.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&");H=H.replace(/<(?![a-z\/?\$!])/gi,"<");return H};var e=function(H){H=H.replace(/\\(\\)/g,k);H=H.replace(/\\([`*_{}\[\]()>#+-.!])/g,k);return H};var n=function(H){H=H.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,'<a href="$1">$1</a>');H=H.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(I,J){return B(q(J))});return H};var B=function(J){function I(L){var K="0123456789ABCDEF";var M=L.charCodeAt(0);return(K.charAt(M>>4)+K.charAt(M&15))}var H=[function(K){return"&#"+K.charCodeAt(0)+";"},function(K){return"&#x"+I(K)+";"},function(K){return K}];J="mailto:"+J;J=J.replace(/./g,function(K){if(K=="@"){K=H[Math.floor(Math.random()*2)](K)}else{if(K!=":"){var L=Math.random();K=(L>0.9?H[2](K):L>0.45?H[1](K):H[0](K))}}return K});J='<a href="'+J+'">'+J+"</a>";J=J.replace(/">.+:/g,'">');return J};var q=function(H){H=H.replace(/~E(\d+)E/g,function(I,K){var J=parseInt(K);return String.fromCharCode(J)});return H};var s=function(H){H=H.replace(/^(\t|[ ]{1,4})/gm,"~0");H=H.replace(/~0/g,"");return H};var z=function(H){H=H.replace(/\t(?=\t)/g," ");H=H.replace(/\t/g,"~A~B");H=H.replace(/~B(.+?)~A/g,function(I,L,K){var N=L;var J=4-N.length%4;for(var M=0;M<J;M++){N+=" "}return N});H=H.replace(/~A/g," ");H=H.replace(/~B/g,"");return H};var w=function(L,I,J){var H="(["+I.replace(/([\[\]\\])/g,"\\$1")+"])";if(J){H="\\\\"+H}var K=new RegExp(H,"g");L=L.replace(K,k);return L};var k=function(H,J){var I=J.charCodeAt(0);return"~E"+I+"E"}};var Showdown=Attacklab.showdown;if(Attacklab.fileLoaded){Attacklab.fileLoaded("showdown.js")};
\ No newline at end of file diff --git a/askbot/skins/common/media/js/wmd/showdown.js b/askbot/skins/common/media/js/wmd/showdown.js new file mode 100644 index 00000000..257b8bd1 --- /dev/null +++ b/askbot/skins/common/media/js/wmd/showdown.js @@ -0,0 +1,1332 @@ +// +// showdown.js -- A javascript port of Markdown. +// +// Copyright (c) 2007 John Fraser. +// +// Original Markdown Copyright (c) 2004-2005 John Gruber +// <http://daringfireball.net/projects/markdown/> +// +// Redistributable under a BSD-style open source license. +// See license.txt for more information. +// +// The full source distribution is at: +// +// A A L +// T C A +// T K B +// +// <http://www.attacklab.net/> +// + +// +// Wherever possible, Showdown is a straight, line-by-line port +// of the Perl version of Markdown. +// +// This is not a normal parser design; it's basically just a +// series of string substitutions. It's hard to read and +// maintain this way, but keeping Showdown close to the original +// design makes it easier to port new features. +// +// More importantly, Showdown behaves like markdown.pl in most +// edge cases. So web applications can do client-side preview +// in Javascript, and then build identical HTML on the server. +// +// This port needs the new RegExp functionality of ECMA 262, +// 3rd Edition (i.e. Javascript 1.5). Most modern web browsers +// should do fine. Even with the new regular expression features, +// We do a lot of work to emulate Perl's regex functionality. +// The tricky changes in this file mostly have the "attacklab:" +// label. Major or self-explanatory changes don't. +// +// Smart diff tools like Araxis Merge will be able to match up +// this file with markdown.pl in a useful way. A little tweaking +// helps: in a copy of markdown.pl, replace "#" with "//" and +// replace "$text" with "text". Be sure to ignore whitespace +// and line endings. +// + + +// +// Showdown usage: +// +// var text = "Markdown *rocks*."; +// +// var converter = new Attacklab.showdown.converter(); +// var html = converter.makeHtml(text); +// +// alert(html); +// +// Note: move the sample code to the bottom of this +// file before uncommenting it. +// + + +// +// Attacklab namespace +// +var Attacklab = Attacklab || {} + +// +// Showdown namespace +// +Attacklab.showdown = Attacklab.showdown || {} + +// +// converter +// +// Wraps all "globals" so that the only thing +// exposed is makeHtml(). +// +Attacklab.showdown.converter = function() { + +// +// Globals: +// + +// Global hashes, used by various utility routines +var g_urls; +var g_titles; +var g_html_blocks; + +// Used to track when we're inside an ordered or unordered list +// (see _ProcessListItems() for details): +var g_list_level = 0; + +var makeHtmlBase = function(text) { +// +// Main function. The order in which other subs are called here is +// essential. Link and image substitutions need to happen before +// _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a> +// and <img> tags get encoded. +// + + // Clear the global hashes. If we don't clear these, you get conflicts + // from other articles when generating a page which contains more than + // one article (e.g. an index page that shows the N most recent + // articles): + g_urls = new Array(); + g_titles = new Array(); + g_html_blocks = new Array(); + + // attacklab: Replace ~ with ~T + // This lets us use tilde as an escape char to avoid md5 hashes + // The choice of character is arbitray; anything that isn't + // magic in Markdown will work. + text = text.replace(/~/g,"~T"); + + // attacklab: Replace $ with ~D + // RegExp interprets $ as a special character + // when it's in a replacement string + text = text.replace(/\$/g,"~D"); + + // Standardize line endings + text = text.replace(/\r\n/g,"\n"); // DOS to Unix + text = text.replace(/\r/g,"\n"); // Mac to Unix + + // Make sure text begins and ends with a couple of newlines: + text = "\n\n" + text + "\n\n"; + + // Convert all tabs to spaces. + text = _Detab(text); + + // Strip any lines consisting only of spaces and tabs. + // This makes subsequent regexen easier to write, because we can + // match consecutive blank lines with /\n+/ instead of something + // contorted like /[ \t]*\n+/ . + text = text.replace(/^[ \t]+$/mg,""); + + // Turn block-level HTML blocks into hash entries + text = _HashHTMLBlocks(text); + + // Strip link definitions, store in hashes. + text = _StripLinkDefinitions(text); + + text = _RunBlockGamut(text); + + text = _UnescapeSpecialChars(text); + + // attacklab: Restore dollar signs + text = text.replace(/~D/g,"$$"); + + // attacklab: Restore tildes + text = text.replace(/~T/g,"~"); + + return text; +} + +this.makeHtml = function(text){ + if (enableMathJax === false){ + return makeHtmlBase(text); + } + else { + MathJax.Hub.queue.Push( + function(){ + $('#previewer').html(makeHtmlBase(text)); + } + ); + MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'previewer']); + return $('#previewer').html(); + } +} + + +var _StripLinkDefinitions = function(text) { +// +// Strips link definitions from text, stores the URLs and titles in +// hash references. +// + + // Link defs are in the form: ^[id]: url "optional title" + + /* + var text = text.replace(/ + ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1 + [ \t]* + \n? // maybe *one* newline + [ \t]* + <?(\S+?)>? // url = $2 + [ \t]* + \n? // maybe one newline + [ \t]* + (?: + (\n*) // any lines skipped = $3 attacklab: lookbehind removed + ["(] + (.+?) // title = $4 + [")] + [ \t]* + )? // title is optional + (?:\n+|$) + /gm, + function(){...}); + */ + var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm, + function (wholeMatch,m1,m2,m3,m4) { + m1 = m1.toLowerCase(); + g_urls[m1] = _EncodeAmpsAndAngles(m2); // Link IDs are case-insensitive + if (m3) { + // Oops, found blank lines, so it's not a title. + // Put back the parenthetical statement we stole. + return m3+m4; + } else if (m4) { + g_titles[m1] = m4.replace(/"/g,"""); + } + + // Completely remove the definition from the text + return ""; + } + ); + + return text; +} + +var _HashHTMLBlocks = function(text) { + // attacklab: Double up blank lines to reduce lookaround + text = text.replace(/\n/g,"\n\n"); + + // Hashify HTML blocks: + // We only want to do this for block-level HTML tags, such as headers, + // lists, and tables. That's because we still want to wrap <p>s around + // "paragraphs" that are wrapped in non-block-level tags, such as anchors, + // phrase emphasis, and spans. The list of tags we're looking for is + // hard-coded: + var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del" + var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math" + + // First, look for nested blocks, e.g.: + // <div> + // <div> + // tags for inner block must be indented. + // </div> + // </div> + // + // The outermost tags must start at the left margin for this to match, and + // the inner nested divs must be indented. + // We need to do this before the next, more liberal match, because the next + // match will start at the first `<div>` and stop at the first `</div>`. + + // attacklab: This regex can be expensive when it fails. + /* + var text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_a) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*?\n // any number of lines, minimally matching + </\2> // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,hashElement); + + // + // Now match more liberally, simply from `\n<tag>` to `</tag>\n` + // + + /* + var text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_b) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*? // any number of lines, minimally matching + .*</\2> // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,hashElement); + + // Special case just for <hr />. It was easier to make a special case than + // to make the other regex more complicated. + + /* + text = text.replace(/ + ( // save in $1 + \n\n // Starting after a blank line + [ ]{0,3} + (<(hr) // start tag = $2 + \b // word break + ([^<>])*? // + \/?>) // the matching end tag + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,hashElement); + + // Special case for standalone HTML comments: + + /* + text = text.replace(/ + ( // save in $1 + \n\n // Starting after a blank line + [ ]{0,3} // attacklab: g_tab_width - 1 + <! + (--[^\r]*?--\s*)+ + > + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,hashElement); + + // PHP and ASP-style processor instructions (<?...?> and <%...%>) + + /* + text = text.replace(/ + (?: + \n\n // Starting after a blank line + ) + ( // save in $1 + [ ]{0,3} // attacklab: g_tab_width - 1 + (?: + <([?%]) // $2 + [^\r]*? + \2> + ) + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,hashElement); + + // attacklab: Undo double lines (see comment at top of this function) + text = text.replace(/\n\n/g,"\n"); + return text; +} + +var hashElement = function(wholeMatch,m1) { + var blockText = m1; + + // Undo double lines + blockText = blockText.replace(/\n\n/g,"\n"); + blockText = blockText.replace(/^\n/,""); + + // strip trailing blank lines + blockText = blockText.replace(/\n+$/g,""); + + // Replace the element text with a marker ("~KxK" where x is its key) + blockText = "\n\n~K" + (g_html_blocks.push(blockText)-1) + "K\n\n"; + + return blockText; +}; + +var _RunBlockGamut = function(text) { +// +// These are all the transformations that form block-level +// tags like paragraphs, headers, and list items. +// + text = _DoHeaders(text); + + // Do Horizontal Rules: + var key = hashBlock("<hr />"); + text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key); + text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm,key); + text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm,key); + + text = _DoLists(text); + text = _DoCodeBlocks(text); + text = _DoBlockQuotes(text); + + // We already ran _HashHTMLBlocks() before, in Markdown(), but that + // was to escape raw HTML in the original Markdown source. This time, + // we're escaping the markup we've just created, so that we don't wrap + // <p> tags around block-level tags. + text = _HashHTMLBlocks(text); + text = _FormParagraphs(text); + + return text; +} + + +var _RunSpanGamut = function(text) { +// +// These are all the transformations that occur *within* block-level +// tags like paragraphs, headers, and list items. +// + + text = _DoCodeSpans(text); + text = _EscapeSpecialCharsWithinTagAttributes(text); + text = _EncodeBackslashEscapes(text); + + // Process anchor and image tags. Images must come first, + // because ![foo][f] looks like an anchor. + text = _DoImages(text); + text = _DoAnchors(text); + + // Make links out of things like `<http://example.com/>` + // Must come after _DoAnchors(), because you can use < and > + // delimiters in inline links like [this](<url>). + text = _DoAutoLinks(text); + text = _EncodeAmpsAndAngles(text); + text = _DoItalicsAndBold(text); + + // Do hard breaks: + text = text.replace(/ +\n/g," <br />\n"); + return text; +} + +var _EscapeSpecialCharsWithinTagAttributes = function(text) { +// +// Within tags -- meaning between < and > -- encode [\ ` * _] so they +// don't conflict with their use in Markdown for code, italics and strong. +// + + // Build a regex to find HTML tags and comments. See Friedl's + // "Mastering Regular Expressions", 2nd Ed., pp. 200-201. + var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi; + + text = text.replace(regex, function(wholeMatch) { + var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`"); + tag = escapeCharacters(tag,"\\`*_"); + return tag; + }); + + return text; +} + +var _DoAnchors = function(text) { +// +// Turn Markdown link shortcuts into XHTML <a> tags. +// + // + // First, handle reference-style links: [link text] [id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[] // or anything else + )* + ) + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + )()()()() // pad remaining backreferences + /g,_DoAnchors_callback); + */ + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeAnchorTag); + + // + // Next, inline-style links: [link text](url "optional title") + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[\]] // or anything else + ) + ) + \] + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + <?(.*?)>? // href = $4 + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // Title = $7 + \6 // matching quote + [ \t]* // ignore any spaces/tabs between closing quote and ) + )? // title is optional + \) + ) + /g,writeAnchorTag); + */ + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag); + + // + // Last, handle reference-style shortcuts: [link text] + // These must come last in case you've also got [link test][1] + // or [link test](/foo) + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ([^\[\]]+) // link text = $2; can't contain '[' or ']' + \] + )()()()()() // pad rest of backreferences + /g, writeAnchorTag); + */ + text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag); + + return text; +} + +var writeAnchorTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) { + if (m7 == undefined) m7 = ""; + var whole_match = m1; + var link_text = m2; + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (url == "") { + if (link_id == "") { + // lower-case and turn embedded newlines into spaces + link_id = link_text.toLowerCase().replace(/ ?\n/g," "); + } + url = "#"+link_id; + + if (g_urls[link_id] != undefined) { + url = g_urls[link_id]; + if (g_titles[link_id] != undefined) { + title = g_titles[link_id]; + } + } + else { + if (whole_match.search(/\(\s*\)$/m)>-1) { + // Special case for explicit empty url + url = ""; + } else { + return whole_match; + } + } + } + + url = escapeCharacters(url,"*_"); + var result = "<a href=\"" + url + "\""; + + if (title != "") { + title = title.replace(/"/g,"""); + title = escapeCharacters(title,"*_"); + result += " title=\"" + title + "\""; + } + + result += ">" + link_text + "</a>"; + + return result; +} + + +var _DoImages = function(text) { +// +// Turn Markdown image shortcuts into <img> tags. +// + + // + // First, handle reference-style labeled images: ![alt text][id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + )()()()() // pad rest of backreferences + /g,writeImageTag); + */ + text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeImageTag); + + // + // Next, handle inline images: ![alt text](url "optional title") + // Don't forget: encode * and _ + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + \s? // One optional whitespace character + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + <?(\S+?)>? // src url = $4 + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // title = $7 + \6 // matching quote + [ \t]* + )? // title is optional + \) + ) + /g,writeImageTag); + */ + text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeImageTag); + + return text; +} + +var writeImageTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) { + var whole_match = m1; + var alt_text = m2; + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (!title) title = ""; + + if (url == "") { + if (link_id == "") { + // lower-case and turn embedded newlines into spaces + link_id = alt_text.toLowerCase().replace(/ ?\n/g," "); + } + url = "#"+link_id; + + if (g_urls[link_id] != undefined) { + url = g_urls[link_id]; + if (g_titles[link_id] != undefined) { + title = g_titles[link_id]; + } + } + else { + return whole_match; + } + } + + alt_text = alt_text.replace(/"/g,"""); + url = escapeCharacters(url,"*_"); + var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\""; + + // attacklab: Markdown.pl adds empty title attributes to images. + // Replicate this bug. + + //if (title != "") { + title = title.replace(/"/g,"""); + title = escapeCharacters(title,"*_"); + result += " title=\"" + title + "\""; + //} + + result += " />"; + + return result; +} + + +var _DoHeaders = function(text) { + + // Setext-style headers: + // Header 1 + // ======== + // + // Header 2 + // -------- + // + text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm, + function(wholeMatch,m1){return hashBlock("<h1>" + _RunSpanGamut(m1) + "</h1>");}); + + text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm, + function(matchFound,m1){return hashBlock("<h2>" + _RunSpanGamut(m1) + "</h2>");}); + + // atx-style headers: + // # Header 1 + // ## Header 2 + // ## Header 2 with closing hashes ## + // ... + // ###### Header 6 + // + + /* + text = text.replace(/ + ^(\#{1,6}) // $1 = string of #'s + [ \t]* + (.+?) // $2 = Header text + [ \t]* + \#* // optional closing #'s (not counted) + \n+ + /gm, function() {...}); + */ + + text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm, + function(wholeMatch,m1,m2) { + var h_level = m1.length; + return hashBlock("<h" + h_level + ">" + _RunSpanGamut(m2) + "</h" + h_level + ">"); + }); + + return text; +} + +// This declaration keeps Dojo compressor from outputting garbage: +var _ProcessListItems; + +var _DoLists = function(text) { +// +// Form HTML ordered (numbered) and unordered (bulleted) lists. +// + + // attacklab: add sentinel to hack around khtml/safari bug: + // http://bugs.webkit.org/show_bug.cgi?id=11231 + text += "~0"; + + // Re-usable pattern to match any entirel ul or ol list: + + /* + var whole_list = / + ( // $1 = whole list + ( // $2 + [ ]{0,3} // attacklab: g_tab_width - 1 + ([*+-]|\d+[.]) // $3 = first list item marker + [ \t]+ + ) + [^\r]+? + ( // $4 + ~0 // sentinel for workaround; should be $ + | + \n{2,} + (?=\S) + (?! // Negative lookahead for another list item marker + [ \t]* + (?:[*+-]|\d+[.])[ \t]+ + ) + ) + )/g + */ + var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; + + if (g_list_level) { + text = text.replace(whole_list,function(wholeMatch,m1,m2) { + var list = m1; + var list_type = (m2.search(/[*+-]/g)>-1) ? "ul" : "ol"; + + // Turn double returns into triple returns, so that we can make a + // paragraph for the last item in a list, if necessary: + list = list.replace(/\n{2,}/g,"\n\n\n");; + var result = _ProcessListItems(list); + + // Trim any trailing whitespace, to put the closing `</$list_type>` + // up on the preceding line, to get it past the current stupid + // HTML block parser. This is a hack to work around the terrible + // hack that is the HTML block parser. + result = result.replace(/\s+$/,""); + result = "<"+list_type+">" + result + "</"+list_type+">\n"; + return result; + }); + } else { + whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g; + text = text.replace(whole_list,function(wholeMatch,m1,m2,m3) { + var runup = m1; + var list = m2; + + var list_type = (m3.search(/[*+-]/g)>-1) ? "ul" : "ol"; + // Turn double returns into triple returns, so that we can make a + // paragraph for the last item in a list, if necessary: + var list = list.replace(/\n{2,}/g,"\n\n\n");; + var result = _ProcessListItems(list); + result = runup + "<"+list_type+">\n" + result + "</"+list_type+">\n"; + return result; + }); + } + + // attacklab: strip sentinel + text = text.replace(/~0/,""); + + return text; +} + +_ProcessListItems = function(list_str) { +// +// Process the contents of a single ordered or unordered list, splitting it +// into individual list items. +// + // The $g_list_level global keeps track of when we're inside a list. + // Each time we enter a list, we increment it; when we leave a list, + // we decrement. If it's zero, we're not in a list anymore. + // + // We do this because when we're not inside a list, we want to treat + // something like this: + // + // I recommend upgrading to version + // 8. Oops, now this line is treated + // as a sub-list. + // + // As a single paragraph, despite the fact that the second line starts + // with a digit-period-space sequence. + // + // Whereas when we're inside a list (or sub-list), that line will be + // treated as the start of a sub-list. What a kludge, huh? This is + // an aspect of Markdown's syntax that's hard to parse perfectly + // without resorting to mind-reading. Perhaps the solution is to + // change the syntax rules such that sub-lists must start with a + // starting cardinal number; e.g. "1." or "a.". + + g_list_level++; + + // trim trailing blank lines: + list_str = list_str.replace(/\n{2,}$/,"\n"); + + // attacklab: add sentinel to emulate \z + list_str += "~0"; + + /* + list_str = list_str.replace(/ + (\n)? // leading line = $1 + (^[ \t]*) // leading whitespace = $2 + ([*+-]|\d+[.]) [ \t]+ // list marker = $3 + ([^\r]+? // list item text = $4 + (\n{1,2})) + (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+)) + /gm, function(){...}); + */ + list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm, + function(wholeMatch,m1,m2,m3,m4){ + var item = m4; + var leading_line = m1; + var leading_space = m2; + + if (leading_line || (item.search(/\n{2,}/)>-1)) { + item = _RunBlockGamut(_Outdent(item)); + } + else { + // Recursion for sub-lists: + item = _DoLists(_Outdent(item)); + item = item.replace(/\n$/,""); // chomp(item) + item = _RunSpanGamut(item); + } + + return "<li>" + item + "</li>\n"; + } + ); + + // attacklab: strip sentinel + list_str = list_str.replace(/~0/g,""); + + g_list_level--; + return list_str; +} + + +var _DoCodeBlocks = function(text) { +// +// Process Markdown `<pre><code>` blocks. +// + + /* + text = text.replace(text, + /(?:\n\n|^) + ( // $1 = the code block -- one or more lines, starting with a space/tab + (?: + (?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width + .*\n+ + )+ + ) + (\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width + /g,function(){...}); + */ + + // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug + text += "~0"; + + text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g, + function(wholeMatch,m1,m2) { + var codeblock = m1; + var nextChar = m2; + + codeblock = _EncodeCode( _Outdent(codeblock)); + codeblock = _Detab(codeblock); + codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines + codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace + + codeblock = "<pre><code>" + codeblock + "\n</code></pre>"; + + return hashBlock(codeblock) + nextChar; + } + ); + + // attacklab: strip sentinel + text = text.replace(/~0/,""); + + return text; +} + +var hashBlock = function(text) { + text = text.replace(/(^\n+|\n+$)/g,""); + return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n"; +} + + +var _DoCodeSpans = function(text) { +// +// * Backtick quotes are used for <code></code> spans. +// +// * You can use multiple backticks as the delimiters if you want to +// include literal backticks in the code span. So, this input: +// +// Just type ``foo `bar` baz`` at the prompt. +// +// Will translate to: +// +// <p>Just type <code>foo `bar` baz</code> at the prompt.</p> +// +// There's no arbitrary limit to the number of backticks you +// can use as delimters. If you need three consecutive backticks +// in your code, use four for delimiters, etc. +// +// * You can use spaces to get literal backticks at the edges: +// +// ... type `` `bar` `` ... +// +// Turns to: +// +// ... type <code>`bar`</code> ... +// + + /* + text = text.replace(/ + (^|[^\\]) // Character before opening ` can't be a backslash + (`+) // $2 = Opening run of ` + ( // $3 = The code block + [^\r]*? + [^`] // attacklab: work around lack of lookbehind + ) + \2 // Matching closer + (?!`) + /gm, function(){...}); + */ + + text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, + function(wholeMatch,m1,m2,m3,m4) { + var c = m3; + c = c.replace(/^([ \t]*)/g,""); // leading whitespace + c = c.replace(/[ \t]*$/g,""); // trailing whitespace + c = _EncodeCode(c); + return m1+"<code>"+c+"</code>"; + }); + + return text; +} + + +var _EncodeCode = function(text) { +// +// Encode/escape certain characters inside Markdown code runs. +// The point is that in code, these characters are literals, +// and lose their special Markdown meanings. +// + // Encode all ampersands; HTML entities are not + // entities within a Markdown code span. + text = text.replace(/&/g,"&"); + + // Do the angle bracket song and dance: + text = text.replace(/</g,"<"); + text = text.replace(/>/g,">"); + + // Now, escape characters that are magic in Markdown: + text = escapeCharacters(text,"\*_{}[]\\",false); + +// jj the line above breaks this: +//--- + +//* Item + +// 1. Subitem + +// special char: * +//--- + + return text; +} + + +var _DoItalicsAndBold = function(text) { + + // <strong> must go first: + if (codeFriendlyMarkdown === true){ + text = text.replace(/(\*\*)(?=\S)([^\r]*?\S[\*]*)\1/g, + "<strong>$2</strong>"); + + text = text.replace(/(\*)(?=\S)([^\r]*?\S)\1/g, + "<em>$2</em>"); + } + else { + text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\1/g, + "<strong>$2</strong>"); + + text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, + "<em>$2</em>"); + } + + return text; +} + + +var _DoBlockQuotes = function(text) { + + /* + text = text.replace(/ + ( // Wrap whole match in $1 + ( + ^[ \t]*>[ \t]? // '>' at the start of a line + .+\n // rest of the first line + (.+\n)* // subsequent consecutive lines + \n* // blanks + )+ + ) + /gm, function(){...}); + */ + + text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, + function(wholeMatch,m1) { + var bq = m1; + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + bq = bq.replace(/^[ \t]*>[ \t]?/gm,"~0"); // trim one level of quoting + + // attacklab: clean up hack + bq = bq.replace(/~0/g,""); + + bq = bq.replace(/^[ \t]+$/gm,""); // trim whitespace-only lines + bq = _RunBlockGamut(bq); // recurse + + bq = bq.replace(/(^|\n)/g,"$1 "); + // These leading spaces screw with <pre> content, so we need to fix that: + bq = bq.replace( + /(\s*<pre>[^\r]+?<\/pre>)/gm, + function(wholeMatch,m1) { + var pre = m1; + // attacklab: hack around Konqueror 3.5.4 bug: + pre = pre.replace(/^ /mg,"~0"); + pre = pre.replace(/~0/g,""); + return pre; + }); + + return hashBlock("<blockquote>\n" + bq + "\n</blockquote>"); + }); + return text; +} + + +var _FormParagraphs = function(text) { +// +// Params: +// $text - string to process with html <p> tags +// + + // Strip leading and trailing lines: + text = text.replace(/^\n+/g,""); + text = text.replace(/\n+$/g,""); + + var grafs = text.split(/\n{2,}/g); + var grafsOut = new Array(); + + // + // Wrap <p> tags. + // + var end = grafs.length; + for (var i=0; i<end; i++) { + var str = grafs[i]; + + // if this is an HTML marker, copy it + if (str.search(/~K(\d+)K/g) >= 0) { + grafsOut.push(str); + } + else if (str.search(/\S/) >= 0) { + str = _RunSpanGamut(str); + str = str.replace(/^([ \t]*)/g,"<p>"); + str += "</p>" + grafsOut.push(str); + } + + } + + // + // Unhashify HTML blocks + // + end = grafsOut.length; + for (var i=0; i<end; i++) { + // if this is a marker for an html block... + while (grafsOut[i].search(/~K(\d+)K/) >= 0) { + var blockText = g_html_blocks[RegExp.$1]; + blockText = blockText.replace(/\$/g,"$$$$"); // Escape any dollar signs + grafsOut[i] = grafsOut[i].replace(/~K\d+K/,blockText); + } + } + + return grafsOut.join("\n\n"); +} + + +var _EncodeAmpsAndAngles = function(text) { +// Smart processing for ampersands and angle brackets that need to be encoded. + + // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: + // http://bumppo.net/projects/amputator/ + text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"); + + // Encode naked <'s + text = text.replace(/<(?![a-z\/?\$!])/gi,"<"); + + return text; +} + + +var _EncodeBackslashEscapes = function(text) { +// +// Parameter: String. +// Returns: The string, with after processing the following backslash +// escape sequences. +// + + // attacklab: The polite way to do this is with the new + // escapeCharacters() function: + // + // text = escapeCharacters(text,"\\",true); + // text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); + // + // ...but we're sidestepping its use of the (slow) RegExp constructor + // as an optimization for Firefox. This function gets called a LOT. + + text = text.replace(/\\(\\)/g,escapeCharacters_callback); + text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g,escapeCharacters_callback); + return text; +} + + +var _DoAutoLinks = function(text) { + + text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>"); + + // Email addresses: <address@domain.foo> + + /* + text = text.replace(/ + < + (?:mailto:)? + ( + [-.\w]+ + \@ + [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+ + ) + > + /gi, _DoAutoLinks_callback()); + */ + text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, + function(wholeMatch,m1) { + return _EncodeEmailAddress( _UnescapeSpecialChars(m1) ); + } + ); + + return text; +} + + +var _EncodeEmailAddress = function(addr) { +// +// Input: an email address, e.g. "foo@example.com" +// +// Output: the email address as a mailto link, with each character +// of the address encoded as either a decimal or hex entity, in +// the hopes of foiling most address harvesting spam bots. E.g.: +// +// <a href="mailto:foo@e +// xample.com">foo +// @example.com</a> +// +// Based on a filter by Matthew Wickline, posted to the BBEdit-Talk +// mailing list: <http://tinyurl.com/yu7ue> +// + + // attacklab: why can't javascript speak hex? + function char2hex(ch) { + var hexDigits = '0123456789ABCDEF'; + var dec = ch.charCodeAt(0); + return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15)); + } + + var encode = [ + function(ch){return "&#"+ch.charCodeAt(0)+";";}, + function(ch){return "&#x"+char2hex(ch)+";";}, + function(ch){return ch;} + ]; + + addr = "mailto:" + addr; + + addr = addr.replace(/./g, function(ch) { + if (ch == "@") { + // this *must* be encoded. I insist. + ch = encode[Math.floor(Math.random()*2)](ch); + } else if (ch !=":") { + // leave ':' alone (to spot mailto: later) + var r = Math.random(); + // roughly 10% raw, 45% hex, 45% dec + ch = ( + r > .9 ? encode[2](ch) : + r > .45 ? encode[1](ch) : + encode[0](ch) + ); + } + return ch; + }); + + addr = "<a href=\"" + addr + "\">" + addr + "</a>"; + addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part + + return addr; +} + + +var _UnescapeSpecialChars = function(text) { +// +// Swap back in all the special characters we've hidden. +// + text = text.replace(/~E(\d+)E/g, + function(wholeMatch,m1) { + var charCodeToReplace = parseInt(m1); + return String.fromCharCode(charCodeToReplace); + } + ); + return text; +} + + +var _Outdent = function(text) { +// +// Remove one level of line-leading tabs or spaces +// + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + text = text.replace(/^(\t|[ ]{1,4})/gm,"~0"); // attacklab: g_tab_width + + // attacklab: clean up hack + text = text.replace(/~0/g,"") + + return text; +} + +var _Detab = function(text) { +// attacklab: Detab's completely rewritten for speed. +// In perl we could fix it by anchoring the regexp with \G. +// In javascript we're less fortunate. + + // expand first n-1 tabs + text = text.replace(/\t(?=\t)/g," "); // attacklab: g_tab_width + + // replace the nth with two sentinels + text = text.replace(/\t/g,"~A~B"); + + // use the sentinel to anchor our regex so it doesn't explode + text = text.replace(/~B(.+?)~A/g, + function(wholeMatch,m1,m2) { + var leadingText = m1; + var numSpaces = 4 - leadingText.length % 4; // attacklab: g_tab_width + + // there *must* be a better way to do this: + for (var i=0; i<numSpaces; i++) leadingText+=" "; + + return leadingText; + } + ); + + // clean up sentinels + text = text.replace(/~A/g," "); // attacklab: g_tab_width + text = text.replace(/~B/g,""); + + return text; +} + + +// +// attacklab: Utility functions +// + + +var escapeCharacters = function(text, charsToEscape, afterBackslash) { + // First we have to escape the escape characters so that + // we can build a character class out of them + var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g,"\\$1") + "])"; + + if (afterBackslash) { + regexString = "\\\\" + regexString; + } + + var regex = new RegExp(regexString,"g"); + text = text.replace(regex,escapeCharacters_callback); + + return text; +} + + +var escapeCharacters_callback = function(wholeMatch,m1) { + var charCodeToEscape = m1.charCodeAt(0); + return "~E"+charCodeToEscape+"E"; +} + +} // end of Attacklab.showdown.converter + + +// Version 0.9 used the Showdown namespace instead of Attacklab.showdown +// The old namespace is deprecated, but we'll support it for now: +var Showdown = Attacklab.showdown; + +// If anyone's interested, tell the world that this file's been loaded +if (Attacklab.fileLoaded) { + Attacklab.fileLoaded("showdown.js"); +} diff --git a/askbot/skins/common/media/js/wmd/wmd-min.js b/askbot/skins/common/media/js/wmd/wmd-min.js new file mode 100644 index 00000000..aa643f1a --- /dev/null +++ b/askbot/skins/common/media/js/wmd/wmd-min.js @@ -0,0 +1 @@ +var Attacklab=Attacklab||{};Attacklab.wmdBase=function(){var y=top.Attacklab;var E=top.document;var s=top.RegExp;var l=top.navigator;y.Util={};y.Position={};y.Command={};y.Global={};var a=y.Util;var C=y.Position;var h=y.Command;var v=y.Global;v.isIE=/msie/.test(l.userAgent.toLowerCase());v.isIE_5or6=/msie 6/.test(l.userAgent.toLowerCase())||/msie 5/.test(l.userAgent.toLowerCase());v.isIE_7plus=v.isIE&&!v.isIE_5or6;v.isOpera=/opera/.test(l.userAgent.toLowerCase());v.isKonqueror=/konqueror/.test(l.userAgent.toLowerCase());var c="粗体 <strong> Ctrl-B";var f="斜体 <em> Ctrl-I";var z="超链接 <a> Ctrl-L";var u="引用 <blockquote> Ctrl-.";var e="代ç <pre><code> Ctrl-K";var d="图片 <img> Ctrl-G";var q="æ•°å—ç¼–å·åˆ—表 <ol> Ctrl-O";var t="项目符å·åˆ—表 <ul> Ctrl-U";var i="æ ‡é¢˜ <h1>/<h2> Ctrl-H";var p="水平线 <hr> Ctrl-R";var m="撤销 Ctrl-Z";var j="é‡åš Ctrl-Y";var B="<p style='margin-top: 0px'><b>输入图片地å€</b></p><p>示例:<br />http://www.cnprog.com/images/temp.jpg \"我的截图\"</p>";var D="<p style='margin-top: 0px'><b>输入Web地å€</b></p><p>示例:<br />http://www.cnprog.com/ \"我的网站\"</p>";var n='<div>æˆ–è€…ä¸Šä¼ æœ¬åœ°å›¾ç‰‡ï¼š</div><input type="file" name="file-upload" id="file-upload" size="26" onchange="return ajaxFileUpload($(\'#image-url\'));"/><br><img id="loading" src="/media/images/indicator.gif" style="display:none;"/>';var b="http://";var g="http://";var o="images/";var A=500;var x=100;var k="http://wmd-editor.com/";var r="WMD website";var w="_blank";y.PanelCollection=function(){this.buttonBar=E.getElementById("wmd-button-bar");this.preview=E.getElementById("previewer");this.output=E.getElementById("wmd-output");this.input=E.getElementById("editor")};y.panels=undefined;y.ieCachedRange=null;y.ieRetardedClick=false;a.isVisible=function(F){if(window.getComputedStyle){return window.getComputedStyle(F,null).getPropertyValue("display")!=="none"}else{if(F.currentStyle){return F.currentStyle.display!=="none"}}};a.addEvent=function(G,F,H){if(G.attachEvent){G.attachEvent("on"+F,H)}else{G.addEventListener(F,H,false)}};a.removeEvent=function(G,F,H){if(G.detachEvent){G.detachEvent("on"+F,H)}else{G.removeEventListener(F,H,false)}};a.fixEolChars=function(F){F=F.replace(/\r\n/g,"\n");F=F.replace(/\r/g,"\n");return F};a.extendRegExp=function(H,J,G){if(J===null||J===undefined){J=""}if(G===null||G===undefined){G=""}var I=H.toString();var F;I=I.replace(/\/([gim]*)$/,"");F=s.$1;I=I.replace(/(^\/|\/$)/g,"");I=J+I+G;return new s(I,F)};a.createImage=function(F){var H=o+F;var G=E.createElement("img");G.className="wmd-button";G.src=H;return G};a.prompt=function(M,P,H){var I;var F;var K;var J=0;if(arguments.length==4){J=arguments[3]}if(P===undefined){P=""}var L=function(Q){var R=(Q.charCode||Q.keyCode);if(R===27){N(true)}};var N=function(Q){a.removeEvent(E.body,"keydown",L);var R=K.value;if(Q){R=null}else{R=R.replace("http://http://","http://");R=R.replace("http://https://","https://");R=R.replace("http://ftp://","ftp://");if(R.indexOf("http://")===-1&&R.indexOf("ftp://")===-1){R="http://"+R}}I.parentNode.removeChild(I);F.parentNode.removeChild(F);H(R);return false};var G=function(){F=E.createElement("div");F.className="wmd-prompt-background";style=F.style;style.position="absolute";style.top="0";style.zIndex="1000";if(v.isKonqueror){style.backgroundColor="transparent"}else{if(v.isIE){style.filter="alpha(opacity=50)"}else{style.opacity="0.5"}}var Q=C.getPageSize();style.height=Q[1]+"px";if(v.isIE){style.left=E.documentElement.scrollLeft;style.width=E.documentElement.clientWidth}else{style.left="0";style.width="100%"}E.body.appendChild(F)};var O=function(){I=E.createElement("div");I.className="wmd-prompt-dialog";I.style.padding="10px;";I.style.position="fixed";I.style.width="400px";I.style.zIndex="1001";var Q=E.createElement("div");Q.innerHTML=M;Q.style.padding="5px";I.appendChild(Q);var S=E.createElement("form");S.onsubmit=function(){return N(false)};style=S.style;style.padding="0";style.margin="0";style.cssFloat="left";style.width="100%";style.textAlign="center";style.position="relative";I.appendChild(S);K=E.createElement("input");if(J==1){K.id="image-url"}K.type="text";K.value=P;style=K.style;style.display="block";style.width="80%";style.marginLeft=style.marginRight="auto";S.appendChild(K);if(J==1){var R=E.createElement("div");R.innerHTML=n;R.style.padding="5px";S.appendChild(R)}var U=E.createElement("input");U.type="button";U.onclick=function(){return N(false)};U.value="OK";style=U.style;style.margin="10px";style.display="inline";style.width="7em";var T=E.createElement("input");T.type="button";T.onclick=function(){return N(true)};T.value="Cancel";style=T.style;style.margin="10px";style.display="inline";style.width="7em";if(/mac/.test(l.platform.toLowerCase())){S.appendChild(T);S.appendChild(U)}else{S.appendChild(U);S.appendChild(T)}a.addEvent(E.body,"keydown",L);I.style.top="50%";I.style.left="50%";I.style.display="block";if(v.isIE_5or6){I.style.position="absolute";I.style.top=E.documentElement.scrollTop+200+"px";I.style.left="50%"}E.body.appendChild(I);I.style.marginTop=-(C.getHeight(I)/2)+"px";I.style.marginLeft=-(C.getWidth(I)/2)+"px"};G();top.setTimeout(function(){O();var R=P.length;if(K.selectionStart!==undefined){K.selectionStart=0;K.selectionEnd=R}else{if(K.createTextRange){var Q=K.createTextRange();Q.collapse(false);Q.moveStart("character",-R);Q.moveEnd("character",R);Q.select()}}K.focus()},0)};C.getTop=function(H,G){var F=H.offsetTop;if(!G){while(H=H.offsetParent){F+=H.offsetTop}}return F};C.getHeight=function(F){return F.offsetHeight||F.scrollHeight};C.getWidth=function(F){return F.offsetWidth||F.scrollWidth};C.getPageSize=function(){var G,H;var F,K;if(self.innerHeight&&self.scrollMaxY){G=E.body.scrollWidth;H=self.innerHeight+self.scrollMaxY}else{if(E.body.scrollHeight>E.body.offsetHeight){G=E.body.scrollWidth;H=E.body.scrollHeight}else{G=E.body.offsetWidth;H=E.body.offsetHeight}}if(self.innerHeight){F=self.innerWidth;K=self.innerHeight}else{if(E.documentElement&&E.documentElement.clientHeight){F=E.documentElement.clientWidth;K=E.documentElement.clientHeight}else{if(E.body){F=E.body.clientWidth;K=E.body.clientHeight}}}var J=Math.max(G,F);var I=Math.max(H,K);return[J,I,F,K]};y.inputPoller=function(O,H){var F=this;var K=y.panels.input;var G;var I;var L;var J;this.tick=function(){if(!a.isVisible(K)){return}if(K.selectionStart||K.selectionStart===0){var Q=K.selectionStart;var P=K.selectionEnd;if(Q!=G||P!=I){G=Q;I=P;if(L!=K.value){L=K.value;return true}}}return false};var N=function(){if(!a.isVisible(K)){return}if(F.tick()){O()}};var M=function(){J=top.setInterval(N,H)};this.destroy=function(){top.clearInterval(J)};M()};y.undoManager=function(Q){var U=this;var O=[];var M=0;var L="none";var G;var R;var H;var K;var F=function(W,V){if(L!=W){L=W;if(!V){I()}}if(!v.isIE||L!="moving"){H=top.setTimeout(N,1)}else{K=null}};var N=function(){K=new y.TextareaState();R.tick();H=undefined};this.setCommandMode=function(){L="command";I();H=top.setTimeout(N,0)};this.canUndo=function(){return M>1};this.canRedo=function(){if(O[M+1]){return true}return false};this.undo=function(){if(U.canUndo()){if(G){G.restore();G=null}else{O[M]=new y.TextareaState();O[--M].restore();if(Q){Q()}}}L="none";y.panels.input.focus();N()};this.redo=function(){if(U.canRedo()){O[++M].restore();if(Q){Q()}}L="none";y.panels.input.focus();N()};var I=function(){var V=K||new y.TextareaState();if(!V){return false}if(L=="moving"){if(!G){G=V}return}if(G){if(O[M-1].text!=G.text){O[M++]=G}G=null}O[M++]=V;O[M+1]=null;if(Q){Q()}};var P=function(V){var X=false;if(V.ctrlKey||V.metaKey){var W=V.charCode||V.keyCode;var Y=String.fromCharCode(W);switch(Y){case"y":U.redo();X=true;break;case"z":if(!V.shiftKey){U.undo()}else{U.redo()}X=true;break}}if(X){if(V.preventDefault){V.preventDefault()}if(top.event){top.event.returnValue=false}return}};var T=function(V){if(!V.ctrlKey&&!V.metaKey){var W=V.keyCode;if((W>=33&&W<=40)||(W>=63232&&W<=63235)){F("moving")}else{if(W==8||W==46||W==127){F("deleting")}else{if(W==13){F("newlines")}else{if(W==27){F("escape")}else{if((W<16||W>20)&&W!=91){F("typing")}}}}}}};var J=function(){a.addEvent(y.panels.input,"keypress",function(W){if((W.ctrlKey||W.metaKey)&&(W.keyCode==89||W.keyCode==90)){W.preventDefault()}});var V=function(){if(v.isIE||(K&&K.text!=y.panels.input.value)){if(H==undefined){L="paste";I();N()}}};R=new y.inputPoller(V,x);a.addEvent(y.panels.input,"keydown",P);a.addEvent(y.panels.input,"keydown",T);a.addEvent(y.panels.input,"mousedown",function(){F("moving")});y.panels.input.onpaste=V;y.panels.input.ondrop=V};var S=function(){J();N();I()};this.destroy=function(){if(R){R.destroy()}};S()};y.editor=function(O){if(!O){O=function(){}}var L=y.panels.input;var I=0;var P=this;var K;var R;var G;var M;var N;var U=function(W){L.focus();if(W.textOp){if(N){N.setCommandMode()}var Y=new y.TextareaState();if(!Y){return}var Z=Y.getChunks();var V=function(){L.focus();if(Z){Y.setChunks(Z)}Y.restore();O()};var X=W.textOp(Z,V);if(!X){V()}}if(W.execute){W.execute(P)}};var S=function(){if(N){F(document.getElementById("wmd-undo-button"),N.canUndo());F(document.getElementById("wmd-redo-button"),N.canRedo())}};var F=function(V,X){var Y="0px";var Z="-20px";var W="-40px";if(X){V.style.backgroundPosition=V.XShift+" "+Y;V.onmouseover=function(){this.style.backgroundPosition=this.XShift+" "+W};V.onmouseout=function(){this.style.backgroundPosition=this.XShift+" "+Y};if(v.isIE){V.onmousedown=function(){y.ieRetardedClick=true;y.ieCachedRange=document.selection.createRange()}}if(!V.isHelp){V.onclick=function(){if(this.onmouseout){this.onmouseout()}U(this);return false}}}else{V.style.backgroundPosition=V.XShift+" "+Z;V.onmouseover=V.onmouseout=V.onclick=function(){}}};var J=function(){var Z=document.getElementById("wmd-button-bar");var W="0px";var Y="-20px";var ae="-40px";var ak=document.createElement("ul");ak.id="wmd-button-row";ak=Z.appendChild(ak);var ad=document.createElement("li");ad.className="wmd-button";ad.id="wmd-bold-button";ad.title=c;ad.XShift="0px";ad.textOp=h.doBold;F(ad,true);ak.appendChild(ad);var ac=document.createElement("li");ac.className="wmd-button";ac.id="wmd-italic-button";ac.title=f;ac.XShift="-20px";ac.textOp=h.doItalic;F(ac,true);ak.appendChild(ac);var ah=document.createElement("li");ah.className="wmd-spacer";ah.id="wmd-spacer1";ak.appendChild(ah);var ai=document.createElement("li");ai.className="wmd-button";ai.id="wmd-link-button";ai.title=z;ai.XShift="-40px";ai.textOp=function(ap,aq){return h.doLinkOrImage(ap,aq,false)};F(ai,true);ak.appendChild(ai);var al=document.createElement("li");al.className="wmd-button";al.id="wmd-quote-button";al.title=u;al.XShift="-60px";al.textOp=h.doBlockquote;F(al,true);ak.appendChild(al);var am=document.createElement("li");am.className="wmd-button";am.id="wmd-code-button";am.title=e;am.XShift="-80px";am.textOp=h.doCode;F(am,true);ak.appendChild(am);var aa=document.createElement("li");aa.className="wmd-button";aa.id="wmd-image-button";aa.title=d;aa.XShift="-100px";aa.textOp=function(ap,aq){return h.doLinkOrImage(ap,aq,true)};F(aa,true);ak.appendChild(aa);var ag=document.createElement("li");ag.className="wmd-spacer";ag.id="wmd-spacer2";ak.appendChild(ag);var ab=document.createElement("li");ab.className="wmd-button";ab.id="wmd-olist-button";ab.title=q;ab.XShift="-120px";ab.textOp=function(ap,aq){h.doList(ap,aq,true)};F(ab,true);ak.appendChild(ab);var ao=document.createElement("li");ao.className="wmd-button";ao.id="wmd-ulist-button";ao.title=t;ao.XShift="-140px";ao.textOp=function(ap,aq){h.doList(ap,aq,false)};F(ao,true);ak.appendChild(ao);var aj=document.createElement("li");aj.className="wmd-button";aj.id="wmd-heading-button";aj.title=i;aj.XShift="-160px";aj.textOp=h.doHeading;F(aj,true);ak.appendChild(aj);var X=document.createElement("li");X.className="wmd-button";X.id="wmd-hr-button";X.title=p;X.XShift="-180px";X.textOp=h.doHorizontalRule;F(X,true);ak.appendChild(X);var af=document.createElement("li");af.className="wmd-spacer";af.id="wmd-spacer3";ak.appendChild(af);var V=document.createElement("li");V.className="wmd-button";V.id="wmd-undo-button";V.title=m;V.XShift="-200px";V.execute=function(ap){ap.undo()};F(V,true);ak.appendChild(V);var an=document.createElement("li");an.className="wmd-button";an.id="wmd-redo-button";an.title=j;if(/win/.test(l.platform.toLowerCase())){an.title=j}else{an.title="é‡åš - Ctrl+Shift+Z"}an.XShift="-220px";an.execute=function(ap){ap.redo()};F(an,true);ak.appendChild(an);S()};var H=function(){if(/\?noundo/.test(E.location.href)){y.nativeUndo=true}if(!y.nativeUndo){N=new y.undoManager(function(){O();S()})}J();var W="keydown";if(v.isOpera){W="keypress"}a.addEvent(L,W,function(Y){if(Y.ctrlKey||Y.metaKey){var Z=Y.charCode||Y.keyCode;var X=String.fromCharCode(Z).toLowerCase();if(Z===46){X=""}if(Z===190){X="."}switch(X){case"b":U(document.getElementById("wmd-bold-button"));break;case"i":U(document.getElementById("wmd-italic-button"));break;case"l":U(document.getElementById("wmd-link-button"));break;case".":U(document.getElementById("wmd-quote-button"));break;case"k":U(document.getElementById("wmd-code-button"));break;case"g":U(document.getElementById("wmd-image-button"));break;case"o":U(document.getElementById("wmd-olist-button"));break;case"u":U(document.getElementById("wmd-ulist-button"));break;case"h":U(document.getElementById("wmd-heading-button"));break;case"r":U(document.getElementById("wmd-hr-button"));break;case"y":U(document.getElementById("wmd-redo-button"));break;case"z":if(Y.shiftKey){U(document.getElementById("wmd-redo-button"))}else{U(document.getElementById("wmd-undo-button"))}break;default:return}if(Y.preventDefault){Y.preventDefault()}if(top.event){top.event.returnValue=false}}});a.addEvent(L,"keyup",function(X){if(X.shiftKey&&!X.ctrlKey&&!X.metaKey){var Y=X.charCode||X.keyCode;if(Y===13){fakeButton={};fakeButton.textOp=h.doAutoindent;U(fakeButton)}}});if(L.form){var V=L.form.onsubmit;L.form.onsubmit=function(){Q();if(V){return V.apply(this,arguments)}}}};var Q=function(){if(y.showdown){var V=new y.showdown.converter()}var W=L.value;var X=function(){L.value=W};if(!/markdown/.test(y.wmd_env.output.toLowerCase())){if(V){L.value=V.makeHtml(W);top.setTimeout(X,0)}}return true};this.undo=function(){if(N){N.undo()}};this.redo=function(){if(N){N.redo()}};var T=function(){H()};this.destroy=function(){if(N){N.destroy()}if(G.parentNode){G.parentNode.removeChild(G)}if(L){L.style.marginTop=""}top.clearInterval(M)};T()};y.TextareaState=function(){var F=this;var G=y.panels.input;this.init=function(){if(!a.isVisible(G)){return}this.setInputAreaSelectionStartEnd();this.scrollTop=G.scrollTop;if(!this.text&&G.selectionStart||G.selectionStart===0){this.text=G.value}};this.setInputAreaSelection=function(){if(!a.isVisible(G)){return}if(G.selectionStart!==undefined&&!v.isOpera){G.focus();G.selectionStart=F.start;G.selectionEnd=F.end;G.scrollTop=F.scrollTop}else{if(E.selection){if(E.activeElement&&E.activeElement!==G){return}G.focus();var H=G.createTextRange();H.moveStart("character",-G.value.length);H.moveEnd("character",-G.value.length);H.moveEnd("character",F.end);H.moveStart("character",F.start);H.select()}}};this.setInputAreaSelectionStartEnd=function(){if(G.selectionStart||G.selectionStart===0){F.start=G.selectionStart;F.end=G.selectionEnd}else{if(E.selection){F.text=a.fixEolChars(G.value);var K;if(y.ieRetardedClick&&y.ieCachedRange){K=y.ieCachedRange;y.ieRetardedClick=false}else{K=E.selection.createRange()}var L=a.fixEolChars(K.text);var J="\x07";var I=J+L+J;K.text=I;var M=a.fixEolChars(G.value);K.moveStart("character",-I.length);K.text=L;F.start=M.indexOf(J);F.end=M.lastIndexOf(J)-J.length;var H=F.text.length-a.fixEolChars(G.value).length;if(H){K.moveStart("character",-L.length);while(H--){L+="\n";F.end+=1}K.text=L}this.setInputAreaSelection()}}};this.restore=function(){if(F.text!=undefined&&F.text!=G.value){G.value=F.text}this.setInputAreaSelection();G.scrollTop=F.scrollTop};this.getChunks=function(){var H=new y.Chunks();H.before=a.fixEolChars(F.text.substring(0,F.start));H.startTag="";H.selection=a.fixEolChars(F.text.substring(F.start,F.end));H.endTag="";H.after=a.fixEolChars(F.text.substring(F.end));H.scrollTop=F.scrollTop;return H};this.setChunks=function(H){H.before=H.before+H.startTag;H.after=H.endTag+H.after;if(v.isOpera){H.before=H.before.replace(/\n/g,"\r\n");H.selection=H.selection.replace(/\n/g,"\r\n");H.after=H.after.replace(/\n/g,"\r\n")}this.start=H.before.length;this.end=H.before.length+H.selection.length;this.text=H.before+H.selection+H.after;this.scrollTop=H.scrollTop};this.init()};y.Chunks=function(){};y.Chunks.prototype.findTags=function(G,I){var F=this;var H;if(G){H=a.extendRegExp(G,"","$");this.before=this.before.replace(H,function(J){F.startTag=F.startTag+J;return""});H=a.extendRegExp(G,"^","");this.selection=this.selection.replace(H,function(J){F.startTag=F.startTag+J;return""})}if(I){H=a.extendRegExp(I,"","$");this.selection=this.selection.replace(H,function(J){F.endTag=J+F.endTag;return""});H=a.extendRegExp(I,"^","");this.after=this.after.replace(H,function(J){F.endTag=J+F.endTag;return""})}};y.Chunks.prototype.trimWhitespace=function(F){this.selection=this.selection.replace(/^(\s*)/,"");if(!F){this.before+=s.$1}this.selection=this.selection.replace(/(\s*)$/,"");if(!F){this.after=s.$1+this.after}};y.Chunks.prototype.skipLines=function(H,G,F){if(H===undefined){H=1}if(G===undefined){G=1}H++;G++;var I;var J;this.selection=this.selection.replace(/(^\n*)/,"");this.startTag=this.startTag+s.$1;this.selection=this.selection.replace(/(\n*$)/,"");this.endTag=this.endTag+s.$1;this.startTag=this.startTag.replace(/(^\n*)/,"");this.before=this.before+s.$1;this.endTag=this.endTag.replace(/(\n*$)/,"");this.after=this.after+s.$1;if(this.before){I=J="";while(H--){I+="\\n?";J+="\n"}if(F){I="\\n*"}this.before=this.before.replace(new s(I+"$",""),J)}if(this.after){I=J="";while(G--){I+="\\n?";J+="\n"}if(F){I="\\n*"}this.after=this.after.replace(new s(I,""),J)}};h.prefixes="(?:\\s{4,}|\\s*>|\\s*-\\s+|\\s*\\d+\\.|=|\\+|-|_|\\*|#|\\s*\\[[^\n]]+\\]:)";h.unwrap=function(G){var F=new s("([^\\n])\\n(?!(\\n|"+h.prefixes+"))","g");G.selection=G.selection.replace(F,"$1 $2")};h.wrap=function(G,F){h.unwrap(G);var H=new s("(.{1,"+F+"})( +|$\\n?)","gm");G.selection=G.selection.replace(H,function(I,J){if(new s("^"+h.prefixes,"").test(I)){return I}return J+"\n"});G.selection=G.selection.replace(/\s+$/,"")};h.doBold=function(F,G){return h.doBorI(F,G,2,"strong text")};h.doItalic=function(F,G){return h.doBorI(F,G,1,"emphasized text")};h.doBorI=function(L,J,K,F){L.trimWhitespace();L.selection=L.selection.replace(/\n{2,}/g,"\n");L.before.search(/(\**$)/);var I=s.$1;L.after.search(/(^\**)/);var G=s.$1;var M=Math.min(I.length,G.length);if((M>=K)&&(M!=2||K!=1)){L.before=L.before.replace(s("[*]{"+K+"}$",""),"");L.after=L.after.replace(s("^[*]{"+K+"}",""),"")}else{if(!L.selection&&G){L.after=L.after.replace(/^([*_]*)/,"");L.before=L.before.replace(/(\s?)$/,"");var H=s.$1;L.before=L.before+G+H}else{if(!L.selection&&!G){L.selection=F}var N=K<=1?"*":"**";L.before=L.before+N;L.after=N+L.after}}return};h.stripLinkDefs=function(G,F){G=G.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm,function(K,L,H,I,J){F[L]=K.replace(/\s*$/,"");if(I){F[L]=K.replace(/["(](.+?)[")]$/,"");return I+J}return""});return G};h.addLinkDef=function(M,I){var F=0;var H={};M.before=h.stripLinkDefs(M.before,H);M.selection=h.stripLinkDefs(M.selection,H);M.after=h.stripLinkDefs(M.after,H);var G="";var L=/(\[(?:\[[^\]]*\]|[^\[\]])*\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g;var K=function(O){F++;O=O.replace(/^[ ]{0,3}\[(\d+)\]:/," ["+F+"]:");G+="\n"+O};var J=function(P,Q,R,O){if(H[R]){K(H[R]);return Q+F+O}return P};M.before=M.before.replace(L,J);if(I){K(I)}else{M.selection=M.selection.replace(L,J)}var N=F;M.after=M.after.replace(L,J);if(M.after){M.after=M.after.replace(/\n*$/,"")}if(!M.after){M.selection=M.selection.replace(/\n*$/,"")}M.after+="\n\n"+G;return N};h.doLinkOrImage=function(F,G,I){F.trimWhitespace();F.findTags(/\s*!?\[/,/\][ ]?(?:\n[ ]*)?(\[.*?\])?/);if(F.endTag.length>1){F.startTag=F.startTag.replace(/!?\[/,"");F.endTag="";h.addLinkDef(F,null)}else{if(/\n\n/.test(F.selection)){h.addLinkDef(F,null);return}var H=function(L){if(L!==null){F.startTag=F.endTag="";var K=" [999]: "+L;var J=h.addLinkDef(F,K);F.startTag=I?"![":"[";F.endTag="]["+J+"]";if(!F.selection){if(I){F.selection="alt text"}else{F.selection="link text"}}}G()};if(I){a.prompt(B,b,H,1)}else{a.prompt(D,g,H)}return true}};a.makeAPI=function(){y.wmd={};y.wmd.editor=y.editor;y.wmd.previewManager=y.previewManager};a.startEditor=function(){if(y.wmd_env.autostart===false){a.makeAPI();return}var G;var F;var H=function(){y.panels=new y.PanelCollection();F=new y.previewManager();var I=F.refresh;G=new y.editor(I);F.refresh(true)};a.addEvent(top,"load",H)};y.previewManager=function(){var H=this;var V;var F;var N;var M;var S;var O;var I=3000;var P="delayed";var K=function(X,Y){a.addEvent(X,"input",Y);X.onpaste=Y;X.ondrop=Y;a.addEvent(X,"keypress",Y);a.addEvent(X,"keydown",Y);F=new y.inputPoller(Y,A)};var R=function(){var X=0;if(top.innerHeight){X=top.pageYOffset}else{if(E.documentElement&&E.documentElement.scrollTop){X=E.documentElement.scrollTop}else{if(E.body){X=E.body.scrollTop}}}return X};var L=function(){if(!y.panels.preview&&!y.panels.output){return}var Z=y.panels.input.value;if(Z&&Z==S){return}else{S=Z}var Y=new Date().getTime();if(!V&&y.showdown){V=new y.showdown.converter()}if(V){Z=V.makeHtml(Z)}var X=new Date().getTime();M=X-Y;G(Z);O=Z};var U=function(){if(N){top.clearTimeout(N);N=undefined}if(P!=="manual"){var X=0;if(P==="delayed"){X=M}if(X>I){X=I}N=top.setTimeout(L,X)}};var J=function(X){if(X.scrollHeight<=X.clientHeight){return 1}return X.scrollTop/(X.scrollHeight-X.clientHeight)};var W=function(){if(y.panels.preview){y.panels.preview.scrollTop=(y.panels.preview.scrollHeight-y.panels.preview.clientHeight)*J(y.panels.preview)}if(y.panels.output){y.panels.output.scrollTop=(y.panels.output.scrollHeight-y.panels.output.clientHeight)*J(y.panels.output)}};this.refresh=function(X){if(X){S="";L()}else{U()}};this.processingTime=function(){return M};this.output=function(){return O};this.setUpdateMode=function(X){P=X;H.refresh()};var Q=true;var G=function(aa){var X=C.getTop(y.panels.input)-R();if(y.panels.output){if(y.panels.output.value!==undefined){y.panels.output.value=aa;y.panels.output.readOnly=true}else{var Z=aa.replace(/&/g,"&");Z=Z.replace(/</g,"<");y.panels.output.innerHTML="<pre><code>"+Z+"</code></pre>"}}if(y.panels.preview){y.panels.preview.innerHTML=aa}W();if(Q){Q=false;return}var Y=C.getTop(y.panels.input)-R();if(v.isIE){top.setTimeout(function(){top.scrollBy(0,Y-X)},0)}else{top.scrollBy(0,Y-X)}};var T=function(){K(y.panels.input,U);L();if(y.panels.preview){y.panels.preview.scrollTop=0}if(y.panels.output){y.panels.output.scrollTop=0}};this.destroy=function(){if(F){F.destroy()}};T()};h.doAutoindent=function(F,G){F.before=F.before.replace(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]*\n$/,"\n\n");F.before=F.before.replace(/(\n|^)[ ]{0,3}>[ \t]*\n$/,"\n\n");F.before=F.before.replace(/(\n|^)[ \t]+\n$/,"\n\n");if(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]+.*\n$/.test(F.before)){if(h.doList){h.doList(F)}}if(/(\n|^)[ ]{0,3}>[ \t]+.*\n$/.test(F.before)){if(h.doBlockquote){h.doBlockquote(F)}}if(/(\n|^)(\t|[ ]{4,}).*\n$/.test(F.before)){if(h.doCode){h.doCode(F)}}};h.doBlockquote=function(F,G){F.selection=F.selection.replace(/^(\n*)([^\r]+?)(\n*)$/,function(L,K,J,I){F.before+=K;F.after=I+F.after;return J});F.before=F.before.replace(/(>[ \t]*)$/,function(J,I){F.selection=I+F.selection;return""});F.selection=F.selection.replace(/^(\s|>)+$/,"");F.selection=F.selection||"Blockquote";if(F.before){F.before=F.before.replace(/\n?$/,"\n")}if(F.after){F.after=F.after.replace(/^\n?/,"\n")}F.before=F.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/,function(I){F.startTag=I;return""});F.after=F.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/,function(I){F.endTag=I;return""});var H=function(J){var I=J?"> ":"";if(F.startTag){F.startTag=F.startTag.replace(/\n((>|\s)*)\n$/,function(L,K){return"\n"+K.replace(/^[ ]{0,3}>?[ \t]*$/gm,I)+"\n"})}if(F.endTag){F.endTag=F.endTag.replace(/^\n((>|\s)*)\n/,function(L,K){return"\n"+K.replace(/^[ ]{0,3}>?[ \t]*$/gm,I)+"\n"})}};if(/^(?![ ]{0,3}>)/m.test(F.selection)){h.wrap(F,y.wmd_env.lineLength-2);F.selection=F.selection.replace(/^/gm,"> ");H(true);F.skipLines()}else{F.selection=F.selection.replace(/^[ ]{0,3}> ?/gm,"");h.unwrap(F);H(false);if(!/^(\n|^)[ ]{0,3}>/.test(F.selection)&&F.startTag){F.startTag=F.startTag.replace(/\n{0,2}$/,"\n\n")}if(!/(\n|^)[ ]{0,3}>.*$/.test(F.selection)&&F.endTag){F.endTag=F.endTag.replace(/^\n{0,2}/,"\n\n")}}if(!/\n/.test(F.selection)){F.selection=F.selection.replace(/^(> *)/,function(I,J){F.startTag+=J;return""})}};h.doCode=function(F,G){var I=/\S[ ]*$/.test(F.before);var K=/^[ ]*\S/.test(F.after);if((!K&&!I)||/\n/.test(F.selection)){F.before=F.before.replace(/[ ]{4}$/,function(L){F.selection=L+F.selection;return""});var J=1;var H=1;if(/\n(\t|[ ]{4,}).*\n$/.test(F.before)){J=0}if(/^\n(\t|[ ]{4,})/.test(F.after)){H=0}F.skipLines(J,H);if(!F.selection){F.startTag=" ";F.selection="enter code here"}else{if(/^[ ]{0,3}\S/m.test(F.selection)){F.selection=F.selection.replace(/^/gm," ")}else{F.selection=F.selection.replace(/^[ ]{4}/gm,"")}}}else{F.trimWhitespace();F.findTags(/`/,/`/);if(!F.startTag&&!F.endTag){F.startTag=F.endTag="`";if(!F.selection){F.selection="enter code here"}}else{if(F.endTag&&!F.startTag){F.before+=F.endTag;F.endTag=""}else{F.startTag=F.endTag=""}}}};h.doList=function(Q,J,I){var S=/(\n|^)(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*$/;var R=/^\n*(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*/;var F="-";var N=1;var L=function(){var T;if(I){T=" "+N+". ";N++}else{T=" "+F+" "}return T};var M=function(T){if(I===undefined){I=/^\s*\d/.test(T)}T=T.replace(/^[ ]{0,3}([*+-]|\d+[.])\s/gm,function(U){return L()});return T};Q.findTags(/(\n|^)*[ ]{0,3}([*+-]|\d+[.])\s+/,null);if(Q.before&&!/\n$/.test(Q.before)&&!/^\n/.test(Q.startTag)){Q.before+=Q.startTag;Q.startTag=""}if(Q.startTag){var H=/\d+[.]/.test(Q.startTag);Q.startTag="";Q.selection=Q.selection.replace(/\n[ ]{4}/g,"\n");h.unwrap(Q);Q.skipLines();if(H){Q.after=Q.after.replace(R,M)}if(I==H){return}}var K=1;Q.before=Q.before.replace(S,function(T){if(/^\s*([*+-])/.test(T)){F=s.$1}K=/[^\n]\n\n[^\n]/.test(T)?1:0;return M(T)});if(!Q.selection){Q.selection="List item"}var O=L();var G=1;Q.after=Q.after.replace(R,function(T){G=/[^\n]\n\n[^\n]/.test(T)?1:0;return M(T)});Q.trimWhitespace(true);Q.skipLines(K,G,true);Q.startTag=O;var P=O.replace(/./g," ");h.wrap(Q,y.wmd_env.lineLength-P.length);Q.selection=Q.selection.replace(/\n/g,"\n"+P)};h.doHeading=function(H,I){H.selection=H.selection.replace(/\s+/g," ");H.selection=H.selection.replace(/(^\s+|\s+$)/g,"");if(!H.selection){H.startTag="## ";H.selection="Heading";H.endTag=" ##";return}var J=0;H.findTags(/#+[ ]*/,/[ ]*#+/);if(/#+/.test(H.startTag)){J=s.lastMatch.length}H.startTag=H.endTag="";H.findTags(null,/\s?(-+|=+)/);if(/=+/.test(H.endTag)){J=1}if(/-+/.test(H.endTag)){J=2}H.startTag=H.endTag="";H.skipLines(1,1);var K=J==0?2:J-1;if(K>0){var G=K>=2?"-":"=";var F=H.selection.length;if(F>y.wmd_env.lineLength){F=y.wmd_env.lineLength}H.endTag="\n";while(F--){H.endTag+=G}}};h.doHorizontalRule=function(F,G){F.startTag="----------\n";F.selection="";F.skipLines(2,1,true)}};Attacklab.wmd_env={};Attacklab.account_options={};Attacklab.wmd_defaults={version:1,output:"Markdown",lineLength:40,delayLoad:false};if(!Attacklab.wmd){Attacklab.wmd=function(){Attacklab.loadEnv=function(){var b=function(d){if(!d){return}for(var c in d){Attacklab.wmd_env[c]=d[c]}};b(Attacklab.wmd_defaults);b(Attacklab.account_options);b(top.wmd_options);Attacklab.full=true;var a="bold italic link blockquote code image ol ul heading hr";Attacklab.wmd_env.buttons=Attacklab.wmd_env.buttons||a};Attacklab.loadEnv()};Attacklab.wmd();Attacklab.wmdBase();Attacklab.Util.startEditor()};
\ No newline at end of file diff --git a/askbot/skins/common/media/js/wmd/wmd-test.html b/askbot/skins/common/media/js/wmd/wmd-test.html new file mode 100644 index 00000000..d748501a --- /dev/null +++ b/askbot/skins/common/media/js/wmd/wmd-test.html @@ -0,0 +1,158 @@ +<!DOCTYPE html> +<html> + + <head> + <title>Test WMD Page</title> + + <link rel="stylesheet" type="text/css" href="wmd.css" /> + + <meta http-equiv="pragma" content="no-cache"> + <meta http-equiv="cache-control" content="no-cache"> + <meta http-equiv="pragma-directive" content="no-cache"> + <meta http-equiv="cache-directive" content="no-cache"> + <meta http-equiv="expires" content="0"> + + <script type="text/javascript" src="jQuery/jquery-1.2.6.js"></script> + <script type="text/javascript" src="showdown.js"></script> + </head> + + <body> + <div id="wmd-button-bar" class="wmd-panel"></div> + <br/> + <textarea id="editor" class="wmd-panel"></textarea> + <br/> + <div id="previewer" class="wmd-panel"></div> + <br/> + <div id="wmd-output" class="wmd-panel"></div> + + <p>To test that page up/down and arrow keys work, copy this above the WMD + control.</p> + + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + + <script type="text/javascript" src="wmd.js"></script> + </body> +</html>
\ No newline at end of file diff --git a/askbot/skins/common/media/js/wmd/wmd.css b/askbot/skins/common/media/js/wmd/wmd.css new file mode 100644 index 00000000..f1091a35 --- /dev/null +++ b/askbot/skins/common/media/js/wmd/wmd.css @@ -0,0 +1,130 @@ +/*body +{ + background-color: White +} +*/ +.wmd-panel +{ +} + +#wmd-button-bar +{ + background-color: White; +} + +#wmd-input +{ + height: 500px; + background-color: Gainsboro; + border: 1px solid DarkGray; + margin-top: -20px; +} + +#wmd-preview +{ + background-color: LightSkyBlue; +} + +#wmd-output +{ + background-color: Pink; +} + +#wmd-button-row +{ + position: relative; + margin-left: 5px; + margin-right: 5px; + margin-bottom: 5px; + margin-top: 10px; + padding: 0px; + height: 20px; +} + +.wmd-spacer +{ + width: 1px; + height: 20px; + margin-left: 14px; + + position: absolute; + background-color: Silver; + display: inline-block; + list-style: none; +} + +.wmd-button +{ + width: 20px; + height: 20px; + margin-left: 5px; + margin-right: 5px; + + position: absolute; + background-image: url(images/wmd-buttons.png); + background-repeat: no-repeat; + background-position: 0px 0px; + display: inline-block; + list-style: none; +} + +.wmd-button > a +{ + width: 20px; + height: 20px; + margin-left: 5px; + margin-right: 5px; + + position: absolute; + display: inline-block; +} + + +/* sprite button slicing style information */ +#wmd-button-bar #wmd-bold-button {left: 0px; background-position: 0px 0;} +#wmd-button-bar #wmd-italic-button {left: 25px; background-position: -20px 0;} +#wmd-button-bar #wmd-spacer1 {left: 50px;} +#wmd-button-bar #wmd-link-button {left: 75px; background-position: -40px 0;} +#wmd-button-bar #wmd-quote-button {left: 100px; background-position: -60px 0;} +#wmd-button-bar #wmd-code-button {left: 125px; background-position: -80px 0;} +#wmd-button-bar #wmd-image-button {left: 150px; background-position: -100px 0;} +#wmd-button-bar #wmd-attachment-button {left: 175px; background-position: -120px 0;} +#wmd-button-bar #wmd-spacer2 {left: 200px;} +#wmd-button-bar #wmd-olist-button {left: 225px; background-position: -140px 0;} +#wmd-button-bar #wmd-ulist-button {left: 250px; background-position: -160px 0;} +#wmd-button-bar #wmd-heading-button {left: 275px; background-position: -180px 0;} +#wmd-button-bar #wmd-hr-button {left: 300px; background-position: -200px 0;} +#wmd-button-bar #wmd-spacer3 {left: 325px;} +#wmd-button-bar #wmd-undo-button {left: 350px; background-position: -220px 0;} +#wmd-button-bar #wmd-redo-button {left: 375px; background-position: -240px 0;} +#wmd-button-bar #wmd-help-button {right: 0px; background-position: -260px 0;} + + +.wmd-prompt-background +{ + background-color: Black; +} + +.wmd-prompt-dialog +{ + border: 1px solid #999999; + background-color: #F5F5F5; +} + +.wmd-prompt-dialog > div { + font-size: 1em; + font-family: arial, helvetica, sans-serif; +} + + +.wmd-prompt-dialog > form > input[type="text"] { + border: 1px solid #999999; + color: black; +} + +.wmd-prompt-dialog > form > input[type="button"]{ + border: 1px solid #888888; + font-family: trebuchet MS, helvetica, sans-serif; + font-size: 1em; + font-weight: bold; +} diff --git a/askbot/skins/common/media/js/wmd/wmd.js b/askbot/skins/common/media/js/wmd/wmd.js new file mode 100644 index 00000000..bc3b5a0c --- /dev/null +++ b/askbot/skins/common/media/js/wmd/wmd.js @@ -0,0 +1,2438 @@ +var Attacklab = Attacklab || {}; + +Attacklab.wmdBase = function(){ + + // A few handy aliases for readability. + var wmd = top.Attacklab; + var doc = top.document; + var re = top.RegExp; + var nav = top.navigator; + + // Some namespaces. + wmd.Util = {}; + wmd.Position = {}; + wmd.Command = {}; + wmd.Global = {}; + + var util = wmd.Util; + var position = wmd.Position; + var command = wmd.Command; + var global = wmd.Global; + + + // Used to work around some browser bugs where we can't use feature testing. + global.isIE = /msie/.test(nav.userAgent.toLowerCase()); + global.isIE_5or6 = /msie 6/.test(nav.userAgent.toLowerCase()) || /msie 5/.test(nav.userAgent.toLowerCase()); + global.isIE_7plus = global.isIE && !global.isIE_5or6; + global.isOpera = /opera/.test(nav.userAgent.toLowerCase()); + global.isKonqueror = /konqueror/.test(nav.userAgent.toLowerCase()); + + var toolbar_strong_label = $.i18n._('bold') + " <strong> Ctrl-B"; + var toolbar_emphasis_label = $.i18n._('italic') + " <em> Ctrl-I"; + var toolbar_hyperlink_label = $.i18n._('link') + " <a> Ctrl-L"; + var toolbar_blockquote_label = $.i18n._('quote') + " <blockquote> Ctrl-."; + var toolbar_code_label = $.i18n._('preformatted text') + " <pre><code> Ctrl-K"; + var toolbar_image_label = $.i18n._('image') + " <img> Ctrl-G"; + var toolbar_attachment_label = $.i18n._('attachment') + " Ctrl-F"; + var toolbar_numbered_label = $.i18n._('numbered list') + " <ol> Ctrl-O"; + var toolbar_bulleted_label = $.i18n._('bulleted list') + " <ul> Ctrl-U"; + var toolbar_heading_label = $.i18n._('heading') + " <h1>/<h2> Ctrl-H"; + var toolbar_horizontal_label = $.i18n._('horizontal bar') + " <hr> Ctrl-R"; + var toolbar_undo_label = $.i18n._('undo') + " Ctrl-Z"; + var toolbar_redo_label = $.i18n._('redo') + " Ctrl-Y"; + + // ------------------------------------------------------------------- + // YOUR CHANGES GO HERE + // + // I've tried to localize the things you are likely to change to + // this area. + // ------------------------------------------------------------------- + + // The text that appears on the upper part of the dialog box when + // entering links. + var imageDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter image url') + '</p>'; + var linkDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter url') + '</p>'; + var fileDialogText = "<p>" + $.i18n._('upload file attachment') + '</p>'; + // The default text that appears in the dialog input box when entering + // links. + var imageDefaultText = "http://"; + var linkDefaultText = "http://"; + + // The location of your button images relative to the base directory. + var imageDirectory = "images/"; + + // Some intervals in ms. These can be adjusted to reduce the control's load. + var previewPollInterval = 500; + var pastePollInterval = 100; + + // The link and title for the help button + var helpLink = "http://wmd-editor.com/"; + var helpHoverTitle = "WMD website"; + var helpTarget = "_blank"; + var localUploadFileName = null; + + // ------------------------------------------------------------------- + // END OF YOUR CHANGES + // ------------------------------------------------------------------- + + // A collection of the important regions on the page. + // Cached so we don't have to keep traversing the DOM. + wmd.PanelCollection = function(){ + this.buttonBar = doc.getElementById("wmd-button-bar"); + this.preview = doc.getElementById("previewer"); + this.output = doc.getElementById("wmd-output"); + this.input = doc.getElementById("editor"); + }; + + // This PanelCollection object can't be filled until after the page + // has loaded. + wmd.panels = undefined; + + // Internet explorer has problems with CSS sprite buttons that use HTML + // lists. When you click on the background image "button", IE will + // select the non-existent link text and discard the selection in the + // textarea. The solution to this is to cache the textarea selection + // on the button's mousedown event and set a flag. In the part of the + // code where we need to grab the selection, we check for the flag + // and, if it's set, use the cached area instead of querying the + // textarea. + // + // This ONLY affects Internet Explorer (tested on versions 6, 7 + // and 8) and ONLY on button clicks. Keyboard shortcuts work + // normally since the focus never leaves the textarea. + wmd.ieCachedRange = null; // cached textarea selection + wmd.ieRetardedClick = false; // flag + + // Returns true if the DOM element is visible, false if it's hidden. + // Checks if display is anything other than none. + util.isVisible = function (elem) { + + if (window.getComputedStyle) { + // Most browsers + return window.getComputedStyle(elem, null).getPropertyValue("display") !== "none"; + } + else if (elem.currentStyle) { + // IE + return elem.currentStyle.display !== "none"; + } + }; + + + // Adds a listener callback to a DOM element which is fired on a specified + // event. + util.addEvent = function(elem, event, listener){ + if (elem.attachEvent) { + // IE only. The "on" is mandatory. + elem.attachEvent("on" + event, listener); + } + else { + // Other browsers. + elem.addEventListener(event, listener, false); + } + }; + + + // Removes a listener callback from a DOM element which is fired on a specified + // event. + util.removeEvent = function(elem, event, listener){ + if (elem.detachEvent) { + // IE only. The "on" is mandatory. + elem.detachEvent("on" + event, listener); + } + else { + // Other browsers. + elem.removeEventListener(event, listener, false); + } + }; + + // Converts \r\n and \r to \n. + util.fixEolChars = function(text){ + text = text.replace(/\r\n/g, "\n"); + text = text.replace(/\r/g, "\n"); + return text; + }; + + // Extends a regular expression. Returns a new RegExp + // using pre + regex + post as the expression. + // Used in a few functions where we have a base + // expression and we want to pre- or append some + // conditions to it (e.g. adding "$" to the end). + // The flags are unchanged. + // + // regex is a RegExp, pre and post are strings. + util.extendRegExp = function(regex, pre, post){ + + if (pre === null || pre === undefined) + { + pre = ""; + } + if(post === null || post === undefined) + { + post = ""; + } + + var pattern = regex.toString(); + var flags; + + // Replace the flags with empty space and store them. + pattern = pattern.replace(/\/([gim]*)$/, ""); + flags = re.$1; + + // Remove the slash delimiters on the regular expression. + pattern = pattern.replace(/(^\/|\/$)/g, ""); + pattern = pre + pattern + post; + + return new re(pattern, flags); + }; + + + // Sets the image for a button passed to the WMD editor. + // Returns a new element with the image attached. + // Adds several style properties to the image. + util.createImage = function(img){ + + var imgPath = imageDirectory + img; + + var elem = doc.createElement("img"); + elem.className = "wmd-button"; + elem.src = imgPath; + + return elem; + }; + + +// This simulates a modal dialog box and asks for the URL when you +// click the hyperlink or image buttons. +// +// text: The html for the input box. +// defaultInputText: The default value that appears in the input box. +// makeLinkMarkdown: The function which is executed when the prompt is dismissed, either via OK or Cancel +util.prompt = function(text, defaultInputText, makeLinkMarkdown, dialogType){ + + // These variables need to be declared at this level since they are used + // in multiple functions. + var dialog;// The dialog box. + var background;// The background beind the dialog box. + var input;// The text box where you enter the hyperlink. + + if (defaultInputText === undefined) { + defaultInputText = ""; + } + + // Used as a keydown event handler. Esc dismisses the prompt. + // Key code 27 is ESC. + var checkEscape = function(key){ + var code = (key.charCode || key.keyCode); + if (code === 27) { + close(true); + } + }; + + // Dismisses the hyperlink input box. + // isCancel is true if we don't care about the input text. + // isCancel is false if we are going to keep the text. + var close = function(isCancel){ + util.removeEvent(doc.body, "keydown", checkEscape); + var text = input.value; + + if (isCancel){ + text = null; + } + else{ + // Fixes common pasting errors. + text = text.replace('http://http://', 'http://'); + text = text.replace('http://https://', 'https://'); + text = text.replace('http://ftp://', 'ftp://'); + + if (text.indexOf('http://') === -1 && text.indexOf('ftp://') === -1) { + if (dialogType == 'link'){ + //add http only to urls + text = 'http://' + text; + } + } + } + + dialog.parentNode.removeChild(dialog); + background.parentNode.removeChild(background); + makeLinkMarkdown(text); + return false; + }; + + // Creates the background behind the hyperlink text entry box. + // Most of this has been moved to CSS but the div creation and + // browser-specific hacks remain here. + var createBackground = function(){ + + background = doc.createElement("div"); + background.className = "wmd-prompt-background"; + style = background.style; + style.position = "absolute"; + style.top = "0"; + + style.zIndex = "1000"; + + // Some versions of Konqueror don't support transparent colors + // so we make the whole window transparent. + // + // Is this necessary on modern konqueror browsers? + if (global.isKonqueror){ + style.backgroundColor = "transparent"; + } + else if (global.isIE){ + style.filter = "alpha(opacity=50)"; + } + else { + style.opacity = "0.5"; + } + + var pageSize = position.getPageSize(); + style.height = pageSize[1] + "px"; + + if(global.isIE){ + style.left = doc.documentElement.scrollLeft; + style.width = doc.documentElement.clientWidth; + } + else { + style.left = "0"; + style.width = "100%"; + } + + doc.body.appendChild(background); + }; + + // Create the text input box form/window. + var createDialog = function(){ + + // The main dialog box. + dialog = doc.createElement("div"); + dialog.className = "wmd-prompt-dialog"; + dialog.style.padding = "10px;"; + dialog.style.position = "fixed"; + dialog.style.width = "400px"; + dialog.style.zIndex = "1001"; + + // The dialog text. + var question = doc.createElement("div"); + question.innerHTML = text; + question.style.padding = "5px"; + dialog.appendChild(question); + + // The web form container for the text box and buttons. + var form = doc.createElement("form"); + form.onsubmit = function(){ return close(false); }; + style = form.style; + style.padding = "0"; + style.margin = "0"; + style.cssFloat = "left"; + style.width = "100%"; + style.textAlign = "center"; + style.position = "relative"; + dialog.appendChild(form); + + // The input text box + input = doc.createElement("input"); + if(dialogType == 'image' || dialogType == 'file'){ + input.id = "image-url"; + } + input.type = "text"; + if (dialogType == 'file'){ + input.disabled = "disabled"; + }; + + input.value = defaultInputText; + style = input.style; + style.display = "block"; + style.width = "80%"; + style.marginLeft = style.marginRight = "auto"; + form.appendChild(input); + + // The upload file input + if(dialogType == 'image' || dialogType == 'file'){ + var upload_container = $('<div></div>'); + var upload_input = $('<input type="file" />'); + upload_input.attr('name', 'file-upload'); + upload_input.attr('id', 'file-upload'); + upload_input.attr('size', 26); + + var startUploadHandler = function(){ + localUploadFileName = $(this).val(); + return ajaxFileUpload($('#image-url'), startUploadHandler); + }; + + upload_input.change(startUploadHandler); + + upload_container.append(upload_input); + upload_container.append($('<br/>')); + + var spinner = $('<img />'); + spinner.attr('id', 'loading'); + spinner.attr('src', mediaUrl("media/images/indicator.gif")); + spinner.css('display', 'none'); + + upload_container.append(spinner); + upload_container.css('padding', '5px'); + $(form).append(upload_container); + } + + // The ok button + var okButton = doc.createElement("input"); + okButton.type = "button"; + okButton.onclick = function(){ + var isCancel = false; + if ($.trim($(input).val()) === ''){ + isCancel = true; + } + return close(isCancel); + }; + okButton.value = "OK"; + style = okButton.style; + style.margin = "10px"; + style.display = "inline"; + style.width = "7em"; + + // The cancel button + var cancelButton = doc.createElement("input"); + cancelButton.type = "button"; + cancelButton.onclick = function(){ return close(true); }; + cancelButton.value = "Cancel"; + style = cancelButton.style; + style.margin = "10px"; + style.display = "inline"; + style.width = "7em"; + + // The order of these buttons is different on macs. + if (/mac/.test(nav.platform.toLowerCase())) { + form.appendChild(cancelButton); + form.appendChild(okButton); + } + else { + form.appendChild(okButton); + form.appendChild(cancelButton); + } + + util.addEvent(doc.body, "keydown", checkEscape); + dialog.style.top = "50%"; + dialog.style.left = "50%"; + dialog.style.display = "block"; + if(global.isIE_5or6){ + dialog.style.position = "absolute"; + dialog.style.top = doc.documentElement.scrollTop + 200 + "px"; + dialog.style.left = "50%"; + } + doc.body.appendChild(dialog); + + // This has to be done AFTER adding the dialog to the form if you + // want it to be centered. + dialog.style.marginTop = -(position.getHeight(dialog) / 2) + "px"; + dialog.style.marginLeft = -(position.getWidth(dialog) / 2) + "px"; + + }; + + createBackground(); + + // Why is this in a zero-length timeout? + // Is it working around a browser bug? + top.setTimeout(function(){ + createDialog(); + var defTextLen = defaultInputText.length; + if (input.type == 'text' && input.selectionStart !== undefined) { + input.selectionStart = 0; + input.selectionEnd = defTextLen; + } + else if (input.createTextRange) { + var range = input.createTextRange(); + range.collapse(false); + range.moveStart("character", -defTextLen); + range.moveEnd("character", defTextLen); + range.select(); + } + + input.focus(); + }, 0); +}; + + + // UNFINISHED + // The assignment in the while loop makes jslint cranky. + // I'll change it to a better loop later. + position.getTop = function(elem, isInner){ + var result = elem.offsetTop; + if (!isInner) { + while (elem.offsetParent) { + elem = elem.offsetParent; + result += elem.offsetTop; + } + } + return result; + }; + + position.getHeight = function (elem) { + return elem.offsetHeight || elem.scrollHeight; + }; + + position.getWidth = function (elem) { + return elem.offsetWidth || elem.scrollWidth; + }; + + position.getPageSize = function(){ + + var scrollWidth, scrollHeight; + var innerWidth, innerHeight; + + // It's not very clear which blocks work with which browsers. + if(self.innerHeight && self.scrollMaxY){ + scrollWidth = doc.body.scrollWidth; + scrollHeight = self.innerHeight + self.scrollMaxY; + } + else if(doc.body.scrollHeight > doc.body.offsetHeight){ + scrollWidth = doc.body.scrollWidth; + scrollHeight = doc.body.scrollHeight; + } + else{ + scrollWidth = doc.body.offsetWidth; + scrollHeight = doc.body.offsetHeight; + } + + if(self.innerHeight){ + // Non-IE browser + innerWidth = self.innerWidth; + innerHeight = self.innerHeight; + } + else if(doc.documentElement && doc.documentElement.clientHeight){ + // Some versions of IE (IE 6 w/ a DOCTYPE declaration) + innerWidth = doc.documentElement.clientWidth; + innerHeight = doc.documentElement.clientHeight; + } + else if(doc.body){ + // Other versions of IE + innerWidth = doc.body.clientWidth; + innerHeight = doc.body.clientHeight; + } + + var maxWidth = Math.max(scrollWidth, innerWidth); + var maxHeight = Math.max(scrollHeight, innerHeight); + return [maxWidth, maxHeight, innerWidth, innerHeight]; + }; + + // Watches the input textarea, polling at an interval and runs + // a callback function if anything has changed. + wmd.inputPoller = function(callback, interval){ + + var pollerObj = this; + var inputArea = wmd.panels.input; + + // Stored start, end and text. Used to see if there are changes to the input. + var lastStart; + var lastEnd; + var markdown; + + var killHandle; // Used to cancel monitoring on destruction. + // Checks to see if anything has changed in the textarea. + // If so, it runs the callback. + this.tick = function(){ + + if (!util.isVisible(inputArea)) { + return; + } + + // Update the selection start and end, text. + if (inputArea.selectionStart || inputArea.selectionStart === 0) { + var start = inputArea.selectionStart; + var end = inputArea.selectionEnd; + if (start != lastStart || end != lastEnd) { + lastStart = start; + lastEnd = end; + + if (markdown != inputArea.value) { + markdown = inputArea.value; + return true; + } + } + } + return false; + }; + + + var doTickCallback = function(){ + + if (!util.isVisible(inputArea)) { + return; + } + + // If anything has changed, call the function. + if (pollerObj.tick()) { + callback(); + } + }; + + // Set how often we poll the textarea for changes. + var assignInterval = function(){ + // previewPollInterval is set at the top of the namespace. + killHandle = top.setInterval(doTickCallback, interval); + }; + + this.destroy = function(){ + top.clearInterval(killHandle); + }; + + assignInterval(); + }; + + // Handles pushing and popping TextareaStates for undo/redo commands. + // I should rename the stack variables to list. + wmd.undoManager = function(callback){ + + var undoObj = this; + var undoStack = []; // A stack of undo states + var stackPtr = 0; // The index of the current state + var mode = "none"; + var lastState; // The last state + var poller; + var timer; // The setTimeout handle for cancelling the timer + var inputStateObj; + + // Set the mode for later logic steps. + var setMode = function(newMode, noSave){ + + if (mode != newMode) { + mode = newMode; + if (!noSave) { + saveState(); + } + } + + if (!global.isIE || mode != "moving") { + timer = top.setTimeout(refreshState, 1); + } + else { + inputStateObj = null; + } + }; + + var refreshState = function(){ + inputStateObj = new wmd.TextareaState(); + poller.tick(); + timer = undefined; + }; + + this.setCommandMode = function(){ + mode = "command"; + saveState(); + timer = top.setTimeout(refreshState, 0); + }; + + this.canUndo = function(){ + return stackPtr > 1; + }; + + this.canRedo = function(){ + if (undoStack[stackPtr + 1]) { + return true; + } + return false; + }; + + // Removes the last state and restores it. + this.undo = function(){ + + if (undoObj.canUndo()) { + if (lastState) { + // What about setting state -1 to null or checking for undefined? + lastState.restore(); + lastState = null; + } + else { + undoStack[stackPtr] = new wmd.TextareaState(); + undoStack[--stackPtr].restore(); + + if (callback) { + callback(); + } + } + } + + mode = "none"; + wmd.panels.input.focus(); + refreshState(); + }; + + // Redo an action. + this.redo = function(){ + + if (undoObj.canRedo()) { + + undoStack[++stackPtr].restore(); + + if (callback) { + callback(); + } + } + + mode = "none"; + wmd.panels.input.focus(); + refreshState(); + }; + + // Push the input area state to the stack. + var saveState = function(){ + + var currState = inputStateObj || new wmd.TextareaState(); + + if (!currState) { + return false; + } + if (mode == "moving") { + if (!lastState) { + lastState = currState; + } + return; + } + if (lastState) { + if (undoStack[stackPtr - 1].text != lastState.text) { + undoStack[stackPtr++] = lastState; + } + lastState = null; + } + undoStack[stackPtr++] = currState; + undoStack[stackPtr + 1] = null; + if (callback) { + callback(); + } + }; + + var handleCtrlYZ = function(event){ + + var handled = false; + + if (event.ctrlKey || event.metaKey) { + + // IE and Opera do not support charCode. + var keyCode = event.charCode || event.keyCode; + var keyCodeChar = String.fromCharCode(keyCode); + + switch (keyCodeChar) { + + case "y": + undoObj.redo(); + handled = true; + break; + + case "z": + if (!event.shiftKey) { + undoObj.undo(); + } + else { + undoObj.redo(); + } + handled = true; + break; + } + } + + if (handled) { + if (event.preventDefault) { + event.preventDefault(); + } + if (top.event) { + top.event.returnValue = false; + } + return; + } + }; + + // Set the mode depending on what is going on in the input area. + var handleModeChange = function(event){ + + if (!event.ctrlKey && !event.metaKey) { + + var keyCode = event.keyCode; + + if ((keyCode >= 33 && keyCode <= 40) || (keyCode >= 63232 && keyCode <= 63235)) { + // 33 - 40: page up/dn and arrow keys + // 63232 - 63235: page up/dn and arrow keys on safari + setMode("moving"); + } + else if (keyCode == 8 || keyCode == 46 || keyCode == 127) { + // 8: backspace + // 46: delete + // 127: delete + setMode("deleting"); + } + else if (keyCode == 13) { + // 13: Enter + setMode("newlines"); + } + else if (keyCode == 27) { + // 27: escape + setMode("escape"); + } + else if ((keyCode < 16 || keyCode > 20) && keyCode != 91) { + // 16-20 are shift, etc. + // 91: left window key + // I think this might be a little messed up since there are + // a lot of nonprinting keys above 20. + setMode("typing"); + } + } + }; + + var setEventHandlers = function(){ + + util.addEvent(wmd.panels.input, "keypress", function(event){ + // keyCode 89: y + // keyCode 90: z + if ((event.ctrlKey || event.metaKey) && (event.keyCode == 89 || event.keyCode == 90)) { + event.preventDefault(); + } + }); + + var handlePaste = function(){ + if (global.isIE || (inputStateObj && inputStateObj.text != wmd.panels.input.value)) { + if (timer === undefined) { + mode = "paste"; + saveState(); + refreshState(); + } + } + }; + + // pastePollInterval is specified at the beginning of this namespace. + poller = new wmd.inputPoller(handlePaste, pastePollInterval); + + util.addEvent(wmd.panels.input, "keydown", handleCtrlYZ); + util.addEvent(wmd.panels.input, "keydown", handleModeChange); + + util.addEvent(wmd.panels.input, "mousedown", function(){ + setMode("moving"); + }); + wmd.panels.input.onpaste = handlePaste; + wmd.panels.input.ondrop = handlePaste; + }; + + var init = function(){ + setEventHandlers(); + refreshState(); + saveState(); + }; + + this.destroy = function(){ + if (poller) { + poller.destroy(); + } + }; + + init(); + }; + + // I think my understanding of how the buttons and callbacks are stored in the array is incomplete. + wmd.editor = function(previewRefreshCallback){ + + if (!previewRefreshCallback) { + previewRefreshCallback = function(){}; + } + + var inputBox = wmd.panels.input; + + var offsetHeight = 0; + + var editObj = this; + + var mainDiv; + var mainSpan; + + var div; // This name is pretty ambiguous. I should rename this. + + // Used to cancel recurring events from setInterval. + var creationHandle; + + var undoMgr; // The undo manager + + // Perform the button's action. + var doClick = function(button){ + + inputBox.focus(); + + if (button.textOp) { + + if (undoMgr) { + undoMgr.setCommandMode(); + } + + var state = new wmd.TextareaState(); + + if (!state) { + return; + } + + var chunks = state.getChunks(); + + // Some commands launch a "modal" prompt dialog. Javascript + // can't really make a modal dialog box and the WMD code + // will continue to execute while the dialog is displayed. + // This prevents the dialog pattern I'm used to and means + // I can't do something like this: + // + // var link = CreateLinkDialog(); + // makeMarkdownLink(link); + // + // Instead of this straightforward method of handling a + // dialog I have to pass any code which would execute + // after the dialog is dismissed (e.g. link creation) + // in a function parameter. + // + // Yes this is awkward and I think it sucks, but there's + // no real workaround. Only the image and link code + // create dialogs and require the function pointers. + var fixupInputArea = function(){ + + inputBox.focus(); + + if (chunks) { + state.setChunks(chunks); + } + + state.restore(); + previewRefreshCallback(); + }; + + var noCleanup = button.textOp(chunks, fixupInputArea); + + if(!noCleanup) { + fixupInputArea(); + } + + } + + if (button.execute) { + button.execute(editObj); + } + }; + + var setUndoRedoButtonStates = function(){ + if(undoMgr){ + setupButton(document.getElementById("wmd-undo-button"), undoMgr.canUndo()); + setupButton(document.getElementById("wmd-redo-button"), undoMgr.canRedo()); + } + }; + + var setupButton = function(button, isEnabled) { + + var normalYShift = "0px"; + var disabledYShift = "-20px"; + var highlightYShift = "-40px"; + + if(isEnabled) { + button.style.backgroundPosition = button.XShift + " " + normalYShift; + button.onmouseover = function(){ + this.style.backgroundPosition = this.XShift + " " + highlightYShift; + }; + + button.onmouseout = function(){ + this.style.backgroundPosition = this.XShift + " " + normalYShift; + }; + + // IE tries to select the background image "button" text (it's + // implemented in a list item) so we have to cache the selection + // on mousedown. + if(global.isIE) { + button.onmousedown = function() { + wmd.ieRetardedClick = true; + wmd.ieCachedRange = document.selection.createRange(); + }; + } + + if (!button.isHelp) + { + button.onclick = function() { + if (this.onmouseout) { + this.onmouseout(); + } + doClick(this); + return false; + }; + } + } + else { + button.style.backgroundPosition = button.XShift + " " + disabledYShift; + button.onmouseover = button.onmouseout = button.onclick = function(){}; + } + }; + + var makeSpritedButtonRow = function(){ + var buttonBar = document.getElementById("wmd-button-bar"); + var normalYShift = "0px"; + var disabledYShift = "-20px"; + var highlightYShift = "-40px"; + + var buttonRow = document.createElement("ul"); + buttonRow.id = "wmd-button-row"; + buttonRow = buttonBar.appendChild(buttonRow); + + + var boldButton = document.createElement("li"); + boldButton.className = "wmd-button"; + boldButton.id = "wmd-bold-button"; + boldButton.title = toolbar_strong_label; + boldButton.XShift = "0px"; + boldButton.textOp = command.doBold; + setupButton(boldButton, true); + buttonRow.appendChild(boldButton); + + var italicButton = document.createElement("li"); + italicButton.className = "wmd-button"; + italicButton.id = "wmd-italic-button"; + italicButton.title = toolbar_emphasis_label; + italicButton.XShift = "-20px"; + italicButton.textOp = command.doItalic; + setupButton(italicButton, true); + buttonRow.appendChild(italicButton); + + var spacer1 = document.createElement("li"); + spacer1.className = "wmd-spacer"; + spacer1.id = "wmd-spacer1"; + buttonRow.appendChild(spacer1); + + var linkButton = document.createElement("li"); + linkButton.className = "wmd-button"; + linkButton.id = "wmd-link-button"; + linkButton.title = toolbar_hyperlink_label; + linkButton.XShift = "-40px"; + linkButton.textOp = function(chunk, postProcessing){ + return command.doLinkOrImage(chunk, postProcessing, 'link'); + }; + setupButton(linkButton, true); + buttonRow.appendChild(linkButton); + + var quoteButton = document.createElement("li"); + quoteButton.className = "wmd-button"; + quoteButton.id = "wmd-quote-button"; + quoteButton.title = toolbar_blockquote_label; + quoteButton.XShift = "-60px"; + quoteButton.textOp = command.doBlockquote; + setupButton(quoteButton, true); + buttonRow.appendChild(quoteButton); + + var codeButton = document.createElement("li"); + codeButton.className = "wmd-button"; + codeButton.id = "wmd-code-button"; + codeButton.title = toolbar_code_label; + codeButton.XShift = "-80px"; + codeButton.textOp = command.doCode; + setupButton(codeButton, true); + buttonRow.appendChild(codeButton); + + var imageButton = document.createElement("li"); + imageButton.className = "wmd-button"; + imageButton.id = "wmd-image-button"; + imageButton.title = toolbar_image_label; + imageButton.XShift = "-100px"; + imageButton.textOp = function(chunk, postProcessing){ + return command.doLinkOrImage(chunk, postProcessing, 'image'); + }; + setupButton(imageButton, true); + buttonRow.appendChild(imageButton); + + var attachmentButton = document.createElement("li"); + attachmentButton.className = "wmd-button"; + attachmentButton.id = "wmd-attachment-button"; + attachmentButton.title = toolbar_attachment_label; + attachmentButton.XShift = "-120px"; + attachmentButton.textOp = function(chunk, postProcessing){ + return command.doLinkOrImage(chunk, postProcessing, 'file'); + }; + setupButton(attachmentButton, true); + buttonRow.appendChild(attachmentButton); + + var spacer2 = document.createElement("li"); + spacer2.className = "wmd-spacer"; + spacer2.id = "wmd-spacer2"; + buttonRow.appendChild(spacer2); + + var olistButton = document.createElement("li"); + olistButton.className = "wmd-button"; + olistButton.id = "wmd-olist-button"; + olistButton.title = toolbar_numbered_label; + olistButton.XShift = "-140px"; + olistButton.textOp = function(chunk, postProcessing){ + command.doList(chunk, postProcessing, true); + }; + setupButton(olistButton, true); + buttonRow.appendChild(olistButton); + + var ulistButton = document.createElement("li"); + ulistButton.className = "wmd-button"; + ulistButton.id = "wmd-ulist-button"; + ulistButton.title = toolbar_bulleted_label; + ulistButton.XShift = "-160px"; + ulistButton.textOp = function(chunk, postProcessing){ + command.doList(chunk, postProcessing, false); + }; + setupButton(ulistButton, true); + buttonRow.appendChild(ulistButton); + + var headingButton = document.createElement("li"); + headingButton.className = "wmd-button"; + headingButton.id = "wmd-heading-button"; + headingButton.title = toolbar_heading_label; + headingButton.XShift = "-180px"; + headingButton.textOp = command.doHeading; + setupButton(headingButton, true); + buttonRow.appendChild(headingButton); + + var hrButton = document.createElement("li"); + hrButton.className = "wmd-button"; + hrButton.id = "wmd-hr-button"; + hrButton.title = toolbar_horizontal_label; + hrButton.XShift = "-200px"; + hrButton.textOp = command.doHorizontalRule; + setupButton(hrButton, true); + buttonRow.appendChild(hrButton); + + var spacer3 = document.createElement("li"); + spacer3.className = "wmd-spacer"; + spacer3.id = "wmd-spacer3"; + buttonRow.appendChild(spacer3); + + var undoButton = document.createElement("li"); + undoButton.className = "wmd-button"; + undoButton.id = "wmd-undo-button"; + undoButton.title = toolbar_undo_label; + undoButton.XShift = "-220px"; + undoButton.execute = function(manager){ + manager.undo(); + }; + setupButton(undoButton, true); + buttonRow.appendChild(undoButton); + + var redoButton = document.createElement("li"); + redoButton.className = "wmd-button"; + redoButton.id = "wmd-redo-button"; + redoButton.title = toolbar_redo_label; + if (/win/.test(nav.platform.toLowerCase())) { + redoButton.title = toolbar_redo_label; + } + else { + // mac and other non-Windows platforms + redoButton.title = $.i18n._('redo') + " - Ctrl+Shift+Z"; + } + redoButton.XShift = "-240px"; + redoButton.execute = function(manager){ + manager.redo(); + }; + setupButton(redoButton, true); + buttonRow.appendChild(redoButton); + /* + var helpButton = document.createElement("li"); + helpButton.className = "wmd-button"; + helpButton.id = "wmd-help-button"; + helpButton.XShift = "-240px"; + helpButton.isHelp = true; + + var helpAnchor = document.createElement("a"); + helpAnchor.href = helpLink; + helpAnchor.target = helpTarget + helpAnchor.title = helpHoverTitle; + helpButton.appendChild(helpAnchor); + + setupButton(helpButton, true); + buttonRow.appendChild(helpButton); + */ + setUndoRedoButtonStates(); + }; + + var setupEditor = function(){ + + if (/\?noundo/.test(doc.location.href)) { + wmd.nativeUndo = true; + } + + if (!wmd.nativeUndo) { + undoMgr = new wmd.undoManager(function(){ + previewRefreshCallback(); + setUndoRedoButtonStates(); + }); + } + + makeSpritedButtonRow(); + + + var keyEvent = "keydown"; + if (global.isOpera) { + keyEvent = "keypress"; + } + + util.addEvent(inputBox, keyEvent, function(key){ + + // Check to see if we have a button key and, if so execute the callback. + if (key.ctrlKey || key.metaKey) { + + var keyCode = key.charCode || key.keyCode; + var keyCodeStr = String.fromCharCode(keyCode).toLowerCase(); + + // Bugfix for messed up DEL and . + if (keyCode === 46) { + keyCodeStr = ""; + } + if (keyCode === 190) { + keyCodeStr = "."; + } + + switch(keyCodeStr) { + case "b": + doClick(document.getElementById("wmd-bold-button")); + break; + case "i": + doClick(document.getElementById("wmd-italic-button")); + break; + case "l": + doClick(document.getElementById("wmd-link-button")); + break; + case ".": + doClick(document.getElementById("wmd-quote-button")); + break; + case "k": + doClick(document.getElementById("wmd-code-button")); + break; + case "g": + doClick(document.getElementById("wmd-image-button")); + break; + case "o": + doClick(document.getElementById("wmd-olist-button")); + break; + case "u": + doClick(document.getElementById("wmd-ulist-button")); + break; + case "h": + doClick(document.getElementById("wmd-heading-button")); + break; + case "r": + doClick(document.getElementById("wmd-hr-button")); + break; + case "y": + doClick(document.getElementById("wmd-redo-button")); + break; + case "z": + if(key.shiftKey) { + doClick(document.getElementById("wmd-redo-button")); + } + else { + doClick(document.getElementById("wmd-undo-button")); + } + break; + default: + return; + } + + + if (key.preventDefault) { + key.preventDefault(); + } + + if (top.event) { + top.event.returnValue = false; + } + } + }); + + // Auto-indent on shift-enter + util.addEvent(inputBox, "keyup", function(key){ + if (key.shiftKey && !key.ctrlKey && !key.metaKey) { + var keyCode = key.charCode || key.keyCode; + // Character 13 is Enter + if (keyCode === 13) { + fakeButton = {}; + fakeButton.textOp = command.doAutoindent; + doClick(fakeButton); + } + } + }); + + if (inputBox.form) { + var submitCallback = inputBox.form.onsubmit; + inputBox.form.onsubmit = function(){ + convertToHtml(); + if (submitCallback) { + return submitCallback.apply(this, arguments); + } + }; + } + }; + + // Convert the contents of the input textarea to HTML in the output/preview panels. + var convertToHtml = function(){ + + if (wmd.showdown) { + var markdownConverter = new wmd.showdown.converter(); + } + var text = inputBox.value; + + var callback = function(){ + inputBox.value = text; + //value is assigned here + }; + + if (!/markdown/.test(wmd.wmd_env.output.toLowerCase())) { + if (markdownConverter) { + inputBox.value = markdownConverter.makeHtml(text); + //value is assigned here + top.setTimeout(callback, 0); + } + } + return true; + }; + + + this.undo = function(){ + if (undoMgr) { + undoMgr.undo(); + } + }; + + this.redo = function(){ + if (undoMgr) { + undoMgr.redo(); + } + }; + + // This is pretty useless. The setupEditor function contents + // should just be copied here. + var init = function(){ + setupEditor(); + }; + + this.destroy = function(){ + if (undoMgr) { + undoMgr.destroy(); + } + if (div.parentNode) { + div.parentNode.removeChild(div); + } + if (inputBox) { + inputBox.style.marginTop = ""; + } + top.clearInterval(creationHandle); + }; + + init(); + }; + + // The input textarea state/contents. + // This is used to implement undo/redo by the undo manager. + wmd.TextareaState = function(){ + + // Aliases + var stateObj = this; + var inputArea = wmd.panels.input; + + this.init = function() { + + if (!util.isVisible(inputArea)) { + return; + } + + this.setInputAreaSelectionStartEnd(); + this.scrollTop = inputArea.scrollTop; + if (!this.text && inputArea.selectionStart || inputArea.selectionStart === 0) { + this.text = inputArea.value; + } + + }; + + // Sets the selected text in the input box after we've performed an + // operation. + this.setInputAreaSelection = function(){ + + if (!util.isVisible(inputArea)) { + return; + } + + if (inputArea.selectionStart !== undefined && !global.isOpera) { + + inputArea.focus(); + inputArea.selectionStart = stateObj.start; + inputArea.selectionEnd = stateObj.end; + inputArea.scrollTop = stateObj.scrollTop; + } + else if (doc.selection) { + + if (doc.activeElement && doc.activeElement !== inputArea) { + return; + } + + inputArea.focus(); + var range = inputArea.createTextRange(); + range.moveStart("character", -inputArea.value.length); + range.moveEnd("character", -inputArea.value.length); + range.moveEnd("character", stateObj.end); + range.moveStart("character", stateObj.start); + range.select(); + } + }; + + this.setInputAreaSelectionStartEnd = function(){ + + if (inputArea.selectionStart || inputArea.selectionStart === 0) { + + stateObj.start = inputArea.selectionStart; + stateObj.end = inputArea.selectionEnd; + } + else if (doc.selection) { + + stateObj.text = util.fixEolChars(inputArea.value); + + // IE loses the selection in the textarea when buttons are + // clicked. On IE we cache the selection and set a flag + // which we check for here. + var range; + if(wmd.ieRetardedClick && wmd.ieCachedRange) { + range = wmd.ieCachedRange; + wmd.ieRetardedClick = false; + } + else { + range = doc.selection.createRange(); + } + + var fixedRange = util.fixEolChars(range.text); + var marker = "\x07"; + var markedRange = marker + fixedRange + marker; + range.text = markedRange; + var inputText = util.fixEolChars(inputArea.value); + + range.moveStart("character", -markedRange.length); + range.text = fixedRange; + + stateObj.start = inputText.indexOf(marker); + stateObj.end = inputText.lastIndexOf(marker) - marker.length; + + var len = stateObj.text.length - util.fixEolChars(inputArea.value).length; + + if (len) { + range.moveStart("character", -fixedRange.length); + while (len--) { + fixedRange += "\n"; + stateObj.end += 1; + } + range.text = fixedRange; + } + + this.setInputAreaSelection(); + } + }; + + // Restore this state into the input area. + this.restore = function(){ + + if (stateObj.text !== undefined && stateObj.text != inputArea.value) { + inputArea.value = stateObj.text; + //value is assigned here + } + this.setInputAreaSelection(); + inputArea.scrollTop = stateObj.scrollTop; + }; + + // Gets a collection of HTML chunks from the inptut textarea. + this.getChunks = function(){ + + var chunk = new wmd.Chunks(); + + chunk.before = util.fixEolChars(stateObj.text.substring(0, stateObj.start)); + chunk.startTag = ""; + chunk.selection = util.fixEolChars(stateObj.text.substring(stateObj.start, stateObj.end)); + chunk.endTag = ""; + chunk.after = util.fixEolChars(stateObj.text.substring(stateObj.end)); + chunk.scrollTop = stateObj.scrollTop; + + return chunk; + }; + + // Sets the TextareaState properties given a chunk of markdown. + this.setChunks = function(chunk){ + + chunk.before = chunk.before + chunk.startTag; + chunk.after = chunk.endTag + chunk.after; + + if (global.isOpera) { + chunk.before = chunk.before.replace(/\n/g, "\r\n"); + chunk.selection = chunk.selection.replace(/\n/g, "\r\n"); + chunk.after = chunk.after.replace(/\n/g, "\r\n"); + } + + this.start = chunk.before.length; + this.end = chunk.before.length + chunk.selection.length; + this.text = chunk.before + chunk.selection + chunk.after; + this.scrollTop = chunk.scrollTop; + }; + + this.init(); + }; + + // before: contains all the text in the input box BEFORE the selection. + // after: contains all the text in the input box AFTER the selection. + wmd.Chunks = function(){ + }; + + // startRegex: a regular expression to find the start tag + // endRegex: a regular expresssion to find the end tag + wmd.Chunks.prototype.findTags = function(startRegex, endRegex){ + + var chunkObj = this; + var regex; + + if (startRegex) { + + regex = util.extendRegExp(startRegex, "", "$"); + + this.before = this.before.replace(regex, + function(match){ + chunkObj.startTag = chunkObj.startTag + match; + return ""; + }); + + regex = util.extendRegExp(startRegex, "^", ""); + + this.selection = this.selection.replace(regex, + function(match){ + chunkObj.startTag = chunkObj.startTag + match; + return ""; + }); + } + + if (endRegex) { + + regex = util.extendRegExp(endRegex, "", "$"); + + this.selection = this.selection.replace(regex, + function(match){ + chunkObj.endTag = match + chunkObj.endTag; + return ""; + }); + + regex = util.extendRegExp(endRegex, "^", ""); + + this.after = this.after.replace(regex, + function(match){ + chunkObj.endTag = match + chunkObj.endTag; + return ""; + }); + } + }; + + // If remove is false, the whitespace is transferred + // to the before/after regions. + // + // If remove is true, the whitespace disappears. + wmd.Chunks.prototype.trimWhitespace = function(remove){ + + this.selection = this.selection.replace(/^(\s*)/, ""); + + if (!remove) { + this.before += re.$1; + } + + this.selection = this.selection.replace(/(\s*)$/, ""); + + if (!remove) { + this.after = re.$1 + this.after; + } + }; + + + wmd.Chunks.prototype.skipLines = function(nLinesBefore, nLinesAfter, findExtraNewlines){ + + if (nLinesBefore === undefined) { + nLinesBefore = 1; + } + + if (nLinesAfter === undefined) { + nLinesAfter = 1; + } + + nLinesBefore++; + nLinesAfter++; + + var regexText; + var replacementText; + + this.selection = this.selection.replace(/(^\n*)/, ""); + this.startTag = this.startTag + re.$1; + this.selection = this.selection.replace(/(\n*$)/, ""); + this.endTag = this.endTag + re.$1; + this.startTag = this.startTag.replace(/(^\n*)/, ""); + this.before = this.before + re.$1; + this.endTag = this.endTag.replace(/(\n*$)/, ""); + this.after = this.after + re.$1; + + if (this.before) { + + regexText = replacementText = ""; + + while (nLinesBefore--) { + regexText += "\\n?"; + replacementText += "\n"; + } + + if (findExtraNewlines) { + regexText = "\\n*"; + } + this.before = this.before.replace(new re(regexText + "$", ""), replacementText); + } + + if (this.after) { + + regexText = replacementText = ""; + + while (nLinesAfter--) { + regexText += "\\n?"; + replacementText += "\n"; + } + if (findExtraNewlines) { + regexText = "\\n*"; + } + + this.after = this.after.replace(new re(regexText, ""), replacementText); + } + }; + + // The markdown symbols - 4 spaces = code, > = blockquote, etc. + command.prefixes = "(?:\\s{4,}|\\s*>|\\s*-\\s+|\\s*\\d+\\.|=|\\+|-|_|\\*|#|\\s*\\[[^\n]]+\\]:)"; + + // Remove markdown symbols from the chunk selection. + command.unwrap = function(chunk){ + var txt = new re("([^\\n])\\n(?!(\\n|" + command.prefixes + "))", "g"); + chunk.selection = chunk.selection.replace(txt, "$1 $2"); + }; + + command.wrap = function(chunk, len){ + command.unwrap(chunk); + var regex = new re("(.{1," + len + "})( +|$\\n?)", "gm"); + + chunk.selection = chunk.selection.replace(regex, function(line, marked){ + if (new re("^" + command.prefixes, "").test(line)) { + return line; + } + return marked + "\n"; + }); + + chunk.selection = chunk.selection.replace(/\s+$/, ""); + }; + + command.doBold = function(chunk, postProcessing){ + return command.doBorI(chunk, postProcessing, 2, "strong text"); + }; + + command.doItalic = function(chunk, postProcessing){ + return command.doBorI(chunk, postProcessing, 1, "emphasized text"); + }; + + // chunk: The selected region that will be enclosed with */** + // nStars: 1 for italics, 2 for bold + // insertText: If you just click the button without highlighting text, this gets inserted + command.doBorI = function(chunk, postProcessing, nStars, insertText){ + + // Get rid of whitespace and fixup newlines. + chunk.trimWhitespace(); + chunk.selection = chunk.selection.replace(/\n{2,}/g, "\n"); + + // Look for stars before and after. Is the chunk already marked up? + chunk.before.search(/(\**$)/); + var starsBefore = re.$1; + + chunk.after.search(/(^\**)/); + var starsAfter = re.$1; + + var prevStars = Math.min(starsBefore.length, starsAfter.length); + + // Remove stars if we have to since the button acts as a toggle. + if ((prevStars >= nStars) && (prevStars != 2 || nStars != 1)) { + chunk.before = chunk.before.replace(re("[*]{" + nStars + "}$", ""), ""); + chunk.after = chunk.after.replace(re("^[*]{" + nStars + "}", ""), ""); + } + else if (!chunk.selection && starsAfter) { + // It's not really clear why this code is necessary. It just moves + // some arbitrary stuff around. + chunk.after = chunk.after.replace(/^([*_]*)/, ""); + chunk.before = chunk.before.replace(/(\s?)$/, ""); + var whitespace = re.$1; + chunk.before = chunk.before + starsAfter + whitespace; + } + else { + + // In most cases, if you don't have any selected text and click the button + // you'll get a selected, marked up region with the default text inserted. + if (!chunk.selection && !starsAfter) { + chunk.selection = insertText; + } + + // Add the true markup. + var markup = nStars <= 1 ? "*" : "**"; // shouldn't the test be = ? + chunk.before = chunk.before + markup; + chunk.after = markup + chunk.after; + } + + return; + }; + + command.stripLinkDefs = function(text, defsToAdd){ + + text = text.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm, + function(totalMatch, id, link, newlines, title){ + defsToAdd[id] = totalMatch.replace(/\s*$/, ""); + if (newlines) { + // Strip the title and return that separately. + defsToAdd[id] = totalMatch.replace(/["(](.+?)[")]$/, ""); + return newlines + title; + } + return ""; + }); + + return text; + }; + + command.addLinkDef = function(chunk, linkDef){ + + var refNumber = 0; // The current reference number + var defsToAdd = {}; // + // Start with a clean slate by removing all previous link definitions. + chunk.before = command.stripLinkDefs(chunk.before, defsToAdd); + chunk.selection = command.stripLinkDefs(chunk.selection, defsToAdd); + chunk.after = command.stripLinkDefs(chunk.after, defsToAdd); + + var defs = ""; + var regex = /(\[(?:\[[^\]]*\]|[^\[\]])*\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g; + + var addDefNumber = function(def){ + refNumber++; + def = def.replace(/^[ ]{0,3}\[(\d+)\]:/, " [" + refNumber + "]:"); + defs += "\n" + def; + }; + + var getLink = function(wholeMatch, link, id, end){ + + if (defsToAdd[id]) { + addDefNumber(defsToAdd[id]); + return link + refNumber + end; + + } + return wholeMatch; + }; + + chunk.before = chunk.before.replace(regex, getLink); + + if (linkDef) { + addDefNumber(linkDef); + } + else { + chunk.selection = chunk.selection.replace(regex, getLink); + } + + var refOut = refNumber; + + chunk.after = chunk.after.replace(regex, getLink); + + if (chunk.after) { + chunk.after = chunk.after.replace(/\n*$/, ""); + } + if (!chunk.after) { + chunk.selection = chunk.selection.replace(/\n*$/, ""); + } + + chunk.after += "\n\n" + defs; + + return refOut; + }; + + command.doLinkOrImage = function(chunk, postProcessing, itemType){ + + chunk.trimWhitespace(); + chunk.findTags(/\s*!?\[/, /\][ ]?(?:\n[ ]*)?(\[.*?\])?/); + + if (chunk.endTag.length > 1) { + + chunk.startTag = chunk.startTag.replace(/!?\[/, ""); + chunk.endTag = ""; + command.addLinkDef(chunk, null); + + } + else { + + if (/\n\n/.test(chunk.selection)) { + command.addLinkDef(chunk, null); + return; + } + + // The function to be executed when you enter a link and press OK or Cancel. + // Marks up the link and adds the ref. + var makeLinkMarkdown = function(link){ + + if (link !== null) { + + chunk.startTag = chunk.endTag = ""; + //var linkDef = " [999]: " + link; + + //var num = command.addLinkDef(chunk, linkDef); + chunk.startTag = (itemType == 'image') ? "![" : "["; + chunk.endTag = "](" + link + ")"; + + if (!chunk.selection) { + if (itemType == 'image') { + chunk.selection = $.i18n._("image description"); + } + else if (itemType == 'file'){ + chunk.selection = localUploadFileName || $.i18n._("file name"); + localUploadFileName = null; + } + else { + chunk.selection = $.i18n._("link text"); + } + } + } + else { + if (itemType == 'image' || itemType == 'file'){ + return; + } + } + postProcessing(); + }; + + if (itemType == 'image') { + // add forth param to identify image window + util.prompt(imageDialogText, imageDefaultText, makeLinkMarkdown, 'image'); + } + else if (itemType == 'file'){ + util.prompt(fileDialogText, '', makeLinkMarkdown, 'file'); + } + else { + util.prompt(linkDialogText, linkDefaultText, makeLinkMarkdown, 'link'); + } + return true; + } +}; + + util.makeAPI = function(){ + wmd.wmd = {}; + wmd.wmd.editor = wmd.editor; + wmd.wmd.previewManager = wmd.previewManager; + }; + + util.startEditor = function(){ + + if (wmd.wmd_env.autostart === false) { + util.makeAPI(); + return; + } + + var edit; // The editor (buttons + input + outputs) - the main object. + var previewMgr; // The preview manager. + + // Fired after the page has fully loaded. + var loadListener = function(){ + + wmd.panels = new wmd.PanelCollection(); + + previewMgr = new wmd.previewManager(); + var previewRefreshCallback = previewMgr.refresh; + + edit = new wmd.editor(previewRefreshCallback); + + previewMgr.refresh(true); + + }; + + util.addEvent(top, "load", loadListener); + }; + + wmd.previewManager = function(){ + + var managerObj = this; + var converter; + var poller; + var timeout; + var elapsedTime; + var oldInputText; + var htmlOut; + var maxDelay = 3000; + var startType = "delayed"; // The other legal value is "manual" + + // Adds event listeners to elements and creates the input poller. + var setupEvents = function(inputElem, listener){ + + util.addEvent(inputElem, "input", listener); + inputElem.onpaste = listener; + inputElem.ondrop = listener; + + util.addEvent(inputElem, "keypress", listener); + util.addEvent(inputElem, "keydown", listener); + // previewPollInterval is set at the top of this file. + poller = new wmd.inputPoller(listener, previewPollInterval); + }; + + var getDocScrollTop = function(){ + + var result = 0; + + if (top.innerHeight) { + result = top.pageYOffset; + } + else + if (doc.documentElement && doc.documentElement.scrollTop) { + result = doc.documentElement.scrollTop; + } + else + if (doc.body) { + result = doc.body.scrollTop; + } + + return result; + }; + + var makePreviewHtml = function(){ + + // If there are no registered preview and output panels + // there is nothing to do. + if (!wmd.panels.preview && !wmd.panels.output) { + return; + } + + var text = wmd.panels.input.value; + if (text && text == oldInputText) { + return; // Input text hasn't changed. + } + else { + oldInputText = text; + } + + var prevTime = new Date().getTime(); + + if (!converter && wmd.showdown) { + converter = new wmd.showdown.converter(); + } + + if (converter) { + text = converter.makeHtml(text); + } + + // Calculate the processing time of the HTML creation. + // It's used as the delay time in the event listener. + var currTime = new Date().getTime(); + elapsedTime = currTime - prevTime; + + pushPreviewHtml(text); + htmlOut = text; + }; + + // setTimeout is already used. Used as an event listener. + var applyTimeout = function(){ + + if (timeout) { + top.clearTimeout(timeout); + timeout = undefined; + } + + if (startType !== "manual") { + + var delay = 0; + + if (startType === "delayed") { + delay = elapsedTime; + } + + if (delay > maxDelay) { + delay = maxDelay; + } + timeout = top.setTimeout(makePreviewHtml, delay); + } + }; + + var getScaleFactor = function(panel){ + if (panel.scrollHeight <= panel.clientHeight) { + return 1; + } + return panel.scrollTop / (panel.scrollHeight - panel.clientHeight); + }; + + var setPanelScrollTops = function(){ + + if (wmd.panels.preview) { + wmd.panels.preview.scrollTop = (wmd.panels.preview.scrollHeight - wmd.panels.preview.clientHeight) * getScaleFactor(wmd.panels.preview); + } + + if (wmd.panels.output) { + wmd.panels.output.scrollTop = (wmd.panels.output.scrollHeight - wmd.panels.output.clientHeight) * getScaleFactor(wmd.panels.output); + } + }; + + this.refresh = function(requiresRefresh){ + + if (requiresRefresh) { + oldInputText = ""; + makePreviewHtml(); + } + else { + applyTimeout(); + } + }; + + this.processingTime = function(){ + return elapsedTime; + }; + + // The output HTML + this.output = function(){ + return htmlOut; + }; + + // The mode can be "manual" or "delayed" + this.setUpdateMode = function(mode){ + startType = mode; + managerObj.refresh(); + }; + + var isFirstTimeFilled = true; + + var pushPreviewHtml = function(text){ + + var emptyTop = position.getTop(wmd.panels.input) - getDocScrollTop(); + + // Send the encoded HTML to the output textarea/div. + if (wmd.panels.output) { + // The value property is only defined if the output is a textarea. + if (wmd.panels.output.value !== undefined) { + wmd.panels.output.value = text; + //value is assigned here + wmd.panels.output.readOnly = true; + } + // Otherwise we are just replacing the text in a div. + // Send the HTML wrapped in <pre><code> + else { + var newText = text.replace(/&/g, "&"); + newText = newText.replace(/</g, "<"); + wmd.panels.output.innerHTML = "<pre><code>" + newText + "</code></pre>"; + } + } + + if (wmd.panels.preview) { + wmd.panels.preview.innerHTML = text; + } + + setPanelScrollTops(); + + if (isFirstTimeFilled) { + isFirstTimeFilled = false; + return; + } + + var fullTop = position.getTop(wmd.panels.input) - getDocScrollTop(); + + if (global.isIE) { + top.setTimeout(function(){ + top.scrollBy(0, fullTop - emptyTop); + }, 0); + } + else { + top.scrollBy(0, fullTop - emptyTop); + } + }; + + var init = function(){ + + setupEvents(wmd.panels.input, applyTimeout); + makePreviewHtml(); + + if (wmd.panels.preview) { + wmd.panels.preview.scrollTop = 0; + } + if (wmd.panels.output) { + wmd.panels.output.scrollTop = 0; + } + }; + + this.destroy = function(){ + if (poller) { + poller.destroy(); + } + }; + + init(); + }; + + // When making a list, hitting shift-enter will put your cursor on the next line + // at the current indent level. + command.doAutoindent = function(chunk, postProcessing){ + + chunk.before = chunk.before.replace(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]*\n$/, "\n\n"); + chunk.before = chunk.before.replace(/(\n|^)[ ]{0,3}>[ \t]*\n$/, "\n\n"); + chunk.before = chunk.before.replace(/(\n|^)[ \t]+\n$/, "\n\n"); + + if(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]+.*\n$/.test(chunk.before)){ + if(command.doList){ + command.doList(chunk); + } + } + if(/(\n|^)[ ]{0,3}>[ \t]+.*\n$/.test(chunk.before)){ + if(command.doBlockquote){ + command.doBlockquote(chunk); + } + } + if(/(\n|^)(\t|[ ]{4,}).*\n$/.test(chunk.before)){ + if(command.doCode){ + command.doCode(chunk); + } + } + }; + + command.doBlockquote = function(chunk, postProcessing){ + + chunk.selection = chunk.selection.replace(/^(\n*)([^\r]+?)(\n*)$/, + function(totalMatch, newlinesBefore, text, newlinesAfter){ + chunk.before += newlinesBefore; + chunk.after = newlinesAfter + chunk.after; + return text; + }); + + chunk.before = chunk.before.replace(/(>[ \t]*)$/, + function(totalMatch, blankLine){ + chunk.selection = blankLine + chunk.selection; + return ""; + }); + + chunk.selection = chunk.selection.replace(/^(\s|>)+$/ ,""); + chunk.selection = chunk.selection || "Blockquote"; + + if(chunk.before){ + chunk.before = chunk.before.replace(/\n?$/,"\n"); + } + if(chunk.after){ + chunk.after = chunk.after.replace(/^\n?/,"\n"); + } + + chunk.before = chunk.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/, + function(totalMatch){ + chunk.startTag = totalMatch; + return ""; + }); + + chunk.after = chunk.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/, + function(totalMatch){ + chunk.endTag = totalMatch; + return ""; + }); + + var replaceBlanksInTags = function(useBracket){ + + var replacement = useBracket ? "> " : ""; + + if(chunk.startTag){ + chunk.startTag = chunk.startTag.replace(/\n((>|\s)*)\n$/, + function(totalMatch, markdown){ + return "\n" + markdown.replace(/^[ ]{0,3}>?[ \t]*$/gm, replacement) + "\n"; + }); + } + if(chunk.endTag){ + chunk.endTag = chunk.endTag.replace(/^\n((>|\s)*)\n/, + function(totalMatch, markdown){ + return "\n" + markdown.replace(/^[ ]{0,3}>?[ \t]*$/gm, replacement) + "\n"; + }); + } + }; + + if(/^(?![ ]{0,3}>)/m.test(chunk.selection)){ + command.wrap(chunk, wmd.wmd_env.lineLength - 2); + chunk.selection = chunk.selection.replace(/^/gm, "> "); + replaceBlanksInTags(true); + chunk.skipLines(); + } + else{ + chunk.selection = chunk.selection.replace(/^[ ]{0,3}> ?/gm, ""); + command.unwrap(chunk); + replaceBlanksInTags(false); + + if(!/^(\n|^)[ ]{0,3}>/.test(chunk.selection) && chunk.startTag){ + chunk.startTag = chunk.startTag.replace(/\n{0,2}$/, "\n\n"); + } + + if(!/(\n|^)[ ]{0,3}>.*$/.test(chunk.selection) && chunk.endTag){ + chunk.endTag=chunk.endTag.replace(/^\n{0,2}/, "\n\n"); + } + } + + if(!/\n/.test(chunk.selection)){ + chunk.selection = chunk.selection.replace(/^(> *)/, + function(wholeMatch, blanks){ + chunk.startTag += blanks; + return ""; + }); + } + }; + + command.doCode = function(chunk, postProcessing){ + + var hasTextBefore = /\S[ ]*$/.test(chunk.before); + var hasTextAfter = /^[ ]*\S/.test(chunk.after); + + // Use 'four space' markdown if the selection is on its own + // line or is multiline. + if((!hasTextAfter && !hasTextBefore) || /\n/.test(chunk.selection)){ + + chunk.before = chunk.before.replace(/[ ]{4}$/, + function(totalMatch){ + chunk.selection = totalMatch + chunk.selection; + return ""; + }); + + var nLinesBack = 1; + var nLinesForward = 1; + + if(/\n(\t|[ ]{4,}).*\n$/.test(chunk.before)){ + nLinesBack = 0; + } + if(/^\n(\t|[ ]{4,})/.test(chunk.after)){ + nLinesForward = 0; + } + + chunk.skipLines(nLinesBack, nLinesForward); + + if(!chunk.selection){ + chunk.startTag = " "; + chunk.selection = "enter code here"; + } + else { + if(/^[ ]{0,3}\S/m.test(chunk.selection)){ + chunk.selection = chunk.selection.replace(/^/gm, " "); + } + else{ + chunk.selection = chunk.selection.replace(/^[ ]{4}/gm, ""); + } + } + } + else{ + // Use backticks (`) to delimit the code block. + + chunk.trimWhitespace(); + chunk.findTags(/`/, /`/); + + if(!chunk.startTag && !chunk.endTag){ + chunk.startTag = chunk.endTag="`"; + if(!chunk.selection){ + chunk.selection = "enter code here"; + } + } + else if(chunk.endTag && !chunk.startTag){ + chunk.before += chunk.endTag; + chunk.endTag = ""; + } + else{ + chunk.startTag = chunk.endTag=""; + } + } + }; + + command.doList = function(chunk, postProcessing, isNumberedList){ + + // These are identical except at the very beginning and end. + // Should probably use the regex extension function to make this clearer. + var previousItemsRegex = /(\n|^)(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*$/; + var nextItemsRegex = /^\n*(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*/; + + // The default bullet is a dash but others are possible. + // This has nothing to do with the particular HTML bullet, + // it's just a markdown bullet. + var bullet = "-"; + + // The number in a numbered list. + var num = 1; + + // Get the item prefix - e.g. " 1. " for a numbered list, " - " for a bulleted list. + var getItemPrefix = function(){ + var prefix; + if(isNumberedList){ + prefix = " " + num + ". "; + num++; + } + else{ + prefix = " " + bullet + " "; + } + return prefix; + }; + + // Fixes the prefixes of the other list items. + var getPrefixedItem = function(itemText){ + + // The numbering flag is unset when called by autoindent. + if(isNumberedList === undefined){ + isNumberedList = /^\s*\d/.test(itemText); + } + + // Renumber/bullet the list element. + itemText = itemText.replace(/^[ ]{0,3}([*+-]|\d+[.])\s/gm, + function( _ ){ + return getItemPrefix(); + }); + + return itemText; + }; + + chunk.findTags(/(\n|^)*[ ]{0,3}([*+-]|\d+[.])\s+/, null); + + if(chunk.before && !/\n$/.test(chunk.before) && !/^\n/.test(chunk.startTag)){ + chunk.before += chunk.startTag; + chunk.startTag = ""; + } + + if(chunk.startTag){ + + var hasDigits = /\d+[.]/.test(chunk.startTag); + chunk.startTag = ""; + chunk.selection = chunk.selection.replace(/\n[ ]{4}/g, "\n"); + command.unwrap(chunk); + chunk.skipLines(); + + if(hasDigits){ + // Have to renumber the bullet points if this is a numbered list. + chunk.after = chunk.after.replace(nextItemsRegex, getPrefixedItem); + } + if(isNumberedList == hasDigits){ + return; + } + } + + var nLinesUp = 1; + + chunk.before = chunk.before.replace(previousItemsRegex, + function(itemText){ + if(/^\s*([*+-])/.test(itemText)){ + bullet = re.$1; + } + nLinesUp = /[^\n]\n\n[^\n]/.test(itemText) ? 1 : 0; + return getPrefixedItem(itemText); + }); + + if(!chunk.selection){ + chunk.selection = "List item"; + } + + var prefix = getItemPrefix(); + + var nLinesDown = 1; + + chunk.after = chunk.after.replace(nextItemsRegex, + function(itemText){ + nLinesDown = /[^\n]\n\n[^\n]/.test(itemText) ? 1 : 0; + return getPrefixedItem(itemText); + }); + + chunk.trimWhitespace(true); + chunk.skipLines(nLinesUp, nLinesDown, true); + chunk.startTag = prefix; + var spaces = prefix.replace(/./g, " "); + command.wrap(chunk, wmd.wmd_env.lineLength - spaces.length); + chunk.selection = chunk.selection.replace(/\n/g, "\n" + spaces); + + }; + + command.doHeading = function(chunk, postProcessing){ + + // Remove leading/trailing whitespace and reduce internal spaces to single spaces. + chunk.selection = chunk.selection.replace(/\s+/g, " "); + chunk.selection = chunk.selection.replace(/(^\s+|\s+$)/g, ""); + + // If we clicked the button with no selected text, we just + // make a level 2 hash header around some default text. + if(!chunk.selection){ + chunk.startTag = "## "; + chunk.selection = "Heading"; + chunk.endTag = " ##"; + return; + } + + var headerLevel = 0; // The existing header level of the selected text. + + // Remove any existing hash heading markdown and save the header level. + chunk.findTags(/#+[ ]*/, /[ ]*#+/); + if(/#+/.test(chunk.startTag)){ + headerLevel = re.lastMatch.length; + } + chunk.startTag = chunk.endTag = ""; + + // Try to get the current header level by looking for - and = in the line + // below the selection. + chunk.findTags(null, /\s?(-+|=+)/); + if(/=+/.test(chunk.endTag)){ + headerLevel = 1; + } + if(/-+/.test(chunk.endTag)){ + headerLevel = 2; + } + + // Skip to the next line so we can create the header markdown. + chunk.startTag = chunk.endTag = ""; + chunk.skipLines(1, 1); + + // We make a level 2 header if there is no current header. + // If there is a header level, we substract one from the header level. + // If it's already a level 1 header, it's removed. + var headerLevelToCreate = headerLevel == 0 ? 2 : headerLevel - 1; + + if(headerLevelToCreate > 0){ + + // The button only creates level 1 and 2 underline headers. + // Why not have it iterate over hash header levels? Wouldn't that be easier and cleaner? + var headerChar = headerLevelToCreate >= 2 ? "-" : "="; + var len = chunk.selection.length; + if(len > wmd.wmd_env.lineLength){ + len = wmd.wmd_env.lineLength; + } + chunk.endTag = "\n"; + while(len--){ + chunk.endTag += headerChar; + } + } + }; + + command.doHorizontalRule = function(chunk, postProcessing){ + chunk.startTag = "----------\n"; + chunk.selection = ""; + chunk.skipLines(2, 1, true); + } +}; + + +Attacklab.wmd_env = {}; +Attacklab.account_options = {}; +Attacklab.wmd_defaults = {version:1, output:"Markdown", lineLength:40, delayLoad:false}; + +if(!Attacklab.wmd) +{ + Attacklab.wmd = function() + { + Attacklab.loadEnv = function() + { + var mergeEnv = function(env) + { + if(!env) + { + return; + } + + for(var key in env) + { + Attacklab.wmd_env[key] = env[key]; + } + }; + + mergeEnv(Attacklab.wmd_defaults); + mergeEnv(Attacklab.account_options); + mergeEnv(top["wmd_options"]); + Attacklab.full = true; + + var defaultButtons = "bold italic link blockquote code image ol ul heading hr"; + Attacklab.wmd_env.buttons = Attacklab.wmd_env.buttons || defaultButtons; + }; + Attacklab.loadEnv(); + + }; + + Attacklab.wmd(); + Attacklab.wmdBase(); + Attacklab.Util.startEditor(); +}; + diff --git a/askbot/skins/common/media/style/openid.css b/askbot/skins/common/media/style/openid.css new file mode 100644 index 00000000..0d201df2 --- /dev/null +++ b/askbot/skins/common/media/style/openid.css @@ -0,0 +1,45 @@ +#openid_form { + width: 470px; +} + #openid_form legend { + font-weight: bold; + } +#openid_choice { + display: none; +} +#openid_input_area { + clear: both; + padding: 10px; +} +#openid_btns, #openid_btns br { + clear: both; +} + #openid_highlight { + padding: 3px; + background-color: #FFFCC9; + float: left; + } + .openid_large_btn { + width: 100px; + height: 60px; + border: 1px solid #DDD; + margin: 3px; + float: left; + } + .openid_small_btn { + width: 24px; + height: 24px; + border: 1px solid #DDD; + margin: 3px; + float: left; + } + a.openid_large_btn:focus { + outline: none; + } + a.openid_large_btn:focus + { + -moz-outline-style: none; + } + .openid_selected { + border: 4px solid #DDD; + } diff --git a/askbot/skins/default/media/images/bigbutton.png b/askbot/skins/default/media/images/bigbutton.png Binary files differnew file mode 100644 index 00000000..2a7c0f05 --- /dev/null +++ b/askbot/skins/default/media/images/bigbutton.png diff --git a/askbot/skins/default/media/images/bigbuttonhover.png b/askbot/skins/default/media/images/bigbuttonhover.png Binary files differnew file mode 100644 index 00000000..cf4bacca --- /dev/null +++ b/askbot/skins/default/media/images/bigbuttonhover.png diff --git a/askbot/skins/default/media/images/contributorsback.png b/askbot/skins/default/media/images/contributorsback.png Binary files differnew file mode 100644 index 00000000..dd728383 --- /dev/null +++ b/askbot/skins/default/media/images/contributorsback.png diff --git a/askbot/skins/default/media/images/feed-icon-small.png b/askbot/skins/default/media/images/feed-icon-small.png Binary files differindex b3c949d2..2794b0f5 100755..100644 --- a/askbot/skins/default/media/images/feed-icon-small.png +++ b/askbot/skins/default/media/images/feed-icon-small.png diff --git a/askbot/skins/default/media/images/logo.gif b/askbot/skins/default/media/images/logo.gif Binary files differindex 03eb79f4..ac4ceda6 100644 --- a/askbot/skins/default/media/images/logo.gif +++ b/askbot/skins/default/media/images/logo.gif diff --git a/askbot/skins/default/media/images/scopearrow.png b/askbot/skins/default/media/images/scopearrow.png Binary files differnew file mode 100644 index 00000000..73dc6744 --- /dev/null +++ b/askbot/skins/default/media/images/scopearrow.png diff --git a/askbot/skins/default/media/images/sprites.png b/askbot/skins/default/media/images/sprites.png Binary files differnew file mode 100644 index 00000000..dcc1bdc3 --- /dev/null +++ b/askbot/skins/default/media/images/sprites.png diff --git a/askbot/skins/default/media/images/sprites_source/sprites.svg b/askbot/skins/default/media/images/sprites_source/sprites.svg new file mode 100644 index 00000000..34898e30 --- /dev/null +++ b/askbot/skins/default/media/images/sprites_source/sprites.svg @@ -0,0 +1,732 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="210mm" + height="297mm" + id="svg5653" + version="1.1" + inkscape:version="0.48.1 r9760" + sodipodi:docname="sprites.svg"> + <defs + id="defs5655"> + <linearGradient + id="linearGradient3865" + inkscape:collect="always"> + <stop + id="stop3867" + offset="0" + style="stop-color:#0975cf;stop-opacity:1" /> + <stop + id="stop3869" + offset="1" + style="stop-color:#14b3de;stop-opacity:0" /> + </linearGradient> + <linearGradient + id="linearGradient3824" + inkscape:collect="always"> + <stop + id="stop3826" + offset="0" + style="stop-color:#9f9f8d;stop-opacity:1" /> + <stop + id="stop3828" + offset="1" + style="stop-color:#44443a;stop-opacity:1" /> + </linearGradient> + <linearGradient + id="linearGradient3812" + inkscape:collect="always"> + <stop + id="stop3814" + offset="0" + style="stop-color:#9f9f8d;stop-opacity:1" /> + <stop + id="stop3816" + offset="1" + style="stop-color:#44443a;stop-opacity:1" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient7944" + id="linearGradient7950" + x1="-1656.4215" + y1="3870.6523" + x2="-1656.4216" + y2="3887.7998" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient7944"> + <stop + style="stop-color:#ffffff;stop-opacity:1;" + offset="0" + id="stop7946" /> + <stop + style="stop-color:#e4e4e4;stop-opacity:1" + offset="1" + id="stop7948" /> + </linearGradient> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient7944" + id="linearGradient6226" + gradientUnits="userSpaceOnUse" + x1="-1656.4215" + y1="3870.6523" + x2="-1656.4216" + y2="3887.7998" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient7944" + id="linearGradient6228" + gradientUnits="userSpaceOnUse" + x1="-1656.4215" + y1="3870.6523" + x2="-1656.4216" + y2="3887.7998" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient5675" + id="radialGradient5683" + cx="-2600.8416" + cy="2819.7468" + fx="-2600.8416" + fy="2819.7468" + r="16.18819" + gradientTransform="matrix(0.58002994,0.69397701,-0.72276743,0.59013931,945.88619,2917.0459)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient5675"> + <stop + style="stop-color:#9f9f8d;stop-opacity:1" + offset="0" + id="stop5677" /> + <stop + style="stop-color:#757563;stop-opacity:1" + offset="1" + id="stop5679" /> + </linearGradient> + <radialGradient + r="16.18819" + fy="2819.7468" + fx="-2600.8416" + cy="2819.7468" + cx="-2600.8416" + gradientTransform="matrix(0.58002994,0.69397701,-0.72276743,0.59013931,3626.1545,288.43467)" + gradientUnits="userSpaceOnUse" + id="radialGradient5712" + xlink:href="#linearGradient5675" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3812" + id="radialGradient3804" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.58002994,0.69397701,-0.72276743,0.59013931,3488.6545,301.93467)" + cx="-2600.8416" + cy="2819.7468" + fx="-2600.8416" + fy="2819.7468" + r="16.18819" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3824" + id="radialGradient3822" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.58002994,0.69397701,-0.72276743,0.59013931,3671.135,288.43467)" + cx="-2600.8416" + cy="2819.7468" + fx="-2600.8416" + fy="2819.7468" + r="16.18819" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3815" + id="radialGradient3821" + cx="222.6344" + cy="161.02299" + fx="222.6344" + fy="161.02299" + r="11.136931" + gradientTransform="matrix(1.0362639,-1.062432,1.063838,1.0176009,-176.68455,228.7811)" + gradientUnits="userSpaceOnUse" /> + <linearGradient + inkscape:collect="always" + id="linearGradient3815"> + <stop + style="stop-color:#ffffff;stop-opacity:1" + offset="0" + id="stop3817" /> + <stop + style="stop-color:#ffffff;stop-opacity:0" + offset="1" + id="stop3819" /> + </linearGradient> + <radialGradient + r="11.136931" + fy="161.02299" + fx="222.6344" + cy="161.02299" + cx="222.6344" + gradientTransform="matrix(0.25937215,-1.0764281,1.4011863,0.30094439,-58.042568,347.29527)" + gradientUnits="userSpaceOnUse" + id="radialGradient3838" + xlink:href="#linearGradient3865" + inkscape:collect="always" /> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath5733"> + <rect + style="opacity:0.42723006;fill:#436871;fill-opacity:1;stroke:none" + id="rect5735" + width="5.5" + height="60.5" + x="-1266" + y="3940.3623" + ry="0" /> + </clipPath> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5704" + id="linearGradient5765" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,6.3333332,234,-21267.853)" + x1="-1477" + y1="3997.8623" + x2="-1477" + y2="3976.8623" /> + <linearGradient + inkscape:collect="always" + id="linearGradient5704"> + <stop + style="stop-color:#436871;stop-opacity:1" + offset="0" + id="stop5706" /> + <stop + style="stop-color:#c9dbdf;stop-opacity:0;" + offset="1" + id="stop5708" /> + </linearGradient> + <clipPath + clipPathUnits="userSpaceOnUse" + id="clipPath5776"> + <rect + style="opacity:0.42723006;fill:#436871;fill-opacity:1;stroke:none" + id="rect5778" + width="5.75" + height="56.625" + x="-1260.375" + y="3997.4873" + ry="0" /> + </clipPath> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient5704" + id="linearGradient5710" + x1="-1477" + y1="3997.8623" + x2="-1477" + y2="3976.8623" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,6.3333332,1795.4506,-24803.226)" /> + <filter + color-interpolation-filters="sRGB" + inkscape:collect="always" + id="filter4997-0"> + <feGaussianBlur + inkscape:collect="always" + stdDeviation="0.65508698" + id="feGaussianBlur4999-3" /> + </filter> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.4142136" + inkscape:cx="250.462" + inkscape:cy="491.05925" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1316" + inkscape:window-height="744" + inkscape:window-x="50" + inkscape:window-y="24" + inkscape:window-maximized="1"> + <sodipodi:guide + orientation="0,1" + position="1,1061.5" + id="guide6194" /> + <sodipodi:guide + orientation="1,0" + position="62.5,992" + id="guide3030" /> + </sodipodi:namedview> + <metadata + id="metadata5658"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Capa 1" + inkscape:groupmode="layer" + id="layer1"> + <rect + style="fill:#35575a;fill-opacity:1;stroke:none" + id="rect5684" + width="743" + height="355" + x="1" + y="5.3621826" /> + <rect + style="fill:#ffffff;fill-opacity:1;stroke:none" + id="rect5682" + width="600" + height="207" + x="58" + y="83.362183" + inkscape:export-filename="/home/bcorrales/personal/askbot/sprites.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + y="87.862183" + x="107" + height="28" + width="243.25" + id="rect6341" + style="fill:#16160f;fill-opacity:1;stroke:none" /> + <rect + style="fill:#f5dd69;fill-opacity:1;stroke:none" + id="rect6196" + width="41.25" + height="21" + x="63" + y="87.862183" /> + <path + transform="matrix(1.0191083,0,0,0.98765432,1762.2659,-3727.1824)" + d="m -1647,3873.8623 a 9.5,9.5 0 1 1 -19,0 9.5,9.5 0 1 1 19,0 z" + sodipodi:ry="9.5" + sodipodi:rx="9.5" + sodipodi:cy="3873.8623" + sodipodi:cx="-1656.5" + id="path7928" + style="fill:#c9a90d;fill-opacity:1;stroke:none" + sodipodi:type="arc" /> + <path + sodipodi:type="arc" + style="fill:url(#linearGradient7950);fill-opacity:1;stroke:none" + id="path7922" + sodipodi:cx="-1656.5" + sodipodi:cy="3873.8623" + sodipodi:rx="9.5" + sodipodi:ry="9.5" + d="m -1647,3873.8623 a 9.5,9.5 0 1 1 -19,0 9.5,9.5 0 1 1 19,0 z" + transform="matrix(1.0191083,0,0,0.98765432,1761.629,-3728.4169)" /> + <text + transform="scale(1.1035306,0.90618241)" + xml:space="preserve" + style="font-size:19.10287285px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b96161;fill-opacity:1;stroke:none;font-family:Arial Rounded MT Bold;-inkscape-font-specification:Arial Rounded MT Bold" + x="62.464367" + y="112.6709" + id="text7924" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan7926" + x="62.464367" + y="112.6709" + style="font-size:14.30124187px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#b96161;fill-opacity:1;font-family:Trebuchet MS;-inkscape-font-specification:Trebuchet MS">X</tspan></text> + <path + sodipodi:type="arc" + style="fill:#c9a90d;fill-opacity:1;stroke:none" + id="path6208" + sodipodi:cx="-1656.5" + sodipodi:cy="3873.8623" + sodipodi:rx="9.5" + sodipodi:ry="9.5" + d="m -1647,3873.8623 a 9.5,9.5 0 1 1 -19,0 9.5,9.5 0 1 1 19,0 z" + transform="matrix(1.0191083,0,0,0.98765432,1762.2659,-3727.1824)" /> + <path + transform="matrix(1.0191083,0,0,0.98765432,1761.629,-3728.4169)" + d="m -1647,3873.8623 a 9.5,9.5 0 1 1 -19,0 9.5,9.5 0 1 1 19,0 z" + sodipodi:ry="9.5" + sodipodi:rx="9.5" + sodipodi:cy="3873.8623" + sodipodi:cx="-1656.5" + id="path6210" + style="fill:url(#linearGradient6228);fill-opacity:1;stroke:none" + sodipodi:type="arc" /> + <text + sodipodi:linespacing="125%" + id="text6212" + y="112.6709" + x="62.464367" + style="font-size:19.10287285px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#b96161;fill-opacity:1;stroke:none;font-family:Arial Rounded MT Bold;-inkscape-font-specification:Arial Rounded MT Bold" + xml:space="preserve" + transform="scale(1.1035306,0.90618241)"><tspan + style="font-size:14.30124187px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#b96161;fill-opacity:1;font-family:Trebuchet MS;-inkscape-font-specification:Trebuchet MS" + y="112.6709" + x="62.464367" + id="tspan6214" + sodipodi:role="line">X</tspan></text> + <path + transform="matrix(1.0191083,0,0,0.98765432,1782.2659,-3727.1824)" + d="m -1647,3873.8623 a 9.5,9.5 0 1 1 -19,0 9.5,9.5 0 1 1 19,0 z" + sodipodi:ry="9.5" + sodipodi:rx="9.5" + sodipodi:cy="3873.8623" + sodipodi:cx="-1656.5" + id="path6218" + style="fill:#c9a90d;fill-opacity:1;stroke:none" + sodipodi:type="arc" /> + <path + sodipodi:type="arc" + style="fill:url(#linearGradient6226);fill-opacity:1;stroke:none" + id="path6220" + sodipodi:cx="-1656.5" + sodipodi:cy="3873.8623" + sodipodi:rx="9.5" + sodipodi:ry="9.5" + d="m -1647,3873.8623 a 9.5,9.5 0 1 1 -19,0 9.5,9.5 0 1 1 19,0 z" + transform="matrix(1.0191083,0,0,0.98765432,1781.629,-3728.4169)" /> + <text + transform="scale(1.1035306,0.9061824)" + xml:space="preserve" + style="font-size:19.10287285px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#e90f0f;fill-opacity:1;stroke:none;font-family:Arial Rounded MT Bold;-inkscape-font-specification:Arial Rounded MT Bold" + x="80.587997" + y="112.6709" + id="text6222" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan6224" + x="80.587997" + y="112.6709" + style="font-size:14.30124187px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#e90f0f;fill-opacity:1;font-family:Trebuchet MS;-inkscape-font-specification:Trebuchet MS">X</tspan></text> + <path + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="/home/bcorrales/personal/oxfam/arte/disenoindex.png" + id="path5443" + d="m 118.12608,94.030535 c -1.0424,-0.859469 -2.66478,-0.610365 -3.61221,0.548988 -0.95263,1.157954 -0.86987,2.798821 0.17873,3.655691 1.0444,0.861168 2.66667,0.612064 3.61631,-0.549588 0.94503,-1.162052 0.86746,-2.798222 -0.17854,-3.655591 z m 5.88263,18.686595 -12.99549,-10.6378 c -0.44703,-0.36346 -0.64755,-0.93014 -0.58638,-1.50242 -0.05,-0.11386 -0.087,-0.2505 -0.10985,-0.41064 l -1.33739,-8.835794 c -0.14424,-0.949634 0.5206,-1.76262 1.48163,-1.808503 l 8.91926,-0.441729 c 0.38495,-0.01899 1.49952,0.354863 1.78501,0.584574 l 12.99449,10.637502 c 0.74232,0.60366 0.7989,1.77001 0.12665,2.5924 l -7.71322,9.43426 c -0.66824,0.82178 -1.8207,0.99492 -2.56061,0.38925 z" + clip-rule="evenodd" + style="fill:#e7e8a8;fill-opacity:1;fill-rule:evenodd;stroke:none" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + style="fill:#16160f;fill-opacity:1;fill-rule:evenodd" + clip-rule="evenodd" + d="m 118.54252,95.166497 c -0.92055,-0.758108 -2.28652,-0.618962 -3.04183,0.304482 -0.75951,0.922345 -0.62036,2.289418 0.30498,3.045526 0.92224,0.759507 2.28822,0.620461 3.04513,-0.305082 0.75321,-0.925943 0.61866,-2.289018 -0.30479,-3.045326 z m 5.77547,15.775213 -11.47288,-9.38528 c -0.39445,-0.32067 -0.58837,-0.79999 -0.56038,-1.27301 -0.047,-0.097 -0.084,-0.21191 -0.11056,-0.345863 l -1.50572,-7.398547 c -0.16224,-0.795193 0.36786,-1.442844 1.18105,-1.440845 l 7.54948,0.01 c 0.32578,3.99e-4 1.28701,0.357962 1.53911,0.560484 l 11.47158,9.385081 c 0.65525,0.53279 0.75211,1.50442 0.21612,2.15966 l -6.14833,7.51601 c -0.5325,0.65474 -1.50312,0.75031 -2.15627,0.21591 z" + id="path5445" + inkscape:export-filename="/home/bcorrales/personal/oxfam/arte/disenoindex.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" + inkscape:transform-center-x="0.5180824" + inkscape:transform-center-y="-0.28622416" /> + <path + inkscape:connector-curvature="0" + id="path5457" + d="m 201.60421,88.7079 c -5.0386,0.159728 -7.45306,6.825068 -4.44845,10.23363 -5.35784,2.62945 -3.73419,8.6476 -3.90826,13.70496 6.23105,0 12.46221,0 18.69326,0 -0.0342,-5.17704 1.38659,-11.61812 -4.44823,-13.962091 3.5491,-4.275375 -0.52838,-10.736311 -5.88832,-9.976499 z" + style="fill:#e7e8a8;fill-opacity:1;stroke:none" /> + <path + sodipodi:type="arc" + style="fill:#16160f;fill-opacity:1;stroke:none" + id="path5461" + sodipodi:cx="-1766" + sodipodi:cy="1210.3622" + sodipodi:rx="20.875" + sodipodi:ry="19.875" + d="m -1746.6683,1217.8622 a 20.875,19.875 0 1 1 0.021,-0.05" + sodipodi:start="0.38694167" + sodipodi:end="6.6674319" + sodipodi:open="true" + transform="matrix(0.23246322,0,0,0.23246322,612.84081,-186.42964)" /> + <path + style="fill:#16160f;fill-opacity:1;stroke:none" + d="m 200.32341,99.85026 c -2.77296,0 -5.03938,2.03973 -5.40307,4.70966 l -0.021,0 0,0.11384 c -0.0243,0.20805 -0.0408,0.42712 -0.0408,0.64178 0,0.21102 0.0177,0.41631 0.0408,0.62105 l 0,5.0718 15.40196,0 0,-5.0718 c 0.0232,-0.20474 0.0408,-0.41003 0.0408,-0.62105 0,-0.21466 -0.0177,-0.43373 -0.0408,-0.64178 l 0,-0.11384 -0.021,0 c -0.3638,-2.66993 -2.63021,-4.70966 -5.40306,-4.70966 l -1.03504,0 -1.35592,2.81554 -1.36629,-2.81554 -0.79699,0 z" + id="path5463" + inkscape:connector-curvature="0" /> + <path + style="opacity:0.95734594;fill:#e7e8a8;fill-opacity:1;stroke:none" + d="m 287.95443,89.851557 c -1.6542,0.05548 -2.75231,2.086378 -1.97699,3.52883 -0.63135,1.023863 -1.18707,3.287681 -2.84533,2.512825 -1.58254,0.673792 -2.41713,-1.603711 -3.98172,-0.91457 -2.15656,0.508372 -2.50044,3.955277 -0.28646,4.609836 0.66658,0.118355 1.38854,0.192142 1.38577,1.016282 1.32012,1.04282 0.20536,3.35241 -1.27491,3.51052 -2.03524,0.99474 -1.52604,4.44608 0.79456,4.64673 1.48119,0.14147 2.53871,-1.5326 4.09258,-0.89608 1.17551,0.24938 1.76747,1.60242 2.05078,2.54048 -1.0087,1.8897 1.18605,4.16804 3.10405,3.20566 1.39067,-0.4601 1.85188,-2.07121 1.37652,-3.31653 0.41369,-0.83912 1.05271,-1.65965 1.6075,-2.34648 1.24643,-0.35941 2.55425,-0.14896 3.50119,0.71142 2.08378,0.88286 4.38154,-1.75378 2.95628,-3.63072 -0.53953,-1.15942 -2.19299,-0.66667 -2.50358,-1.94916 -0.82635,-1.06372 -0.34544,-2.40575 0.47111,-3.251898 0.51485,-0.512163 1.80066,-0.202313 2.15249,-1.136301 1.70737,-1.912451 -1.15266,-5.077339 -3.21491,-3.547415 -0.69552,1.09312 -1.98439,0.810455 -3.03932,0.840598 -0.98808,-0.566532 -1.66816,-1.890814 -1.84763,-2.900808 0.49774,-1.685634 -0.70875,-3.40169 -2.52198,-3.233219 z" + id="path5491" + inkscape:connector-curvature="0" /> + <path + id="path5404" + d="m 288.16682,91.024751 c -0.69043,0 -1.25641,0.565885 -1.25641,1.256321 0,0.415167 0.20601,0.779571 0.51734,1.006942 l -2.22628,3.815471 -4.22185,-0.0092 c 0,0 0,-0.0092 0,-0.0092 -0.11993,-0.565515 -0.62747,-0.988542 -1.22877,-0.988542 -0.69034,0 -1.24707,0.556638 -1.24707,1.247166 0,0.690435 0.55673,1.247074 1.24707,1.247074 0.21813,0 0.4221,-0.05825 0.60056,-0.156913 l 2.01389,3.51967 -1.85688,3.19642 c -0.13232,-0.0472 -0.27629,-0.0841 -0.42497,-0.0841 -0.69044,0 -1.24717,0.55673 -1.24717,1.24726 0,0.69052 0.55673,1.25641 1.24717,1.25641 0.54915,0 1.01452,-0.35784 1.18244,-0.84994 l 3.88926,-0.0185 2.19872,3.72291 c -0.28692,0.22904 -0.48036,0.57421 -0.48036,0.96996 0,0.69053 0.55664,1.24726 1.24717,1.24726 0.69044,0 1.25641,-0.55673 1.25641,-1.24726 0,-0.37153 -0.16764,-0.70403 -0.42497,-0.93297 l 2.24487,-3.7599 4.02786,-0.009 c 0.13796,0.54037 0.62682,0.94231 1.21018,0.94231 0.69053,0 1.24717,-0.55673 1.24717,-1.24716 0,-0.69053 -0.55664,-1.25642 -1.24717,-1.25642 -0.18003,0 -0.3534,0.0425 -0.5081,0.11087 l -1.95849,-3.4089 2.05087,-3.538262 c 0.18262,0.104485 0.38447,0.166344 0.60971,0.166344 0.69053,0 1.25641,-0.556638 1.25641,-1.247073 0,-0.690621 -0.56588,-1.247259 -1.25641,-1.247259 -0.63921,0 -1.15415,0.480262 -1.22867,1.099407 l -4.13864,0.01849 -2.32808,-3.833871 c 0.28794,-0.229035 0.48045,-0.573467 0.48045,-0.969956 0,-0.690528 -0.55673,-1.256413 -1.24726,-1.256413 z" + style="opacity:0.95734594;fill:#16160f;fill-opacity:1;stroke:none" + inkscape:connector-curvature="0" /> + <path + transform="matrix(0.05048908,0,0,0.04995915,432.79113,-34.802929)" + d="m -2780.5,2735.8623 a 83.5,82.5 0 1 1 -167,0 83.5,82.5 0 1 1 167,0 z" + sodipodi:ry="82.5" + sodipodi:rx="83.5" + sodipodi:cy="2735.8623" + sodipodi:cx="-2864" + id="path5754" + style="opacity:0.95734594;fill:#e7e8a8;fill-opacity:1;stroke:none" + sodipodi:type="arc" /> + <rect + style="fill:#e9e9e1;fill-opacity:1;stroke:none" + id="rect3032" + width="45" + height="55" + x="62.5" + y="119.61218" /> + <path + style="fill:url(#radialGradient5712);fill-opacity:1" + d="m 67.6121,160.27637 c -0.094,-0.046 -0.2146,-0.1465 -0.2675,-0.2235 -0.092,-0.1328 -0.097,-0.507 -0.1104,-7.2852 l -0.014,-7.1451 5.5933,-4.8985 c 3.0763,-2.6941 5.6262,-4.9108 5.6664,-4.9262 0.044,-0.017 2.2915,1.9154 5.6947,4.8961 l 5.6214,4.9239 -0.014,7.1474 c -0.013,6.7953 -0.019,7.1546 -0.1108,7.2883 -0.2172,0.3162 -0.1184,0.3086 -4.0168,0.3086 l -3.5623,0 -6e-4,-3.0266 c -6e-4,-1.6648 -0.016,-3.1187 -0.035,-3.2313 -0.022,-0.1319 -0.098,-0.2677 -0.2151,-0.3832 l -0.1811,-0.1789 -3.1523,0 -3.1523,0 -0.181,0.1789 c -0.1168,0.1155 -0.1931,0.2513 -0.2152,0.3832 -0.019,0.1126 -0.034,1.5665 -0.035,3.2313 l -5e-4,3.0266 -3.5704,0 c -3.1432,0 -3.591,-0.012 -3.7418,-0.085 z m -4.3178,-15.0177 c -0.4595,-0.5139 -0.817,-0.9502 -0.7943,-0.9695 0.023,-0.019 3.6131,-3.1609 7.9784,-6.9811 4.3654,-3.82019 7.9797,-6.94589 8.0317,-6.94589 0.052,0 3.6512,3.11599 7.9984,6.92429 4.3473,3.8085 7.9377,6.949 7.9789,6.9791 0.059,0.043 -0.096,0.24591 -0.764,0.9929 -0.7293,0.8159 -0.8498,0.9293 -0.9245,0.8704 -0.047,-0.038 -3.2709,-2.8571 -7.1641,-6.26639 -3.8931,-3.40961 -7.0985,-6.1989 -7.1231,-6.1989 -0.025,0 -3.2475,2.8051 -7.1619,6.23339 -3.9144,3.4285 -7.1401,6.2475 -7.1685,6.2648 -0.028,0.018 -0.4273,-0.3892 -0.887,-0.9031 z m 3.9274,-9.9518 0,-2.96499 2.0326,0 2.0326,0 0,0.9707 c 0,1.5539 0.2495,1.16 -2.0161,3.1826 -1.0729,0.95779 -1.9729,1.74949 -1.9999,1.75909 -0.03,0.011 -0.048,-1.1677 -0.048,-2.9474 z" + id="path5673" + inkscape:connector-curvature="0" /> + <path + inkscape:connector-curvature="0" + id="path3802" + d="m -69.8879,173.77637 c -0.094,-0.046 -0.2146,-0.1465 -0.2675,-0.2235 -0.092,-0.1328 -0.097,-0.507 -0.1104,-7.2852 l -0.014,-7.1451 5.5933,-4.8985 c 3.0763,-2.6941 5.6262,-4.9108 5.6664,-4.9262 0.044,-0.017 2.2915,1.9154 5.6947,4.8961 l 5.6214,4.9239 -0.014,7.1474 c -0.013,6.7953 -0.019,7.1546 -0.1108,7.2883 -0.2172,0.3162 -0.1184,0.3086 -4.0168,0.3086 l -3.5623,0 -6e-4,-3.0266 c -6e-4,-1.6648 -0.016,-3.1187 -0.035,-3.2313 -0.022,-0.1319 -0.098,-0.2677 -0.2151,-0.3832 l -0.1811,-0.1789 -3.1523,0 -3.1523,0 -0.181,0.1789 c -0.1168,0.1155 -0.1931,0.2513 -0.2152,0.3832 -0.019,0.1126 -0.034,1.5665 -0.035,3.2313 l -5e-4,3.0266 -3.5704,0 c -3.1432,0 -3.591,-0.012 -3.7418,-0.085 z m -4.3178,-15.0177 c -0.4595,-0.5139 -0.817,-0.9502 -0.7943,-0.9695 0.023,-0.019 3.6131,-3.1609 7.9784,-6.9811 4.3654,-3.82019 7.9797,-6.94589 8.0317,-6.94589 0.052,0 3.6512,3.11599 7.9984,6.92429 4.3473,3.8085 7.9377,6.949 7.9789,6.9791 0.059,0.043 -0.096,0.24591 -0.764,0.9929 -0.7293,0.8159 -0.8498,0.9293 -0.9245,0.8704 -0.047,-0.038 -3.2709,-2.8571 -7.1641,-6.26639 -3.8931,-3.40961 -7.0985,-6.1989 -7.1231,-6.1989 -0.025,0 -3.2475,2.8051 -7.1619,6.23339 -3.9144,3.4285 -7.1401,6.2475 -7.1685,6.2648 -0.028,0.018 -0.4273,-0.3892 -0.887,-0.9031 z m 3.9274,-9.9518 0,-2.96499 2.0326,0 2.0326,0 0,0.9707 c 0,1.5539 0.2495,1.16 -2.0161,3.1826 -1.0729,0.95779 -1.9729,1.74949 -1.9999,1.75909 -0.03,0.011 -0.048,-1.1677 -0.048,-2.9474 z" + style="fill:url(#radialGradient3804);fill-opacity:1" /> + <rect + y="119.61218" + x="107.48047" + height="55" + width="45" + id="rect3818" + style="fill:#e9e9e1;fill-opacity:1;stroke:none" /> + <path + inkscape:connector-curvature="0" + id="path3820" + d="m 112.59257,160.27637 c -0.094,-0.046 -0.2146,-0.1465 -0.2675,-0.2235 -0.092,-0.1328 -0.097,-0.507 -0.1104,-7.2852 l -0.014,-7.1451 5.5933,-4.8985 c 3.0763,-2.6941 5.6262,-4.9108 5.6664,-4.9262 0.044,-0.017 2.2915,1.9154 5.6947,4.8961 l 5.6214,4.9239 -0.014,7.1474 c -0.013,6.7953 -0.019,7.1546 -0.1108,7.2883 -0.2172,0.3162 -0.1184,0.3086 -4.0168,0.3086 l -3.5623,0 -6e-4,-3.0266 c -6e-4,-1.6648 -0.016,-3.1187 -0.035,-3.2313 -0.022,-0.1319 -0.098,-0.2677 -0.2151,-0.3832 l -0.1811,-0.1789 -3.1523,0 -3.1523,0 -0.181,0.1789 c -0.1168,0.1155 -0.1931,0.2513 -0.2152,0.3832 -0.019,0.1126 -0.034,1.5665 -0.035,3.2313 l -5e-4,3.0266 -3.5704,0 c -3.1432,0 -3.591,-0.012 -3.7418,-0.085 z m -4.3178,-15.0177 c -0.4595,-0.5139 -0.817,-0.9502 -0.7943,-0.9695 0.023,-0.019 3.6131,-3.1609 7.9784,-6.9811 4.3654,-3.82019 7.9797,-6.94589 8.0317,-6.94589 0.052,0 3.6512,3.11599 7.9984,6.92429 4.3473,3.8085 7.9377,6.949 7.9789,6.9791 0.059,0.043 -0.096,0.24591 -0.764,0.9929 -0.7293,0.8159 -0.8498,0.9293 -0.9245,0.8704 -0.047,-0.038 -3.2709,-2.8571 -7.1641,-6.26639 -3.8931,-3.40961 -7.0985,-6.1989 -7.1231,-6.1989 -0.025,0 -3.2475,2.8051 -7.1619,6.23339 -3.9144,3.4285 -7.1401,6.2475 -7.1685,6.2648 -0.028,0.018 -0.4273,-0.3892 -0.887,-0.9031 z m 3.9274,-9.9518 0,-2.96499 2.0326,0 2.0326,0 0,0.9707 c 0,1.5539 0.2495,1.16 -2.0161,3.1826 -1.0729,0.95779 -1.9729,1.74949 -1.9999,1.75909 -0.03,0.011 -0.048,-1.1677 -0.048,-2.9474 z" + style="fill:url(#radialGradient3822);fill-opacity:1" /> + <rect + style="opacity:0.79620852;fill:#deded0;fill-opacity:1;stroke:none" + id="rect4547" + width="48" + height="40" + x="155.08926" + y="120.0357" /> + <image + width="35.911209" + height="35.911209" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABHNCSVQICAgIfAhkiAAAIABJREFU eJzsvXmQZEd9Lvplnqpeqqv3npmepXtmejSrFiyQLI2EjEASviBkgwFfzPUG2KwXjAUY/IwJ2xEO hx3Y9wXhwPfG4/qZZ2PfZ5v3MA/bYOtyMeCREJLQgjQS2mZGs2im9727qs7J98eprM7KyvXUqV5m zhdRUefkye3Ukt/3++Uv8wAZMmTIkCFDhgwZMmTIkCFDhgwZMmTIkCFDhgwZMmTIkCFDhgwZMmTI kCFDhgwZMmTIkCFDhq0BstEdyJAhgxMogN0AOgEUAAxX09uDINjOGKOI/88dAAaksu3V8u3VV2Ro pwJgpZpnVbo2C2ARACOERGEYXhTyXKpeWwXwkqWNDBkybAJkAiBDho3HMIBexARfCIJgF2OsE8Ag gBxiQmeWOiIAoUNaxaE/OeE4QCweOFj1um3sYACmq+1PAViJoug8YpFwDsAcgAsOfcmQIUOLkAmA DBlajwDAXgA7AAxQSvcgJvXe6rtM0gBQrr5XEJPpKmJCF0ldRfAmuJA/R86eBUC9QKDVc1Itz18A kNeUnwUwD2AyiqKziMXCJQAvIvMiZMjQUmQCIEOG9BAA2A9gNAiCnYyxHQC2IbbkRaJmiMm4gpjk uMs9xBrhy/AhbxXK9iwN0JG2K2QRwYUBFwq5ahtcKMjj0QyACULIxTAMLwA4g1gY+IieDBkyaJAJ gAwZkqELwBiAfZTSUQC7EJO9aLWWEZNVGbEFz89ly9ZG7knIO63yzYoAW3lRJIjCIIc4XiGHRiEx BeBCFEVnAJwG8AKAhSb7mSHDFYdMAGTIYAcFcBWAg5TSA4jn6vuxRuQRYpItI7bmy2i05HUk70LO iQk8iiI5kM8blNL2Joq7CAhdnpyUh4uBjuq5GJswB+BcFEWnAPwIwLPIphAyZDAiEwAZMjSiG8DV QRAcZIztR2zdc0QASohJeRlrVj2HL9Fbyb1JEm926gBwjwdogKN40AkAmzCg1Tx5rImCoHotBHCJ EHI6DMNnATyFON4gQ4YMVWQCIEOG2Jq/OgiCw4yxMdS78jnZL2HNsudQkasX0TuSe1IST3OuPLBn UcIqHgwiwUcY8HYCrImCTinvNCHk+TAMfwTgJOKphAwZrlhkAiDDlYg8gGuDILiaMXYYwHbEhM8Q E34JMeGXsObGdyX7hjQLybuQexIib4X7m9qzNMBFOGhFgkYcqASAThSQ6rU2rAkCPu5NE0KeDsPw KQA/RPx9Z8hwxSATABmuFOwG8OOU0kOIl+RxMluFG+E3Q/YmkreRe1Ii3ywCwKWcSSQ0iIMmRAGv q616rVA9BuLv4WwURc8BeBDAWVOHM2S4HJAJgAyXKwIArwiC4BWMsaMA+hCTYgUx6S8iJnxOlDbC b4bsTSRvI+okRG7bNKgZJBkzbALAdF0lDpKKApUgIIhFQBvilR28vUVCyFNhGD4O4HGkE0uRIcOm QiYAMlxOKAB4FaX0BsRL9PJYc+uvIt5whpOxF+E3SfYmErcRfBIyb2X0exIvgG2cMdWpupZUFLgI ggDx8kPuHSCIfwtnoij6PoCHEXuLMmTY8sgEQIatjiKAGyilNyLehIdibXOdBcTEr3Lr+xJ+M2Rv ImSXLX63OmyiwTQOqcomEgWegkD0DnQgFgQU8e/gdBRFP0AsBua0Pc+QYZMjEwAZtiLaEc/n3wzg QDUtRD3pA2Yr35fwmyF7E8mnTfCtdP9zpD1umASCqq2kosBHEKi8A22If3t8qiBCLAYeBPAQMs9A hi2GTABk2CqgAG6klN4E4DDiAdhG+lorPwHhN0P2SUk+CZlvVgGQdKxREXtSUeAjCGzeAb73ABcD ZQAvRlH0AGLPQBYzkGHTIxMAGTY7DgRBcDtj7DqsPcp2BfF8fjOk70v4rSB7G1mvB5mvF2xjjc9Y lFQUOAsCTzHApwm6qm2sVAMIv4N4V8IMGTYlMgGQYTOiF8BtVWt/B2JyXkU838rn9HWkb3Lti2V8 Cb8ZstcRedoEv56CIe2xQ1efazsuosBHEOjEAKCfKhD3GyhU25+qBg/+G7KdCDNsMmQCIMNmwo9R Sl8H4FD1nG+3O4fG5XpK0re49kXS9yV8F7JPm+ivJA+AbzmX+mSC9xEESjEAGL0D/Jg/8bAd8bbS OcS/nxeiKPo2gEesPc+QYR2QCYAMG40eAK+jlB5HbPlHWCN9TuxGaz8l0k+D8H0JO02C3wixkOb4 4VuXnL9ZQdCsGNB5BfgDjDqxNkUwW/UKfBPZKoIMG4hMAGTYKBymlN4J4GrEgyLfjW8eji5+R/d+ pDkG6kkzyXp8V9LNPADpewBc8vnsP2DyDljFgINXgB9zr0Ae8e/0R1EU/U8AT1v6miFD6sgEQIb1 BAVwa9XNvxvxALiMeG5UtvZbQfo+Vn4S634jPQBbHc16AFzy+Ow3oPMOpCEGRK9AsdrWeBRF/wbg u8hWEGRYJ2QCIMN6oAfAHZTSWxAPeBHirXj53L6Pi78Z0t8ows+IPjma8QDY8rgKgjTEgMkr0IH4 PxIAWIqi6ASy6YEM64BMAGRoJbYHQXAPY+x6xINbCTHxL1Svu1r760H6aSzJ2yii30iBsVFjSBLC N11vqRhw9Aq0IY6DyQOoEEIeD8Pw6wDOG/qWIUNiZAIgQyuwn1L6BgDXISYnZze/xtpPi/R9rPyN JvzL0WvQyvGmWUHg6h1IKgZcvQJ8eqCA2FvGAJyMougbAJ7XdT5DhiTIBECGNHGUUvomAAcRk/cy gBnEBK5y8yex9psh/WYIvxWEfDmSfFK0YixqZvMhF++ATQwk8QqIooA/oZDHCZyKouifATxp6HeG DM7IBECGNHCMUvrTiB/GU0Hs5p+Ffn6/GWt/vUh/qy/Ru1ywXksNWyEGmvEKyEKgE/HqAQrgfBRF XwXwQ0OfM2SwIhMAGZrB1VXi34eY1Dnxi8v4mnHz+1j7m4H0N4LoN4O42IhxpNk2WyUGkngFXKcH eMBgL9aEwNcAPG7ob4YMWmQCIEMSHKOUvhnJiV/l5k9i7buQ/lYl/M1A7Gljo2MAkpZ32Y3QVQyo vAKm6QFXIfAPyKYGMngiEwAZfLCfUvoziJ/GV0YczT8HNfGb5vddrf2kLv5WkP5W3rdfhs///nJ8 vkAz5WwbDtmmCLy8ApY4AVkInIqi6P9FFiyYwRGZAMjggt2U0rcAuAZra/hnkC7xt9La38jH6raC QLfS/zaN+0/rftN8jHErvAJJhQBfNcBjBJ6OougrAM5p+pghA4CtNZBkWH/0BkHwdsbYK6vnS4iJ Xwzu8yH+Ztz8W4H015vs5PY26v/Mmmg76WfWSpe/bxlbehrTA7IQYIiDA2vXqudcCKC6j8DfIXsK YQYNMgGQQYU8gDdW9+rPIV7ON4365XxpEX8Saz8t0t8owrf978R6k+xxn7RdHTZq2sSn/HoLAh8x 4OoVsAkBBrVHQCUE+PLBUvUJhN9A/CjtDBlqyARABhm3UUrvRjyvWAIwhZjkfYL7ZOJ3nd9PYu2v F+mnTfY6kk9r9zqfvtjQ7GfsGpNBHNpaD1GQxufajFdA9R3bPAJtQhmepx2xCOgCMF/dTOjbmn5l uAKRCYAMHGOU0v8EYA9i4p9DPNcPaKz+dSL+rUT6qv8TU1xLOn9sy7ORUwC6cxcxZ8tjEwYu39Nm EwMmIaC6JscJyEKACwDZG5BD7NHrq75fiqLob5AFCmZAJgAyrM3z34CYwOfR+EjeVhB/Eje/DyG3 OgagGbL3Gfzr8gRBkBsYGBgBQLq6ukYIIXkAaG9v381JgFLaEwTBoFwxpbSPUtqvvJsqoiiajaJo Sk4Pw7CWHkVRZXV19SVeZGFh4TQAzMzMnCuXy/y3YSN10/fvIgibFQVpxgC45jWliXEUpt+AKAQY 7B4BUQh0IBYClBDyWDU+IHvg0BWMTABcuSAAfpJS+h8QuwqXEM/zawP81oH4NzPp6wjfxSK3pRMA 6OjoKHR3d+8oFAq7KaUdnZ2d+ymlhSAIdhBCikEQbFN2jKz/35gx/ccWRdF0FEUzlUplnDG2sLq6 +lIYhkuLi4vnFhcXJ5eWlvjSURvxuwoD8XtIEh+yUWLANg2keudlbB4BUQjUYgcQewG6ED99sBRF 0X0A/hXmh2ZluEyRCYArE4eq7v7tMM/zt4L407b2WzkdIP8/VFaanF9F9rUyQRDQgYGBvV1dXSNt bW07c7ncUD6f353L5XYittC8CX29BICJ9H3KMMZKYRieq1QqFyqVymSpVHp5YWHh9NTU1EthGFbQ KA5MwqAVcSOtiq1QeS18PEQ+UwMBYPQIdCBeLdAJYDyKor8F8CNL/zNcZsgEwJWFziAI3skYuxEx ic8hdvcD9eTvSvzi8WYm/qRWvonwVel1ZN/X1zfc09Ozr6OjY29bW9toLpfbGQTBTsBO2hth1acN m2BQXQ/DcLxSqZyrVCrnFhcXX1xcXDw1NTV1AXryt4mFhmYd0ziatfRV9btMD7hMCcgBggx2j0Ae 9d6AdsTTAgEh5AdhGP4tYm9ghisAW3+UyeCKW6q7+HUhXXd/GsS/WUhfnsPXkbuch/T09Az19fUd 7OzsvKqtrW1/Pp/fSwgp6Ii8FVZ+mqLBxdpP4hFwKStfq3oMzqyurr64vLz87Ozs7HMzMzMX+WXU /9ZMQkHZnOVcRCvGS/n35x0XgkYhoFs62FFNFzcQAmLvQLH6Wqo+X+CE+y1k2KrIBMDlj0FK6bsQ P6K3BGCy+n4lE79u0HWahw2CINixY8fhrq6uQ+3t7Yfy+fwYpbRPRcBJiNtUxofkxbzNkLVLed11 33ZdhQFjbL5UKj2/urr6wsLCwtOXLl16RjF9oBIEaXikXC19U145v8uKDj6F4OsZkL0BOiHQgTg2 oB3A6SiKvgRg3ND/DFscmQC4vHFn9Wl9AeJ9+1UP7LkciD9N0m84D4Igv3379sPFYvFIZ2fn0Xw+ fxhArhnidim72acBfEhfYdU31YZ8jTEWlcvlH62urj6zsLDwzPj4+MlyuVyCWhC4eAeamZ5SwRak KOcTz2XPlJxXFga6jYVM0wLytsI9AMLq3gH3WfqcYYtic48wGZJiB6X0lwAcALCC2OqvwM3q32ji 30jS58dkaGhopL+//5UdHR1H8/n8UUJImyvhi+m6Y1N517ptIIQktvxdSNy3Dt9zn77J6VVB8NTK ysrTMzMzj42Pj7/AL0EvCHS/ZdfphGZiAGxQead0U1YmIcAQCwGdN4C/t2MtSPBcFEV/BeDlBP3O sImRCYDLDz9JKX0T4j/5PNb2Aa+gOXd/M8v51pP4baSveicdHR1d27Ztu7q7u/vG9vb2a2WXvg/Z +5bzOWeMtcQzkHTOPwmJS0Tt3YbrdTE9iqLFUqn05Nzc3PcnJyefWFpa4sGv4m/c5B1wEQccRJOu yudSl0tZMU1856SfZFogh1gA9CH2BvwvAP+k6U+GLYhMAFw+GKSUvhvAVYit/glo9u5vobu/VcTf EtLv6enZtn379uOdnZ3X5vP5qwkh1EbeJpK3ufFdPQMqJMnjY7GnNVevIvc0RUEzwYlieqlUenp5 efnxqamp709NTZ3nWRQvSNegeOdQraW3fXEsYR5bQKB87jMtoHq2QA/iqYFzURR9EVlswGWBTABc HriNUvo2xOo9idW/1Ynf2b0/MDCwe3Bw8HihULgxl8vt9SV8HdmbBAF3xfsIBPHcpSwnN1W+NISA Dwn7ELhrHEGSOkzXxbQwDM8tLS09ODk5+f3JyckzUAsBedqAQ/VUS5sl7zKF4DrNYPMQmKYFWPWc i4A8oN07gHsDegFUoij6KoB/17SdYYsgEwBbG8XqXP91iJ/0NQHNXL+j1b8ViF9l7RtJv6+vb+f2 7dtvKxQKNwVBsNuFdF0J35ZPd00+dnHti4JA13/T9bSFgJzmap0nsfDT8hA4iIHxxcXF+ycmJk5M T0+fhV4M2LwEYpr47hIn4DIuy9MMNo+AnE6FNNkbIAoBeSfBdqx5A56regMWHPqbYRMiEwBbF9dU yb8L8UN7ZoBahH9aQX6bkfh1Lv6642Kx2D88PHxroVA4ns/nD/iSvipPmqJAVc43L5DM8k87At90 7hHFbz32LevTviqtUqmcXVpaeuDChQvfXlhYmITdKyD/X1T/JQ6XOAHVj0FVj+rcJJRdpgVyABAE QTsAMMZkbwDfTngpiqK/A/C45V4ybEJkAmDrgVYf3nM7YjKfQbyxj6/Vv17u/maI38fap/l8vn3X rl039vT0vKatre1aV9K3zeubCN/HA6DLl1aAn4nsXAWCirib8RyoLH5b267HpjZN6S59kdNLpdLT 8/Pz3z537tyD5XKZ75QnBxAC8X/M5BWQz9MYg1UigGnSVe9UyKP0BgRB0C6JACDeN2AA8S6CD4Rh +P9gbYzJsAWQCYCthW2U0vcC2I040G8Kjbv5bRarv5nrNuul7njbtm1jQ0NDr+vs7LxF3H3PRvo2 QvclfFfPQMPNGkhfJDM5psAHqukDE6KoMZ7NlcxlIWMj2GYCCn2mJFynKixtrCwvL39/enr62xcu XHgK8e+TT5/pvAKq6QIozm0xAL7jtc+0gMkbUBMBAMAYE7cTFncRvBBF0V8C4Ls0ZtjkyATA1sFN lNJ3Iv7jzSPex78VVv9WIH6az+c7R0ZGbuvu7r5DDObzIX2Tle/jIVC9q/ogHnOSFEnVJARkAned 29fV7UqCrla0SjDI+U1E34xg8BEmrn3SXZPiBS7Mz8/fd+HChe9WlxVyMQA0igJZWMteAfHdNi77 CgWZ8JkiTTUtIG8pbPIGFAH0Iw4Q/AqAByz3kGETIBMAmx+5IAjewRi7DfpAP1+rP4m7fz2I3+Tm 59b+vqGhoTsLhcKrAXT4uu9t19KKAxCPRbI3gVJay2+Drj5XkrXlteVzJWFVOZmAZZFi+6xc2nad YkhDDDDGSisrK9+bmJj410uXLj0LveUvBtoCjf9Fk0egrmnLdVN5l2kBKuXh0wEUjd6ANjQGCHaQ tQcLlZFh0yITAJsbg5TS9yN2+S8jdvkz6AP9fK3+NNz9Lj5lXR4T8ddZIiMjI6/q7++/J5/PH7bN yetEgc4L4BoH4DKXLxILY6xG6i7QeQBU5GOzmJPO2ycN/POJGbARtvwZ6qZsXOrz8Sa4TBHYPuty ufz8zMzMP505c+Z+NIpv1Yob1fSAeEwUaTJ8xnHTtIAcOyD+BwMpLV8VAUzwBvAthbsQ7yL4chRF /xeASx79y7COyATA5sUrqlH+7Vh7bK+ryz+p1b9e7n4d8dcd5/P5jj179tzW29t7dxAEO5OQtA/p mzwAOsvfRBom0moGKmtevGY6V9XhOjeuq99XgPhML4hTC6KnQPVbsAkSW3vNegWk6YHx+fn5fzpz 5sy3q0GDshhXTQ3IQkD8z7pa+z7eAU74ch0qbwBPC4S02koBSQQA8TLBAQArURT9PYDHLP3JsAHI BMDmxM9QSu9CTOrjSO7yT2r1byTx00Kh0L179+6f7O7ufj0hpMdm0YvXkpK+6zy/bq5bR8itEABi 3c248XXpSYLkfKcjXPtpmlpQTR2oPhOXKYIkgsGUztOiKFpYWlr65rlz576+sLAwVb2sig+Qpwls HgE4Xjflt3kD5DyiCODv8nJB8cFC7Yg3DuqIoug7AP5B0ZcMG4hMAGwudFSj/K9GvLRvAq13+afp 7m+K+Pv6+nbu3Lnz7s7Ozp+glLYBzVn7tmNbfIBIJlEU1VnNrsTeagHAkeZ8vqk+VR6TByFpPIGu DVs+Dkpp3XfoM11h8wQkFFOV5eXlExcvXvxHYbfBSHq3eQTEaz7z/7Klr8urKlP3HxWuyVMCuSAI OoCaCADWpgS6EQcJvhhF0X9HvIIpwyZAJgA2D3ZSSj8IYBDxzloz1fQ68ndw+auIH2gcTAD14KJD EmHgRPxDQ0OjO3bseGtHR8dNzVr7JpJ3zcetfHFAT0rkLuXkPD7z96r60yJil77IHpFWTAe4iADd NdVvRM6rW/Ko679rfIEurVQqPXbp0qW/u3jx4nNQCwCVENAFCyaZ/3e5JosB+V30BtQ9TyAIgg5J BOQQ7xnQD2AqiqK/AHDBo98ZWoRMAGwOvIJS+i7Ef5YZxDv7+bj8N5vV70T8AwMDI7t27fqZ9vb2 4zbid7X2k5A+RxRFiKJIe73hJqXrrZrvt8E1HkCVljSPmJ5UXJjy2KYVxGu6aRm5nCgIuIfA14vh Eydgq2t1dfXRixcv/o/x8fFTUAsB12BBokgTYZsWkAWFyiPA/8tyTIDoDdDtIMhXCfC4gEoURX+L LC5gw5EJgI3HGyilPwW3+f4kgX5Jrf5miF9Oa3D179q16y2dnZ0/4Ur84juPrPclf/mcMVZz7XPY ovZVUxI2uORztfpV+Wz1+7rPVWm+dbRKBOjq9XXrM8ZqIoC/27wZSYWAra6VlZUHX3755S9PTk6e Rr2gd50a4Pl9pgV88qm8AeKzBMS0mjdAmBKQlwr2AmivPl74nx37lKEFyATAxoEGQfBLjLGbYZjv T+jyb6XV7+vu54xK+/r6duzcufMt1Tl+CrgRfxpp/Fwm/SSWvi09aT4RNrIUrddm6kyTxH2I2KWP rh6GZqx3fi7GDKg8A6p6fWMEbPeysrJy4sKFC1+empriDyEybSqk2lOAQ/eDY4prJu+Bzhsg/rdl z0CdCABqUwLixkE8LqCLEPJUGIZfQrZfwIYgEwAbgwKl9EMArkK8vG8advJPy+XfKqtfS/zFYnFw ZGTkLYVC4XZCSA5YP+Lnlh1/BUEAuX0VmhEGrnlNROETF9CsEEjDG2Crz5Ug+XVX0te1YeoToJ82 CMMQlFIEQVDzBpmmGHR99f2+hHuIVlZWvnv+/Pm/n5mZuYh6stfFCqj+30Q6lyH/b3VQTd+Jbai2 EFY+VEghAoqIhcD5anDgvKEfGVqATACsP3ZWyX8A8fp+eUtfn/n+9XL5+xB/zeWfz+cL+/fv/+li sfhGXVR/EkLXxQZwK45DnNMX61FBle5C8Gl7AUTPhC2Pa7prXh9vgK8I8C1vC8zzqdfnXuU6KaV1 v6sk3gjX70sqEy0tLd136tSp/7GysrKARiEA1I8F4n9fPFb9kHTXdD86gnqhYJsS4CKAoV4EqKYE ugH0AZirioCXNX3I0AJkAmB9cRWl9AOII2JtwX4+8/02q191bks3XVMNHOKL7t+//7V9fX0/GwRB H9A64tdZ+0wI+BLbVR3rIOdJKhJ4Pl9L3VamFUKgFSJAZxHb+u/SnqtQMLXj2l/uGdDVmVT0mPJF UbQwOzv7t6dPn74vDMMyGqcBAPtzB2xQEbqqvMuUAKRjl7iATsQGUan6MKHnHPudoUlkAmD98EpK 6S8j/synEa+F9SX/9XT5J3L379ix46rh4eH35HK5/SoCTov4VdY+d9/yOsT3uptwdO2n6QEw5dUR Q7PTAK5CoJXeAJEIm7XOVefNPITIlE83xcDjBcQpApsXIA0hEIbhufHx8S+eO3fuMdR7AkzTAvLY 4OLqt+X1mRIwiQAmiYAOxEugEUXRlwE8bOhrhpSQCYD1wR2U0rdiLdI/RHrz/SZLPy2rX+cqrP3B e3p6to2MjLyjo6PjVplAZeLmEAOveD6R2HXiQIzaDsOwZu3L5K+Di2XvUk+r8okDv2/sQJpCIA0R IFvCSWIMfAnW1neXfLo6xTYJIQiCAEEQWPO73JdLvtXV1e+fPXv2r2ZmZi5ALQB03gAIx/KPSsyj 8wZASmeA1hugiwtgkKYEWH1cgLhC4F8B/E9N+xlSQiYAWowgCN7GGLsTscU/gfgPmoT8N5PVL87z d+zbt++e7u7un5Ln+VVEzs9lovcl/kqlUpde66wDyfo8oMclr48XIG34TAO4CIE0RYAvudquyWk+ hG1CM1MOPE8ul1P+VlR1u4gTS18qi4uL3zh16tTfV+MDRCFgevAQYP7/c7RqSkAVHCiLgDasrRB4 MAzDLzv0N0NCZAKgdSBBELybMXYj4mV+k0DiSP9Wk78r8QOC1T8yMnLD0NDQuyilg67ufhXRi5a7 rgyAGvHL9TR03MHt7zo1kPY0QFLogtA41ksIJCV92zWe5kOISQhbB9epBJung3sExN+Ey9SCDqZ7 jKJoZmpq6i9Pnz79HTSKANV0gGocsbn6k04JmIIDgcZNg9qq98d3DuwG0E0IeTIMw7+S+p4hJWQC oDXIVR/jew3ibX35Q0A4+a/3fH+qVn+xWBzYu3fvL6u27jXN6euI3hYHEIYhwjDWRjwq2wSXYD9Z sNjqsdW3HtCRiogk8+w6rLcIsJG1jYx9PQsubfsQttgnWQi4fA5Jv9NSqfTY2bNnvzA9Pf0y4v9s iHrSN60WAJqfEhCvq6YLVXEBBGtxAfzRwgDQJoiALgC9hJDnwzD8c6yNlRlSQiYA0kcbpfTXABxA vMRvBukF+5nIPg3yN1n9BADZv3//6/r7+3+eUloAGsm2mZdcR6VSqQ3MsufABBO524jfJwCwGdgs els5jlYLAV8R4DvH7zKf79Mf3/bldBcR4VPeJWAwjdgAACszMzN/+/zzz38NawJA9AS4xAbooBIB OsPBFBfAUC8CxOBAlQgA1pYJnoui6L8BKFn6msEDmQBIFwVK6UcB7IF9jX9a5O9r3evSxT+2qNIJ qtv3jo6O/ko+n7/axd0vB/jZzsVjHtwn5qvrqMX1r7pu8hq4eAPShq49F0HgU7YZQnTJL7mkneqw kaCPS9ylPlOdLt4K2zy+Lr8IQgjy+bzRI+DyGdjuv1KpPHfu3Ln/NjExcQrqaQHV0kEI77bAPzjk U4kAwL5CgIsAhnoRUES8TPBCda+ABU3bGTyRCYD00EMpvRfANsTEPw8z+bdyvj81qz8IgtzY2Ng9 3d3dP6MK8jNZ8L7WfxiGtTX8uh37fOb3m/EE2NpIgiRWvy6vr4DwcdvkmyvBAAAgAElEQVT7lhfJ y5W8be27ignduc/9uRCv/IRIn6kNsY4gCJRCQFc+4fdZmZ+f//+ef/75vwvDcBVr44opRqBWFeyB f6pjFXRiwLRpkM4T0IVYBExEUfR/IB5jMzSJTACkg94q+Q8BmEWsUOvIfx2D/ZJa/fJcP922bdu+ Xbt2fSCXy+21Wf02L4ApX6VSQRiGdXECKovdRv424nf1JKjgKwB88/sSsK2N9fAGiOSVxIJ3tahd 8rsIiCReAF19pnt2aYdS2iAEkogKU5kwDM+//PLL//Xll19+CmZvgDz22B4upJsSUOU3iQDxWAwO zANrwYGCCOBPE5yuioAZZGgKmQBoHn2U0o8jfta1cne/TU7+4nHN6j9w4MBPF4vFt8kP7TFZ/WKQ n+i6V7n/ATQE99U6oxAbDZ3XEL/pugquRJ12Pht83ODNCoGkIiAJCZryufTD5GnQ9culPpc0H0+D K2GLQsDkDfD5PcjnCwsLX3nuuef+7zAMS2jcO0DlFYDw7jIlYPMKqIIDAfMKAVkEyI8Uno2i6AtY C7DOkACZAGgOg1XLvw/pkr8v8Zuu6Vx4Kquf9PX1DY+MjLy/ra3tqK/VbxMC/DwMQ5TL8UpIeY5f 1V5d5y3EL0I375+UpF2nDVR5fNz+rmWbEQLNiAAd8bvWkdSyd+2zi0jw6aOtPlW6y6oCMS2XyyGX y2nz6dqx1ctRqVROvfTSS/979UmDkfQSxyDVvgG6KQH5B6cTAmIdshjQiQCKNRHQAbUImK+KgAlk SITAniWDBoNVy78X8da+S1hb5hfBTv5MOOdIQv4+okD1x6u9j46O3rp79+7fyOfzu2QLny+/k936 4rl4nUc/i9cYYyiXyzWrX14vLROYTOAqMaDzDujEg48lr5uycC2fVn22+7S1reuPzzlQTyguQkx3 fz4eGdFF7pJX10dVmq8oa+WUEY9/kf9Tcn0+n6mYRint6+vre11HR8f8zMzMC2gkdjnwF8K57YPS TQm45pPL8DYZgIAxVqGUkioixGNpGfESwesYY08CWLb0MYMCmQBIhj4D+QNq8pddbUDryN/lz1cj /3w+33X06NEP9Pb2vp1Smle592XSF9fj64QBL88Yq83z8zTVhkAcKq+AC5nbPBYmuOb1IW3XfL59 dE2X++H6eYnnJpJMSwQk9cio0IynRYRJeMj5XD8j1bmczpe+yv8nOa/r70D6LwednZ2vGhwcHFtY WHiyXC6XUE/4Ole9yxckkraprKouVfyAOBVREwEAqEIEXMMYO4lMBHgjEwD+6K2Sfx/igD9X8gc2 hvz5n1rl8qfDw8NHx8bGfqutre2ITPwuVj9f4yy/+HVO/IyxurK8DZkIfK1+0yCpKq+CLwGZRAZ/ 8fv1hasI8SEGU//5uc417iJK5OMkIimpIBDzqj5zHVEmhVzWRv6+wZu8Tv6fUXkDbPXY8uZyuV2D g4O3BUFwfn5+/qLcvPAu/hl14kDMr7Lw5WN5rFN5Ani6OFZSQQQEVRHAt1XvI4QcZYw9hXjL9QyO yASAH3oopR9D/NSqWazN+SclfzngxnSMBOnin0t0+dMgCPIHDx58++Dg4PuCICjK5C+TjEzuMtHL 18IwRKlUaqivrnMK4pRhIwbTaoE0yF/un8ky0/XB5T5tbfv037V+k7u8WUJ2LW8TAS5CRP6sXb0A Pt+hrR4ddH1x+b3zKTOgfrpMJUBd6pfKdRaLxdt6e3sL09PTTzLGIjR6A5iUVuua8qbWysnHLl+I 2J6qLdkTwEUAf7BaPyHkGGPshwBWkcEJ6fneLn8UKKW/gXidvxjwt9nJnx/XXsVicWD//v0fSSPQ T2WhqJb1yYORy2N7TddNA1wzA3baFqNreVfSMgX+uUa0m64nXYrmEg3vE3AH6B+8Y6tD1X7SFQCu Uf6moD/fFRFyGmPxvhhtbW3G7ztJ0CUAVCqVF06dOvVHs7Ozl9AYHMikY9W4JUO03nWeADFNThcD AYlwLK4O6ED8/ADG4mWCnYgNs+nqjoHZZkEOyASAG9qqbv/dcF/nnzb5NzvfTwDQ7du3H9q9e/ev B0HQD+gtVcBtHb9I5GEYolKp1FyXcv1iO7XOOVhhOvEg5hHfTXW5pqcpBGRr1gZbIJutLp+Ifpf8 LiSuy6dbMZCkrE/7qjqT1KXLo9tnIK3ofV37uVwO+Xy+Ib+pPt01SWwtXLp06b+cO3fuUcTjFB/D 5OWBpqcL2owQOY2XkT0PgFkE1J4kiPp9ArgIuBRF0X9Ftm2wFdkUgB05SulHAIwhtvxbSf5pWP1c fctR/sHY2Njrd+zY8RFKaReQHvmL0f1iOof8EKC6DhsEgHxNty2wi1vdpZztfpuBT53idV0sga28 a17VdYvr2FiPeOwTkKcra+qLD5IKOt/2VJ+lq2Uul1Fd5yJbDMJ17aPle23r6uq6rbu7m01OTp7k ydBPCbh4K3k5+ViXX9WWOC0gCpFaTACJbyRAPP5WAGwjhBxijP0A2VMEjcgEgBmEUvoBAEcRk3/D 9r6bjPw56tRzPp/vPHLkyPu6u7vfTAih4iClI3bT/L54XqlU6qx+1SCjC2QyWe6q/QPksq7EJLfl QrytgInIbWTuKwRMn7dL/5oRATJ5+3xPgLunRNW26Xw94XvPPvXyVTVAo1D36Zein6S9vf3awcHB /TMzM4+EYSg/fU8mfjHd2CzqydtUThYBQKPwMImAEuJxeBuldB9j7FFNnzMgEwBGBEHwbgCvRLzv 9CzSJX8XBZ2E/GvufgC0p6dn+6FDh36rvb39OpVFbVvCpxMCURRhdXW1Lrpfhm0pk+44Cdm7WKau BJz2gO0zOJsI3VbWJb3VIkAWKj4iQCXSklrurlDVZYqzcK1LF/3vK6R0/x3GGKIoQqVSafjP+kJu I5fL7R4aGjpeLpefWF5eXoCe+OuqUaTJBK7KK5dTjY8q74MoAspVEQCsiQAGYJhSOswYe8LS9ysW mQDQIAiCn2WMvRqxy38aW4v8CQC6e/fu60ZGRn4rl8ttlwdV1fa8to18+CBTqVRQKpUayFoWF2K6 jhTkYx3pmAhB1b4qzdaWqR5XiHWnVY9vGVW66dyU31UEpLX+3tQfl89jPbwArkskdf2Qj31FiHxN 3FjLVq+p39L/t7uvr++1+Xz+/Ozs7DllgWox6dh3OsAlr1g3H9/EsVXnCQCAPZTSHsbY05b2rkhk AkCNOwghb0Ic6c/3mo6whcj/4MGDbx4YGHgff7KWivxE8pfTZeLnVkepVKptVKIif5sFbyJ608Do O/i7tGGrwwfNEn6adetEgKv1KV83Wfviu628jxfA9dgVrqRtmpd3Af+f+ML1t8nzqFYhhGFo3V3T 1p6Uluvq6rq1p6enfXJy8gnUjzG1ItV3bpXL1xuaEPKr0nVp8vgpiw2VCOC7r+5jjFUAnDH064pE JgAa8UpK6c8j3lBisprGl/uVAYAxxtee8h8Yw/qSv+gKa1jff/To0V8tFov3VNfLNpCvzq0vnsvp YRhidXW1rp5aZwwWmo/VrbPyXax/Uxumul365opWCQCxfhMZuwgmH1FlIhIXkktbBLi27fs9pJ3f d9WFXLdLf3SfS7lcVopzH2+AnNbW1nZkcHBw78zMzMMhdzc0jmXimAQ0Erou1snkFXCZDqDCdUop DQCEwj2HiHcPPMwYmwIgb3x0RSMTAPU4QCl9H2ICn0D8w6oj/6r177K3f1rkr/vDcPIH1oL9CkeP Hv1YR0fHcZWVL0cOi9a6KAx4fn5cKpVqA4tYlh/XdU5BMC7kL9eruqaDK/En8QiY7kV1by55moVu 0Fa5jV0GeB9CU1nSrRY+YjsuSyRd6jFdc/mufMSTS7siTN4Kl6kB/pTNXC7nLbh0ablcbs/AwMA1 CwsLDwpbCEN411n/toh/+diWl5/LqwQiAIwxFlFKc4jHZyKIgBwh5GrG2ClkjxGuIRMAa9hBKf0o 4jWmfM5/s5I/IFn+1WC/T+fz+UMyIcnz/TxNt5c/396XMYaVlZW6df08vw/h2qxvsV5VfaaBy0T+ cj9U/TQhKXG7EkwzxOl7XzJxqsomterlY1v+pOXSWFbokl9Ms/XVlOYqwGxwFSPSun5UKpXaf9lW l+k/xBEEwdDAwMDx1dXVH6ysrCxquuPi2pev+U4HyG1xY4gBgEEEFEi8ZfCziKd3r3hkAiBGobrR TxEx+XOi57v8RZuM/InwokNDQ6P79u37TC6X22GyRoFGstft87+6uorV1dVaWq1hoo74VwkO+Zru WFWnakmhWE4nKmyiwHUwbdaqdS3fbHsuA7epP76kb7qWtghQ9dPlXk19MIlRU1mXz8CXXFX5dRa+ 7+fGBQHfSlh81LDr96k5L/b29r6GEPKjhYUF/hjepCsEfKYDxHJiHtEToBIBAYCIxNsGlwH0EEKO MMYew9r4fsUiEwBrG/3sRuwaWoZ6i1++CoDP94sbTJjW+cOQ5ppXS/67du36sT179vwmpbQbaLQ+ ZPKX02XyB4Dl5eWGJ5JxmLb2tQ1SJiIwiQEZJvLXHbsSvwtMn6FKgLmiWSFgOndJa5bo0wZvR7cH gmt5VTonSJf8vA+ueXz6k/S+5HKm/vEpAd3zBGx9Upy3FYvFV7e1tb08Ozt7lifbug3/6QCR4FXX +bnoSeCe0YgxxqpjSQ71IqCfEHKgukfAFb1R0BUvAIIg+EUA16Fxi98IjeQvbo8JrIkBESqLvyXk PzY29vqhoaEPUUrzgJ78OanK5/KLMYbl5WWIdckxArWOKESB2LacR0XIunxJyFpnYdkGOp88SQja JBCa6ZeunOncJS2JCHApbxJ/pnK2FQa2PtvypSVmXMSEaYVBEtGoEjFiHXLshmpKwFS35TwoFAq3 FIvFcGpqyrbEzmXuRuclIIrrBPr8tYBANIoASgipIB6zt1NKt7P44UFXLK50AfAGQsgdiOeDZqBf 6y/vjQ00kr/s0mol+QeHDh362d7e3nfqIv1NAkAV7Fcul2tR/mJ9Yh7dNZ900zUX60S8R/lYl8dW l65sWuTQTBu+/ZDzpy0CXMqkSarN1msTNC5TIK3c40AH+XtM4l1QlSmXyyCE1O0Z4Fqnqo329vbr +vv7+8fHxx8Rm5arQqMl39BdRRn5WEf6cj5RBASMsbA65lAAhBDCgxh3V58j8IKhX5c1rmQB8ApK 6c8hXu7ns9afE/16kz+tvoLDhw//Qnd390/JhKkjf5UYANaIfWVlBWure/T16a6b0lWDiIsF6ELq OkvGVUjI9aZJ+mK9Pu2b8vi2bSqbVAQ08/n4egFMn4nL78VWzsW74JLHBWlsb6z7zmzTE3J6GIaI oqguLsCnP3J9+Xz+qoGBgR1TU1MPsbUb5aQP6VwsrPpQVMQvH4tl5XRuJImxWbU9ArA2lvIAwQOM sUkAlxR9uexxpQqAYUrpf0b8I5mEYrmftNZf3uhnI8ifAKDHjh371a6urtfLpKGy9FWWv7jTHxDP 9/OH+NQaVHgJxDY4dBsBmchfVdaWV3WuC0T0JYZmSF8nrtKoM42+JhEBLtd19bZKQMi/rTQscteN gZIIC1tZVbrrPdnK6n4jKhFQqVSQz+eb+k44crnc/v7+/j2Tk5MPMcb4+KgSAS5z7q6WvniuKiMa bYFheeARxtiPcAWuDLgSBUAnpfReAF2I3f5l2Jf7cdJ3JX8dEpN/EAS5Y8eO/efOzs6fUFneIqmL ZA80Rv4TEm/sw5f4yQOsrn4VVCQoXlMd+1yT08T7NJVxsahdCEvMq7pP3b3bytlg+8x19dv67pIm t2+792atW9fvQXVfPu0kRRptNSMKTXXZNhVS7Zsg7uBYKpWQy+WM3jRXIZPL5Ub7+/v3z8zMfF/Y MEgmfZUnQIZuTHTxCIieAT5+MsR7BDBJBHDDr5sQcrC6MkB+ANJljStOAFBK3w9gH9QR/y7L/cR3 Hfm7rgJwJf+2o0ePfrSjo+Mm3cDsssEPf1UqldoSP3kQluf7dVH/YlnbnL7qWDX4q87l+zSJA7lu FVwHNBfCTjqg+4gB2z2bnrynq8+W5krItk2BXInDBa6fVRpwIXHT52j7jalEUxKBkESUyP0Xdw80 xQV4iIDdAwMDR6anp09URYCK7G0WviqfSgSoynLiVy0PFDcK4ssDgXi8H6CUjlYfIXzF4EoTAG8h hBxH/HQ/8dG+qoh/cbmfOJ8ENP5YW0b++Xy+4+jRox9rb29/pTxIJNndb3V1FSsrKw0PDhHL6wjX ZB2K103HpuWCqkFGl9/UJx1s15O479OyLpP2fT3IVEVYqjxJ+mT77dj6lgTy/SQhXt1nYmrH5Zrc F5ddAXVlxGuyYJT7wPcLyOfzxvtxSQ+CYMfg4OAr5ubmTlT4c4vV8F0dwAlddV0lMpj0TrC2MoAg 5r+ArK0M2MEY6wTwnEO/LgtcSQLgFZTStyMO+puupqmC/lQR/0Aj+avm+tMm/8KRI0c+2dbWdo2K jGVytJH/ysoKyuWydj2wqg7xGkczy/58rGwbubuSho1gTZsOqeqR+60TTrr7TtpPl8/BBtW2vq7n SZCmcJGRdGfANPrgunogqUAziV5TOVMZlegQ0/h+AWmIAErpYH9///ULCwvfK5fLq1gb42TPqQ9M ywLlNF0wIl8ZIAYFBqiO74SQMcbYBK6QoMArRQAMUko/hPjLbgj600T8u6z1byn5Hzt27H/L5/OH XcjfNue/vLxce3a4joyBxkeKyse+y/5sAsFlQHGd87fVI8OF+Ju10JPWZRMCSdqX89k+QxeBZRJ9 rnAlO9fP2LdNHTEmQRrCRlWnqo9p9UPeQjgMQ7S1tTVdN6W0v7+//8b5+fl/L5fLK84dqnZLblZ6 Vx3rPiD5GsOaCIgzxPcUAcgTQg4xxk4iniK+rHElCIAcpfTXAPRDE/Snifh3We4nprukydCRf8eR I0c+qSN/m6UvEg1jDEtLS4iiSGm1yvXqrpmOXUg+KfHY+pAkTfz8VPCx2m3tNdNGq0SAqUwSEeDb hkt9pmtpkbVPm6r2ffqYNI8JvoLJNGUgpkVRhHK5jLa2Nq/vTpVGKe3p6+t7xdzc3L9XKpUy0OCq r3VDc1zXhPRugpyHW/tMeFHFygAeFLj/Stgp8LIXAEEQvBPANYjn/ZdgD/rzjfj3IX/dUpYa+VcD /j6mc/vLL5UngJ8zxrC4uFi7JtYhpslz3zpCV9Xjktd07FrOZCWqypsGriTXXJGUhJP2N0n7aVup rt/zevUpqeDYTJsCue4/IP4+dGVMuwWK5eS01dVV5PN5634btrSqJ+Da6enp71QDA8VM8phq+yGo LH2dMCBCmrw6QF4ZwIMC+bg/RCkdqHoCLltc7gLgZkLIPYjXd87CP+jPFvHvMxq4kH/u6NGjH1UF /KnIX7Rk5fMoirC4uKgso6qTn/N3lXtcvq5Kl9PEduR023lS8tfBpX8u0H0XaYgHX/JSlfEVAUm+ E1+4ltO1ldaGPLryzazD1+Uz/W55elqCwkXc+PSd98tlmaBLGqV0UFgdoAsM5MTs+sXK46icJo+5 8rm4XTA/pyTeKZACGGGMzQO44NifLYfLWQAMUUo/gJjQJ6tpzQT9QXMuw+YR0JL/kSNHPiQv9QPM hKMSA2EYYmlpyUjo4jV5sNIRkbyJkFiP7dgmEnRlkhKVDNP92JAmybtA147P/aUtApLWZavHl1B1 pNnM92KK1PdJV1039dm1DhGmejjJq8qapi1s91MqlRAEgXaZoGudQRDs6O/vH5ucnLxf2CyooSjq o/dtEIlfNNRUNyVa/2KavFNggJgTAhLvD/A0Yu/xZYfLVQDwef9erO3xb5v3VwX9pR3xryR/APTo 0aO/Ytrkx/VVqVSwtLSk3L1PR8IqESDn0+3cpxMVcv26vKo6Te25nqvat/VfVW49CF8HXb99SLMV fUlarytx+uRrlliTLgdM87fhI/h092uKi3CNmeDpKrHAnyGg2z7YQwTs6u/vH52cnHyANd6M73SA WEaV31S+IShQs1NgNyFk7+UaD3BZCoAgCN4K4BVwm/c3Bf3xdPFdPnZNk8m/5nI6fPjwL/DtfQG1 de5K/ouLi3VKXbdkT75uWvpnEiVyXl05V/InpDFAz4XsfdJM9fkSrOmVBmyDdZI03XVXUZWkrqRI KgZc2291IJ5P3iS/V5f6fASw6XPkGwY1KwJyudxIX1/fzvHx8e+h3mpXuexVN6v60oj0LqeL5Yjw qrWtiAfg3uEhSmmxul3wZYXLUQBcQwh5O+IlHOIT/nTz/q5Bf2K6b5qK/Anip/q9vZkH+/BXuVyu uf11BKwiVjldJjAd0ZvSTdflYznNRv6qtCRkaLtPE1zzpiUIdOWTEH4zSErwzYiQVsNEkq1ox5Ru 29ZX9S5e93lioG5DIFVeWQQQovcEuCKXy+3r6+vrnZiYEJ8iKBKyDJtSk8dYVTmR9ImUxuMBoupU AH98cLl6bZQxdgnAhKUfWwqXmwAoUko/jPgLm8WahW+b928m6M+V/In0CsbGxl7f29v7zmbJf3V1 Ven21wkBOU1M14kE+dxG7qo2Vflt575lbWkqMk0y+Cct04wY8BEoPuV8Pm/ftn2vJ62nVZsWpSkM mumjS9yDrwiwtaP7LfD9RFxFgK7NfD5/sLu7uzI5OXkS9da5y5JAZVNoHLv5eCvnk0UCFwXiJkH8 CawRgE5CyFWMsccBlDz6tKlxWQkASumvAtiD2PLnlr7LvD+QPOjPBpUAoHv27HnV4ODgB6o/NC35 V+/LSP7Ly8tKV76N+OU0l8frulgiYj9MeWzHSchfl09XXzMDfLNl0xAePp+BT70u+ZoRFj7t+5CW SzmXtpolfl+B0urlhS7fhYsAEkUAYN462FY3ALS3t7+ivb395ZmZmTNY88LqrHnVOaCOA7CVE/Oa 4gEoiZcGlgF0U0qHqyLgssDlJABuJYTciXiP/wXUu/516/3Xa96/jvwHBwf37t69+xOU0jbAnfzl c9HyVxG+PK+vI37ToKd7FLCqjG6wcLUwfQWArT5dH3R1JUEaRNGslZ2mlboR9TeDpNvtutSbZj4b TPfgGvgn1mX6T9ueIWD7n/Fjl+cH6OoQUSgUbqSUPjM/P38RjR4AoNFahyKPKr/LD4NIL4bGeAD+ vAAGYCdjbAXAOYe6Nz0uFwEwWH3KXwj9Pv+69f6tnvfn7xQALRaLg2NjY5+hlPbIf1QdiavOS6VS bc5f9UwAfiynyec2S91Ur+5Y166uDVU9PiTkSvJpWHe678n2cqnXtx+28r5E7toHn3qSfNYu3xNj LLXlgDoiTBPN/AaS3JNrQKT4WdvKyN8rY6xhOiDhb4x2dXW9amVl5XsrKyvzhuIu5F9rypIuEr7s cZDjAQhiERAh9ghcdblsFXw5CABCKf0ggG2Iyb9uyd8Gz/vzYwqAdnR0dB08ePDTQRDs0BG16cl+ /CUG/InXgMZofrGOWocM5KTqk1ivmKbKJ/fHRAY28aArZ+qvrYxpC2BTGy5EbuunrQ5XseDTvq8I 8C3n099m7k2Ey1a8zdYtwuU7cxENLsJG9xtwTTPVm8ZUCU8TPS9yYGCS/wkhpL23t/eG+fn571Yf HsShWpJtu3GdB4GgsSw/l1cjUDTuD0BQXRpYfXTwo4q2thTS/wetP36SUvpmxEF/c6hf8lfWLPmT rX+VGBDfRSQhfxIEQe7YsWOfamtru1b+k+usRhP5q8rqovlVZKoSCjYSdiVp29ME5TRdH13KJimT lASbKbNnzx709PRg586dAIB9+/aBEIJCoYDh4eG6vG1tbdizZ09d2vnz57GyUv88lUuXLmFhYQEA 8Pzzz9fSpqencebMmVo+36f88eumcqanCprq0dWtu24ra0pz7R8/NvXN5TNzadfnMzT1W9eWzjMi X1OV9/m+oihqyNPV1YX29nZr/03XK5XKsydPnvzNUqm0hDWjjY/d8pStzSMgj8X8nVv+4jkV3lF9 zwHIBUHQAaC9WibPGCsC6Iui6LsAvmW8yU2OrS4AdlBKfxPxFzNeTZOtf3He38X138y8P1G8U8Qb /bynUCjcqSJR0wtYm/evVCqYn5/XkrcoAEwbAfFjVX65XjFNV5fquq4e+Zrctqpd3bW08/hcV+Ud GBjAyMgIRkdHMTw8jL1796Kvrw9DQ0POdaWJqakpzMzM4MUXX8SFCxdw5swZnD59GhMTE9Yd5WzH tmtiWlLSk8lMlV9FRM0KAJ86dHW51JOmABDzu5C2Lb9NZOjyF4tFZxGgu1YqlR544oknfh/15B9i bdxmWBvTAbMVLo7FMunL10URwAelALEI6ATQBiCPWAR0A2iPougLWOOeLYctLQAopZ8AsB/xF1AX 9W94xC//EcgbAEE4B9Q/KhfrX1aawVVXXfXm3t7e/2gj/+o9NRAtIQRhGGJ+fl5JxCqr3sWydw3w 09Wnyq8jbxMB24RFM+e2fpjymtDf34/Dhw/j0KFD2L9/P0ZHR1EsFp3KbjSWlpZw+vRpPP/883jm mWdw8uRJTE1N1a63gsBcLHVbGVt+TnBJBYB47CsAbH13TXdpz9XKl9uziQaTV8BWP7D2+Xd3d9ce J5xEAADA4uLil59++um/QDx+i54ALgJEj4BI7g3NQE328rto/QNrIiBXfUEUAYyxdgBDhJBLYRh+ wdD+psZWFgB3UkrfCnfXv26r3zTJn7/XflC7du26fnh4+BO0yrYm8udWuYr8uasXgNZyl8WDfN3W tghVHrk+uV7xuitR64SASx0+eVyI3ZRn+/btuO6663Ds2DEcPHgQ27dvt9a3lTAxMYFnnnkGzzzz DB5++GGcP38eQPoCQDxOQwDo8tn6pkr39T7Y+qFrw+ezcmnDVr+N5DlU3hTVsUv9PT09tdUBrp+/ jImJic+ePn36W2gcx0UvrjyGQ3FumgqQ81EhvU4ECAIAiEVAF4dPJ98AACAASURBVOKpgH8D8F3j zWxSbFUBMEgp/W3EX/RE9b2Vrn8f8geqP5y+vr4d+/fv/31KaVFniavm+UULnTGGubm5tYYUJM7h +lhf3V4BYhumqQMXa96WR3XsuwtgK8m/ra0N11xzDa699lrccMMNlx3h2zA+Po6HH34YP/jBD/DY Y4/V4g9cLVrT9SSELl9T5XchMFU5WxmTxS2Xd7HsbQLApc82a15Xl24aQO6b7XuWr4v1RlEEQgj6 +vpq25K73LPieumll176+Pj4+PNY8wCI8QCquAAd5DFaTJcFgmoqQIwHkKcC2qIo+u/YgrsEbkkB QCn9KIBDiD/wFbi7/tOa91eRPz+mAGg+n28/duzY7+Vyub0qy9b0EvPMzs4iiqKGJ9fJlrZtAyBV u3JdYn7T1IHu2OUpgaZraQsA14h/Xq5YLOKGG27ATTfdhOuuu67p7U4vF0RRhMcffxwPPPAATpw4 gdnZ2dq1JF4A1zI++U0W+3oJAJlcTW24EL6pTVNbST0bNpK3lRXLRVGEIAjQ19dX+x+6ihwRURRd ePrpp399eXl5DmvjOV+TL04JAOqxWwSfKpDHbFEEiEacKAZyiEkfkghoZ4wNEUIuhGH4f1pvaJNh KwqAWyilv4DY7T+LjXX9a380x44d+wB/uh9gdr+rdvGjlGJubq6245b8KE6TcNBF4evI3UTwrkJA 5743kbiP+19176o6bflkdHV14YYbbsDx48fxYz/2Y4mWCV5peOSRR3DixAncf//9mJ9fW7adtgDg x7b8aQYC+vZVrsvFA2A7NvXR1JYq3UWAuAou3XXVOX/lcjn09fXV/odJRECpVHr4iSee+B3EYzof 2+WgQNm4g+ZcHrNV5C+LAnEqIC8IAGDNC9AbRdE/AxCfbbDpsdUEQBel9DOIl2SMA4lc/zLZJyV/ QP2DCcbGxl7f39//Lhfy13kBFhcXsbq6WssnCgAd2au8AXIZn8cEi/nlMqo0U31yvbqyqnyqdFt+ m5i45ppr8LrXvQ4333xzZuknRBRFePDBB/H1r38djzzyiLMAEI99RYMrSTcrAPj9udTh0h9TPabP wlaHTRDp+qPrg22lgK5O2foXr7W3t6Onp0d7Py4iYGFh4a+feeaZL0E/FSDHA+gqla1//q6aGtBN BXARkMfaVEAvABJF0Z8hfgLtlsCW2ggoCIJ3AhhDvNd/GfoNf+QfhctWvzISkf/27dsP7dix48OE EKegP9VraWkJKysr1rX6KtKvdc5ikfsu+1O1YavHJgBcnxdguh+Xdvh5T08P3vCGN+CDH/wg7r77 boyOjmYWfxMghGDPnj24/fbb8frXvx4dHR24cOEClpeX6/K0Ai6ksVH1u3ie5PzNtOWbR3VvSQU3 r8v0nw/DEIyx2soAV7EvIp/PXx0EwfNzc3MX+G3IXYXbuM7zimV047puukDeIAgk3iWwh1Layxh7 2npDmwRbyQNwsDr3v4S1Hf8AtfW/Xq5/fkwB0EKh0Hf48OE/oJT2qwhLRdry+erqKubm5hAEgVIc 8Lp0darEgiqvyep3qY/DtumP7s/uQ+jNnh84cABvetObcMstt2SEvw64//778ZWvfAVPPfUUAD9L XXfd1eL1dbG7zGnb6rBdt3kSXL0hqmtJpwd8rruW4efyckxxeWBnZ6fy3lwEVxRFC6dPn/71qamp c1jzAvBlgqLRV6tWUY08htumBOSlgUH1lZdiAVD1AnRHUfQ3AF603tAmwFbxABBK6QcAFBDP/ase 8yvu9S++bE/5S0r+NTUIxDv9HT58+DdyudyIK1GLgX2UUpTLZczNzdXS5dgA3bHKM6BqX+6LmEc8 VlnmJuJMQuYmb0FaAuCVr3wl3v/+9+Pnfu7nMDo62jJrNEM9RkZGcNddd+GGG27A8vIyTp8+rc3r +52YvD2EuG3Jm7SdJGWSioZmy6ogfj62+3PxqtnqktNLpRJyuZxyys3Rk9HW3d197fT09DfDMOSB gCqXvjxWqz4oVTnRmytyiJhee0QwY4wpnhXQQQjZw7bINsFbRQDcRQj5ccTkvwz1Y35te/1DkybD 1/VPAdCDBw++rVAoOAX98WORVBljmJ2dbSBc04N+VMc28rYRb1Iydylj8zbY2nHpE6UUt99+O37t 134Nd999N7Zt24YMG4PBwUHceuutuOOOO1CpVHDq1Cll9HraSCr0dKSXtD4XgjbVnbRtV1Eh1u06 LeBC9iohxq+XSiW0t7c3rGoy1S2CUtrf3d1dnJiYeBjmOX/Z26vstvRuGucbuoL4scEBYt4RRcMA YywCcEZRblNhKwiAPkrpexCT+kw1rbYhhGavfybk4+eulr4pj0opBsPDw0cHBwffW1WDVstbRbRz c3N1itqUN800HSmr0lR/2KSWvK4PqnNd/fL5a17zGtx7772444476oKOMmwsisUibrzxRtxxxx1Y WlrCiy++6Gy9pk2ASeHrXfDJm8QaN13T9dVE8j5tJPXa8H6VSiV0dnZ6CQwR+Xz+UC6Xe2Fubu58 NUkUAUm+fHmMl4WBmE4g8ErVC8B3C6TV/lNCyF7G2A8R71C7abHpBUAQBL8IYAQx+Zue9Ce6/FWB fxy+rn8O+cfAn/BX3Ldv36fkzX4APZHLpLq4uIhSqeRk4QPqPQBciZgQ/TLBupuV6lmvAEBfi4gQ guPHj+PjH/847rrrLnR3d2vLZ9hYdHV14eabb8btt9+O5eVlvPDCC6m30ergwFbBJjB8RYAMV2+E bl5e5S2weRDEPHLeMAzR0dFhLGNCoVC4fnFx8d9WV1eXUO+uFyG671XpDU1Lx+K5LBL4VEAgBATy wO8IQJFSOsgYe9J6MxuIzS4ADhJC3ow48G8Ba/P8EeI5GHFdqMtjfpO6/mXLv7Y85NChQ+9ta2s7 qiJAHeGLr9XVVSwsLCgDAnkZn+18dSTJIbvedILBJEBUaaa8chmfh/+Y+nnw4EF86lOfwt13351Z /FsI3d3dOH78OG677Ta89NJLePnll5uu03VuO402XNCKfiTxBNjKJrknVy+fCZVKBYSQ2nbBviCE tPf09Oy9ePHit6APzgbM47/cWZVQEK9xNz9BfZ2B6AVAzEcUwDBj7BzWPNebDptZAPDAv27EH6Au 8I+v+Re/6Fa4/uVgkGDv3r2v7u3tfVsS8gfiP8Hs7CwopXWkyNf8q0hZPDftASBCJSrkazoPg+lP byqrgs47YBtQ5OtDQ0N473vfi/e85z3o7+/Xtpdhc6O3txd33nknxsbG8Nxzz9VtKuSDZufa02pD 1abNsm+2DVtZ+b/j81n5CA5TOzpxUiqVkM/nGzY5s7XNEQTBzmKxuDg1NfWjapKv8WdrxDYVQHkb QkAgRTwFwAB0kjgg8GHrzWwQNrMAuJUQcivsgX/i8o+0Xf+iq0j80mlPT8/2PXv2fIIQkleRlEz2 soXPGMPMzIyTFa/aD0B8t62nNxG2Trzoyprq1fVB15Yqv0kMtLW14a1vfSs+9rGPYWxsTNlGhq2H kZER3H333SgWizh58mRt90sRrbLsXepdr2mFtKP+Xcqo7t9G3rpr4jljTCkK5LSVlRV0dHRYHzKm Q3t7+ytKpdIDy8vLfH9q3XQAoHf7mzwD4lSAmJcf86kAWvUCVIT8DEAfY2wJwAVsQmxWAdBGKX0f 4g92AfVPgbIF/vkGhJiiR5Wu/yAIcocOHfpEEAQ7Xa1/2fXO9/g3eQtMxxy6NJ93VTu6NFM7ujT5 WpLja6+9Fp/+9Kdx/PhxpcWQYWuDUoqjR4/izjvvxPnz53H27Fnnsi4Waxpopn5b2VZY/679sPVN NFpsdcp5xXP5e+J7CDQZFEi7u7uvGR8f/1fGmKgc5Xl+eUxnmnxiHlkI8HdRFOgCAoOqF6CdELKb MfYDrHmrNw0260j6RkLINYitf93DfkyBfypSV6XL1+Vj/iXXbQl58ODBt5j2+QfUD+fh1xYXF7Gy stJwzVcAqB7/q/IguAgAW0CfjwBw9QCYxAs/LhQKeN/73od3v/vdWYDfFYBCoYDbb78dIyMjeOKJ J7C66hdE3QoRYPpNuyINL4Ltf9VMmybPm6kNHWQvgmrHQHGjoCiK0N7e7tUGB6W0r7e3t2t8fJwv DVR2CXqjUOcZ4O9EysOka6qAQAIAJA4I7GaMBQBOOd/UOmEzCoA+Sum7ERM+d+vUrH9N4B+Hisht PwgdRPLn73Tbtm37t2/f/kEibfXLj3Vkzgm2XC5jfn6+Lg1Qz7u7bAUs98H0ICBfQnf1POiEhKpu U1n5/JZbbsFv//Zv4+jRo8o6M1y+2LdvH974xjdienoazz//vHf5VgmBVrjhfer2EQHNCAO5rC3y 3+QlcEkrl8tNbRKUz+cPU0pPzs/P84hS0TCUrXwT4avOVUahKArkgEC+WyAfDAmJYwFOIjZoNw02 nQAIguBnAeyFftmfy45/unl+2y9f5foHquQfBEFw4MCBT1FKB0yWt0yc/MUYw9TUVN01OZ/u3JYu 12kqp5tvM9Xn6lFwGaBsMQsdHR348Ic/jHe+853apUIZLn+0tbXhlltuwVVXXYUf/OAHWFnxGztb NXfvIy5atSeBa3ozQsjVk6fLr/Mq8LFQ9gysrq6is7MzcTxAoVA4OjU1dV8YhiXoXfyqFQOqc9UK APFc9gLwVyjtEAgSTwUUKaVFxtgz1htZR2w2ATBMCPk5mJf9qXb8MwX++a4EUH3xFAC96qqrfrqz s/PVNstb9QJQe7yvSSyo6lK1oWpL7pPOkyAfi3lU5eQ2VWm6QUHMK/dVlf/YsWP4nd/5HVx99dXK ejJceRgZGcFrX/tanDlzBufPn7cXQGsD93xd67750yZtl7QkwYJyukjmKu+A6CXQtV8ul1EoFIx9 MfSxu7u7OzcxMaHbhpdo0mFIl4lfFAMq7zPfIbAWC4C1nQJ3McaeR8xtmwKbSgBQSn8BwA74L/uT A/985vzlumTXfwCA9vX17RweHv4IISRIYv2vrKxgaWnJOb+LNW4SEa5ppnOT1a9KMw1eto1/KKV4 xzvegQ9/+MPZXH+GBhQKBdxxxx0oFAp49NFHtVsKyw+nSRubYaOhJM8PsImAZrwaLmV144fsCQjD EISQ2pMDfdvJ5XKHoyh6aHFxcZp3F2teAFXAn2kFgHguu/vF66KhyFC/LJBgbVlggVLav5k2B9pM AmAvIeQtABarL+76B+qtf27xi8eqyP8kgX/y/E5ticfBgwfvzeVyw0nIPwxDzM7O1q7xdxevgXxd TLPFCOjSkjwK2Eb8clsq6Nrq7+/HZz7zGdx+++1NWT8ZLn8cO3YMx48fx0MPPYSFhTVDaj2IuZk2 fCz7Zh4Q5FtORcg62Lx8Lm3KaVywiXXz5wUk2R+AEEIKhcLhiYmJb1T34wcaRYDK4IPmvNZV4bro BRDTGeqXBeYRc2wk5NnOGDuNOMB9w7FpBEA18G8AceCf6OJXPeoXqCd+wN3ydw384wKA7N+//3XF YvE/2MhSJnd+PjU1pVwGI5bR7fwntyGXl+uxWequln0SASAfq+5BznPs2DH83u/9HkZGRpTlMmSQ MTAwgLvuugsvvPBC3ZTAZhePLuSd1BXvej1Jn2zt6AIEXYwB3fLA1dVVFAqFRN8ppbS/q6urMjk5 +RTqAwFdb1aeKtB1QjYYgfplgRGNB/MAa8sCOyml2xhjjzv2paXYLALgCCHkjYjnRpagt/5lq9/2 xTYb+EeKxeK23bt330sIaUti/c/Pz9ft86/Lp7OiXcjbdQmf606APkJB15YOYp577rkH9957L7q6 uoxlMmSQ0d7ejte+9rWIoghPPPFELb2VImCzCIwk/fApoxP0Lq5/kcRVeXQeB3EM4V6BKIqUQcAu 99LW1nZ0dXX1u8vLy+L2krqpAJ17H4o8sgdALCd7jgOFFwAABhljlwBMWW+kxdgUAqD6tL8exNa/ uOlPOYoivg+AatMfEaZpADmPDuIXSBC7/t+fz+fHbFa3ygNQLpdrj/h1Ka+7LtZZ11kHorZ5B1Rt +QgFXRsq8Hzt7e346Ec/ire85S3GrYMzZDCBEILrr78eBw8exAMPPFC3g+BmEwKulrZr3SJ5ul5L +pnY/tu+XglRJKimBDj4VsFJlgYSQoJisTh28eLF+2A2BHUB5HIDKsIX00VhUOMfwQvAtwgGYi/A jurmQBuKzSAAriaE3AVgHvVb/pYAyFv+mqx/29y/6gcgzs0A0oY/o6OjN/T29v6szUrWCQFxyZ/q us0LoGpPhC8p+1rxrgLAtKxPBKUU3d3d+PSnP40bb7xRmy9DBh+MjIzgpptuwokTJ7C8vFx3zcUr 5Qo5sr1VImM9PQ2qttbj2QW6vshTAqurq+jq6kr0mQRBsL1QKExOT0/zjSREDuHnxi4Jx6rVYSL5 q7wABGtbBPOVAPw++xljEwAmvW8sRWy4+UUpfSPiL0R8rCMAQDH3L6s13Rdq+mLlMrLrnwBAPp/v GBwcfI+qAhNB87SFhQWEYWh8SpnO1WZSzLo8pro5bC68JArfx2LZuXMnPvvZz+Kaa65xKpMhgysO HDiAP/3TP8X+/fsbrrUiqM63rC+BuQiMtAjYpx2fMUIet2wGjEz+fBqAB1D79hsAenp63l0sFvsg kTLUrny5QpORqfMqcG4Jq69yGIbLUp5VAFEQBLdYb6DF2GgBcDWAfYit/zLWNv4pGcqIUwSugR22 vA1xAPv3738T3/AH8PvhVyqVWoRyEveY7g/n05dmg4lE2AZQl7aOHDmCz372s9i5c6dzuxky+GD7 9u343Oc+V/Muib/NtK3VJPX5eg3WS5wAZgNEl9d1THQxbuTPRuz/4uIiSiU1Jdj6Siktjo6O/iJi b3fNu4tGS73WNMwEL0OOTTPtSbOK6rJ2Qsg8Y2wIwEGHNlqG9fM1KUAp/QSAUQDjkASAZP3L8/++ UwCq6QAxEIT/GAIAtFgsDh0+fPhPAHSYLH0xXdyXf3x8vLaeVS6jq8PlXEw35RH7pCpj2mlLdb9y 3ao0VdwAx0033YRPfvKTyrW9VxpOnz6NmZkZTE5O4uzZsyiVSlhZWamLZo+iCKdOnaorNzIyUjcX umPHDhQKBeRyOYyOjmJgYAB9fX3Yt2/fFR9XUalU8Ed/9Ee47777rALANAetu+brUdAtfTPlcyFw 3V4IpmumMnK/XI7FczmPrj5ZmKmEGu8nPw+CANu3b080ZcEYi1566aWPjI+PP4c1jqkg5gD+Li8n 5zBxJNG86raPR8wr+SAIOgC0A8gDaGOMDRBCJsMw/KLxBlqIxuiK9cMRxNb/HNTWv0qF6chfvi6n yceq+ZyaKty7d+9/QpX8XSDmW1hYQLlc1hJiEre/fE1Osy25kWGq07cuVd9F3HbbbfjYxz6mDOS5 nHHhwgW88MILeOmll2qviYmJujwuZMFx5syZunPT/vgDAwMYGRnB6Ogo9u7di7GxMezZsyfBXWxN 5HI5fOpTn0JHRwe+9rWvbYrNe1oB2Vvoek0FFy9eGp+jOB2gO+ZPSRXHpEqlgrm5OfT29nr3jRBC h4eHf3l8fPwzqLf+WfU8Es4buixcUw10utgylQpniJ8FwAAwQshc1QswBuAF7Q20EBs2KlNKfxLx ByXOjzAAzGHuH3IZ4Vh1XXUuW/8EABkeHj7a0dFxq87yNVnmYRhibs5/fwebSLDNndVuTLGmVpdP le6TZqqbp9155534yEc+ckVYpM8++yxOnjyJZ599Fs8++6z1d+BD/r4D79TUFCYnJ/Hoo4/WyheL RRw+fBiHDh3CoUOHcO2113rVudVAKcW9996L9vZ2fPnLXwaQ7px5q93zrm2o8qmI1SV/s7C1Jxo1 4jWR6HX1ALFxVSgUkM/nndoW0dbWdsPo6OjNZ86cOYG1ZXlcAHByF4leZ0zK0wUma6kuYD0MQ1b1 AvCyJcSxAMfDMLyiBMBexHMfC4g/BJe5f/5B6lw1cl7TdSK9UwAIgoDu2LHjXcoCDta6uNsfY8zo FgcaLXEXL4ALGds8BrbytjQXvOlNb8L73//+RGW3AmZmZvDEE0/gkUcewZNPPlm3K50NzQ64Di7P hrSFhQU8/PDDePjhh8EYQ6FQwLXXXotXvepVuP766zEwMNBUnzYrPvShD6GzsxN/+Zd/2UBAMpIE 9fl+l75tNCsWXESAryhwaU9Vv43g5XZV+aanp7F9+3Zt30wYHBz81XPnzj0chmGEWAQwrEXn8xf3 BtR1S5EmX5fPubhQeRZWeRohZIExNgxgD4CzvvfULDZkGSCl9B0AtqNx179QY/3rXP4Q0kxeAjmv yvqno6OjtxWLxdf7WP/8eGVlBQsLC3Vp4m6Ach2666p8ujSxjM+De+T88r3o6lDlVeW75557Lkvy n5ubw3e+8x38zd/8Df7iL/4CDz30EM6dO6cNUFLBl3xa5b4ul8s4d+4cvv/97+OrX/0qHn/8cSwu LmLbtm3o7OxsSZsbheuvvx6MMTz22GOpf57yVFzaSCrAfeu1ndvKi/CZRrR5LeVpyTAMQSlN9KwA Qkh3V1dXaXJy8knU84luO/m64ppj3TlPqzNGGWOs+rjgHNa8Dx3VJwWeNN5AC7ARAmAbIeStiJf9 8T3/+Q4eIWvc9U83728SBTCkc/B5fwqA5vP5wt69ez9BCOlUkZvteGJiwkqMsojQET4h7pv+6Ija 1GdbflM+3efCz++88058+MMfbiizVVGpVHD//ffjr//6r/GFL3wBjz76KMbHx73r8Q0c06WnbXHy 6xMTE3j00Ufx1a9+FT/84Q8BALt371bux74Vcf3112NpaQlPPpnec1hcvguV9Z1220l+WyqoPAPN 9k2uXz7WxQHo6iIk3hugWCwm6l97e/uR+fn5r5dKpdpcPOotfPm8rnnp3fbhilMLNb6pCoDa7oCE EMIY287iJwUued9UE1j3f3cQBG8DMIJG67+k2PVPZdWrlJrLFyFa/+IXQgCQgwcP/sf29vbrk1j/ s7OzKJVKDS5/2cKXrXTZGteRsHhs65eqfpPYUOXXtS3nl6+95jWvwb333tsyq2U9cfbsWfzDP/wD Pv/5z+O73/0uLl682JDHdp9JCKJZJJkekDE+Po4HH3wQ//iP/4iJiQkMDg6iv78/rS5uGG688UZM Tk7iRz/6kTVvGp+jCT4WctLraYlOG3SEbRo3xLl/Xbuy9S/mjaJI6aly+FxzXV1dhfHx8QehNiqJ lFZXveWa+BLT6vapqXoBgHovQIFSWmCM2X+cKWK9BUA3IeSdiCMhF1C/BEO0/mWLX17H70P4Yn7x i6lZ/8VicWjXrl2/hrWtGpXErSLSMAwxNTVlFQm6Y9UTAeU8Yn9s73KaSTjISCIA+PHNN9+MT37y k1veYnzqqafw53/+5/jiF7+IZ599FuVy2V4oIXwH6FbON6tQLpfx3HPP4etf/zqeeuop9Pf3Y3h4 uKk6Nxq33HILzp49ixdeaC7mKm3rOI3vW4ZvH01LBOX6dJ4NnRfBpS/ymKKaSuB1l8tldHR0JHpi YC6XO1Aul08sLS3Nwi1eTBYIEN6hOef5dV6AHNYEQEgIoYyxIcbYUzDHwqWK9R6tX08IOYy1pX8R 1Ov+kwb6uXyZdZY/AHLVVVf9Qj6fv8rHyubW/dTUVG3Nv+4l16M713kI5D7ZHv5Td8OGP6CrwLB5 AI4cOYLf/d3fVUbnbhWcOHECn//85/GVr3wFFy5csAqgZpDEqmuFN8FHgFy8eBHf+ta3cP/996Ot rQ1jY2NebW0mvPrVr8bJkydx9qx7zJXOQk0K1+C+ZvPorqvSffrUrAfDJhRcpk5KpRKKxaJTP6S6 SGdnZ/+lS5e+A71hmSQWQCzLr4uvWp0sfkYAL895uIvFN16/5reFWE8BEFBKf7F6vIT6Hf249W/b 91+GKl13Lis3AoD29PTs2LFjxwdQtf5NlrR8XiqV6h72w0lctu7luuQ6Xa16E2Gr8ujS5akKmxAw 1blr1y78wR/8wZZ9ot9DDz2EP/mTP8G//Mu/YHp6GoDfoOmDjZgSSLvumZkZfO9738N3vvMddHd3 Y+/evSn0bH1BCMEtt9yC+++/v/adN1OXL5KsNmgmT5q/52amDnzbM41PQByfk8vlEgUE5nK50SiK HlxcXORP5FN5mmvVac6JlJco0uRyvCz3AvB4AAKgjRAyxBh7DG5B7U1jPQXALYSQGxBv+8vn+sto fOIfYLbkXbwDMkQRUPfAnwMHDvxSPp8/YCNUmcwppZiYmKi5qWTyVxG2ypNgOjdZ/ap2VGTtIzB0 beoEQF9fH/7wD/8Q27Zta7i+2fHUU0/hj//4j/G1r32ttnxTjtnQwXcgcx3wmxlcfZZxpdGn+fl5 nDhxAidOnMDw8PCW2+K5ra0Nr371q/HNb34TS0vNxV0lJbY086ftpXKByUvm6ynQ1Wcrz70ASe6/ o6Oj/9KlS9+G2dA0/VFUwYKyy18k/TpPQDUWoFaeEMIAFBljSwAag45agHUTAJTSnwfQhbVH/tYC /RhjFdTvpyyrMVc1pHPh1FQXBPLv6+vbvW3btveRGHFGg6Uupi8sLNSePMbJXxcroKpPV7dOAOjE gG35n0o4JLH85eNcLoff//3f33Ku4EuXLuHP/uzP8KUvfUlp/W3EQAqkG5TV7HyyT97Z2Vl861vf wjPPPIMDBw4od2rbrCgUCrjxxhtx3333eS3lTAMb8TtLYqUnJXDTb5DnU0X9+/aNLwtsb2+35pcR BMGeKIoeWlxcnES9ANBZ8bK1L75DcU2Vnx9TxF5x0QsAAO2U0iHG2KPGzqeE9RIAhwghd2Ltkb98 619u/QON7heVO8YWCOg6908B0LGxsXfl8/l9NutfPmaMYXJyUptPR7RcKMhtmNqq3ZhhMyCb14HD NcbAJkAA4OMf/zh+/Md/HFsFpVIJX/7yl/G5z32uYVtd85Dd5AAAIABJREFUEb6DUrNIYwlXK6cN XNphjOHChQv4xje+gcXFRRw7dmzLbP3c39+PsbEx3HfffYnrkDe+cUWav7FWRvybxgHf8j75Xdst lUro6upKtONoZ2fn9osXL/4v1AsA1auhm9I70MhNKk+AyEUBY6wsewEYYz2MsUsAZrxvyBPrIgAo pW8DsA1r1n/tVbX+xYf+mOZiVHAJ/AOkR0EODAyMDg0N/UoS639ubg4rKyt1hM6vqebXbcRs8gLI eXTXdPWK77p71OX5/9l792jJiup+/FOn+3bf98yd9zAzMDAzgMIEMkjQ0aACKpBEIyaGQFYS8/iZ mLVgGYwGTMhDRTHBqCtGQKOCr0UkakyAAD4IRr8IykMEBgaRR4bHME/mztzbt7vP+f3RXX2rq+ux d5063Zd8v5+1enV31a5d+5xTp/ajXrb8N7/5zXjrW9+KFwsefPBBfPCDH8Sdd96JZrPpL4Bug6so FKH8Kd4/tV6ufGmaYtu2bbjtttuwdu1aHHbYYdbyCwnr1q1DlmVdWydTkfcZUtpYXnk47TjWagRT nS45bH2ab08BIVpnBzSbTYyOjrLqBIBSqbQ6y7J7p6enn8d8pNl0NoDN0/c5nbrnD3QbFkmSJEPo jgIMt5cEPuwUPgL6YQBMCCF+Da1x/4OY9/6BlgEgVwPYxvbVNDU64IPLCks2bNjwh+VyeZ3L+zcp yTRNO96/aczf5nX7ogCuen0ycQwAUxkbvYnu+OOPx3ve854Xxf7+s7Oz+NSnPoXPfvazOHDgAICw cGNsQ6Do8XkfbIakzMtb16FDh/Cd73wHTz/9NI477jgMDw/7Cw0YP//zP49t27axVgZwYVOu/Vje KUScw3wkL9NvG52rXgqNSmtbGliv1zE6Ohq0DHlkZGTVc8899030evzqcIBJJxnFdKSpeZ1l6KVS SS4JTAFkorUkcGmWZdtQ8JLAfhgArxPzS//kWH8TvZP/1LF/E1wRAV/r6Qq7LFu2bP3SpUt/D7B7 wDZlLjf9MdHYvqmrASi0pjI2ha7nqfx9BoApf8mSJfjwhz/8opjxv23bNrzvfe/r7GqnwtdpcTwV KvqxAiCv96/mxzBCHn/8cfzXf/0X1q9f/6KYJLh161bcdtttPQc5URRYCEJC8HloKEvr8vCxGTO2 eji0tnpVgyBN09AowMokSR46cODAM0qy7oz6Isy2/2q6mtfhl6ZpWiqVBLSNgdrXW+iSwKINAJEk yfloXdRBmMP/pk1+9Ml/1OEAnVZV/J3vo4466v8rl8trOJ420Gpg6pa/JiPAtasfRYGbaFXYjBMb H/3bVo+NTr2u97///Qt+2VeapviXf/kX/NM//VPnbAYTuOlFI68XGFP5c+t25R86dAjf/va3MTMz g5/7uZ9b0JGjSqWCLVu24KabbiIPFQFxvWtXHXnlcClc05p8Tt2++k08bHVSDHCT3HmiANVqdeVz zz13K7oj0ZwN6FyevylN6iN1YyB1SWA1SZLJ9pLAwlC0AXCCEOIVaO36R1365xv/19N9kzS6Jv4t WbLkiKVLl/6uaKFFSPD+hRDYt28f6vW60wBwRQVsv6kH8wDzBoapjOlaTNel8zLx0Mv+zu/8Dk4/ /XQsZOzbtw8f+MAHcPvttzs7NBWDNgRizPKPrXyK4P/QQw/hBz/4AbZs2RK0eUu/MDU1hbGxMdxx xx2F18VtY3nbZKzxfSoPnzHCjWzo9KaJ0c1m0xihJEQBVrTnAuyEeSigw8pQXNdBeshfaB+ZJr39 LE3TTDFcsrYxNZFl2V4Acq+C6CjUHE+S5FVoXWDNQyqHAOQkQIrHb6PTH0RX6GX16tVvFEIYt/y1 ed1Aa9MJOY5sg2oBcyxqn7KyTbhy1W+Da5KXLfx7/PHH49xzz3XyHTQeeughXHTRRXjood4DtUJn SBfp1YXypyrnfnj/XJ6PPfYYLrzwQvzwhz8k1TUovOUtb8ErXvEKMr3pWcYM73Ngq9e3za+PB9VD 9/GkGOM+Wj30r5Y7ePBg8JLO5cuXvwnaLrGGjx6pps5HU+nld0NJ1zEHIC2VSpuDLoaIIiMAE0KI c9Ba9ncI894/MB/+p2z7a1L0lDF//TuZmJhYru76B9C9/71796LRaHR57LZIgCu8r08c1Gls9Zt4 uXhQ82308gUbGxvDBz/4QUxMTPTe5QWCm266CR/96Ee7NnQxdR6+jitvvg9FjPFT6GIYhVT46Gu1 Gv7rv/4LQ0NDOO6441i8+4mTTz4ZN910U2evDxeKDv9T63Ep+X61PRU+o4FiFOg0ptC/jtAoQJIk 62q12m0zMzMH0B2RlorfFhlQGZt0j/zW6WQUQKC1J4A8Jlg9JXCqvRqgkMmARRoArxWtyX8H0D3R T+77X0fv5D9beD9kOEC9uXLd/29UKpVjKYpSzWs0GtizZ4+RzmUMqOmU367wvenbtZqAwkfnYbq+ d73rXdi8uVAjNBhpmuKf//mfcd1117GWP4UMCXDpYyoFTohVjya52phOZ6OVvznev0vOrL3kbufO nTj55JMX5LyA4eFhbNiwAbfccksUfrEiTSHRLBcohnLsiIDuwVNk0uWxOTNAay7AyMgIey8KIYSo VqulXbt23YVej93ngLoUv20IoSuioAwDqEsCR9rO8g7WxRBRmAGQJMl5AIbQmvynHu9rOvUPyrce EaC0apVe3uAu5T88PDyxZs2aCwGUXd6/6feePXt6vH/Xen/bTH71t2+HPpe37pNfr1dPM9WpQsr2 mte8Br/zO7/Tk78QMDs7iw996EP47ne/20njdCiu+7qQwBm3DRnjLcr7p5R97LHH8JOf/AQvf/nL jTu5DRpr167Frl278PDD/uXYoW2Hc491I4wL1/vBXelAWVHg4uMrb5LJZzioNI1GwzjXxCfn0NDQ 4fv27bux0WjU4D+Lpou19m3SSTq9+pGTAaXyT9CKVFeSJFlc1GTAokzvIwEsQ/euf+qpf9L7l6De ZEkL0GZodh7K2rVrXwdg2KcM9Px6vY5Dhw45rWCbxUyxkmU6pVPX+VE6A1+YzcZjYmIC73jHO7z8 B4EXXngBl156Ke655x4SPcVTXogoWvmHyhLqsZrK3X///bjooos6e2ssNLzjHe9wnnXR73bkqyOW DCaF7AMlpK/SqbQm49Pl5evpugE/MzODWs039cyI4cMPP/yNmPfCu1aQOcrpEQMqZLkGgHqj0agJ IebQniwP4GCWZaMA1nAvhIJCDIBSqUSZ/JehOzJgG1/Ry7gMBX28RQAQpVIpmZiYOLOL0NHA1YZn 2kBGbbTURm8q68rnwhVK9NVp4vVHf/RHWLJkSZAsRWL37t34i7/4C2zfvp3lsRatIGPC9ixjK/9B ev8q7ZNPPomLLroIzz77LKvOfmB8fBzvfOc7yfRcL72fxmeMCYJc3iZwhuD0qIHPKJA0Qoie/Rwo 9QPA6OjoL5dKpQqUZXro9fDV3xzntRMJR/fOtzbUAWTlcvmlBP5sFGEAlLMsOw6tZX9dBoBonXZE vVlAt8L3GQe2smLt2rVbkyRZxrWem82mcea/KVTv40Udo5Z0tskvFF6Uul0Gw4knnog3vOENxrxB 4vnnn8d73/tePPXUU500k+LiKso0TReEMcCV3ZaudoK+NmoawrL9d8nhg6/cs88+i4suuqjQnfhC ceqpp+K1r32tl45ruEnENAJiGbqxxv1N/RZnvg6FxmYUHDx4EI1Gw1TEiSRJpo444ojToYTiZZas EmY9pusnU7Ta5tia0jIAqRDiYJZla9EaUo+KIgyAnwMwgnnlXwdQF0LUms2mbfKfjjyGAqCMqQAQ k5OTXdqM4v0D6PL+84SqrEIzwodcxaDTUL3jarWKP/3TP/Xy7Deef/55XHLJJUYvkestLzRDwKf4 XXkmRU8xACl5OvS65Mfm/XPnH+zatQvvfOc78cQTT5Bl6hcuuOACTE5OWvPzKllqiD1PP5DX0KDO E8gjC2X41JZn6ovlUd/U+iUWLVr0FszrEaBb+csPlO+eSwFIOkzqvybaw+SNRmNGGwaYQ0v5H+nh xUZ0AyBJkpPRuqgaeArcNhTgK9fx9NtpXQ9kxYoVR1YqFWv4xDaxJMsyawhJb2iUMS29ThtfF51t uEF/CVwWtu/lPP/887FmTSHDTcHYvXs3Lr30Ujz//PMA6Aqfq/j0oZ0ijQFfHZT6qZEerly2/6HD VhwZ9u/fj4svvhhPP/00uUw/sHz5cvzhH/5hV9pCiBrpCFHyvnlRAM1r53roVFk4TpbeFx44cCBo iCNJknVr1qzZgvb28TDvD9CpVlaJXt1lilp3vHsDvQkNtPYE2MS+EA9iGwDDADaiNflvDvOT/2zg KnvAPflPbx1i2bJlZwLuRmhKm56e7niEISF/ap4r32UQ5O18TC/4smXL8Ja3vCUX39jYv38//uqv /grPPPOMlzbECLAZVTpNXoOAw4eSr39kW81Tj+2/i78aNeF4/7Z6AGDXrl14z3veg127dpF59ANv etObsH79emNe0UMksRDSf9nybe2FE4GKLZOaLkTr8DabI+fD1NTUL6F3/F+NCKhDAbbwvwm2MiZI HXoIwCoAUZfLxDYATkIrVDGrJgoh5rTwv2vyn46MQAMtTwAQlUplZGRk5FW2Ai4LVoaObJN69KgB x0p1dbwuJW97kXQL13RdlM757W9/O0ZGRhyS9xdzc3N43/veh6eeeoocLrU9K6pS9cGkBCkfDl+u jHnDzz4eLsOXWw+lPqA1J+Dd7343Dh48GFRvEUiSxLkyhqIkTeA8vzxj5aa6TMabjY+Lr68PovDQ aXwRURdv1Rh54YUXSNeno1KpvGJycnIpuicDAgZH05Cmw6T01SiAOjmw0Wg0ZtvDAJKu3q4jahQg qgGQJMlJaF1EXcvievo2L98URpFpqpUmAIh169a9Bq2oBAuHDh1CvV7vUTomy9Y2FBAKiqLTX1qu xW3isXnz5gW113+apvjwhz+MRx55pJOmG102cJSO6d71M7TLMRBsMM0DCOVlolHbmW2+QSzvX/39 1FNP4a//+q+DJnIVha1bt2Lr1q3BwyESVIOWQu8y5ijPJdRIc43T2+hc9VCMBh+tqUy9Xsf09LST 3sIjWb169S9h/oAefZjZNBwA9EarOYfadek4MT9xXg4DbOBehwsxDYBRAOsxv/Zfn/xHAcXLd4VO 1AeSTExMvAHgN859+/Z18vQOztXxWYXWFJc+1sz1aF10VF463wsuuIBUT79w1VVX4c477wQQplxc 3jK1U+R48FSERgYkfEqeEunwpYUoDZuBHCKjinvvvRd/93d/R6bvBy644AIMDfVOyM7TVjgRltgG amjkIgRqpMDnNLkcLvlfpzVFLYQQnT7dV4eO0dHR15fLZdN+AKriz5T/HGe3cymG/1mj0ZgFMCeE kNvoz6C1v07vmceBiGkAvAytGzBrya+j+8Af9Whg103z3VDdKgMArFq1alOpVDq8i9BiserWotxA Qvd8bCEpV56eT+2gXd4/xfLmKM1TTz0VGzdudNL0E9/4xjdw0003daWp9y/EwzSlU5+JSk9V4KFD ASb5JHxGZ2zlXzRc3r+Kb3/727jmmmv6JpcPa9euxdlnn92TnvfexYre5OEfQmsq4+orffVQw/Um nrY+e25ujnSug44kSZavXr36ZeheEqgbAlylrzqw8qMOjavn5qiQadGiANEMgCRJjoc5/K/Dd7My wwcOesAwJrN06dLTAb73LyeM2DwtqYBtIVIfKKErzkuuj71xDYwkSfC2t72NXF/RePDBB/HZz37W q6zyKtMQPi7esSIGrvJpmlon48VQ/tR8tU5VHtuEQE6dtjKf//zn8YMf/IBdtii87W1v64kCFBEB CUGsYQjuXCauDLbyrn6XylstIz+hGwMtWrToTMyvBtBD/r5hAJ/+8ulC9bsBoFEqlY50CsxALANg GC2rZAbz1ktDmfxHUeJ5rCgJASCpVCrVarX6SpXY5zVLxauPFfkans8DpxggvmUqvhdV7XQ542VZ luGMM87A+vXrnfX3C3v37sWHPvShzphvqILi0OvDMf30gCWoEYU8/LlpPuXF7Yxt/DlG3WWXXYYd Owo5E4WN5cuX481vfnNPeojnLEExGKhGhs2RyDNWb6OhRtBsPLgyUQ0XPe/QoUNoNps99D5Uq9VT xsfHF8E8BKBGAUyGQJfooC/9AwAowwByX4BZAEsRaTVALAPg59u81LF+VaHL0wDV8L/p23dTTJEB fUIGDjvssJcLIUjjJGojmZ6e7jQQ0/i/Su+zUm31uEK7all9rEytg6MMXC9XkiQL5rCfNE3xoQ99 CHv37u1Kpyiq0GiAyzAq2hjgeO56+8s7XhwzuiJlUmWLed9UXtPT0/irv/qr0D3eo+O8887rHGLk U0o+xHqnffy4RiZHOdv6Nf03xzniyGR7N2S6bWdXAsqrV68+A93hf6B3+Nl2QaZotum/OiwuHWld L8rVAFGiAFEMgCRJTkRLSLlswQVKNEClVQ0EnYdElzU2MTHxWoDeeOVvNfzvFcyjSHyGQIhlSwHH Gj/rrLMWzKY/X/ziF/Hggw8a80z3Wb/OkGgARwGHGgWh4Xq9fdkMUh8fbhpVQbh+6/La6EOMjp/9 7Ge46qqrSLRFwxYFAMKNqBiIpfxN6XnC/pR74us3OfWZIg02A8DHa2xs7HR0DwOo8wH0KADA9/ap S+IbAJqxhgFiGABlAEegtVGB3LRAnQdg8tp9oNAbra6JiYmlQ0NDXQfYUxrV3Nxcz+Q/X1lKOIwa Sg0NZ/uscNfwwlvf+lZWnUXhwQcfxFe+8hUnDUWZ5VXOoeVcnxB5gF6lr+dTeHHT8ip/E0zXQYWt nq9//eu444472PyKwHnnndczFyBE0XJAuee+dG7YnltXjPKufL3ftDlW+v9arYbZWds8dTtKpdLG ZcuWHQnzngCq0uc8YJZeFPOrAQ6htRqgzKjLiBgGwLEAKtDC/+3x/1n0hv91j15Py/OGiFWrVr1K CMG+LnXPaOq4khrytylyTsdn40UxSFydsulF3Lp164IY+z948CCuuOIK0nadJhrTtYaGU/sR+tdh q1N/nhzFX6Ty99VtgmlyYIj3r9J++MMfti7t6ieWLl2K0047rfM/T9vhOhQhzyymhw24NwDiGCLU uQ0+GV3RQmmIhp4PsHTp0tPQvTUw0DsETRkGsOm7VPt0NgVC99b69Xb9hzkFJiC3AVAqlY5HSzDT eIUPLgso074lTDeuc/NHR0dPBegWoRyzNG0UYfJcVKUP0HfA0svZaNRvCs8QCCHwG7/xG0FlY+PT n/40nnvuOQDhXolNgYZ6Smr5mEYBl2dIZIKaHqrUfZEA/frU94Oj/H00+/btw8c+9jHSNRSN888/ v/M79hwIHVSHIiTiEjoJsAjEimKY+nC5zTsXIyMjr0G3kte3CVaHAfSoQMwoeBMAyuXyeo78JuQ2 ALIs24h55U8qAt6NMJUxTb4QS5cuXVsul4+iMFQbxcGDB7u8FJM3rypwSset12FLt9Hq+S4al4wm mV/ykpfgxBNPdPLqB+6//37ccsstZK/GNZHSVpbrCbngC/f7PkWCahjptNzogu+3GvKPrSx0OW+7 7TZ897vfjVpHCDZs2ICXv/zlnf+hBnu/Ik8hUcm8vChODacu3aGy9ZOm9DRNgyYDlkqllatXrz4e vXMA1LkAnaqBKA5xV3nR2hkQABpZluWewJXXAFgNYAlaSxPqaI//CyHqhvC/vvEP4L45vhuoh1zE smXLftElrBoVUBuGPvnPpvht/Ez8dT4mmHi7XpQ8npyKhTD232g08PGPf7zzP0QphUYD+uXF9AMc Y0hP5yikkJC9bN/q+xbD+1fx8Y9/fEGcF3DuuedG5+kyXl33xfX+6FEZX32mtND3h+P4cOrxGZsm pyh0T4DFixefBv/pgBzI4QD5UPSzAVIA9UajUUP7gD0hhNwVcAjAysB6AeQ3AORkO9O6HKoFpNLI 3+reyTqtFSMjIy8HeA2n2Wz27BCldlzyv1qm5wKIXqbvpTWV43hoesegl82yDEuWLMFrX/taEr8i 8YUvfKFnTbcr3Gz6b0uT6TZDoB8eedHwdfI++lDlT6nLVJ5qHFONDvl/165d+NSnPmWVr1/4hV/4 BRx++OHe6J8LLxbDVDfmYslte8a+OVkhxv3s7GzQGRPDw8OvLJfLZdgPB/INAwC9y99DIFfc5YoC 5DIAkiQ5Fu1DCtpJFM9eBzdUIm+wLCsAJMuXL1+vb/3rZNJuKPrYv8vb91nDphC8iVZt2HkUkWuy oA1nn302kiT2IZA8PP300/jqV78KgK/0OaFuW96L2QjgXqtMd/130bvKcgwQat0h+Pd//3c8+uij 0fly8aY3vanzO/Q6KQosRp+xkOCLpLrgitDaeMu0kGOCkySZWrly5UvRPQ8A4E0C9MFGozrIGVq7 Aq6myG1DHk1QAbAOrfC/3KVI7v6nhv9N8Sau0tfL9Nzsqampl+kFTDNSdYUtx4J84/UuD90W4jRe hKfB2nhQyrnKS/zSL/0SiUeR+NSnPoV6fX6laAwjwJUu80zPcCEZAyHKXc2npBet/G388oT+fdeQ pmnXcNKgcNZZZxkPCeKAY8y7EDIPIXQlgI+n6ZpcwwE258l3T7gTsG0nBPquedGiRaeiNQxgGwpQ JwRy9VyX6JjXo3NyV0DMDwPUACxGayggCHkMgKPb5ecItOqyBv1oRP3m6GES1w3sTMbQZ/9T0Gw2 jWtCTZ66rXFyIwYq1BeDMqHFVt7HQ+Kkk07C2rVrnTIVjQceeKCzhpvTydu8eB2hilIt2y9jQK1P Pj+TIcoxbFzp/VD+JjrqO0OBre77779/4BMCFy9ejF/8xdY0JO5sdQ4dlQd17hK3fte1FfXu2Po3 W7RAn3tioqnVal2OCBXVanUrepW9NAT06LR+szPDt67nMtidZxWNNv/gKECwAVAqlY5r/3TdQa4F 5KKXNxT699TU1MqQ8L8+EzR0dqzeGG3gvBwmWu7SFd1o+dVf/VVW+SJw5ZVXdiknXWHYFA2307Ip RqrnryvnvIaBi5eu+Cn1+WSn0pryi1T+Eq4x8pBIA9BqWyHLu2JCHQbggNu2Yg8VcOun9nl5YYtK cIYHXJGNkNUA7RMCj0PviYAw/KciJFpQB5CWy+Vgry7YAMiybD16l/+ZrBkvKya9PrkCy5cvf2UP ESGcZTr4x1bWlE7txHR6k0fkoqfAxEPtDCcmJrB161YyvyLw/e9/H9u3bwdA9yIoHRNFkbv4cRS8 zTDwfUzQI0sUGTjXarteV34M5U+hoRgvnGvJsgw7duzALbfc4pWjSLzsZS/DypWtidl5HQoT8kYT uIZsTMOEuqLJx8MXUeJEPnKsBtiK7l0BbcMALlB1nx4dUP83sixb4SlvRagBMAVgOeaX/9XRWv5n Gv83zXhUlziEonOTh4eHXwbwXrhGo9Ez+59jWVqFCnjpbQ2asvMdNX3r1q2dg0sGgTRNce2113b+ cxVPTEOA4/kXhSzLuo739dGGKP5BKX+T9+/6HfM+X3PNNUFh3VhIkgSvec1rCm1DNr6U580dFrDx oZalRGRck/5MbSuUzmRgzM3NYW6OMordjWq1ejJ6lb++MRCUPJsC19PUjzp03kT3csC6aG0NPAtg FMAE+yIQbgBsan9z7hzF2skM3/Kj3lD5PxkbG5ssl8vHUIXQZ//rDUVtJKYJLL5JgbLBuya02NJD X2r1t60zPv300518isZ3v/td/OxnP2N5eKZri2UIcDypIj4SvjkePsUb0mZMNP1S/jpsXiHX+5d4 5pln8J//+Z9W2n7gjDPOCCpHXRXUz5n8VGWbh2/oNdv6YpOB4ooSBG4KtH5qamolupU/lP9ST+lO MNCr53TohoANGVrOdobA/QCCDIBSqbSx/dO3kJIa4qCW6QmtLF++fIvQ9v6nvCAHDhzoNAzb0bs6 zzwNn/IimehMyoLTeQshMDEx0bVT2SBw3XXXGdMp1xJ6310KVD7Poj19F2xtIo/ip0YT9DTbf869 MSl/G40KV5vn8suyDF/+8pcHOhfg+OOPx6pVq9jtimPs+/o4aii+CMTk73OkbHSmNmWazC1E+AmB S5cufTnMQwDAvP6i3gyqruzKF0KkALJyudw/AyDLssNh3/43ttI3oXNTx8bGepb/9RBrD9I2+79L IKWBcC1Ul9L2TR6kni3gk0HFq1/96oGu/b/33nu71mn7lHyoIqPS+hRv0QaBbew/9Jo5kRFXOdN/ Kj+b8qfws3XaodixYwduu+22KLxCwY0C5G1zIc8qFNTJzlLpcuqltgEOnalN6sMAIcNGIyMjv4D5 pYBq+B+O312iKJ9QZGjNA1geUjhEK0wAWIrW2IM8nrAuhKg1m80Z+Mf/9Yu2fatQb6BqWYlKpfLz 3AvQtw61hZdMoSSuJRqDlhJWdTXyV7/61V5ZioQ86pfTSan/dWXpKkPhT1WWpk8oTIqWK4ctj8rD Jg/lv4mn/jtWJCF0Qpz6//rrryfXVwTOOOOM3JN4+4k8dYcobZtBHtK/usL7LuNSTbPtCeDC0NDQ CdVqdRjdwwCmaACU37bhAPnb9OmaC6DsByC3368BqAIY4V5DiAFwNFoXI7ciLNLTd5URy5cvX58k yTjA8x4OHjzYYwUCvZZhp6IAz4TjndrSuNaziU+1WsVJJ53ELhsLTzzxBO66664umVzwealUGh9C lbrNMPB9OHX66LjRD1/ZQSp/NU9OiKQYaj6Zf/KTn+CBBx6wli8aRx99NCYmguZlGcG5v9xIDrfe GIYKtU8twjAxpYecJyGEqCxfvlwuBzRNBtQdV9vFUHSifgqu+i2H4tmrAdgGQKlUOqotDHUj5ZAQ h0np9yyxMO3+p8M0w3RmZobk9bsmAer8TdECU7n0cEwfAAAgAElEQVQQj1XnaYM+fJBlGU466aSB zv6/4YYbgpSs/t90bSGdk8uT7pcHFjL2z5Ux1HDyKV2KYglR/tL4jjl+/I1vfCMaLy6SJMErXvEK Mr3N+bDRupBnfkAMuByX0BA/dW6Wy/t3yXLo0CHjffXJOz4+fhK6dwQEQB7398GkB3uEFEI0AWRD Q0OruBWwDYAsy9ZifuahlQy9gjvZMssIABgeHj6eyL8D9RAIaqfjejl9HRzFCjU1YFdkwAZTGHGQ a/9rtRq++c1vAphXHpxhD6rC4hoCFCVXhFGgriyh1BEiA+ce+Wh89L7fPjlt8IXDqRGMb3/72wM9 KfCVr+zZniQIoUo0BigRUVdfRaE1wVbeREf19H0rbg4dOkSSTcXw8LBcDmgL+wvDbxdcetAVQahn WTZFkVkF1wAooxVmqGF+/F/d/1+OSdiWPughDFtYQ4V6Azv5lUqlWi6XjwO6H6yvwegdgs16VNPU Tlun4zRUlc4XaaCAQhurEwrB9773vZ6NNtR173k8dlOaTan5vH6qMZLnw7neEMPDdZ2+NO4zsF0P lS9FgVMNbpfstVoNN998szW/aLziFa8gT74NNTZtZTgRxxhGWwgo4/m+spQ0mwGl1xtiLCZJsm58 fHxSskGvIWC6IF3fSR2ob3+vf+Q8gEaj0ZgVQtSg7MOTZdkEmOcCcA2Aw9EyAjoRACFEqKdPhZF2 +fLlxwohKgw+AOYNAF2J57GqKd5KrHkElJdF0mzYsKGzK9kgcOONN3bJI5FXAck0brqvjiK9/qLq 5dwHSiTAxMf0P+8zzVuOyu+GG27IxS8PJicnsXnzZi8dx+CRoDoc3LwQ2lAv31Q+T39J4e+q12YA uGQRQiTLli1ThwFM0QCT9x+qC41lRGtTIKC1SR8ZXAPgyPY35yDlmBfaubHj4+PeN0sf/282mz1j PaqHr5cz8XI1UEqj5byYulyuKIHpJTzhhBO88hSFPXv24L777ouiMHyrAPIoQBt83jwVWda9418s QyOG4h+E8qdGDEIiF6YyjzzyCJ588kmrPEVjy5YthfGOGTEYBEJloazQsnn5rr4+9HCg0dHRnwNt O+CoSl9Ds03DWg7IMgDaB+7IMIQLsS5UD6N0bmq1Wj0OTKgWXojV7YJr45EQD9eU7vMkdQzSALj9 9ts790RXHLbwJFWphUQEfOU5cBkHNiUfw6NxGQ6udEqaj1fRyt+HPJGCb3/726y6YsL3DvocD1sZ yvXHotHp8kQQuJOhQ9qvSsd11EKWA1YqFdNKAJPH74oEmNK4+jMtl8tLGGV4BkCWZath9/6LtG4A 5cZVKpVKuVzeBPDG/+UkD31M31TWFZay7Rxo6+xjRwaodJTwY1H4zne+0/VfVSB6Z0Lp3E0RDo4i VPP6PYkq7/AS5Zoo6aFefz+UPzUyQOGvp+ltsZ847rjjgjfhymOocpbAhfCJKQf1OimRWZnmMzwK mAewCPY5AHkn//nKye9GxpwIyGmZYwAWoTUBsDP5D0BNmQBo2gBICqd/qPsiy5vX2Uxo2bJlmyjj /3ojsC3/85U1NSiuZWoyDmwGCDX86apv+fLlOOyww6z5RWLnzp148MEHe9I5nTzVe+Z4/pKXyUMv AqGdJ1Xpx1T8ks72f1DKH/CPMft4PvbYY3jssces8hWJyclJHHnkkca80KiGb5UElVceL9yWn1cu iiNmojPVYWo3vrlftpUAhHkAx8M+BGCKCpgm/MGQlmm0nYmA9Xp9VgghJwE22pMCy2BsCMQxAA5v X4DcArgoT99WpnMTJyYmyMv/5INrNBqo1WrmiogvotqwXBZmnnBljPAaAJx44olkPrFxxx13WIdE fEol9N6FeMl6fkyDgKP8qfVzjR2O4rfdd98zochs+k3Nl3ANG1Hw/e9/n0RXBKiRuBCv2IZBGrbc umNNwHZFG1ztRo3SNZtNq55wYWRkRM4DkB+gV7+GevkuHiovOTRPHgbgGABr25VxNwAKVfrW8f+h oaFNhrI9UB+8tOxs1mE/wsKcqIHJOuUcDzzI8P/9999PVmQUpc9RzD7vWN9tzscj1DjQ6UN4+ui4 6bY6bGV9zyGvZxjjmfrqlVB3o+w3TMZ4HgWd56Ajbr0xnJci+1bq8Cqnvw/ZD6BSqRwL96FAnaoB 0pCADpvSV/NkpGARlSnZACiVSmuUSnxCFhUdEAAwNDR0dE8GY/y/q/J24/BZkqYG5IoC2JD3hTLJ aaLbtIlkI0VHmqa48847AZjlsnk5PkUUQwnb8kN4Uj4UGVy8uTKH1KWnmX5T/pv4u2g5/DiTdW18 HnjggSDPLgaOPrqnu7KCEt73gXIv8xhTNp55eNhofX2Imkbtw01OoJoWMg+gVCodVSqVKkDXcfW2 8D8FmfahlmmWy+XF1ErIBkCWZSvhnwDoylOtF9eBCCrkjevkL1myZFWSJOQLBFoPd3Z21msFcjs5 at0+nraGm+fF2bhxo4WyWDzwwANdx2tSFIVLWVLTKHWYPAETTYhhoIPSKYZEAlz5FPjup88wMP03 1eGijfGecSMKtVoNd999N7ueGDj88MMxNDS/P0seB8HVhvuFPM8vj+wu44VzX3x6YGZmJkS2yvLl y48Ees4CUJnr//ULsc2dM9FCo5H5DQCTFtoeUA2AIQCLMT8BsN6efDBHmABoEpICtUznpk1MTHTM aeoDT9PU+VBNFqH871POps7OZ8VzOi+Xx297EVetWoXJSXIbiApT+N+nEKg0pjJc5cFV8ByP36RI Qw0LqtLPYyTqaVTji1pHLOWvv5+hhtk999wTVC4vhoaGcPjhh3vp8hqdkgdAmyRH5cWljVl3iMFg U/Cud0ktU6/XO9vFu/jqmJiYkMsBTasAbIUpulHmq7q10RK1Xmvr4gbaejnLsgqIOwJSDYDVaF3A oDYAQrt+MTY2diyDH4DW/v+uziwkEkD11F1hJyovrsW7YcMGqzxF4/777wfQ25npytEEiidquxeU jsV0v7iKmYIiDZM8vG1pFEXPlSum8qfcGwov2TYHATkMkKeNUZUslQcF1OHQENiW4tngalOUiBtF bskvcB7AMejeDwDoNQQ6VWmfHlEM/3VaVznSPACqASDXk1E2AFK/KTBdmOnmAYAol8tHUZiqD5fy MPVGGMNKdjVsqqLn1p1l2cDC/wB6jmA1dfqcMUOOwo/hNefx2l3XEco7jwwUIyq212+jz+P5x6Lb vn37wOYBxH4nffc4ljEbgjxGRh7P31S/qy+39U1CiFADYCPMnr8cxjbpOBdCnGi5I+A4hZhkAJRK JXnMoMkAiO3p6+iynMrl8pGMegC0IgBGxoSQor68jxJe8nWwLuTxcCTWr19Ppo2Jxx9/HC+88ALJ m/RB91DVQ4RMNK7yrnyOYnUpcJtSz1sHF7ayJsVPeU4LQfn7xn6pmJ2dxfbt28n0MbFhw4ZcSpmj 3KlOCYVHyPOkRkdj3I8Ynr+JR+A8gDXVanUYZr1KnQjo042+m5YCyIaGhqJGAJZj3rKQQhSp9IH5 myXHPcSSJUtWCyFGGXUC6N0AiOKFUmaaqqDwtIH6kvg6Rfl73bp1QXLkxaOPPtoji+s/xxDw7bNg 40dVphyvnALq8qRYdfqu30VHMQZsdfrKxOCbl06lffjhh8llYmLVKvdR7TGev0SRkwTzvhdFwmUU UIwSlUYOG7toDHnJ0qVL5URAwBwNUNM7IikfKlTaTLQO5etsGJRlWbwIQJZlS4Geo3thmAAohZAT AFPtvyq4/q3mq/V0btbk5GRncJvayBuNRteEDqlMqC+MScHaGgZl8xsffLKZZNB/+zqbovDTn/60 679N+Zg8ZB8oikyvIy9c3r3rQy0bUz5bnu2/mu4q56rXxcfG2wcKHy7U8nob7Rd8u3JSnQAg3/g/ 1TDl8HTRc8bdObAt5w7hYWtzIcNFo6OjcpK6fjZATxXKB4ZvnUb9SF3bRGsi4JxaTgjRRGvnXi8o BsAQWhMKZjE/07ABYM5Cb1PsLtiUfpcFNTw8zB5Is1lyQG+jMTUiyr4BLp5qOiWNkmeikb+Hhoaw fDnrQKhoePTRR0nKgXsv9GdEUWw22n4gloIP4c81lPQ0St0UWWIr/xB+JgxqS+BqtYqlS5ca82Ia OEUjrwHRz3cQCF9FkGWZdejYhWq1ugH2I4G7qjGkqbDdKFO0IENLLzfR0tFzWZYNgbASgGIArGwL 6poAGBrCMJWxzp4sl8vG2LZLacuHqCpml1JwdaxUcBs5Z3McF/8sy7BmzRpW3TGhdq4UIyBUmZho Kd5w0YpZRcwwrE9+Ux5X8Ycqfx//UN56Wqz9MX7605/m2kkvD0LO5ghprxxDKkZ9McvbvPIi+l+f ExdiAJTL5fXo9v5DHWL9v02/mmhlhMA7DEAxAJa1v3UDgKvw1TLUcurNE+Vy+QhSIeXByofoW9PP CVXZGo5rwqApzSSvDz4ZBnUA0MzMDHbt2tWV5lI0lDF9X5qazlE6RRsEeZU/Vb4QI8iXRqlHppno fDQ2/pQ0zuocG4+ZmRns3r2bzCMmTENzIZ6qy0mIiSKNhTxli1iaaDI8QgyAUqkkz8zpsDZ8KLB5 +i56degdIAwDUAwAGU/WJwFSkMF8IZQyKkSlUhlOkoQd267VakZlT/FQuwQIaGAxvBqXHKYygwr/ P/fccyxlriOG0nIpRJvxZaKL3Tm5wKnbRse5Jz56U3lK2aKVv0yn3l9X/c888wyJR2zoBkCIgqXc V8qSYwpibMLDldfkIITKwpHBhBADQAgxOjk5uRz2YQDbkADA15W2MtJZ906Y9xoApVJpGZSjeAMF yl1mamrqMCEEZ+tiZFnvOI5vkl3sJSy2Bq3Dp5xsZfS8Qe0AKDtV13Wo4C7rM/HjRAV8ZVw8OJ80 TTsfCn3odea5fgqohpspPbbyl/eVc89ceU8//TRJvthYvNi+gzn1noUOhVDAubd5646t0Klt07eM W83XJ5DbeOhYtGjRevjnAHREdDLrzdePEdZly9rfzaGhofwGQJZli+HfAEgKqocrbCEMmU4xLAQA MTY2tp4gQxfm5lrzFPM0Vo5nZaKJNevV1dGrcHUyRYLiVVGVksnD5fLV83SlGKKMi4ZPJp+sPoOA I0MIX249lLSYkPwHFQFYtGh+aTalTceATwHG5p+XNobnz3XqXH10SBRgeHhYDgOYPqoOhOE3DOnq FvtUpFmWjfiIKB71YijL+MT8GQAzaC0BbGB+eKBnqaAGn6dvu2HZ0NDQWoKsXXA9PJsl62qknB3s bPVQNh9S87jDBFNTU04Zi8Kzzz5biOenK2wfX5+CdPEK9dJN8C0tpdRDkYNSnoo8nlXR9eQN/avp zz77LIlXbLiic1zPntp/UPNCn1/Ifip56qaW9fGkzgELWQpYqVSOgHkJYKb8p0QGTLpS6ln102gv BZT6WNJ4DYAyIX8CwKE287pFKB9C6GWZBK05AKtNhK4G5np4Mnwuy7tC165JJ2maIknIIxNdyFNW l0PKqXoZ/YQ8AZBzTfq9tXX2Id4ApZPiegNUcCerceuI7T3mUfzc+vLU5buvVD7qaZX9hIzOFaHw TPl5jDQbQto2B3kMbtXAp8ip791i+h84EdC2EYspEqDCd/GqAWErlwkhGlmWNQBUAZTgiOD7DACp TaRVQYXP07eVkdAnTYgkSdgRgFqthizLuhSS6T/Fs9cNBlO+rzy1PoostrxBRQD27dvXJQfAs/6L MgT0cpRn5UNo/aHI6xFyynAUbL8NDS5vG1544QUW71iYmpqKYrwVqYB99XCXUMZ6vnnK54lihRgA SZLIw/NMhwL1iAG+g6yWFcpvlY9U+iMApq2yeiqQ2oTy1EOVvqmMfrOEugKA0gELIYwRANMkQJe3 GGPWsStftVpNdXI76ZERb9SnEKgGgARXmVDS1PTQTiRviN8WwlefZUz+FLoQ/r40H32e+lw8YqXb 8vbu3WulLxLVatWaF0upU4YYQ5GXZ+z5ByE8bXMMbI5IvV5ny5QkyfJSqVSBefmfqrDzwDVEoOY7 JwJSDQBbCCGm0tfReRLj4+PjSZKQ9jZWIQ0Am9WqPmzfNr62xh/jhYvlvQGtnQAHgf379xu9a66C ciknW/SFyt+n4PIq7hhLAKkKP49h4UsLpbfxoPB10Yeku+oeVARgdNQ9Kbtfnj0VRY/fh4DSDvLu CaDyq9frxjpdPIUQydTU1Br0Kn+Ar/gz7bdNd9roKi7mIRGAIpW+St+Z9TgxMWHd3s7WIBqNRpdS 1xU817Om0FI68JA8Vxm9nMvLKBLS2OJ01BRlp8K1FCxvVMAlQ1Efbv15r8GU7ipHSfPVzeFRtPKX GNSRwK65MdT2QMEgDYnYfVxsmDx9E9T8wDMB5I5sakW6MUABWXfKJYAAMtHaFjifAVAqlRZhXhmr FVBACVHY6LvCJdVqdRmYkEsAJXyTu/J68tTyvkiCj4epI19IcCmsUEUU4kXGNgZ8iL37X17ZQ+6b LT/E61+Iyl/16gYBl3FO9bZ9zyFkm2PKPY5poAD559G4+ts8ToiJRtclFFQqleWwj/+bhgZ8nr7v 5kr6Lme9Uqk4dwP0TQKcBG0PAFWALu/d8K2XkbBunFCpVFYQZehAtdr0xhI6KdBkPdrofXxCJhPa 6NT/4+PskZIoOHjwYI88rusEaBP/fPkmI86W7+KfF1T5i0Qe7yuGx+8qU4QiDy0zqAiAbXiOorSL Or9gUA5Ev+tV+yQqJH1IexkaGlqBXn1miwAIuOfZSadYdY5lemrg29G5WetQICucEYAsy8YIgjXQ vVEB1VKhPAkBQJTLZfb+to1Gg9yBxPJWqPkuGShlY20uFBOu6+Fa5CERATXPVV7foS82TJ58kc+G EnEJjbCEyEFN99VRtPExqAOB9GEAitFPvRdFtTNq3+QyzkPTfZ4/ZZMfF1/KfIHAiYBLMa+Y9T0B 1KWAVF0okaLllMsQv628NA5yzQEYQbcBUAdQazabs+3fIdEBNkqlEtsAoIZtTKEkjlfpm1UaEqLy GSghHWo/oHb2lM6AslmOL59iDFD59Etp5wFFRor8IQrbxYuTnicP4BnAC+05lkqloHIxIleu/UxC sNDurQmU/tfXdkKGAEqlkhoB0G+yHqr3waY/5f8UQHNubm5OCCE35gMIEQDfEMAogBpaZw1zzSBX 6J9SpnPT2tYUC6rVplvZtnCQSqfSmDYLolrunBeMw98k60KBTR6bceDjpZYx8fYZbDoNVQZuB1fE M4jt/cVUlLEVfKhCCeGXdwOuUOj9kg+c50ox+riIpeT1dzT2s1ZBWeqtOls2XSBhOg/Ah/ayddOR wPoFCEMaLGkmqLpSLdMQQsxlWeacFe56C6poGQgxLBVqWaDXYhKlUollAAghMDc3x5rpafrvQ97Q aQwvTsehQ4fI9ceEvv9A3muzlckbGVANiZgefwzlz5UplE4I0fmo8ocYZra6QvI48E26dfEb1FJZ rvLnIFT598uL58yNMaXZ+mrOdVE9fx0hQwCazrKN+3eJg7A9/3Vk2kfAMQzgMgAmFaGoFXKEpEAA gBCis78ttZPSH5rt4dsaCnU8S44lUhooJ+QauqpgUGObrhc8piGglqXQ6MqPajzENhBi8I9lHLhO LKTKYMtzlQvJ88kSwq9ScQ6LFgbbZLK8ytnUX+VFqJFeFDjOVgw51Ps5NzcXwrM8MjIyDvOMf4k8 DrOJjykdCDQAJjQmpgq5Sp9dZnx8fBEcQxWmhp+mac8kQFdImtq4Qq1NascaA4Nc4sRV9nkVLLes pOUcLeuSVzcsYhoQoeWLNLhC+Ral/EMmw2ZZhnLZN/JZLPQ246Kh8ooJat8XanTEMqZNTpdL9pBh P/k/5Fjg8fHxJZJU+wb4Sj9TvvVPF526H0D7I3cl7IHrTZDbVkmXMsRSCbVuZOgCw8PDEx7aHqgP S28otoZj+m+izbLMOH7os8IpVrrtIB1KA5b8B7XEST3pzCWv6z5wXlRbWQkqD1tnlGeeAgd5O0OK wsuLUCVVhOIH/Lt2+up0ncpXJKanp3uckiK9Zgp8SnMhItQR09M497/RaLCHjiqVymL0zgGQEFoe BZLW1NH0GALKt1VwlwFQbRfmjklwPX2p7I30w8PD7AmA0vvnrqm3KXxqGkBT0ioovKnIsmxgcwBM hxD5vLRQQ4Byj3zRHx9CIxL9mIyZN6Lka6MUHoNS/jGMkUEZAFTjfJDePwdF1x/C3zfBL/TehkwE rFQqU7DsbaOKrKTblLivU7HpUPnfGul3DQHIWV2UOxai9FV6eQH6hYpyudz1tlIeoHxYMToz0wxS Lp9YnSElBDuog070TpUa5vTdm1gerPpZSCsmfKAOBfhoTBP/TKAYVnme2aCVPwAsXcr2KaJg//79 XhrqNfr+U9GvcnkNcledHKVOWdZtkjVwJcAkesf/XQpfpoVGznUeTbQceKuj74oAuAyAECG59AJA ViqV2FvbqQ9LD/9Tdv0LiR5Q0vVlhaZ8WV6XnSobpZMpAj6vyndNtjw130XDQYywfxHl83SqNuSZ 2a+vmMgjT0zFr3t5XJkGFQEwnZipot8efV6FmrdMKIocOrHxDZlbNTQ0tEhLEtpv6bXbHGIOZPkU 3Y59BsC6+YTVACiVSsPtm6HekVClzy3TCWckSeLcy9iEZnN+fyJdYeZV+i7oCt5WNzWEzQmBy/+D MgBWrlxJoqMYArZ8Kk0oYitULu+YPPLOgdDzXZ1unuEAH2IPQ2RZhuXL2fuKRYH+bvbba6fAdXKq y1PmIJaha3u+PkjZ9bbtqkfVKVQIIeQqAGjfuuIPhSwv9xswIa1Wq0O24SffHADq9r4mobhDAhJd N6pcLrMnATabTZIido39WwU10FKNDAofwD0J0VfHoI46Xb16NYtef/lC51RI9Cus3y9PJ089IbOd Kfnc8dS894qi/EOMksMOO8yaVyT27t0bJYwdC9TnGTMiELOOmHK46IQQQQZAkiRyIn1epa9GBDLl v2nYvFWhEJnyjvAjAACGGYKq4YcQpW+FchPJoIzXUL3z0MiArxxFwbnksmFQcwBWrVrVk0Y1hAD+ hECTsSTxYhvjjwnO5MiQfCEEaa+JmMqf8ptTN9dYjQXbu+nyuhcqihruyVt3SHkKv8AIwAS6Fbdx nhuBlar0fXQqvVwSGGQAlBWGLqE4ip/75ESSJEERgE6FDgWaR9kXGQmw0fgiAgCwc+dOivjRsXbt WmM6x9Bx0XEUvP5Ch0QXQtDPcVATKPfOBo4Hmmc4gCJDHt4UA8dkrPYDu3fv7kmjKlI9ZE3l4co3 GVOU0H6sEH5RoNxTX9hf5xMYAVCHr02KX0YFbDP4XUpf0ndFFoQQaZZl+hwAu4yOPNM2wHoIIzXQ mASlhj30GZIZ5icjkqE/LFfHYvIk84aNYtFwwq0SO3bsINHFxsjIiHN2te9l49BReen03HIvJpiU Qsx7qdPZ6qNAfx6U5xNL+Ver1YEZAPq7yb1nejnq8+WkxwY3UlCkceGi9TkDIasAhBByBz7TPAAT Mu1DgW37YJUPfxlgNn+KUKZ9S7hMIu5FmMoIAEiSxLlvp+mhyp3eXHS+8Dy1YXHDobZGT9nchCLT oAwAADjqqKOCFY7peXEUWB6D4H+LYVDEPcujZEz1hSikWMofAI488siBHQT09NNPd/2P2ebytOcQ R8NWXkeeqBS3zljGgIk2ZIt1IYQpAqDfEBlB5w6f6/o11fI7v9sRAeODcL0JxjzlKGCKUD74ygg4 djHqMNEeZpqm1vWcnA4oBi0H3I7ORF+r1Yyhxn5gw4YNAOJ78VxlRaG3rUKgfBYKVHliG0qce56H h48mtgwbN2708isC9Xodu3bt6vwvSlnZyoVGAvrR3vM+fyqPkMmx1PfLhHYEQN8DAAjz9Cn0zVqt 1tHNYn5L4KCNgEqGyvSDkfMofFI5IQR7EqA+B6BLAGYnmJfO1YAoaS5FZcOgogDSAJDgKu2YtDp9 0d5WPwyEkHpC71denv0wHnzj1aa8o48+2itXEXj66ac7XiRX+edpU7qRGKONhmyG5sujokjP36b8 geBD1sro9ryll0+dfBTiVEMI0VTKOOtzGQAVreK6JlBMy8VaRhlHcRdwWLscIyDLeifyceqP8QK4 GhvFqn/mmWdI9cSGqXMtqrPLowyzLOs6DW8hgmpYuMb+i/D2ffxjRQ4o5anviQrdSO0XTEZ53hUb eaGfBklFP6MCMffd8LU5V78fuApgDHb9R5kHQIVOm6E1RJ+hZXRYb6JrFUDHOBBCzAUIlCc6oIZN 2Id3mzoG0wOmrrGnNkYKTxcNlZdP1scee8xbrghs2LAB4+PjmJ6e7krnvswhL7/6wubZ/U4HtwOK tQEPByG8YhtmXEM5Dw+fN2bjkyQJNm/eTKojNuQ7SXEU+gGf8RZr7D5W2yzS87fRcnactECPAMDw X3eqXR2IKV+mdSn79j4ATbT0Z1AEQApE3QMxr9I3Ieo6LV9kIAat3mBMhoQr+qD/D/GmHn74YW+Z IpAkCV7ykpcEd26266feL1O5vAre5PXG+ORBHl6cMjGjJL56YxgQvvyXvOQlqFarpHpi49FHH2WF kReCgVBUJIebzkGI509B4CRAPXqtzwHIC914MOU7Qxe+OQC+uEcRSr8LQohhBm8A/oeldvqcMGLI S5EnTEqhNSmCRx99lMS7CJxwwgkAwl9milKn0NvKxlDA/YRLdk60gdN2peKPhVjRA9vqHur1HX/8 8aR6isAjjzwCoPd9LsJA9IHrDed590zwbQOu102htfHmGBsF3XfT0nYXrQtU3annW/W4awggrxAm gXxlTDeLvWaHEiLMMxxAobX9VmkB+sxUDt2OHTtw6NAhjI6y50/mhjQApDxAsRvuhC7psr3sg9h9 rYiOJ6ST77cM1M45lmwnnnhiFD5cpGlqHEImkwwAACAASURBVJajKiHXexQSAcqLEB5F18tR6H1U /gBdT5o2AwLml/fZQv+2+jIAMGwM1AXfMkBdcRfm6WtlcoPb+bg6wdCwUp4QWmgnKK9jUFGAzZs3 94RZi/RqYntONo+syE8McHlKuiImQlJkUN8RrpcZcu+SJMHLXvYyMn1MPPnkk9APYwlRQty24+pb Qp+5S+5BGQZ56+u3DASE6E4bHyd87lOqrCWkVhgqeN+fgvrgYyjtEFrOy0iVMcsyPPjggzQBI6Na rVo72thKz1fHIF7sftUdcp260u+31y/rptYfU77NmzcP7Bjghx56qPA6KG2haENc/S6CdxH0HNqQ YbFqtarvZGvy2ru282VXMo8uHm3dLfmxNwIKqrTAMmxwlTmnQ+LwDjUq8lir999/P4muCLzyla80 pqsdkKszGqRnvFCR5zqKVvqqfKY0bqQhtpxZllnbZD/w4x//2EsT+3r1viemI6KX4/Iq2gGgpvej P8iyzKbwAXNkPY8uVRW/TmOEbw6Ab0kCVdA8Qwi5kGW8A3nUF4ZbzrdBRoxlhKqMLn733HOPs64i sXXrVjIt5Voo5ak8XC/9oE9fK0oJFAmKURw7YhbCa5AGwH333efML1pZxlTuIfm+fVViGh5FImS+ 0dzc3IyWlNf5NZXL4J4jYK3PdUX6zEGu4AsmMhA7hMSNBEg6k4ekI3SpkM5rx44dAzsZcNWqVTjm mGPYnfUgvHTds6Z8iuIfA/3a4IgiP+e6KLShyv+www4b2BbAhw4dci7LzRsF80XSfHXERKgcIbwo tCH0BSNPxVTdqEcTUiGEVan49gFQJwJSkMfTJ5fxPUDfbFlK46I02pDGlfel5vDzeR5F4nWvex2A MO9jEIYAB/1W6i45pMKPvXTPBsoYPvfaqe9EKD/ZFgeBH//4x13PRb03edtHnvumytAPJUntW2M6 awukD7EJQQk3ZtqHWp9OH7QRUAoA2fypgJwKfSCXybLskCXdWibWaV8xXlST109J89VL6Ujuvfde rrjRcMYZZ3T9D+n4BhUVWKjot4Gh1usyMHzKxMWXYjD7DA31o29vm2UZ3vCGN5Blio377rvP+LyK npMB2BWsKz1GNIcqByWtX/QLCKH61HaaYILukwJ7Ml1MJfS5AoUqfYsMuUENK/WjcVIbI9WrM/G8 8847SWWLwKpVq4zbroYqL0q5F8kL7sUgogkmGajDCaHPM5SGY0QfccQRAwv/A8Add9zhpRn0s3Yh VB5OX1tktCEWnxCnMssy/fA8Kyl4utEXGVDTXcaBNwKghg6kEdAPpa+WsW5FbHvQrofF6Xj0xhm7 sXI84RCejzzyCJ599lm2XLHwxje+0Zmfp3OxdZYLrQPVYVPuC6Hz171oKn1IHa48Hw0lTeLNb34z S76Y2L9/v3EYLo/xG9tx8NVrS+uX0u6n5++iC5wg3FDZa3lNOBSzBRx9KpWgk95lAEjh1cKUk/mi RgcYVlQHsU/ZokQIQvgC9oOLTGkUT0wvf/vtt7NlioUzzjgDIyP6MtgWTIZVnhDjQlCgOvql3PPw 15U+V/FzOlfbM8/77G0YGhrC2WefHcQ3Bn70ox/1vN/cCZq2vsB1kl+MdsZVsrHqcLWH2DJxypRK pRD+B/UktJQ+xzrzefo9/7Ms04UNNgB6NGmpVBpBf4cE9GUUXpRKJe9LwX0JOeXzGhgcOXy0d911 F0uWmBgdHcUZZ5wRJHceLFSDIBZiREBC7lEejz/2M6HwOfXUUzE1NZW7rlDo4X+uVx7SR4WsAAmN 9oRGbPLUSUVswyhHBEB6+WrlPkFCDAUASIaHh8vaBkBZ0CoAIYTRAFBQAl/pS+g3w8ojTdOGLc8G yngNt3HF8FJ8RkOMl0LP+8EPftCX2eE2/Nqv/VrnN1fZxJrZXpQSKhp55HZ5V9wJaCEeGWfHPy6o /AYZ/ge6o29FOQWu8nqbKbrN533WIcaCmlfk9YUYAJk5em3z5CkOsStP301Q5RU0CdCkeHUBEw8P tQz16egXwI4ABD4s538unS0vxAhwpfka/b59+wa6HPDYY4/Fli1butJURURBUYpb5+sKq/YLRXjJ IcqY69np97EoUOXfuHEjTjnllMLk8GH79u2d+Tf9Uv6UvqgfbTvEYAzlGbMOF5/AIQCpu/IofSt7 03/TLoBCCOtpgC7lXQfvGEN90kEepT+fMX8T/UzaD43zsEJeTk7jDk3nNHYf7Y033ujlVSTOO+88 a15oyLKojszmdYd+uPXGvI6QTYF0j9F1Xbb/RYATDcqyDL/1W79ViBxU3HzzzT1GZZHo9zvUD2Vs 62dD5PY5bj5+gQbArJ6kfZvySKyZ5YIiAHUicymESsvd5EBN6ybqnUjhZpplKJfLnd96nq0MF5Qj h0Pr4HhflJfhW9/61kCHAV71qlfhyCOPdNLkebEH7bW74JOvSG/fJodPRl/bcxkBRUBvuy7DJE1T LFmyBK9//esLk4eCW2+9NeiehChWbn9g4pf3PaK2F0o5av39MDwlQgyANE0PAu5leBpsNKqeJPFR 5wGE7gRYg/8sAJdAwlCeHRloNpsHiLQdUNds6i8OF9QZ/Bw5bOl5LNhdu3bhhz/8IVuuWEiSBOef fz6Z3qRkuGVjeF5Fdip5vS+O0jaVV3cPpJbPq2i40L1+X50y77d/+7cxNOTbv6w4PPzww/jZz37G LmcyqvJ6roOk5RqhnHpD+gYqTHIHRgAOwe3guoTn6kojhBBZez6fES5NOYf8ClyWUb+pZTIASNPU uBOgC6ZVAKRKGR2gKY3aKDlWb8iLaHrJbr31VjKfIvDLv/zLWLduHbtcDA8zhocTC9z6fbJzFX9e D6+o+6d78SavnyLf0qVLcc4550SXj4P//M//ZJfxGTYUYyA2QtsLNYpRlEHCBYV3YATgAPx6TzcQ VP3Kmcwmy6mrDsIjAM1mcxb0OQA2YVzRARKPZrO5n1EvgO6HxX1pYkUCKHUXYe3aXqybb755oMMA SZLg93//94PL61593k7G5UX300AIlYPqsYfcr6Lvi4uv/pt7H972trdhdHQ0ipyh4BoAoQYZ59nk dTDy1hNahlMnp5/kQg4rc9AeAgD8UQCXrqREEExOdmcY4ODBg0FDALNthlQrJE/IQjc0OjyazSZr DgAA6xwAClwdko0eiLPzlqtObkeo0+7fv3+gmwIBwJlnnon169fnUiY2BRH7pacoQ+pHP7Anz/AE x6jJyzPWvaXIFVKPTr9ixYquZaeDwD333IMdO3aQ6WO2AVUB5nlmeln9f969Bky/uUYqpz5Kui1f /s8xB6DDSs3C/MQ8l950CWstp60EyGBe0QfAbQBQFG+owjfxUPl0DIJGo7GPy1Ad/8vT0YaUcb2Y IfX4XkaqPFmW4frrryeXLQJJkuCCCy7o/I+tuIvyVgdZXuVjaguh12srF+P+cT3TUNl1XHjhhQMd +weAr371q2Ra2733laH2J6HGIIe2SOPblE4pyy1DQUi7qtfre9Gt3/TJgFzhQpzsDK1th41lfHMA TDR5PH0OjwwAZmdn93KZ6+EarpINTafUFaNMiNUMAP/93/+NnTt3suWLiVe96lU967OL3DCmCKOA U7crn8rHdMJd6LX4vP1QxFY23HfvmGOOGfjM/+npaXL4P8/zCy1XxHsQK+qg89N/x+JJSTflhwwB NBoN3QCA8k2FTVfa+JgMjKAhALn+Xt1hKA84hkPnZs3MzLANAJO1FhqijxkJcPHjlqF6C+rvZrOJ r33ta84y/cAFF1xgXalB6aRCDSadfxEGQigfXY6QNfwU3pT0vHyp5WKWefe73x3tGPBQ3HjjjajV asY8/dma8n3gLj320er3NNTrtvH2pVO89ZC+lMOfipAIQNt5NSl/nyC5nez2xD/JI2gjoBckr1Ah wL+QTPtgenp6f5Zl1pZveqhCCOOYDafxmZQGB6plTKmPK58v3Yavf/3rA50MCABHH310z0xtn4LK +zJzPG6bMrZ54iqdz8Cw0ee5Nt+12K4tD8/YhrFOZ/pvu49nnnkmTjzxRLY8sXHdddcZ003vte1Z xHrPKdBl4ZSh5Oc1qin3JYRXyH9TBMAnkxa9dnnwPXrPAVN+x9Nvj//rHXyQATDTZhxiAHCtF+fF Z1nGXglQqVSsCkX9TxYwR4fHeal9L42vjE/OHTt2DHwyIAD8yZ/8CZYvX84qE0t55UHIM+Pwjs0n 7z2LwYOrYHTDy1V+0aJFeNe73hUkV0zcd9992L59u5PG917bjIO8kSBuP2e731zlr/PkyMc1hIrs y4eGhkK2l29MT0/rywB1HSeVdYjSl5DljV5d2yAImgQ4g9ZugENZlg0BcMVAQkIW5DJZlu1i8AXg DtlQG1Gs/1TlrJct4iXIsgzXXHMNWY6iMD4+jj//8z8PLu/yoPuJGAZFTMUf6zyDmDw4dXHrfec7 3znQE/8kPve5z/WkcQxzG0yK1HR/YrUf0/8ijOYQOdT/XIMiT30h4f80TfXxf8k0RFfq8PLIskzd iC9oDgDQuxtgGUC1VCoNt38nLiF0mUC7eDU/BZCmacqeuVapVFrMIiplIP9cAo4RkSfq4OLxwx/+ ENu2bWPzjo1TTz0Vp59+ehReoQokb12D5GPylPMi5nW58kzXzq375JNPxhvf+MZcssbAk08+ie98 5zvW/FjK35Qfw8igyBDDS1fzB2m0cxFiADSbzV0wbMqj/ebAqD8nJibE+Ph4AkCMjo6WsixLoKyi c+0CCHgMACHEQQONfgElzB8GFGPFgKTvaNpGoxE1AtCpKMKLGVIuNBLAiVz4Oo/PfOYzZBmKxHve 854uDy5mx2DzLBdC58Px4FzXEVPpF6X4Kfy5Bsz4+DguvfTSIDlj44tf/CJ5MzAqTagXG9MoCH2W VJ4mOUOumxMNCPkvnUkO0jR9XrLQPtDS4Uiz6U8BQExMTIi2p4+xsTEBzE/+U/YCsI7/A/4IAHsb Xk1YNQzhO1egS+mr6Y1GIzgCAPC9bErn7OJBaZDcEBa34co0W30333wznnnmGasM/cLU1FRPR87p YPJESUKUaV5F6VKS1OV+sRV/DB6mjp3CP0SGLMtw8cUXY82aNUEyx8TevXvxr//6r1GNs1gGqm4U qOmcPsvFn6O487blkD6QAxu/EAOgrbNCIgAmpe+bgJC19/zXjQckSZLLAJgm0MjKQkIbtnJd/+v1 OtsAqFar3QwJHhYH3DI+o8NFzylH5ZWmKa699togfrHxqle9Cm9961uDy8dSiCov/aNPSOPO+PeV Uesv8jrzKiebLFy+XOWhljvrrLNw1lln8QQuCNddd51x6R+1feiI1Y5N/PIaJbaylGdPUd7cPrJf 0HUJBe0hAKB7kp/poqTjK+lMyj4DgMnJSTVP9/SNcJ0DAHiUe7PZ3AfzqX5SKK7Sp5TRrZi0Vqs9 x6gDAP+hUV7G2EpZhg25L47NsqeWk7juuusGvjGQxAUXXICNGzfm4hFqkIXShii7kPqKUNh5eOjt j3ttIR29NMAOO+wwXHLJJTzBC8L+/fuNE2o598NmVIbyo8JniOTlq//WaXw8YsgR639IBKDttKrK 1+TkUo8JBtCa0b9o0SITLx3Z8PCwGB4exvT09JyL0Ofdy70AJF1RSt9VDgcPHnQaAKYGMzQ01LMx iO+hx9gsiPvyUhq7iT+3nJom0+v1Oq688kovn36gWq3iwx/+MMbHxztpC8ELiKE085RbSIpf/c3l yVFsah3qyYDVahUf+chHutrIIHHttddienq68z+PQrUZfT6eHCfAV39MAzqGTKHQ3528xkBIBGB6 enoHenVfqnwoyNDLA5OTk0KJBugOcxeWLVuWawhgP+bDEkUrfVOZDAD279+/C/M7E5JRrVbZDzv0 GFLOCxTLws8TNpO0//Zv/8Y6vKRIrFu3Du973/ty8YjViVGfZ0jHTJUtz4ZNMeqnKqEQOUwGha89 //Vf/zWOOeYYtgxFYO/evfjCF77Q+Z/3XlPpYhgFlHbvanu+8pz6fPC1Ce5/E38XbHsA+Mrt3bt3 B7rX6FP1YUcPLl68mLT5gGnsX04G3LVrV91VlmIAUOhkxbGUvpqWAUCz2XyawReAfykg9b8OzgtA hW8WNDWP+3LWarUFEwUAWvMB/uAP/qDzv2iPgaJ4KDxc/0PkySNLXoMyxKilyiGVC1dJnX/++Qtm 3B8APv3pT+PQodYc6X4ofx8PyrPieuV5DD8bL0q9pvxYcvig12HTIS6kabqn2WzOYV6PmeYBuHRe B1QjAJifCCgNAt8mQABtCCBDa82/aTOgEKWvliPTN5vN/2HWgZGREW6RDkIjAfJ3no7TV6etY3V5 Wq6y3/jGN/Dkk09yRS0Mb3/723HmmWd2/vfz5Y+lPEN5cNJN9YfUaVL6MXiZ0inep47XvOY1uOii i9jyFIWdO3d2tv0NNf58XjaXXyg9lafr+fnabUwD2cYj5B2hOILDw8OsOgCg2Ww+g95wv+7UZjAP B/ToxsWLF4vFixd3/ksFnySJ3Pq3i354eDgBIJcI5hoCaKB1LLC6sX4ZQKW9GdBQO8+1F4Dxojzo uVmNRoO9Zs318KgNJjSf+qL40rhyUjsWFWma4vLLL2eVKRqXXnopNm/e3KOcKOiHsRCzTqr3xjH8 fHxMnWEsb99VB6W8ik2bNuH973//wA/6UXHFFVdgdnY210z/WP0PxXv30YUiD19uH8fhHcLTVl7V IVS+bWfVtgSQNfFPh+rdZ1km2p9kdHQ0GR4eLo2MjCQyr70E0FmX960SQshhgBBPv8PG8t8X3ugs j5ibm3uKW6keAQhR6NxIQCgtl1/MFyzLMtx+++0L4owAiaGhIVxxxRVYt24dALoXGYJYnWBIRxZa hqNEKJ55CPRr5yo8X90rVqzAJz7xiQUz6Q8A7r77btxwww1sT9j0HPLee1ddrnJ5HBsXTci1+Bwz rpNFrcPVP6r/dQPAVF7H3Nzc0+j28k2Kv4vB1NSUqguFGvrXQvo90EP/ErVazTn+D9DG9vejOwLg Qh4jQZZTLafOTMeZmZnHuQyr1WrPBI6QBsc9hlNvXCHHf3Ita27Ha0q7/PLLUa9720zfMDU1hU9+ 8pNYsWJFTx7Fy6IgT2ec13AILUdRthTvMEb9FIUTUv/U1BSuvvpq47MfJD7wgQ9Eee56H5H3nobI YTMKff8paVQZYoDj7Phk0P+bDABfXbOzs4/BPgRgFXBqakpIQ8Cm1AnIgJbzmySJc/wfIBgAzWZz L+LuBeDioYZKuvJ27979hJOJ4WEkSYKhoaGgRu7jX4SyiPVCmPhSIhlPPPEEvvzlLxciQyhWrVqF q666CkuXLgXA97JcCFVOPjl85WJ5ffK5Ug9FytNRc+9vqKLIsgxjY2O48sorsX79erasReKGG27I dYZGSJ/BbdM+Xr56fDxcaXnk1MsV0Udz/5dKJeOW8j6D48CBA0+gV/l3sTB8OkrfdLgV1RBQjIas XC7nNwAA7AGQZVkmowCxlT4JtVrtUJqmz3IrGh0dbVUY0KB05IkEyP8xLGWK1xpqxFx99dULZnMg iXXr1uETn/hE58wA6n3UlaNaLq8H7KPhpPvgug5drjxGjYsfhwen3evXNDo6iquuumrBLPeT2L9/ P6644gprPqdNxDAwbW0ghBc1PYQupJ+N0UfGyHd5/46ys/v27XsWZiVv0nkZ4N/RzwYhRDYxMdH5 LXkKIbJKpRLFANit/O6n0s+gTaRI0zTXPABuYwxVoj6eeXm4eFPqctW3f/9+XHbZZVHkiYmNGzfi k5/8ZCcSwIF+vf3YptXkGdnobB91ExwO1PJcmU1Kn6MQfNftuseLFi3ClVdeieOPP54sc79wxRVX 4Lnn2BuSAqAZ7CZ6W57pHsfuQ3x8++HshPa/3H7dxoOzikzyaDQaT6Fb17nOAzAK6gv9q8MDKp1e ZtmyZVHmAMg9jauYXwo4BICyP2JItEC9aV186vX6zxh8AMxHADqMclqKAP/kMhPfoixhKlwv6Le+ 9S1861vfKqzuUGzcuBFXX301Vq1aBYCvkLnKLMbe/75yrvpDYVPiLhn1aw25Xtt9plzv1NQUPvWp T+GEE04Ivu6icNddd+H666933kPf8+8XTM/DRkfhpfLMKxO3/hBaX1mOAaHrDkpdjUbjcXTv7Q90 67SOQaAu7aNALvszTQocHR0Vw8PDpSzLxPDwcJJlmXjggQeiRADqAA6YaEul0gjmlwLKJYBdsxm1 D7Q8+W0yFHpCJ7Va7VGCvF0wWXHcRmF7AVzWKtWQ8MlGgamztdHpeXoHJWkuu+wy7N+/X2cxcBxx xBH49Kc/3Vkd0A+EdkAhHWeezpZS1maAcA0kV91UI0di9erV+NznPrfgwv4AMDs7i7/8y79kl7P1 BxwjkFtfHiXro48hL6UftaVR27aPL6fekH1karXa45hX8k30GgJdmJqaEkuWLOmZX5e1j/lVPX2Z pn6Pj48naZp2aMfGxlCtVpN6aza3N3xIWlwrhNgL90qAUE/fVMY62fDAgQMPOxkaHmilUkG5XA5S +j5QXjpqh0ypiysflZdJjueeew4f/ehHg+soEqtWrcI111yD4447jvWcQjrEPCF49T+1XAgoRp+r 881bbx6FtmnTJlx77bULbsKfxCc/+UnnJllUheYC9T6GOgexeavGTAhC6nKlUZwzbhkhhHEreR9m ZmYehjkCIL1/AMi0k/26kCRJ6AoAAC1DYHJyktRxUQ2AXej17gGewpf0LkNB9/q70vbs2bMDAWcC 5JkIGELjg4k+z77vIfW5aCX99ddfj//+7/8uSqxcmJycxNVXX43TTz/d67mEIESBu2gp3lUIbJ6S j2dsbz8Er3zlK3HttdcuuKV+EnfffTc+85nPsMq4jCyuoZ83UkB9/nn6NKpypcjHuT+h7xk1b3h4 uLOEnNoXZFmWPv/88z9FtwGQAkhHRkaysbEx69r+JEky+ZH/rRWh52jgDk8hRJYkSdbeitgLkgHQ aDTkPADqvsQq8kYHOmUbjUaz0Wj8lCvA2NjYPOOCFHqIF0/Jj/UycZWBTLvkkkuwd+9ekgz9RrVa xeWXX47f+73fM3o5oUMsIc+B0gZieXUAbWVAqJyucnmVksS5556Lf/zHf2SPs/YLBw4cwJ//+Z+j 2bTvpBqq+Kj8TPmm+5/HAYnl9IRGFmIavxQa6rWpOoNaV5qmz8zNzU2j2wDo+rQ3tZJKPlWVPhXS aJiYmBBS4et85ubm4hkAAJ4HkGXzSwF9yKv09bTO73q9nssAAIprOKbx9JB6qNGAPB0O9aXes2cP 3vve9wbX0w+84x3vwEc+8pEuZaJ7qD7DQC/HQUiEgKuwVdljDEtwysRS+kBrSO79738/Lr744gW1 va+O97///XjqqadI1++6L3nvl49PrOeShw/DQw7i4fpvM4IodbmMGF1n+HgCQFs3GRW/ukRvcnKS vK7fBFXpm/Laewl4JwACdAPgObQuZAjzBwPJMwHk6gB5HoA8E8C2eZAKl6Ggp2UA0rm5uYeIMndA eZg2L9j135ZG2XSnn95i3vK33347vvSlL+Wqu2iceuqp+OIXv4ijjjoqSLFK5erq8GM9k2azyV6K mKdzppazeZcx2l2apli9ejU+//nP41d+5Vdy8Ssa//Ef/4FvfOMb1ny1rYSu8ogFUxvhGiS2vjBU fkp5inycduv7z+3bbRMAXTLNzc1tR/cOgFK3pUD3aX0UA0BV8Oq8gMnJySRNU5GmqRgdHU1GRkaS kZERkaYpawUAQDcA6u0zAdTNgOS3z9vXVwGo9LYzAVTaruUTe/fufcAlqOkBlUolDA8PBzUMah0h fCg8uB04RwbOtV5xxRXYvn07SY5BYd26dfjc5z6Hc845x0vL9RhMRgJ3qZzuvYc+V2oZriEUUt7F Vx2mOPvss3H99dfj2GOPDebZDzz55JP427/9WyeNzYO00VKMvBBlyak7lHcMIyZGX2hKC2mzFL6l UgnVapXFAwAOHjz4YLlczoaGhtJKpSJ1VjoyMtK1SY9TQA02T9+UNjo6KtI0FfV6vQHCCgCAbgAA rf0ASvB77Xqez0Cw8TDNosTu3bv/J8uyAwy5AaBzoEiIF5fnBQyNBlAt4dhehk2WWq2GCy+8ENPT 01Hri43R0VG8973vxd///d/DtKWmilBPJ8Y+EL50VT5uPVRjpijPT70/o6OjuPzyy3H55ZcvqEN9 TGg2m3jnO9+JAwfc3QvHuKLAZRiEoqhnG8rDVi5P38fhQ+WVZb3j/0S5Gnv27OmKALSNCJb+C4kQ qBMKORMAAYYB0D7jGKBNBFSVOBWmaILpO2s2m+wNudXOh2opUixOUzlKGhdFdgxUPPnkk3j3u9+d q/5+4bWvfS2+9KUv4dWvfrWVJo9nwu3cuTQxvSZf24mp9FU+p5xyCr761a/i7LPPDuLdb5RKJfzx H/+xcf93iSLm57iei+ucB65RqbbdUIXsy8vjTIX2r6E0tvqohqrKo9Fo/KxWqx2CNgdAbics9+dv T/xLS6VSqob1qUp/8eLFwhYRkJ+RkRFS+B+gn/IHABUhxLFCiDkADcxvctDMskz9rytwl/Vjy1OH BtT5BAmAZGpqam2lUjnRJqh+AiDQerl37twJIUTnI2nV/2p5nUbNd9GYvrMs60k30drSbDQ+upD/ rrQnnngCQgicfPLJPfkLDWNjY3jDG96AI488EnfffTdmZ2c7eerLb7pWE0wdi6tsLCVOLRMrKkEt ays/Pj6OSy+9FO9+97sxOTkZXMcgcNRRR2Hjxo249dZbnSsA/jdB7Zs4ZfLQcesMiaDJfIojp6at Xr3aaQSaUKvVvr9r1647kiSpCyHqQoiGEKKRJElTCJG2P3KZnlT+Tp7t/A5R1trlr7MJkBACQ0ND AgDK5XInvV6vH9yzZw+p8XIMgFkhjC0YLwAAIABJREFUxMltwSTzDACSJBHZ/B1U767tCk00ph0E 1d9ykmEyMjJSHhsbe4NLWP3mlkol7N69G81mk6X0XcYC1xAwyUc1Bmwyuuio/6lp8v+PfvQjbN68 GYcffnhPmYWIDRs24JxzzsG+ffuwbds2tiIH3B2NqWwM5W+TSffk8tbDLecqf/bZZ+OTn/wkTjzR ap8veGzYsAGbNm3CN7/5za7hjFADK9RI5HrT0tHg8IoVnZT1+2iovGKkhUQUkiTB6tWr2QbR9PT0 v01PT29vK/86gGZb+XcMAOn5l0qlDIAg9DldBIsWLUqSJMmy9g6AQ0NDSbPZTIaHhxMAkJMAH3jg gRdAHHLgzAGYEULILYHJYxpt2CIBFD7qcEIKIN25c+cDaEUhWODOAwgNN4U0RA64CiBW/bJcmqZ4 17veteAnBaoYHx/HX/7lX+JLX/oSNm/e3HPvYnbEIYrCxCP2aYZ5DAbfkcPHHnssvvCFL+Dyyy/3 zr14MeB1r3sdPvKRj6BcLgPIF13Rn58rBB/C31RPHvjaWV5jwueBh5Tn0tjKjI2NGQ0pn3z79++/ D4qOaofz5e+uPfw5UIcHTKH/sbEx0TYoAAC1Wk09htgL7kLc5xhlfOF/E636X+fRoanVarONRoM9 D0ANR9oaHTdcZKPz8XK9rCFWPFWZceDqZKanp/H2t799wR0d7MMxxxyDa665BpdddhnWrFnT9RxM yta3NFDClufq/Kn89Q45hoFBKUM5zGbFihX4m7/5G3zlK19ZkAf55MHrXvc6/MM//AMrHMy51762 4SrnS6fw4hq2VBqOIWLrt0L6ZhuN6b7YaHQdQUGapk8fOHBgF9pD4kDnHICgLX3lWH6pVPLv5a8Z BVmWeU8A7CrPIW42m89i/tAfHaoSz6OBpOXUNcygfKcAsrm5uZ9wGbc3YOiuzNIgXP9d6Xk8hZB8 lY7b+YTUo2Lnzp14+9vfjlqtxi47aJx11ln42te+hr/4i78wbkVL6YR1Rc7ZmS/E6wk93pdbB6We qakpXHLJJbjxxhtJyy5frOAYAdx7TaEJMd5cvELkytOv2NKoPHx9r/6dVzZ9AiDl2tu6qIn5eXCd df9Q9JfqzctJgJKHaTc/FUuWLOny9HUocpNXAAC8OQAAkAghjmuPccjThlIAjbblIa0frjFgojWd ItiZEDg6OloZGxs7w8VUV/ZJkuDAgQOYm5uzjvHr37HmAejpJvlMMlB/+/J89NQyet6ePXuwfft2 nHnmmexxs0GjVCrhpS99Kc4991wsWbIEP/3pT4OWOZo6iJiTA130vnkCVL5UmZYtW4Y/+ZM/wWWX XYYtW7Z0QuT/m7FhwwYcffTRuPXWWws9s0MiROGHRAxCkWW0CXwcYyCmgRHq1JXLZaxevdpar+2a p6env/bCCy88IoSY08f/5SRA9ShfOQFQKnRfH5tlmRgZGelM8mv/R5qmQu5XUC6XRblcFkmSTD/z zDPkRso1AGaEEC9rC6aOwYv27AS5CkCf0NdzXehW+raJgGp+oqQns7Oze1asWHEuHFEM042t1Wpd nbxLwVMm4FENAVdZTholHZhv4JzJgZw0Nf3xxx/HM888g9NOO81It9BRKpVw/PHH47zzzsP69evx 9NNPY9euXf6C4Cvn2F4iB3m8s02bNuFP//RP8bd/+7fYsmULe5b0ix1yYuAtt9zSmUisol/PNWab 0PuI2O3NVBcnrYghAVu5LMuwePFi46oVld70Tu/cufOqWq22TxoAorUCoKl8OrP/y+Vy2g7vZ81m 02tFpWnaOS642WyKRYsWiZGRETQajWR0dDRpNptidHRUZFkmxsbGxPe+970XfDxVcA2ANEmSjQBG hRA1dG972MhaywH1bRChfVNbmfT+M+W3/CTNZjNdsWLFKUmSWI8Ssymz3bt3G5Uzx7On0FC/1d/q SxkzCkAxGkz/bWl63rZt27Bv3z784i/+opV2oUMIgU2bNuEtb3kLTj75ZNTrdTzxxBPBhwpJntwy XFobvSuETOGfJAlOO+00XHzxxXjXu96FY489FqUSt8v43wNpBJiWCPruJzU6lteTp3rnVFCVrHCs QLDRh9TvS8tjNKxcudK5A6CEKnuapk889dRTXwYw1zYApPJvJEnSbHv+nXX/0vtPkgSZNsvfBOn9 l8vlDGhtrJWmqRgfHxfNZlMkSYJyuSwajUZSKpWajz/++CHvBShgv82lUmlVlmUr2waAOubRVAyA zPKhQqVXowMyEiAAiKmpqaWVSuUkGxNTIxsaGsKuXbuQpqlT6as8XFECvZwrzVQHNxrg+h3jPydN T7///vsxMzODrVu3GmlfTDjssMNw+umn461vfSuWLFmCXbt2Yc+ePQDiz/MIpVXLxPTe1q9fj9/9 3d/F5Zdfjje/+c1Yt25dNN4vdqhGgDQM87SHmMo6VAZTWl6DJW+bpxgerrK6IeCrI0kSrFmzhnzd km52dvb2PXv23IGWAVCXXn+SJA2hLP9rLwHM5EfW6TIEJJ0c328v8xNpmoqhoSExOjoq5ubmOnsA zM3N1Xbs2MGakMU2ANI0rQohNgj7hkD6YQiAX/nb5gzoof8uA6BSqYiJiQnnNmMmhTczM4OZmZnO f1c0gOvZU6IGpm9Tmi0aYCtvumaK4o4VBQCAe++9F0K8ODYKomB4eBgnnHACfv3Xfx2vf/3rsXjx YuzcuRMvvECLtHE6VV+nSRnrDOW/evVq/OZv/iYuvvhiXHDBBdiyZYv1QJT/2+GKBLjAmZeht5XQ SW4unrHBlZ2q5E00eYYETHTj4+OYmppi3XchBF544YXrDhw48DMxH/7vDAG0x/874/7KR6+jU2mp VMqkYbBs2TJx8OBBjI6OCqBlMFQqlY4BIMf9h4eHk7m5OQwPDx96/PHHWcvjQ+J5s0KILe0b0MS8 h45SqSTSllmsK3Nby9OVvU6r/k60tGRmZmbPypUr3yKEsMZtTI0+TVPs27ePpfR1OtN/rrGgy+gz BkKiABQDIWYUAADuuusulMtlnHSSNTjzosTU1BROPvlknHfeeTj99NOxcuVKAMCOHTuM9LbOw9Ym OYih+Lds2YJzzjkHf/Znf4aLLroIp5xyCpYtW8aS4/9WqHMCYkwMLHL8PQ9UpR6isG389DTTO2Gr L2SCn41Opi1ZsqRzBgAj+jH3P//zPx9rNpuHhHn8v+P9q7v/qQZAs9kUqtKXWLZsmZDj+zJtfHw8 aTQaYmRkJKlWq0mz2RQjIyMiyzIxOTkpJicnpx988EHWQwmZwjsthNifZdkY0HNojw+hwwFo11NS /meNRqNRr9fvrFQqpzP4WZcDAuYxWxOtTuej8aXboNLbflPL2/IlTaiHYKrj4x//OA4cOICLLroo iOdCx6ZNm7Bp0yb8wR/8Aaanp3HnnXfi7rvvxo9//GPcd9993rFcPcpDRR7F/9KXvhRbtmzBli1b cMopp2DRokWsuv8fuvH6178eH/vYx3DhhReiXncvv46l4PN62Xqeqx36xtOpslLyXHVxw//6fwrd xMREVx6lL2w0Gtvn5uZm0b0EMBPK1r/t/z0C2Jb7qfBNFKxWq2m5XE6azabIsqz5la98hb13ddAa HiHEjizLXmLIMl0U10hQ+WRA12TAns+hQ4f+j8sAMD3McrmM0dFRHDx4UF5PF72eZuPDMQTyGA26 bCaZfbwp9ejWPlc+HZ/97GdRq9VwySWXkMu8GDE+Po7TTjutswqiXq/jnnvuwfbt27F9+3Zs27YN 27Zt6zkKOMQYpNK99KUvxdFHH41Nmzbh6KOPxgknnIDR0VHehf0/eCGNgAsuuMBrBNjAea6m3yGG uyuUTinnM0BiGww+GmpUwFR+aGgI8tAeld53X2dmZr4LoCmEUNf+d0XA1SGAoaGhVFf88n+apqSH ODw8nLbD/mmj0RBAy1D4/9l78yDLjvJO9Jdnu3vdqltVXV2tVndLNK2lBTZ0DGYMHjQYLC/gGRuY eOFwOAx4GWEzEX7h5WGHwcbvzWPGMwxmk2wsjxk/zxhj3jB68pOE8AODDF6wNVggIbRv3a2q6tqr 7nKWfH/cm7fyZuV67qnqrlZ/ESfuOZlffpnn3HPyW/PLJEmc1v8zyCUAJEnynOd516OvkcfYzdxd NX2CnfSFjOnL3AM8zQwAXVhY+Ntms5kRQpySGk1OTg4FABdNX8RzYfoqGEcYKMIKIOLk8Rmq+viv //W/Ynt7G+9///sh+r4uVwjDEK961avwqle9aqT8mWeewcrKCh599FG88MILWFpawoULF/DCCy+A EILHH39cmlSJn7TCMMRLX/pSAP01+YcOHUKr1cL8/DyuvfZatFotnDhxYk/v7wqMwvd93/fhwx/+ sFII2GvzPq/lyuYrFzqMhqltES4oVZ1tGSu3tVSorAOTk5NSfBYoroK1tbW/xiAObsDohwHwg3MQ h53+ZMAn/wmCgE5MTJA4jhmP5CFXNra8WTyeG/xG4DL2UUrDIAhokiQ8o07R99+LOQLEOAEdiLhD AWNjY2MlTdOHgiC4yeUGpqamdvlui3ADuFgKbBm/jY8sjwBhYvD8B+DqeuDhs5/9LC5cuIAPfehD VstsLlc4duwYjh07dtmlzL0CaiEgD6O08Yer6vJq0TY0XBizS995aNtYHBiDN7kFdK4w1XyXZdnT a2tr5zG6Eo7l/h8KBIQLAFT1wWv/MzMzBADCMKQAEMcxAfqZACuVConjmJRKJS+KIi+KIiRJgjAM vVKp5Lw3DuC+FwCDDULICqWU+eRdzfsubWTWhYz/7Xa7X3XoHwAQRRFqtZrVC8KXy8rGlWJd8FU0 TOlbxzGvsbpxtIL7778fb3/7260T7FyBK3DQgAkBLElSXi2ZZ1w2352Jbt72prYuZnYdvs04VPjj WAuAPh8wrXaR0et2u18DtwIOfSsA2/mPWQGsNH8mHAzcBJQxfxOwrYHTNO3l8f8D+QUAEEKex86S PBXs0ti5MhcYMfuL16urq1oBQPVC8LuW2TJy3Ufh+jK6gMtHZfoQXcYgo++ak561e/DBB/FjP/Zj B2oXwStwBVyAxQS4pEi2/Q5VyoptHy7KiqytbT82tIsQEmytACpcSqlS+zfR3tjY+FsAySDqP+Pj AIDRvP+kn/tfagUIgoAGQaC1EIgQhiGtVCpZGIa0XC4T3/dzaf/AGAJAkiRPY3SdPgOeQbNzhicT GMTlf/yvKDTIzun58+cfS9P0Sdd7mJyclJrOx7EIqMrz4uallXeyGHdCMX2w586dw4//+I/j/vvv t+rnClyBgwa33HILPvzhDyMIAqk2P67wb0vHRRN2aaurV7V3HUsRjN/GQuGyEoZrv3rhwgXVBkDD WDaV9s+YPsvuBwBzc3Nkbm5ulzIdhiE9fPgwoiiSWgeCIKClUin3bmzj5PXcJIS8gvQ5KG9+IFw+ AEDNwFUgwxFzAxDhnLRarfkwDF+mIirz4/i+P9wciOGIy+H4MrFcpMvj8L+yMh0NVZmqXlfOXlpV vY7WOGWqOAFCCOI4xt133w3f9y+7XAFX4AoAwMmTJ3Hq1Cnce++9VnkCKB0vha/Yfhy3ga4P1zrZ feW1Qoi/LoxfVhZF0TCXh8uz73a7X7xw4cJfoZ8TZ5j8h9sAaFf2P07Tl9Lk1/sDQBRF1Pd9TE5O egBQLpe9ge+flMtlr1KpkCzLSJZl5FOf+tSG9eAFGCcsOyaELNB+HIDrMj8RTO4BmRDBxwFky8vL n9d2MKYbYBzTls4MZWqjgjymNVvtI6+5z6YfVp5lGT7ykY/g3e9+N7a3ndJXX4ErsC+78o0Lt9xy Cz7ykY8YN04SmZqrtUDW3oQrK7fV7mVtdH24zlUmOrbzpWku56P/TVZXHjY2Nr6Cvvl/ZO0/+gGA FAAdMH92jGj7KoiiiLJDrCuVSjSKIlqr1YhQntv8D4wnACBN06cxatZ3FQJEpq9yB4htMuGcnj9/ /rEsyxYc+9e6AWxNTbK6vMw9jzDgQnOvXQNiP6b+vvCFL+Ctb30rHn/8cSf6V+DFC8899xze8pa3 4C/+4i8u9lCMYBICxmW2RbSxYX66b9iljQ3Td5mfbOddGQ3R/G/5rDaXlpb+Af3lfyzinzF/lvt/ JCBP599nloFGoyGVaEul0q62/LjTNM2XfIKNbZzGAJ4Z/JbRX1IYAggopVEQBKzMB5e/H+pUvzKg FgfDy7rdrtYKIIMwDEdWA7j4l4pg+uMIA+NI1nk1BRc8meAh0zSeeeYZ/Kt/9a/w6U9/2qrPK/Di hT//8z/Hm9/8Zjz44IP4+Z//+ctCCDCB6jsS63Tt8woQLrg2lj8Z3TzzZR6Nn/8tlUrSJcmme+71 en89YLrDFQBCIOCu4D+RBmP6LF/H0aNHd/HBmZkZMjMzQ7rdLmk2mySKIi8MQ69SqZBer0cmJiZQ LpdJp9PpaAdsgHH39tzyPO9G9PMB9MAFRBBC0izL+M2CRIatAh3OLt8/+sIFBeCFYbjRaDT+hW7A Kl/P2tqa1v8v0hDrZNd8uVim+81TpsOR4RYZC5CnXPzQ0jTFX/7lX+KRRx7Bq1/96isb0VyBEdje 3sav/Mqv4Hd+53eGMTtZluHee+/FDTfcgGuvvfYij1APLCbgnnvuyb2LoAwYDRs/uwy/CMVkHI1d VicTFkzWV1srJ/udnZ2VZsZUPU8Gq6urf7C1tfU0IaRLhO1/yWjuf+p5HvV9nxJCEEXRrnz/g/z9 w474tL8sJqBer3tAf5+dSqUynBezLPN838cf/uEfbkkHagljp2YjhDxH+3EAvBuAT4xgA3ybIWnh l+ERAT9l12fPnv12lmVPu97D1NQUfN9XmqzySJsy3EvNCiBeyz4kV7o2+Lpn9/nPfx5vectb8NWv Oqd2uAKXKTzwwAP4wR/8Qdx5550ARt/VXq+Hn/u5n8PnP+9s/Nt3uOWWW/DRj350uDoAcNOcdSCz sNng24ILXZsyG5ou5nxd32I5IUSZ/U9HK8uy5aWlpQfQz34rJv9hUf8UGK7pz6IoysrlshUflJn7 y+UyLZfLtFQqUVbPftvtdq70vzyMawFAlmWU9LcHjtF/MEzj94XVACLwFgFXoNjtVvAAkKmpqWYY hq/UNZZpunEc7wpG02n6MjzZuU2ZWC6O8WJZAUwrDnRtbepU+FtbW7jzzjuxtraGM2fO5DadXoGD DZ1OBx/60Ifwnve8B6urq0o8Zgm4/vrrD4Ql4LrrrsO9997rtJWwDGyEfJuVAbZ4MvxxtX3duQ0t nfavUnImJiaksV8y4HHa7fZ9y8vLfw2gy6L/Pc+Lyc7Wv5nv+6nv+1kQBBmL+pdF/svM/t1ulwzq EATBUPsPw9CbnZ314jiG53kEAIIgIHNzc+0vfvGLY71EYwsA6LsBXo6ddL8MeDfASJIEuDF+Hl+6 BBA7lgwPwPLk5ORbdQRlf3wURVhaWtIuBRRp6Mz+ql8To8/L+G3Oba5ty/K6AviP0vQBPvjgg7jr rrtw/PhxMH/ZFXhxwN/8zd/gHe94Bz7/+c9baZ5ZluGee+45MO6A6667bsQdoAOZWdrVwmfrinPB sXU76Opdff0m5i6jI5bPz88jiiIAds+U4Vy4cOH2drt9bmD+57f+Zeb/dCAADM3/KgGAN/0DQKVS oZRSzM/PD8sbjQaSJCG+75NarUbCMCRpmhIy2PfmAx/4wKZ0wA5QxO4sMYCz6Af8yZ5gXqbPLy3k 3Qu8G0DEzZaWlp5LkuQbLjcAAJVKJVdqYBt/k22drty23oTj4q/jcWzcAzY0XPs+d+4c3vWud+EX f/EXsby87NTnFTh4sLGxgfe85z34sR/7MTz9tL03j1KKOI7xrne968C4Az72sY9ZLxFk5zam+Dzz johrMz/lnWdc3Kc8vuzXdV5mQd8298DjZFl29sKFC9/CjvlfTP/LlgCCDIL/xGQ/QF/zZ9p/pVKh 7GDXsv7L5fKwfHJyEuVymYRhOFb0P4NCtmdL0/SJwSmzKAzXRQ6ug8HBtHXefA/uF7ATFKjmyLa3 t+/WNlb86TMzMyM4OmHA5SOzEQhM4zS1dfWL6cB0b7YThA3YmvbuvvtuvOlNb8Kf/MmfjG06vQKX JnzmM5/BG9/4Rvzpn/6pFf5gYh6mpj6IQsBHP/rR3EsEbYQBGT2bOcyWvo1QktfcX9Qcy5fzeV/E e9DB9vb2fdhxcccYMH9w/n/Cbf2rWvonMn0emMl/ME7SbrelZptSqUSr1Wru7H88FLU/65PoP5ho QDOglIYAoiAI2FqLoqwDDMRgwKEl4JlnnvkLSqnzA5qamoLnec5M31XizvsSi3i2OEXQkwE/8Zro FaEtrK2t4bd+67fw1re+FX/3d3+Xa8xX4NKDr3/96/jRH/1R/PIv/zIWFxelOPw3yBi/6p06SELA 93//948EBuaZA8Rn4wIuQobtmMaxHpjmRtv+VM9DJgDoxjOoyxYXF+/D7tz/I1sAs+h/sT0L4JMF +fFQq9VG6ufm5tBoNMihQ4e8SqVCp6amhjkA3ve+9106FgD09yI+D7vthUWNXQSTVWDI6DEaVzAs 63a7W71e74sO4wcAeJ43fEFcmb7ty38xrAAmurb1eS0DLgKLTftvf/vb+Mmf/En8m3/zb/DMM8/s wr8CBwPOnj2LX/iFX8CP/uiP4utf//quetU7ZfM+HTQhgHcH5P2m+TYuz8xVizeVucxZumtbK4Wq b7G80WhoN2lS3X+SJA9sb28vYif3P9P8h0KAaP4vl8tZrVbLeKZ/7NgxY9QhLwTU63V66NChEddA p9MhlUolJha7DNpAEUGAAABKaeh53jFwKwEGDyjNsizGznp9NnDer89fK7vgzolwPrISAIBXLpe3 arXaD+gIygJjwjDEhQsXtDkAZL+6MpfgQNs+bPrW4dtc58UBRj9i08oDmzqxnlKKJ554Ap/61Kew vLyMG2+8Ubqu9wpcerC6uooPfvCD+KVf+iV885vfHJYXaamilCJNU9x999244YYb8JKXvCT3ePcD ZIGBeS1ztjCOEmATAGi7AsGmP1m9jQWAh8OHD1sl/xHvbX19/ZObm5uPDYL/Rtb/czn/0yAIsiiK siiKMs/zRoQNHfOfm5sj9Xqd8Nezs7NDRTgMQzIxMUHiOCYASLVa7dx9992F+EGLsgAAwOPoM+kS BhkAaT8/QDjICpgHVJYCXmjgLQDD45lnnnkgy7LnXTus1WpWmQHHMe0XbQWwpWPCddHUbdrJrAOu WoaKHoM4jvHHf/zHuOWWW/CBD3zgSqDgJQwbGxv44Ac/iO/5nu/BHXfcgU6nY/1e6N4x2cGAWQLu u+++wu+naOAtAUV/i7Z4tpY8W4aum2Nk53ktqXxfsjox+E8HwrhWFxYWvoJ+6l+W2I6CS/07WAEw tAK4QqPRoOwQqrxKpUIqlQoplUpkYmLCA4B3v/vdY6//Z1CYBQBA6nneEQAN9F0CvBUgybJMzAjI blbU7PlymTuAB5klYBhg2Gw2oyiK/olu0DKt0/d9rK6uGtf8izRk2r6q3NUKYCpT1evw89S7lIna P18utlFpFraQJAn+8R//EZ/61KewsbGB66+//ko2wUsEVldX8YlPfALvfve7cf/99w8z+ZlgHAbH A79E8CBaAmTg+hzGEShM3/A4ffJ4tsKCqQ+ZMHDo0KGhhdB2OSUhBJ1O588Ha/87A80/9jwvIYPd /7ilf8NNf6IooibTf71ep1EUIYoi8Nr/kSNHSLfbJeVymQwUURKGIQmCgFBKSbPZTF75ylcWEgAI FCsAgFLqD9wATFpiAkDgeR6yLJM9bV6Lt32rRXxxRQEB4PV6vedbrdZbCCFKx4/s5S6Xy1heXh5G m8vcASrGLavTMXuTud+F2duY+4s08+vKZExe194G3waSJMEDDzyAP/qjP8LZs2dx/PhxtFqt3PSu QH549tln8aEPfQi/9Eu/hC9/+cvodu3mrTyWKRO9g+gOuPvuu513PZQx7LzPbxxroqnehaHzdbZW Vh48z8NVV11l7YrkaGYLCwsf7Ha7S4QQJgCwQMDU87zE9/10sOY/C4KAhmFIRfN/s9kkwCjTZ3D4 8OHhQKanp8na2hppNptkdnbW63a7Xr1ep5TSoQAwNTXV/vSnP13YMqgiXQDA6GoAtjGQSshwZfpi G9GKwJ9nALKNjY1VUzCgynfF9olmODqzmKsvise1NXnp6Nvi2tDQtd0rEMftsrpARovS/nKwz3zm M3jzm9+MW2+99cqqgX2EBx54AD//8z+Pm2++GZ/85CextbVlxSDEb8nkGtDRULkDbr311gPjDrjt ttt2rQ4A7JitzbNTPScdvk3/Io6Jqdvi2LYV36FWq7UrGY/NPSRJ8sD6+vpz2DH9pxzzTwkX+Mcv /eO1/xtvvBH1ep3W63WrF7nZbA7xZmZmUC6XSavVQhRFpFKp0Le97W2FRP8zKNQCACD1fX8WwCR2 uwFUWQGB3SZ+MUBQ9fBkmj/AuQGCIFhvNBo/pBu0TBqsVCpYXFxElmXagEBdnYgjlvP1sjqxXlYn 6091X7Z1smuXMhnk0eplmozKJKmDp59+Gp/97Gdxzz33oNfr4ZprrkG5nDcs5QrIYGNjA3/2Z3+G X/u1X8PHPvYxPProo1bt8gqfeYXULMsOlCXg+uuvt7YEFGEpkVnwXPp1tQTY0rHV/mX0jx49Ks3G Z5pL1tfXf39zc/NJshP4x2f/G/r+gyBImfZfq9WycrlMgyDAqVOntBMVr/0DOxsATUxMYGpqitRq NUxMTJBSqYR2u+35vh9/53d+Z2H+f6B4AQBZllHP805gxw3gDSQl4nmeN9gbQPyXqHBu+/bJmP+I ILCxsbE0Nzf3zzzPU9qBVYwtyzJsbu7OtugiEKiYuY1AIKs3lenOVW1NuHnKZDCOEOAyyaj6WVlZ wV/91V/hk5/8JJ544glMTEwRObEwAAAgAElEQVTg6NGjzmO6AjvwwAMP4D/9p/+EX/mVX8F9992H hYUFY5s8vv0irVIHXQgQnwUhxJqx5mHwMnx2rXLjuZS5mPN5HJv6ycnJ4dp5FcjmiyzLzj/33HMf p5S2CZf6d+D/H/H9l0qlNIqirFarZQCG5v+pqSnthMf7/qenp0mr1aKHDh0i9XrdL5fLpFQqkTAM ie/7BAA2NjY6d911l5tPyAD5na1q8H3f/18G51vom01i9IWBXpIkXezeTYn5NGRuAdEKIP4S7Lgy /MG5j53sg+HJkyd/qNls/qpu0LKXII5jfOMb3wClFJ7n7WLwsoPRMl2LvyYrgKnO1MaErypzFQJk E4OqrQnXBKbJR3avIt7c3Bze9KY34ZZbbsHLXvayXON4scFDDz2Ez33uc7jzzjuH6XrzMPA8Zt9x QKQZhiFuv/12vPGNbyy8r6Lhnnvuwa233qoNoJRptEVZVPK4F20Yu02ZTPvny3jBSKy/9tprUSqV jM9FrN/c3PzEs88++ykA24SQNiGk43lelwyCAH3f7w2W/qWlUiktl8tZqVSiN954o/TZyOD06dPD 81arRRqNBgH6DJQXALrdrgcAP/IjP6LeESsn7IUAgCAIvodSeg2ADQDxQABIMSoAMKY/XFYxuJb5 +MGdi35/wh2M+XvgBIAgCGove9nL/tTVCgAATz31FJaXl3cxel4gYO11AgGPIzt3+VWdu1oBVPft KiSwMpmmIQOZxqLCtzH56zQgk5DAw5EjR/DDP/zDeOMb3zjycV4B4LHHHsNdd901wvQBt1gTXbmp zhZcaQRBgN/93d89EELA3XffjVtvvRVxLHcDu2j6vPA9jnBm8z+zb1gXyyBj8KpfGaMX6yilqNfr uPrqq4d92CoMWZatP/HEE++I43iJELJF+gGAXUJIz/O83kAASMIwTHzfzyqVSspM/2fOnBnSW1lZ 2TVxTU1N0SNHjoyUt1otAgCNRoPUajVSqVRIu932eAEgCILem9/85m2R3riwJwIAgEO+738/gB6A DvopFNl2wbFgBcgjAIjCAL+3gM8dTAgIbrjhhndUq9V36gYtYzSdTgcPPfSQlfZ/qVoBZPemshDo cE1leXBM+ONaCfi2LsxhZmYGr3nNa/D6178e3/3d341Go5G7/4MI29vb+MpXvoIvfelL+MIXvoCz Z8+O1Lv47veK6Rfh8wb6loCDJAT863/9r4dCQJ53O6+1RiYsmIQHFyuArH4c7f/48eO7koPplAVW 3263/+ypp576PQBbhJDtgfbfGwgAsed5SRAEiUz7n5qa2kX8yJEj9OzZs4S73iUA8Mw/iiLS6XS8 6elptNttb3Nzk/zLf/kvN0h/74FCYa8EAPi+/yMAagDWMYiehJ0AAOwWAlzdAP6gbGgFaDQasy99 6Us/TQjZnQqKEVEwmSeeeGIkL4BoAVAxeYbD095rK4DqfBwrgA2OSlMfRwiwtRIUASZB49WvfjVe +cpX4hWveAXOnDlz2WUd7HQ6eOCBB/C1r30NX/va1/DVr35116ZLJr8rj1cEThFtdLR4ekwI+L7v +77C+tgrEIUAHYhWgSItAi7CgA5XxuRlbcUYCLEdX18ul3HNNddI79UAyTPPPPP27e3tZwfMn8UA MOYf+76f+L6fhmGYhmGYlcvlrNlsZrz2f+TIkZEbZgKAyPwBuQBQq9W8qakpurGx4SVJQl/72tdu 5LkZE+zdjAq83Pf970DfDdAbCADJoI65AtjyCjG3P7B7pQCwm/Gzc6b9Azu7DfJWgBBAeNNNN/1v pVLpTbpByxhAu93Gww8/vC9WAB5PHI+tEOBqBVDdt60QYDL92wgKOpq6MdhYCGz6NN2DOJ5Tp07h 1a9+NV7xilfg1KlTOHnypJb+pQZPPPEEHnnkETzwwAP4m7/5Gzz44INa/CKY+n4zfVc3xEEWAlzM /yK4/m8ya4DJLWASBGxN/3yZqP3z9ceOHZNm/jPNF91u974nn3zyP4DT/smO6Z/5/5MgCNIoitIo irIbbriB1ut1evr0aWOA3vz8PDl37hwB5Kb/+fl5AEClUvF83yerq6vk4Ycf7r397W/vmGjngb0U AMq+778FfSbfxmAnJYxaAXgBgBcCgN2av/hW8YICsGMFYL+73AAzMzPXHDt27P8ihCjzH7hYAURL AGvvagXQlYljKsoi4FqnejYyZq0TAvbSpG/DuG1wTP3I2vu+jxtuuAE33HADrrvuOpw6dQqtVgun Tp3Stt1reOyxx3DhwgU88sgjeOSRR/CNb3wDjzzyiJRxyOBiMP69xDfhHlQhIM8zU73feVw2KgYv lsn6UjF9/txF+69Wqzh27JjxW5fVnzt37ufW1tYe5rT/DumvAOj5vj80/7Po/2azmb7mNa+hosYv g/n5+ZEOp6amyPnz58nJkyfB0v0O1vt7vu8T3/fJ2toaOXPmzDopaPMfEfZSAEAQBK+nlB4GsIl+ MCDbS5kXAJhVgAkBgF08gMwNwA4xGNDHIDnRy1/+8veHYfjPdeOWvRidTgcPP/zwsF6n+YtMX8bc 2bpUF2uArN71fC+sAKY24+K5gGhtyIvD4+aZEPnJdW5uDrOzszh9+jTCMMR1110HoB9nwBJOXXvt tdZuhU6ng8ceewwAsLy8PPTPP/bYY8P39MKFC3j22We1dMZl3EUy/r3CzdPmoAkBP/uzP2vlDmCQ 939zMfnLrk3nOleAiKO7Pn78+DANuOlb5+vjOP77xx9//Ncwqv13Pc+LCSGx7/sxC/5jvn9m+jcJ ACLz590FCwsLnkwA2Nzc9MIwTL7jO75jS0d7HNhTAQDA1b7v/zMA2+hr+rGFFQAYdQUwZi8zr8iE AGYFYBYAfkVAcOTIkRvn5+fv0A1axZjyrAhg1zKGb8P0bawApjLduanOhK+CvELAXloIRJxxzMsm +nvZ1kRjXK19vxh/0Xiu7XV0wzDE7/3e7x14IUDUeHVM21RvKndl/roynVCg0/5rtdpI5D+7L9V9 8PPMhQsXfm1xcfGvCSFbADqe5w3z/w+W/cXM91+pVFJX0/+pU6co0Df5s/JKpUIWFha8RqPhsZz/ s7OzWFtb8wDg5MmT2wOeuSdQdCpgEZ5Dn/mX0M8IKNPcVeMiAo4tR+AFBj7PQAogO3v27CNxHP+9 loDihZ+fn1ealVTSq0hT9hLrxqD7WExjtzm3oa3C193DuJP7uAyqKNO2DS1XGLfvcZ677XuXp972 Wdn+P3mePd8uz/NjEMcxfuZnfgaf+9znnPq/GPADP/ADuP322+H7o3ndZN/tuN++jraJromWbs6T 3YPsfmZnZ63GK5YnSfLE4uLiP6CvnDJ3dUoGOf9JP/MfHeT9p0EQUADSqH8ebrzxRvq6170OjPnz UKlUCAAcPXqUzs3N0dnZWTo9PT3ES9OU7iXzB/ZeAKBpmj4GOUOPgiCIMKqpe4DU5G8CkSvzAgBP LwOQLS0t/YH7rQClUgmtVks6yeg+NtNk5vIByNqNe+7al4mWWO4q7Ojo2jybIhi2afLMy2htGaSM FtN2xmH+ruO1qS+KobsyfRtmL2tjCwdJCPjBH/xB/MRP/ITTf2Gq072HYrnsXIZjO8flEQZqtZo0 xbfN89jY2Phv6FuoR1L+oi8EDNP++r6feZ5Hjx49SlT5/W+88UbKjtnZ2RHexLR/xvyr1apXLpc9 lu2PweTkJPV9v9C0vzLYawEAAB5FX/suU0pD7DB8BiKDZmUiMP8+FDg80xdpj1gCzp49+/UkSf5W N2jVS8OsALbSqYmJ2b7oYp2uTDd+G8jT1oYp5WHaeRm9zSSXt09XwcyVqbnSdR2Ta10RjH9cHB7P 5XnK+pA9O9XR6/Xw0z/90wdCCHj9618/PDcxatm1bR1f7zInubbl68T/XYY3MzOjHKvuftI0feyF F164H/28NSxJXUqEnP+89l+pVOggqQ8FRpk+oysyfxPMz88P44U8zyMnT568LASADiHkHNRMHxhN 3kOEQwc8HZlwwJg/+00xiDlYXFz8RJ6biaJo+KKpJg3pQC1eYBFf92tDQ4ana2/74dr0Mw6Oqo3N mMa9HheKmFTztNW1y8vA95Lxuwgu4zB8GeN3hTiOD4QQ0OnsrBSTCTsy0M1dpvnKVnC0nbN0c51q zOy6Xq+jXC7nep9XV1f/CP2l6iPMH5z2Twihvu9n8/PzOHHiBOr1Oj1y5Mgupq8DmfZ/4sQJevTo UcqW/wHA0tIS6Xa7yV5F/vOwHwIAkiT5FvpMOKT97YFZZH4YBAFLzONyszpcKhy89j8UBM6ePftQ HMdf1naieGEOHz4Mz/OUH5bq49NJt2I72a/NOMc5N9XJ7skEtky7COaomzBM9TbP2mYyNbXV1bvW qQRQm/8oz1iLZPw2NFzeMdN9jyvoMSHg3nvvHYvOXsKdd94JIJ9ioKszCc2234Ts3HYONfXD+/5d xp6m6UOLi4t/h0Fg+kDrH+7453leykz/vu/TRqORzc7OZqdPn85UjH92dpbotH8mNJw4cYIprvzy deJ5Hpmfn++q2hcJ+yIAAFgghKyin5BnBAQph2I0ra/O5C8Dhs9r/vw5LwxkCwsLf0Apdd5dKQxD HD58eGdgDpOviuHbMiARxyRl74UQoKszjc22rSuMI0Dk6V/8j10mU9OkZFO3V88qb3/jMn4Xpm8r 5Nj0K6OnOpg74FIUAm6//Xb8j//xP6yfsU7Ac6kb5zs2MXnVdyOet1otRFFkPQa+bmVl5Y+Z3x+D Zemkv30928aeMgHg+PHjQ9O/1Q1ycPPNN+PMmTMjewXIYHl52UvTNCN7kPZXBvslACBJkm9jIOVQ zgpAKY3CMIywYxUAMGLC54FdE+GX1ZmOEXfA+fPnv50kyV/qxq16kebm5lAqlZw/KpeJy+ZXVVYk uEjUrGyv8YoGG8FN105HN09/prY6MDEyXRvb8v2qF/FcmIvs3bJ9HiqI4xg/9VM/dUkJAbfffjve 97737Srf629G7Et8njKGrRqXbJ5U4fJtfN/H9PS0tJ4tD1S1TZLkG0tLSw9g4PsfaP0pgNTzvITf 8vfo0aO0VCpR3vQvo8tr/jfffDNlh4C2S+vnDszOzu6L9g/sowAA4Gn0MwKyME3xochS/4rxALJo f76NSmDgcVg/KYDs/Pnz/5nmsAIQQqR7ycsmFxvGonv58zB41Qdnc67qSzUOV4nfBc80cdjQzcM8 XOjb0imibRHMtIi+xhmLixCch+mrGH8RQCm9pISA22+/He9973uV76zuGcrmHFm9TpCSge77dWXw snZ8m5mZmWGOFdNYRFhZWfkjXvvnov8TPvjv0KFDiKLISvuXMH1dLNtI+fLyMgGAwXj2BYL96ghA lqbpk77v34BRU71HKQ3CMCzHccznOxaj+WXnwO7lhSIez/hZv+ngPFlYWHjs0KFDny+VSsqMH5TK c8k3m01MTExgfX1d2k6W5EZcQcCu+XJTEhwen09yoSrLcy6rsxkTj6vKmeCKZ1uuomVqrxN2TCD+ l7btZfWmZ20zWbrW5cHfy3HkFXLHpeXaHxMCfv/3fx+33HJLof3Ygqj55/lGVe1kTF+cu1RlprHk VXREQSCKIjSbTeM3LauP4/h/Li8v/yN2tH9+3X9ar9dpFEW03W5nvu9rtf+3ve1totIqA95qLVoA hu3X19f3PPKfh/0UAID+ksBT6KflZZo4S3SgemPYA+Nz/rt82ZRrz9NisQD++fPn//OxY8feQDR7 BKgYz1VXXYWNjQ3tS6hi+uxc15/tr6yNOO5xhACdcKAqMzFrVzyxXLYcUzYGl/YuoNK6XNvZtL8U mP9ejWHc52aLV5RAwOj0ej28853vxB133LHvQsBtt92G3/iN39Deq+w7GOfdMzF6nVBhYvI6YUA1 NpZGm+HphH+xfmVl5ZMAupz2P7Lu3/f9LAiC7NChQ6jVapmo/QtMn4E4ANtlgN7y8jIhhJATJ07s m/kfGF2atx+QBEFQp5S2sLM3AEWfGfu+75Os77ihwgHuVwaymACxXpTAhlLY9vb2RqvVmg2C4Hrd 4GUvWBiGSJIE29vbuqa70gfz9MRfXZ3sV9fO9txUZ9NGBTY4MjzTR22iNe6Er+s/L23TROsiCOnq 8oyv6H6KYPxFWASKtASItLIsw1133YXTp0/v246Qt912m9Tnz8BFUMr7fen6NJ2brA98nSgIsOtG o4GpqaldbXTfPbvXOI6/fP78+f8bfQGgO3ADDHf7azQaWRiGaalUSsMwpI1GI7v22muzN7zhDdm7 3vUuevr0adWQVQKASvsflnU6Ha/T6cQTExP7Zv4H9jcGAAAQxzFbEsgH/jFLhIrZs4fGX7sAT5cd I8mBnn322d+llGr3XFa9WPPz8wiCYNdLKmuve6ltpF7TuFwk8yKYRJGTuOpZ5KFbBPMXx2Tb77ha lniY2rj2ozp0+K79531G4hhtQIVrQ0P3PFTPSLyO4xjvfOc79yUmQGT+qjnEBKa5RvUfuH4Psv5U ZbbzHyFEmfLXFPhHKe2cP3/+DvTX/fcwqv1nvPZfKpWyVquVzs7OZobNfmR+fhseNQwAJISQ+fn5 Pdny1zSA/YYNz/Oex07SH54hg1sRwEdHAnoLgM5KIFoSxD0CMgDp+vr66ubm5u/nuaEgCMAncgDU E7nrB6v7SGS/prI856oxyfqzYRaujE036YzLhFSTnys9sZ0rA9ON0bWNaz9Fjasoxm8zLtP/J/ve bIUeU9+yvpg74J577nGmaQu33XYb3vve92rHogLTnGPz7cveb9077yKUyOYQ1f81NTW1a98DW2i3 23e22+1z2Fn3z1wAaa1WyyYmJjK22U8YhsPAvxtvvJFamv1V9bz2P9JuZWWFdLvdmPSXHe4rXAwB AHEcPwIAlFK2S58HIBhcq94WUSBgYPsV84IG73oYWgGeeOKJ/55l2dNaIoqXeWZmBvV6PdeEI/s4 VWU2v6Yyl3NbJmk7gdgKGar2LuW2fbiMIw9DHpeRu7xHujHoxmbTR56+bdrZMGMbPBnzKBJM9Hq9 Hn7qp35qT4QAnvm7ClKmb073zFSMXkVDpGMah823y9MLwxCtVkva1kSTUrr8wgsv/Cl2cv4n/OH7 fhoEQRoEwTDpDwv8Uw5SDiahwOMOQgghc3Nz+679s4FcDFghhCyinxiIf7gUGLEC8KmBWT0V2vAg e/AU3G6AXPtdyYGSJIlXVlZuy3NDhBAcO3Zs6IOy+UBlki675svFMtmvqh8Rx/XctcymTofnOrnJ yk00TcwwT986cGVGeRiXC2O2ZcgqgcBFIMlTJ+vHZqy2dF3BheZeCAGi5q8bm4oRq9oV8axs3jHT nKaaA0WYm5uziluQtd/Y2PhkHMfr2Mn5P9z0p1arUcb8S6VSxgf+KbR/mTIKoUyMN9vFb1dXV704 jpkLYt/hYgkASJKEWQFGYgFo3wrAA8/0ZVYAUTgQ24i02C/vChgKCU899dSX4zj+a93YVS9nuVy2 zhBounYFG4FA1051bisY2DBGVyaVB/IwcFe6LnRUjFM1Vpvx206WRQltNsxehu9aJ/blUu8qULgc rjSKdAcw5q8ai+39m75jEdf2GY/7XegEAnEszWYTlUpFSUfVBwCkafqt8+fPfx4D3z8ZrPkvl8tZ rVbLWMIftuEPv+zP6ob6YOMOGGr+GGj/s7OzF0X7By6iAIB+euAL2G0FAIAsDEPmGuCZvunP0FkH qOZg1oEE/X0Cfgc7yxPlxBQv+uHDh4ebUthMKCb6qg/E5tdUZrqvooQAm75Nk4vN2G0gDwPU4eel VyRz3iv6Lu+rCd+W8evqXMaY97vLMz4ZbhFCAM/8xXG4/JeyuUTVRtfWpkx2bjNP6cZLKUUQBJie npa2MQX+AcDy8vLvDoL+mPafEEISLuNf5qj9m4BXVHntf9h2dXWVDLR/La/ZS7iYAgBvBSgNxuJj kB5Y00y0ANh8lTJ8CiEQcPCbLC0tPd1ut//U6ibEjgjB8ePHjWtS2a9K2pXhiWU2v6Yy8dw0ZhO+ DUNyZSriuSszkLXX1dkIIjb9FQV5BBNbGrpnaerDhsHmZfx56boyatvDdXxA3x3wjne8I5cQ8PGP fxy//uu/nvu/dxF89pL582ORtbcVCg4dOpQ741+v1/vyysrKI+gv++uVSqWkXC6n5XJ5ZLOfMAyz crmc5dD+Ve4AEUbS/xJCyMzMTNuyjz2B/c4DIMKW7/uHAFQG0hnFIBEDgMz3fT/LMopRJi9eM7Bd Gqhqy0dret1u97FWq/XDhJCSBH+noYTRR1GEJEmwtbWlHYhpTf24+QFMbXXnqnsT8SmVryW2WdMv S1Tiui5Zh29KCMRwimTirE8bQSgPPl9umzMgD21bXFecvGPK28Z1XDbgQi9NU+c8AR//+MeV0f6q d9rlPS7iGds+cxshQiUosKPRaAwD/xiovhvJvNM5f/78byVJskwI6URRxNb7x77vJ77vp2EYJmEY ZqVSKatWq1mj0aBzc3P0u77ru0Tt38bvz+OJvv9h+erqKkmSJK3VahfN/A9cZAsAMNwqmNAdK0BA +5sFsZ0DqXAAow84zzJBRkuWdCgDkKyvry9vbGx82DR+1Ydw1VVXIYoiK81iP7RIvh8b6V01LpM2 4IJXJLPaK6aVZzyujHWce7bRVMcdi+lebTRNW41a1862jW19HshDr9vt4u1vf7uVJUDH/Nm17L5s n0Me5m8CWy3eREP2XnueJ13zb/teb29v/0m73T4XBAEf9JcMNP9h1L+F9q/SNGRBfzIQt/z1Lrb2 D1x8CwDQtwLMAagO1mTyVgDP933m45H946J0xv+qNH1Vm11Zm5aXlx+fnZ39Dt/3j+huQKUBl8tl LC8vD69Vh47WXlkBdOemOlYmaqE2lgBVmQzGaVsEuGrreftwuae8WrAJtwhhzHUsRVoBimxvAyo6 MssXsGMJuOmmm5SWAGb2dx2H7L20fVdNz0q0LJgED5Pg7yosHDp0aFfgnzg+EVhZmqaPPfPMMx8K w7BDCGkHQdAbaP6x7/tJEARJEARpFEVppVLJKpUKnZ+fz6amplTavwxkAelaC8Da2pqXpmlarVYv ugBw0S0AAJAkycPoa94hBrEAlNKRTRIE4B8uuwZ2WwpMwDR+WSxACiA9d+7cv0d/F0M1EcVLPDEx MZRebawApmu+XCyz+dWN1eZDltXb4pnKdGOy6SOv1uFSZ6vputDj6Zo0tUuZ+eexBLi0t9X2dXT3 mvmb+uv1ekpLwEc+8hEl81eNXTYn2LRxEaJU76RIR3Yta8PjqvpgR71eR6PRsJ5/hLrkwoULHyOE tLmo/5gF/fGBf77v0zAM6eTkZDY1NSVq/zqtXsb8VcBi3AghhLRaLX3u+H2CS8ECAADbQRBMU0pr LCUj+mkZKfp7BICLBeC1eBWz1/0ZBKM7Dcr8N8DOPgFbzWYzjaLoVaabkEmjjUYDq6urSBJ9oOel EA8g69uk4ZvGq5LSGQ77gPNo9jK/p0oDM9EvwrIgm4xUvllXZpRHsMhLtyjhI29dEThFMfsiaPLt 0jTFZz/7WayuriJNU3zzm9/Eb//2b+O220bTj+g0eFd//zjWAJsylYBuEhxkv+wIggBHjhzJtT8J AHQ6nf++uLh4XxiGHc/zuoSQnu/7zAKQBEGQhGGYhmGYVSqVjDH/l7zkJWLkvw3z569FzX9E+19f X/d6vV58sX3/DPbPnmqGKd/3/ynpL4mIB0c6EAjiOI576C/NY0w/E355oQCW50OfzODwB4eHvjUi ABAGQVA6ffr0J/JsFgQA7XYb3/rWt4YfIzs8z9vlCrC55svFvvdLCJAxdhcBIS+OLagmSdNk6DK5 8rAXDF0V8OVa5jKGoqwBecc1rmAw7v3naat7b/dCENEBL/DaPksZbpHCgMsvO6666iqp6d/0XQ/o nH/qqaduzbJsLQzDtud5bc/zup7n9Xzf7wVBEIdhmJRKpaRSqaQTExPp5ORkdvXVV2dveMMbMmC4 259JkRTP+V9+CfvwfGNjw2s0GmvkIi794+GScAEMYMXzvAXaDwAcwuA6CMMwxG6LhWiq4X9ZvcxK IOIwEBMDZQDiJEl6i4uL/x45cwNUKhVcddVVUnyVOUx3zZebQPWxqcpk92JzrqJjU6fDKULrEsvH 0Vptn7uujS3j1PU3LqMet8y23OZ52z5XU7+mOpe+TOPYiz5c3lnTe2XzLqi+/7zCmmxucmH67Jia mkK5XJb2qVrzz49lZWXlw1mWbYVhOJLyl5n/gyBImfYvC/wzMH+VS0DG/JnZHwCwvr5Out1u71Jh /sClJQAgjuOHB6eM2XsDN4CMgYvaOwMV0xeBCLi8ZYGlDk7Y9dmzZ7+1vb3930z3oPp4Dh06hImJ Ce1kMY4QoGP04thUk4DthGIjBNgwA1vBw4UJjgu2fcmevUubccdoU8aX6xjTXggZunt1YZA2zF2F X/T7MQ5NU1vTty6rs6FtmjdMtMXxydrrxmv6Fc9LpdJwm1/XZ00pRa/Xu295efl/DqL+GfOPuYQ/ qed5w6Q/URTR2dnZzLDhjw7EgD8Z8Ov+LwnfP4NLSgBAf0XAc9gZF6X9YEBmBYhgF7fgaktmjJ/9 ygIDk0cfffSOLMued6Q9hOPHj+/aNng/hABbRmuqU9Gzbc+XuQgKprHYMgfdmGT0TQzelpYN6O7B RMtlDKr3TYbjQs92PEUxfRvGqGub57ChpepX1U6sV7WzAdlz0dGyfb91NG3nCtO8RWnfFSHm+reZ f7j65fPnz99BCOkODhb4l4rL/iwC/2Qgmv1leJ5wEADY2NjwOp1Ol1yknP8quNQEAPR6vUfRZ7ps jwAZsE2CVMD+TBUO5Q7e7C8KABScNSBJks7S0tL/aboH1QsahiGOHz+uxZHRKlIIGOdjVtEx3Y/t pG/TxkU40NF1YUameuAMkdYAACAASURBVFfGZtOHjuHYjM+2H1sclzG60OXbFcn0bZmzK5houfab Zx4Q+xHp2PwPOmZqQ1P3XeWFmZkZ9D29u8dj895vbGx8Io7jlSAIYkJIz/O8nud5w3X/LN8/0/75 3f447d826I8v549duBsbGz4AzM7OXlLaP3AJCgAAOkmSPI4d6cmn/TgAH4AXRZFs7wDxT7ARDqhQ xg7eNZBidCfB5Nlnn/2HTqeT2xXQbDYxMzMzxFEdOhqyfvIKAbpxmxi/yyRgM0G5CBUycGEgNnWm MdgyaRE3L2OyZS5FMv9x/yvV5O3CwHVltuM14dseYts8/bjUq55BnnG4fP+6ecDUv838I57XajXj kj9dea/X+8Li4uKXBsyfaf9sm9+E1/5l+f4HZGwtx1JGPwAWRM4HAGJzc7NN+rltLim4FAUAAHgK QBd9KwBjxsOHF0URcwVIt1iERhoTcETg++GtAiweIAUQP/LII7+bpulj9rczCldffTVqtZrVZGO6 3nUDjkKAzQevoi2eq3BMuGKZjr6qbC9ANmHlGUMeQSYvDdvnbiNM2AoELng2zNuV6bvStqVp6k9H 1/SNmASLPOPTPbs8z8+2nYgrnpvwwjAcyfbn+v5nWXb+hRdeuE1i+t/F/GWBf7Ozs+Rtb3ub7jZN qwH4VWQjbTY2NgillM7Pz1/0pD8yuFTyAIhAsyzreZ53iF2jH0QB9E9omqYpMKK1j7TnDrHcBpgV gL8eQpZlNMuyb0xMTPwQIUTlpmBjlZY1m00sLy9rd7KStTflB8i7PFBG37QGV9aWUrflgTb1In1d O1n/unJW5zqWIkDW734w/6Lom4TQcfq1GVNROC6wl8Kn7h3VjSXP0lXdf2eTuyKPkiBj/p7nYX5+ HkGwexq1yfMBIFtdXf2t7e3tp4Mg6A6W+3X5fP/imn8+49+b3vQm3HzzzaqHJ1MixfX+7HzXkj8A fq/XIxMTE5uXUuQ/D5eqBQAAzhFCNjAQUgarAYDBXgEDVwB72KxuxFIAs0lHVs/8//y5GBSYLCws PL65ufkx002oPrQwDHHttdcOX3KTJmFzzZerxmHC153baDa6chXI7kOFp2qnuycVvm4seSZ61f+m wnUdm6of03+uutaNLw8tFZ7LvZqeg83/U+R/aHrG49AXy/l6XRvTd6jrV4ev+37zMH/VmPk2zO9v +26KZe12+1MrKyvfCIKgN9D++WV/qWj61wT+qUDG/MV6MfAPQF/7z7IsJYR0Lfq5KHApCwA0juNH BucR3YkD4P80pv3z2ZbEe7L5A5m1gDF+3nogEwJSAL1vf/vbn4nj+K+NN6L44Or1ujQ/gKp9HiHA 9IHKxmiaXGwmH5cJzhbHti8ZPbHcRuBQge3YbNYsu9LVCTY6ZuXK/PPQMuHlZfy2DNhFMCiCwbvQ sGHsNnU296ejYfvfyfBtBAEXRt5sNlGr1az6kkGapt86d+7cn6hM/wPtf8T0zwL/zpw5g9e97nU2 2r+qTrf0j6C/hJ00m81N7U1cZLhUXQAMOkEQ1CilDQDJIIhi+McEQUAGrgDmrwfstX7T187jyVwM BADa7fY/TE1NfT8hRL5jBSOmMO3VajW02210OurMkLLMgDKaNtn+TCZ+ndnf5C6gdP+yA+6lqZ5N PCpXQt6xjJsxLo+womrnKhC4tCtSeMsznry0bKFoenmB/97yCC+iiV1HTyfQq+irfimlKJfLOHTo kLSt5RyyvbS09JtxHC+GYdglhFib/k+fPo0zZ85QB+YviykThYCRpX8bGxteHMe9S2HDHx1cyhYA AMNlgTGAkPZzAoyAEBCo891T4YACj8dnKtxwfwIIloD19fXF5eXlf2u6D90HeuLECZTLZSvtxEaT kOHKPlibet092GgAsj5s6cvuTUZX1VZXLqNhqnfpw0XTcrlvU9uimLhqPK79mzRcWZntWGz+O1sc l2McyHNvqjK+zqYvm29d1bfqWlZuYv6+72N2dtZ53DxsbGx8YnNz85kgCHroJ/yJB2b/WBb1z5v+ 5+fnXf5Enf9/JNMfNzaPEEJardYlrf0Dl74FAADSLMuo53kt9BkvCwakg/M0TVNmAbANBlS5Avg2 gLyduNSQrK2tnW21WpNBENxouhlVMF2j0RgrKNBWm7e1HuiC/mwkdNfAP9fAQVu6rmPKM8FT6ha8 VRTsJfMvQvAYV2Byqc/TZxGgo8u/Eyq8vBq8y7h07/U4/5FJkBB/2fn8/PzIen/Zc9LNB3Ec33/+ /Pk/IoS0fd8f2eyHmf4Hmn8aRVFWrVazRqORTU1N0de+9rU4deqUq/Yv/orBfyNL/3q9Htnc3Nye mJjoKfq4ZOAgCAAAsO77/iyAMvobBPEM3wuCAGmaMsbNL98z+XEYyBg+leCJzH9Yv7Ky8sDs7Oz3 DAQVLciYRRAEqFQqWF1dNU4GOuZtY/K3Zf4mxj4uE3epd2Wyqkmv6AnXhc64TGy/cGysHjoaRTH+ Ip7XxWD8e9Wf+P6LZUW9Xy7CnSvzn5mZsd7kRzafDJb8/VaWZeui6d/3fWb6T3OY/sV5Hdy1ON/z ef75qH+ysbHhUUqz2dnZdUkflxxc8i6AAdA4jr89OGf7BLCAQP7YlYKRA5N1QPVV8DiyFMExgDRJ ku3nn3/+PZTSDePNKD7AZrOJo0ePjuDpzJCqa1lfMhOdDEfWRsUQZHRscW3rTfenAh0TyqMluvTt SluHp/rvbdrlGdN+MX/VvZju0wbPloaunekYB1zfTd03XMTzUvVvMx5Vmazd5OTkMP+JDUjemd7y 8vIHBtn++MC/hM/1Lyb8ue666+iYpn92zTN/sd5DP/DPm5iYMPKASwUOigUAADphGEa0HxCYDdZV EqDvB/B9HwNXgModAKiZvAxU8QS8ZWDEHLS9vb0ZRdFTlUrlDcSgruqCAiml2NzcHGr0vGavo2EK 0rM9tzH1u1oHTOW29SIeP0mYNCS+3NSXSbNSWRhsaBcN+8n8TQwkT9m4Ql1R9eOC6n0z9Z/X9WQa iw1tNmab/0TH8HVtKO1n+mu1Ro2jNhY+vmxzc/PDq6urfxeGYYfT/HvM7+/7fhqGYRKGYcZM/9Vq lV599dX0O7/zO6nG9K9TFkW3r+j/Hy7929zc9Hq9XvdSD/zj4aBYAAAA3W73CUJIBzsWAB6CKIoC 7PwpDHRf1i5TvqSeYlTrZxYBPkUwyxSYPP300/e32+0/MN2L7qOcn59Hs9nUah0yzVinFehwZTg2 uKYxye41jxZig6fqX9efary249SVmTRGWb3tJGx6L1zbyMauoqECW0bvyvx1Y7apV/VbJKi+Pd1/ K7bP269sHDb/pexXvBdZmc03Jt5/uVzexfxN4xBxut3uXUtLS/8f2Vny1yNCtj8x1/+1115LX/ay l9Hp6ek8zF/lEhC3+SVAn/kDwEEI/OPhQAkAAJI4jp8CQCilQ2ZPd68OEE00jGmbQNeGcodsRUAy OOKHH374D+I4/rKpM9WHTwjBNddco00XLNJwFQJkv6oyU7kNrm7iz8OQdGBigjb4prpxGIotsyyi T1e6eZ5PnvsZh6m7MP39YvwmPFe6pjLdd25D2/b/UL0bNt8Ypf00vzMzM0aLmY5ukiQPnTt37g5C SIfz+/c8z2Pm/6HpP4qitFQqZcePH6e1Wo1OT0+7mP5VSiCv9fN4Q5czIcSr1+sb5BLM96+Dg+QC YLAVBMEEpbRC+lsrDnMDEELAuQIYszbZYk3BgOxaZhaSXRMAdHNz82utVutmQkjTdEMq09fk5CRW V1eRJOoskraR+bamftfVArZ96sps6mQ4lO599L2sD5cJneGaxmmLZ0NDde3aXkfDtrwImqa6vcTb C1D917IxFbEypQgB11Yx4H89z8Pc3Bx8f5TNiOPSzRuU0uXFxcVfT9N0NQiCjud5HTLY6Y8F/Q1M /2mpVErL5XJ21VVX0bm5uezEiRPZ/Py8rfYvOxfndYJRs//Q9J+maVypVA6U9g8cPAsAAKDX6z0G IKX97IAeAEr6qYIpAL9UKslcAYDcrKNi+mI7KjnE7IDDTYO2trZWnn/++V8FYPQHqT7CIAhw8uRJ BEGgtASoJHmTJUDEEcfi+sGrcFV9q56DCVfWfx5txgU/rzape+YmPNPYbd4DEw1XfNNzMI1Bd2+m +9OBy/+T53+0pWkas+47zCMU6cYh60+k5/q9ujB/QghmZ2d3MX/ZuDRjTFZXV/9Dp9NZ5IL+htv8 ssA/Pur/qquuos1mM2s0GlTD/GV8gK+TlfE+/yHe5uYmy/h3IKL+RTiIFgAASLIsSz3PmyKjOQGA vjCQDawAYuCeLejiAcRzvn5Eitza2lqtVqvnyuXyP7fqVLE8sFarYWVlxTgZ2Grl7AMVcWzLVHTz jiUvPVvQjUX1TF36U91DHpDRsmHutnTz4hchPORta9tuHFzX57MXgXs6EL9Z8T0Z5x5tyl2YP9Bf 7lcul4f4eYJ/O53OHcvLy18iu9f7x77vxyLzr1Qq2fT0ND169Gg2PT1Nz5w5Q4F+ojXWDdRzO4Q6 mel/uMkPK4/j2KvVahuEkEt+zb8MDqoAAACbQRA0KaVlspMXwBtYAsggNwC/KkAGfLkuElQFsjYj L9HKyspTU1NTlTAMX24kpvhIoijKnSNAR9fE8HV4svq8bgGbOhFHnBAPAoj/XVFMxEZDLgo/D6Ox ZfKu43Idx7j0igCdsMiPx7QKJU+ftnU2lhzdb6vVQqVSUX77NkJ/HMdffOGFF/5w4Pfno/75XP9D 0//c3Bydn5/PpqensyNHjtD5+Xk6PT3N5/rX+fch4KhM/+wgALC1teVlWZaUy+UDqf0DB9QFwKDX 6z0+iAMQ0wBTSilzBYgBgeKfKwPK08KOuZ8KRyac866AeHAkDz300EfHCQoE+jkCrrnmmiHT0B08 PZ1JUFZu20Y2bhezp+r+deZLGxwd/XFB9pzH6SuPZj8uM5fVq94fsf1eMX+bd8L2Odvg79U74vos TRp23nHqxqDqXzUm1bXqd2pqCtVqVXtP/LVYDwBpmn5zYWHhI4SQ7iDoj5n9Y8/zkiAIhgl/oihK 5+bmaK1Wy6anp02mfx5UCh9fzkf8jyjLW1tbPgDSaDRWNX1c8nCQLQBA3xWQ+b4/CW5b4IEkmRFC 6MAKoBN0dEKADR4TKHihYRf+2traV1ut1nd5njejGUu/oUKzLZfLKJVKWF01v3Mumnwe074NfUrl rgabsbrU27QVx8LKZPR1WpoNyNrrGKGun7xar4qmC0O3FfxMbXXltngmGFcQGhf2mr6qP9tAPx2e rZAmnou/zWYT9Xp9pJ0paFe8zrLs2cXFxfelaboWBEF7YPZnUf/DXf4mJyczAOmhQ4doo9HIms1m Nj09TW+66aZMwvx1Zn/ZOTP786Z//vCTJPG2t7c36/X6JbvVrw0cdAEAGLgC0M8QSAFQwr1VQRB4 kr0C+HNAsB5wZSbg2+hcCCRJkqTdbn9lamrqdYSQCRNh1QReqVQQhiHW1taMgxtHCOA/Vhf/vInJ qxjyfpr/XQURHTMdV0gYB2cca8B+M38XGi7afhE4LngXA1yYvaqtS30e5j8xMYFGozEyTgaiq0vj GlhZWlr6tV6vtzgw+3cGjJ9P9pM0m80siqKs1WqllUola7Va2eHDh3V+fxFEbZ8IBx/oxweUe8DQ 9B+3Wi3zJHyJw4F2ATAYrApgmj5/Tz6l1ONcAQzYOW/OZ2Ca0cU2omtAli44AZCsr68vPPvss79I KTWq8LoPd2ZmZpgyWGZ2lJn/xDLZNV8ulqno2NTr6Ov6lT0TGb7peenojFPO15nG7goq86np+dri y/oz/beyMpt+VGNTjcF1jDo8E9jiuYDr81aVqeqLGIPpv9KNRfyt1+tD5s+XMxA3OFO8u7319fV/ 1+12z/LMf2D+Z0F/ycTERDZY7pdWKpWs0Whk4nr/gfYv+vcZ6OK2POGc9/sDGJr+cdBN/wwuBwsA 0N8xMPF9fwoDbZ5bHUAJITQIAn+wYRDPsFXAS4YinlbTN+Bie3t7LQzDR2u12hthIYCpNMxarQYA 2Nw0Lz11Cc7TBQaarAe2AYh5AxVtYS+CA4vSwmSBf0UzIJfxuPbvKnTZ9uVavp+4RdDM894U1bcN nu5/VSkCQH8eajb7qU5kc4L43Yj1A8g2Nzf/49ra2tdYxD8z+/u+zwSAtNFoZCzRT7VazSqVimq9 v85dK56rzP+MN/KR/16SJH6tVls9qFH/IlwuAgAAbIdhWKOUloFdywIBIEvTlAUMyr4C/kXIFOW6 MrFcZlUgAMja2tq5arW6UC6XX6e8G76xgqE1Gg1QSq2EABu6NkKATZnsox+X6avo6kDVRmTIPJjw XaGICV82IevGZ9L8VNc2WmvR9eMy/r1k+jb4Ra3kcAX+PTX93yrhw9ZaI5az80qlgsnJyRF83bep mm+2t7fvWFlZuY/sZPrjTf9JEARJo9FIS6VSUi6X01qtltZqtaHf/yUveYkN8wdgZPq8+V/M9e9t b297SZJ0y+XygdnsxwSXhQuAQbfbfRL9yHumuVMAoP1UwV6pVAo59OEWjoNr3oyvYuQ8iDgUo/sF iKmCM+ykC04ef/zxP9/a2vo9m/vSfeBHjhzB/Pz8EE918LRcy8Ux2JgFVfXifdmW60yhtlqNqa+8 5laXNrZj17Xn6ZgmddX/6gou/4dNe1WZrpzvy+V+XO/dlXaRoPs2ZX3aCHsmeipaum+/Wq3uYv66 PlX0u93uncvLy3eS3Wl+e57nJbVaLa3X6xlb6892+Gs2m9nhw4czRdCfCPw8L2P+ortgl+l/e3ub UErpxMTEZWH6Z3A5WQAAIMuyrO37fgs7OQEADDMFkiAIyMAVwJi0TFPnz21iAnhQuQ92uQeWlpYe bLVaM0EQXG/oo99AYwnwPA8bG2bB1DZIT1ducgkUcS0rFzVfFzp5QdanzIJQFCPIKxDkue88TGUc XFP5uNaAi9HGREv2v4j9FPkOFSWI6YTier0+NPsD+bR+AEiS5CsLCwsfI4S0gyDoDtL8dnnmP2D8 ablcTqvVqinoz9bnz37Fcx87QX/AjubvE0K8arW6TPq70F42cLkJAADQLZVKXpZlNcb0WQUhhBJC siAIvCRJVJs22LxEQ+uCBI/1ycxJokWBtzhgcXHxq9PT08eCIHiJ6cYG9yAtr9frxtUBtkzeRQgQ 63mGacOc8/j+bVcMyCZhGfMW68btW0Vv3AnepFHp8G00xSJoFiUQXCpMX8Ws89DbK3eB7X9rqrex 8jQaDWm0v87nL5sHkiT5+6Wlpf+A/ioupvnzzD8ZbO2blEqllGn+gyV/VJLsx5X5s1+e+fM7/DHz vx/HMbrd7la1Wt2S9HGg4bJyATBot9tnPc/bpv29AoCdDYMIVwbsdgMwUH3lPOOX4VDul5n/gdF9 AvgjBhB/61vfen+v1/tLm3vTfdAzMzM4ceLEcKLRHYyWrp7HkeGLY5L9mkyP45iBVTTF9jocnabj Oq48/ZuuZc87T/9FwKXI/PM8H5s2pnfG9N2oaOYF2ftkcw+6OlfmPzExsWudv21/PKRp+uDS0tIH sizbGDD/DmP+lUolGaT6TYMgYBv8pOVyOWs0Gtn09LRt0J9sTpdp/XzAH7AjCHhA3/SfZVk6NTV1 YLP96eBytAAAANI03QiCYApclkDSTxlMAJAwDDGwAvAau2iyFzX9PPZl0dKwy0WQZRmWl5f/anp6 +nrf94/aEFVpIpVKpdC0waIkz2v4Io7OApDH5C/2q2sntrfFLwJ0VgWbNuP2OQ49WybgOh6b+rz9 jSMMFU07L6jeT/FdKvpeXf4HvrzZbA4z/Kk0f9PcAQBpmj6ytLT0mxLm3y2Xy0kYhnGpVEqjKEoG aX6zarWa1Wq1bG5uLms0GqagP1GhExk/X8av9x9h/BiY/gGgVqstkgO2za8tXLYCAIA0TdPuIEvg iBsAfcbrhWFIkiRh1/zLpGL64tejmu1ttyMeugyyLMvW1ta+3Gq1Xu553rzh3ti9SMvL5TKq1SrW 1tZ2fdx5zPJ5cGyZfx4XgE29DN+VUYuTmulZutCS1edt76IFFqGF2+C6MqK8mmwRbfaK6aveN1l/ ed0DvCCR5xnKmL14PTExgUqlsmu8MtB961mWPbm8vPwbSZKscdH+XUJIr1KpsBS/aRiGaRRFqSzi nwv6A8yWW5nrlTF+0QIQcPXDJX8Dv/9lseRPBpezAAAA3SiKAkppBQOmDwxfymF+AC4eQGfeV5Wr hAbx2mimSpIkWVtb++L09PQ/8TxvVnVTIwQ0QkC9Xsfa2tquRBw2NGyYtktAock6oNKIbLT/cbT8 PILBfsN+aaU2YOO2GJeGLR0b2kXh6vB1WvxeQZ7nrCrXXTebTZTLZeV8IAqmKrwsy55dXl7+jTiO lwaJftos4K9SqcQsv//A55+Uy+W0VCoxn/8w4v/MmTP47u/+btltmZi/zPzP+/35xD9eu90mvV5v q1KpXDZL/mRwWcYA8NBut88SQjrg1v/T/rJAMvhlb7uYRRAYfWHEMmC3i0DWluHIlgfy8QA9AL1O p7P56KOP/q9pmj5mc3+6iaBer+PUqVOIosjKd6nyLZrwxXHo6m3aqszSuglNR0MHssnPpb1uPCpa sufoSl92Lutb165IPNv72Cvmb/Of6e7Fpk2RdF1B9t3Y4JvKVdee52FychKlUkmJp/v2+essy15Y XV39jTiOX2BZ/ggh3XK53KtUKsMUv4Ogv+Fyv2azmTLmP4j4N973AGTMn53ziX1YGcsU6wMg7Xab ZFmWNJvNy2rJnwwudwsAACBN000uSyD4WABCCIIgIAMrAK+5y5g/uHoqKVMB7wqQxRaM9BPHcW97 e/vLU1NTryGE7F5sKwGV5hoEASYnJ7G5uYk4jm1IKWnbmvJtLAAmeroyFT3d+FVavoqGWK6yQhSl RdriFKHh2tIvWpveC+Zvw/TzwH5p8UXGALg+C9V/7fs+JicnEQTBcBz8mHh80xxAKb2wurr6q3yK X0JIp1wu93zf7w0C/hJm9i+VSmm1Wk155v/Sl74U3/u930sBgC37E0Cl/cu0fp75+8KBdrvtA0C1 Wl24XP3+PLwoBAD04wHafDwAFwtACCGEEwJEZg3Imb6rrVh0M4jAXk4KAN1ut7O9vf3FycnJ7/I8 r2XTgYoZep6HVquFbreLTqeTa5mbDeM2TQaqOpNgYCo31dm2ESe3IkAlOJjwx+nLhU4RDDIPIx+H +e8F099rzX2v3ARFPGf+OgxDNJtN+P4Oa1C562R1At651dXV93a73ecJIR3f97uEkG6pVIoZ4w+C IAnDMImiKGHMv1KpZNVqlTabTXrTTTfh8OHDdGpqSsb8Za5Vce7mGT/v+xeT/ZAB8yeVSmWJEJJP Wzpg8GIRAACgl6ap5/s+i2YhfCwAAG8gBIjauUwgAOyEAROzVwEFQLvdbmdjY+MLU1NTZ/LGBPAT 0OTkJNI0xdaWfjmrrVZtU5c3OFDXh6v2v1/gyuz5NrJ2eRldERp+HjwbfFl9UQx9r4UeU3tToF8R MO49qp49pRTlchkTExNagV723Snwnl9ZWXlvlmVnfd9nzL9TKpWGmn8QBHEYhkkQBGm5XE6jKBqu 9Z+ens5e+cpX0sOHD9Nrr72WKpi/CCpfv+gC2JXsB/2gP6/T6axfjuv9VfBiEgAAYCuKogqltMS7 AYC+W4AQkoZh6ClWBuiCTPhrly9fFU8wtATEcdxdXV39QqvVetm4qwMIIZiYmEAQBNjY2NBOJnkD A1V1/MSRxwJQlPavE5BUoNPiXJl9UQLJuKbhvXADjNtXkX2OS3OvaOxlv3mfM6UUtVoNtVrNSQhX nWdZ9uTq6uqvU0oXB8F+HZH5+76fRFGUsLX+g4C/NCfzFxm9rIwx+oC7Hub6b7fbJE3T7uTk5LL0 hi9T2D/16NIBr1QqvYRSGgyEgBQAiwvICCEpALTb7QS7dw5U+f9t4wGYQCG+lPzBpFP2GwIIy+Xy xHXXXfeBIAheZXOTJnP2+vo6nnzySWRZBkLICHPmD56eyMB1moKsToWbt15WZ6uFq/yrMhr7ba6V 9Vu0NcBWC3fR1ovQ7IvU4otyp+wnuL57TKgc5/+r1+vDYD+dW8xG4E/T9JHV1dX/nRCyzBi/jPnz Wf7K5XI6JvMXy2VaP8/8+TX/tN1u+5TSrFqtnicvAr8/Dy82CwAA0DRNN4MgmKSUDt0A2HEJEEII 5YICeeBfKtkXZ2L+orBggmE/SZIkFy5c+MtWq3WN7/snHGhIoVQqYWpqCuvr60gSfXrrcTVyk5Zv o3W4jkHX937BfjGRos3CqnJXDdN1LEXR3y9XgGsfRccBjOtq8TwPjUYDYRhaxeCIdZL7+ebq6ur7 CSGrA81/l9l/j5g/f65SsNj1SMKfdrsdACDVavUFpvy9mODFKAAA/aDAju/7TewwfhYLAAAYJAlK oTbT82UMZF/OuLMMEwJolmXJ8vLyl6ampo7a7h2gY35BEGB6ehqdTgedTkc/CEdtPY/p0LZPlTDh ov2r8EXatuZ/caIfV0Pl6bsyvzwWBBNekWZ5W+ZftCtgLxi+yoq0n/3Z1IvlQRBgYmJiGOxn+z2p ztM0/fvV1dX/gxCyyZn9u7bM/+TJk/Tw4cO45pprxmX+7Fdc7scsqiNBf4QQr1KpLJLLONmPDl6s AgAAxGmaUt/3a9gtBBBgRAiQfVUy0xMD1VfqooZK3Q1ZltGFhYX7p6enDwVBcJ0tMR1DnpycBCEE W1tbTnEBNpOfzeQxrtlfV+ei/e+llcDFtFu0ud+WVlGa8366AvLSHxf200VgMvPzeKYySikqlYqT v1+sE8/TNP2rzc3N/whgi4z6/GNb5t9sNumNN96YSZi/yrcvXsuYPzDqVuWX/3lpmvrtdnu1Wq1u Km/8MocXswAASrMhtgAAIABJREFUAO1SqRRlWVYSXuqMCQJcumBAL4WaLAGmOpVbQQQKAAsLC19t NptpFEXK7Bjix6/7wOv1Omq1GtbX150zB+adSHR1ef3/tvT32i2wFyZrF9xxzf2qOhcmlNcKUsTz 2Kvnvx+Qx/pj+xzr9TrK5fLwWuWuU9WJ5VmW3bu2tvYRANsDxt8mgyQ/A8Y/LvOH4lpk/KyMN/mz WKpdgX+dTieI43hrcnJyZddDehHB/jtGLz0glUrlaJZlFQzW6g98QRkXEJINggIpRtfziy4BnXtA BL4te5E9jL7EvM+KDwwMAEQAopMnT/6LZrP5i9h5yXc60GjoKrxer4ennnoK29vb0sBA/pqnKWPe Oq1BxeCL8v+7MneZAOFq/le5BExgy3xFLbAIM7usrijrxMUIAhzX9bKXIBM6+XenqDgKGS3P81Cr 1YbJfRi4COuikhTH8Sc3Nzf/H17r55h/z/O8hF/qx5j/VVddlTWbzWxmZiYbg/mLZaLWLy73G0b8 dzodkqZpr1arvcC7fV+M8GK3AAAAkiTZCsOwjv7zoNhxCYAQQgkhWRiGXhzHsmQ+rkKU6YUzuRRY fQaALi8vPxqG4Ter1eprCSEl20GoNAzf9zE1NYUkSbC9vT06CAuBwjBpaMci60Nsrwsm1MFeavuu sNcMqGitUVVXFG4eenvRfhzQvbeyurzjySP0hWGIer0Oz/N2jY2/NrntuOtet9v97e3t7b/gmf9g R7+YW+efODJ/lVs1L/Nn10MlqtPpELoT8f+iZv7AFQGAAR0IAQ0MhADmAmAvCScEyJix6cV1sQzI 6LA2VHKOtbW183Ec3z8xMfHPCCE1A+2dTjQMmW0CsrGxYXQJALs1VV1feWIBirQM7LX5nwfTc9Hh 29YV3aboPvfaFbBXjN9G4N0va0Lee6xWq8Od/FTfl0noFmCt0+n82263+w+c1t/xPK/L+fyHuf33 mPnL/P38zn7M/O8DQKfT8QCgUqmcIy/CiH8ZXBEAdiBLkqQdBMEEdhh/BsEaMBAC+Ha2TF/XRgUy wUFGl25vb693Op0vTExMvMLzvBlL+lool8totVpot9vo9dRBsjaavXhtW2fD5HVM3YbpihqZzDrC l+2X+X9c2A9zeh5cm7b7OfYi2xYJ4whOvu+jXq+PmPxl35XJ3y/gPru9vf2+JEkeAzA0+Q80/2F2 v4Hmn0ZRNNzVz5L5i2Bi/nwMAM/8CUYD/0in0/EBkHK5fJ68SNL82sAVAWAUkjRNu0EQ1LHD+He5 BAZWABnjV32xshdc9dLnnX1op9Npr62tfX5ycvIa3/ePWzUyaMNsHwFC7FcJmCblPFq/C3M3lasm vf0AF+tDkZp9kYxyHFeATf045v69MK3vJxQh+JRKJVSrVWlMTR6fPyEEWZY9tLW19ZtZli0MNH52 dMvlcux53siWvmxjn+npaTo7O7tXzJ+dM+YPjAoCTPP3AXjlcnmB9HeGvQIDuCIA7IY4TdM0CIKa wICGL2upVAInBPBmedlLC5gFA9vZR0aTb0uTJIkXFha+MDU1NREEwWlLun3imsmhXq9jYmICm5ub 2sRB42jhKvxxzf8ujL5ooeBiChviGMZtM26QWlEBekUx/4vB9HkBMM94dfEDhBBUq1VEUbSrXIVv c52m6Zc2Nzd/G8Aa5/Pvkn7AX+z7fhyGYez7fsq29C2VSunc3FxWr9eHzP+aa67Jrhld5z8u8+cD pYHRIGlgoPkTQrxyuXyBEPKiXe6ngisCgBy61WrVy7JsuF6GtwYAoFEUYRAU6BqwwiDv7MPTYqmK RZrZ4uLi31Wr1XOlUumfEkKs/2cdowrDEK1WC2ma7goQNNHJw8TFc5n2LCu38fPnEQp0Ey+DvTI9 7wVzs4nYz6PB54X9GkMRY9a9XyZ3Ut7+dHVhGKJarcLzPO23ZwqiFeqSOI7/cHt7+78MGP9IXv8o inqDHf1i3/eTZrOZeZ6XRFGUzc3NZdVqdYT5Cxn+VFZRcf4UtX2R+Yv+/pF0v2maer1eb61cLq8q H+CLGK4IAAro9XrtUqkUUUojYGgBADhNP4oiIrEEAJBq9ioXgevMwEfkyZj/UAhYWVl5AsBXa7Xa qwghjV0dWzA0Wd3ExAQqlQq2traQpm6xNHkD92zb5Cnfr6BAVfyATbs8dUXg29Ial0kX7QrIi7fX NPaiz0qlglKpZGTsMsFEJQBQSle63e6/63a7XyI76/tZdr9hsF8QBHG9Xs9qtVpaLpfTZrOZTU5O 6pg/IFeaZL59mTAA7Nb8Q0iW/HW7XT+O482JiYkl40N8kcIVAUADcRxvlUqlEqU0AEY+Gsb0SalU Qq/XEyVa9qWpBAMYykSQmfttINvc3Fze2Nj4XLPZPOn7/lGXxjqmyAIEkyRBu912bm9rfjS1LUoQ EHFsTPc6hm5LQ0c7T10e2GsmulerFPbLOrHfjN9k6mflYRiiUqnA932j1i+C4Rv6VqfTeX+SJI8P mP424Zb5BUEwjPRvNBop8/dXKpW0XC5nU1NT6ezsbDY5OUklzH/XUCzP+Xz+otlfZP5+t9v1kyTZ ajQaL8g6vQJ9uHiOyYMDpFarzaVpWiZcYiB2TvpZA7PNzc1hHdSmefEcmnLxWpSMdUmD+I8iHBzR 9ddf/9PVavXtww4KMktubW3hueeeQ7fb7Q+U6JMGycr5Mp6xOpgrpWPM4wawdR/sh/nbBc9Fi87D eIsy0RfBuPci+n8vaRXRH6v3PA+lUsmY1Eel9YvXfHmapv9vu93+QyIk9yGE9Aaaf+z7flyr1dLB Er+kXC6nURRljUYjrdfr2dTUVHbkyJGs1WpRDfM3uU75a48r1zF/D33mT7Is61YqlbPkylp/LVyx AFhAHMfbURSVaX8L4aG2P2BYFDuWAFlMALD75ZaBykUggiwZEQ+UO0bKlpb+//a+LUaOYz3v+6uv 0zOz9+GSPKtDilodM2QkHYe24Zw4sGzDiAMHThBED3mI4QCG4+QpDwmQhwCWkRe/JzACGDCQhziJ ZCdAECB2AvjoOLAdx1BynHMoO5Is8UgUKWpJcZfLvcx0d1Uepqu3uqb6NpddXuoDBl3Xnp7Znf6+ /1LV97/t+/77nU7nG0Tkm6drJ2tgxfq+j7W1NQBjMVAG/RxtLOSmQkDWm+YL1F1j0+vTUfc+bchl nq7waTGv610U+S8yxj5vtE0EVMd4nocwDGs39dHfp24sER2PRqNfHQ6H/1GJ98sn+uXJft1uNwnD MPF9P/V9Pw3DMI2iKO12u1wn/+3tbbz88st47bXX9I/UlPxVy1+W9Zg/oGT+Z+Qfdzqdzyz518MK gGYQcRwf+b7fUUUAjXcJlGRLQRBQhQgoPbd2rIMUCmqegYnwTX1ib2/v0yRJ/kev17tBRKuVF6bd nOqIs9frYXl5GYeHh9D2Smh8jraioMrCafOeTUm+7MY9q8tfxayE38Y6nnfi3SKIdFGu/tMi/TqX ft1cYGz1h2FY++jepla/Nv7eaDT6F3Ecy819cvJXkv3iXq8nN/ZJgiBIoyhKO50O73Q6OflfvXpV dLtd8RM/8RNiZWUF165dM3kyy+qmXACgPOFPlqXbn4QQSWb51+9eZmEFQAsI6QnA+J9REj0pngD4 vk+GnAAY6nU/jCoQJsMMev+EB0BWDg8Pd/f29n5naWlptc0TBfOTVxCc67pYW1uD4zg4PDxs7f7V x7WxcNpcZ1uvwyIxD+u6adx4Hpgn4c6a63CWSZCm89bF3qc5n+/7hSS/tr+JmlDZHxwfH/8K5/wz hfiPlc19Ro7jJN1uN5Xr+6Xl3+12016vx9fW1vj58+f5Sy+9hKtXr/Lv//7vFwDqyF8PabYhf08p 55a/ECIJw/Azsrv8NYYVAO0gPQERlOcGZH0kPQOaCNAtfHksCxVUsY56jqYhA31uCgBJksQ7Ozt/ EATBx2EY/gARhRVzJy+0hly73S5WV1eRpqkxSbDqRtnEDT9NfRbBYDqXOmeeLv+28+ZtxU87vo3Y W2QewCLHz4vgm7yn67oIgqA2ya/qGsvqQojjNE3/9fHx8b8FsJ+R/pHc3EeJ9yfdbjf1fT9RXf5R FBUy/V944QVcvXqVX7p0yUT+ZeRuCo2ayF+P+QNjEaBa/mkYhrct+bfD6Zg4zx6cKIo2hRAMyJ8b IOjkMcIAIB4/fix3zGmTFFhXN0H+aEyJgaYEQblsxgfgrqysnN/a2vrnnuf9YOGNG9ykqxLpJI6P j/HZZ5/leweolozp5lRl6cwqBObRN2+oYmJeGfmnkeS3SIKfp3h5UrwETd+XMQbf9/M4PzCb1W+o vz8ajf5lmqafZjH+fGMfIoqznf2SKIpSz/Niz/NSz/NSU7Jft9sVr776qtjc3BSXLl0SBuJHSb2K /NWMf32pn8CJ5c8U8v+UiMp3KLMwwnoApoMMB0QAmJITAEUAoGFOgOlH0uQOVDemTEioeQEcGG8h /MUXX/z3fr8/8jzvNWqxcRBQT5YyLBAEAY6Ojox7BzQl4yahgTbnqxs7zTgTyhK/pjnnaWTqLxKn Qf5PC+mr7y3d/TLO3/b/tC43AABP0/Q3h8PhvwLwgLREvyAIYt/3Y8dxkizen8h4fxAEXE/2u3r1 qrh8+fI8yF99VZG/o7Sz4XBIALgl/+lhBcD0yMMBQghG44RAAPmPjYBcBOg5AaZfctWPxwRTuEAn eX28HoZQx4ovv/zyuwD+ZxRFrzHGKhMEjRdUc4OSewcwxvL8gLaJhvlF17ibZ00ObNK/aJyVN2CR YmEReQDTXtNZW/oqXNedsPoBM6lPKYJ3kiT5lTiOvymJX9/P33XdURRFSRiG8mE+ebxfWv1RFAlJ /qurqybyN92XTIRvKssPL72VwOQmPy4U8g+C4BNL/tPDhgBmh9PtdgeZCMiX6KmhACLi+/v70uxV yblsVz9TvQzq+fQfU1k4QH9ghoyteQD8MAz7L7744j8KguBvl75pyc3TZOWa5sZxjHv37mF3d7cw z+T+r+qbR12/7jbEP+08CVMuwTTzm7bPMu+0++bRP+v4eaAqQdNxHLiu2/h/W0cDqx+c899LkuTX hBB7AIZENPQ8b5SmqXT5J4yxOIqi1HXdxHXdVO7nLzf3iaKIb21tiXPnzvGlpSVREu83XWwV+UvI e5JAkfzV7X2l658pCX/W8p8RVgDMB063290QQjikbBAkO7OyAID9/f0ERdJukw9Q1W4SAWVCwFHa VAEgRYAHwH/hhRe+sbq6+k8YY+cn3mxOVuBwOMQXX3yBvb298UU3IPuyG10boq8ao/dPS+7TkroJ 83B7z3qO084FmBf5nxXpV4ExlhN/w6Q9Y3/VXCJ6mKbpr8dx/PtKjH/oeV7MGBtlr6TT6SSu6ybZ w3zyeL9c5tfr9filS5dEr9cTly5d4tLqB4Br164BMD4ITbZVxfplWXf761n+QDHmb8l/TrACYH5g uidAegGkAGCMcQDY29uTuwVKNEkQbCMGAHNsTS3LeJpJBORCIAzD/qVLl34hDMO/Q0S5f7LpzdlE nKa5x8fHuHfvHvb39wvz6sh9WjGg3lTVOVXXXXW+eUAXGk0Ju05oLMIb0GTMIq37J5H8m7yXSvwS Vf+rbRP8lP+F302S5N8IIXahWP2MsRERxYyx2HGcuNPpFKx+6fIPgoCr5H/x4kVucPk3sfjVskkA yHsQMEn+0vJXs/3jMAw/IZvtPxdYATBfsF6vty6EkEsEQdrKAEUEpECtF8AUyy+DaZz+gzOFBExC QF0t4AHwL1y48MpgMPhnjLEXgXY3b/2GVUU4R0dH2NnZOTUhoKOJ16ANyly/0+K0QgTTzj2tBL5F JAK2RZvzM8by5XxNPVPTWP1CiLtCiF9LkuTbRDQioiGAoe/7kvhHjLHEcZw4iqLUcZy0icv/jMhf trPRaORyzo8yy9+S/5xgBcD8Qf1+f41z7uEkF0CKgcJSwRIRYCL9tiJAHd8mJKBm2eohAc913fDK lSt/r9Pp/CzGSwjLL8Rwc6wjQ7Xv6OgI9+7dy7cWNgkB1TqaJQzQts0Ut5+3R6CtN6ANGS2C2Gc9 x7wJfZHk3+bcRATHcSqT+/S2Ka3+hHP+X5Ikedt13QMiGqZpOvQ8b0RE0t0vl/dJd3+e7Od5Ho+i KB0MBqLf7/MwDKvi/frFlxG/rNeRv76+31X6nIz8H2fr/O0Of3OEFQALwtLS0lqapj4mRUAuAIhI 7O3tyTiWTvxN3P8qqn4YZZ4AU0hAPUpVXkgSXF9ff+n8+fP/1HXdV8vesIpkysjSNOfo6Aj379/H o0ePTj5MRaJgWb+pPmtbFcrcuKp4OA3PwKJXEjTpX3QoYV5z5jmfMQbG2NSeqLo52v/XLSHErwL4 cyXWP2KMDVWrX67t1xP9fN/n3W43XV1dRb/f52tra1x3+fu+T9vb27phYYr962UT6edu/axd3mMA 7eE+o9HITdN0v9Pp3Ca7t//cYQXAArG6uro8Go1CYIL48zJjjD98+FB9wI/JijfV9bamPw5TbkBV WMAUEnAB+C+++OLf6vf7/5CIuhMX1oCQ2oQG4jjGgwcPsLu7C855YX6d+1/3FpjmtGnT+6s+0zzQ JM5fNbdJ2zRj6sadlviYduw850pI0tctfqD8/3QaV39WP+ac/1aapv/Zdd38qX1ENFRj/VmiX2pK 9PN9n4dhyDc3N8Xy8jLXXf4vv/wyNOIHqt3/Za5/1eI3rfEHFPIfjUYuAJYkyW4URXct+S8GVgAs GBsbG/2jo6NIuv9RDAfkrxYioO6HUCccmoQEdCGgP2ZYvvwoita/+tWv/qLv+z9NWZJgW1KoIze1 PU1TPHz4EA8ePMg3FGpiZbXpq2prmiRYhjLPgKzr79MU8ybJswwHtBk3D9KeF/G3cfOXoYXV/y0h xG8Q0U5G+scZ6auJfrnVr7r8gyBIV1ZWhIz1S6tfZvlfvnwZ586d4warH2hm8ettOvnr+/oLKGGA 0WjkAHDiOL7f6/XuVX5hFjPBCoDTQdjr9frAmPiRhQXUUIAsP3z4UM0LACZd+1V3qzLhYILJE6AK ATU0IF+m0IAHwB8MBl87d+7cP3Zd9+un4c4VQmB3dxdffvklhsPhyYdqmRTYpq1J+yLyAVRM6w14 Ekh/nu8z7fhZ5+mQFv80ItI0pkGo4CMhxK8T0Z9Ja19x+Y+IKKmz+ldXV0Wn0+HdbpcvLy/zKIry LP/Lly9ja2tLAKiz/Kvc/QIn9xBgMt5fluznjEYjAkC+739ORF9OfIEWc4UVAKcHv9frLQPjEEB2 LBMBcq8AiUWGA+RRf+522bMEpBAwrha4dOnSjy8tLf0iEV00vWGTm3+b0AAAHBwcYHd3F/v7+8al fRMfesFioGpslZU/D2/AIgh0HmPmKSBmGT/tHBWS8NvmmJj+v+vmKOUHnPN/zxj7luLql68hYywm osRxnJiIUlOsX7f61US/ra0tDAYDsbW1JRTir3L1q3VTvL+O/PW9/ZlC/reJ6CTpx2JhsALgdOH1 +/1lIQTpIkC+HMfhAHD//n1TSEBFVfs0qPIGmEICUgQwaImCrut2L1++/EYURT8HoFO4uBbWX5vQ ADAOD+zu7mJ3dxej0WjiPHVioIl4qGtfdD6AikVav6eVJ9D2XNOOn3UegAnSbyIW64Reg/qIiP5r mqZvO45zKN39mYtfJvkVrH7HcdJut8tlhr8QIlGt/iAIhJroV2L115G/TvQ6+avL+yTR6+QPFMlf +L7/PSI6NLy3xQJgBcDpw1laWloW2YZBZV4AxpgoEQFN8gDkuDZ9ekigiRAgTG4nnOcH9Pv9zYsX L/6DIAj+ev7GC3b/yrajoyPs7u7i0aNHpZZX28TAJoTelvRNIqepB8SEshDEaVvoi7D4z4r01WNZ v6le5tFqUf9DIvoNAHdUaz9z98ekJPkxxlIZ6+/1elxu6COT/HSr/8KFC1hdXRUGqx8oJ/86618e dfIHJq3/fIe/0WjkCCFGQRB8TEQnyt1i4bAC4GxAq6urS0mSuKr1D5SKgCa7BupoEjaYuC7laBIB apseFjA+W8B1XX99ff3q2traz3me91enEQBtQgN6G+cce3t72Nvbw/Hx8ckHnYLsTf1NkgLbjJ0G i858X5T7vsmcs8rqb+Leb9JX1l/zv/YdIvp3RPS+5uofKeSf6El+vV6Pq0v75G5+qtX/8ssvC5X4 gUqrv0nMXx7VJD/V5Q+chAilF0Alf1cIcRAEwS2yG/ycOqwAOEMMBoPecDj0gfFyQABQhQBjTMjj vXv38hUEGqructNumqEKALWuJwiWCYFcBHie5wFwhRD++vr6tdXV1b/ved5fNr1pU1c/UB4br2qL 4xiPHj3C/v6+MXFQtZ6bWP6zkEJTtM0BKMNZrypY9Nh5zJvWw9NE4DW0+t8jov9ARO8ZiF+3+I3u ft/3+Rys/ipL39RWRv4ml79c5ucBYGmaPrRr/M8OVgCcPcKlpaUIABzHSYET8tfLmQgAmiUIzvKD Eqj2BuiCgHW7Xffg4EDdO4ABcHzflwLABeAJIbyNjY1XV1dXf9513b9UeNMWAmAWrwAwFgN7e3vY 398v5AuoKBMB0wiCeYwvw7Ru/2nHtp1zGol6s5B+Xa6JaY7+vjO4+QHgQ8bYbxDRd2m8dW8e38/I P1Gtfkn8qrvf8zwut/H1PE+oGf4lVj9Q/J3nl2YoV7Xp2/mq6/uB8Y6harKfMxqNiIic4XB4t9/v fwGLM4MVAE8G3JWVlR5QDAEA4zCAGhIoEQFlln6bu+LE2Bs3btC7774LYGJpTyE0sLy87HDOGQDi nDuZEHDCMHTF+LkITiYACkLg3LlzX19eXv4F13VfAaYTABJVN/G6ttFohP39fTx69AhxHBuvoWku QF1MeN7u/1mwKJI9bcu97TyV9Gd9b/WcU9Q/Yoy9RUT/O4t9x1mMP5Zr+VVXf0b+vKm7f3NzE3JT H83q1wm9TAiYBAAwucRPfXwvcOLyl22yXSb7IUv22zd8lRaniCfnbmTB1tbWepxzJkWAtPyBk9CA 4g0oe5iQjtq+jOgL427cuJH/b2QiAACwvb3NkiShJEno9u3bBAAbGxtOmqaMc84450wIwYQQjnKU AkA/ekIIf3Nz8weXl5d/njH2F4wX2ZLUp/UKCDHecfDg4ACHh4c4PDwsJYZpBUGTMbPkCswjXDDt uU5zSV6beZLwpxWJpnlt4/pa3y0i+k3G2P9SiD939SsJfgljLCGitNPpcNd1k16vxx3H4WXu/o2N DURRlOrufiC3+guXZfq6DEdTm3zgmUr+vlIGtHh/HMeuEOLY9/2PyCb7PRGwAuAJw2Aw6MVx7ALj vAA9FOA4Ti4Ebt++XZYcqEMAwPXr1+nmzZsFb4FK9AAghYDenvXh+vXrFIahOD4+puFwSMfHx4xz TnEcMyEEaULAEUIwzrn0AjiKR8ARQuSbCWUegVf7/f7Pep73Q4WLn8KqB2bzCsi6FAIHBwel3gH1 vcrqdePPAvMSC6dp8TeZoxK+6X/A9Heuep8yz00NyZuu6c8YY79FRN8mohhm4k9Uq19a/DLO77ou V7P7pbv/K1/5ioiiSFy4cIGXJPnVxfj1elmin0r66q5+kvzVhD8XgBiNRi4ROZzz/SzT3z7Q5wnB 2d+FLEwIV1dXAwBwHEd9boDI2spEAACI7e1tAoAPP/xQ3sU4MGHVVxG90Nv7/b4YDAZiZ2eHAGB/ f5+kCJAegTiOGedcFwFMEQGkeAQcjEMCE0JgfX39a8vLy3/X87wfw0l8sfghG5K6bJ/FKyCRJAke P36Mw8NDHB8f588kMKGtIFDHlSU9lqGJx+AsEglP872rduTT59cJACFE7dp9U1tFzsgfE9F/chzn A83ij5sQv7T4Pc/jurt/bW0N6+vrvNvtCt3dD9Ra/WVCwGT9mxL91CQ/HydZ/oCyvp+IWBzH97rd 7t2JL9HiTGEFwJMLZ2NjIwIm3f9SAKhtqhDY3t5GEAQCAG7evJmHCUzWvkkASPT7/cJdcDAY5PUy ITAajViapiSFgBCCakIDuhBwkAmBpaWlC2tra2/4vv9TRNRXr6WtAFBRRrJNvQISo9EoFwPHx8f5 swnKUEUide7l08SshL1owlete9NDd5pY9KY+/ai/Z12bRvpDxtg7RPTbjLFPZUIfxuRfRvxpGIbc dd0kiiLhum7qui7X4/ye5wnp7h8MBlwnftd16fLly/qHmNbqByYT/YCiy9+4ta9MrvV9/xbZnf2e SFgB8GSDbW5udtI0ZcDYGyA7SkRACgDXr1+fONHNmzd5FdlL6KQvoZK/CpMQAIAWoQGmCwHl6Akh XMdx+ufPn//pKIr+JmPsq8BsAkBt05P06uZW1ZMkwfHxMYbDIYbDYWHfgSpMQ/h111025yxzBKY9 h/qEPUn8s7r01XKbcFJVW1bfYYz9tuM4v0tEj+gkkz/WXqkk/jAMOWMsX9Inid91Xd7pdNIgCLjr umIwGIh+v887nY7R3W8g/qYxfqHVpatfJX3p+q9z+QMn8f4j3/f/3Mb7n1xYAfAU4PLly+Hjx489 YFIEMMaE67r5j/7WrVt8e3ubpAdAIgzD0jttGemrKBMAKnQxcHBwwJIkISkEDB4BXQgwZAmCihCQ qwc8AN65c+d+uN/v/4zjOD8MLTwwjQCoQxsBYKoPh0OMRiOMRiMMh0PEcVwZOtBxFt6AeYqENudT rXr1aDpHlQCoG2/6/tt+ZsPf5TuO4/w313X/SInv66/c2g+CgDuOkxARNxG/muA3GAyE7/tiZWWF R1EkpLv/4sWLWF9fFxcuXBAAoJC/ybrXSb4qw1+25wl82VFN7jO5/J04jgnj9f33wzD8lOz6/ica VgA8PXAGg0EHADzP48CJ5a8KAFnWBQBQFAFNSF+ijPyvX79eaL958+bYBNrZoRY5AiTzBNTQAIpJ g7kQyMov9VM/AAAa/0lEQVRet9vdXFtb+5kwDP8GEa3Ka5jWtW9qM1nMs9RlOU1TxHGM0WiUH9M0 rQ0h1KFJnsNpouz9JbmrFr3uyp/me63qb/t3q0P2Xe8T0Tuu6/4OY+zzjPgTxeJPsldMRGlm7aeM sVRa/Kqrf0HEb6pXCQE90a/K6ocyzs2SZMnzvFtE9LD5t2lxVrAC4OkCbW1thXEcM+BECADNREAY hqIN8UuoAkAnfRPqhEAmAihNUybFQOYZcEqEABPF5YOqV8Dd3Nz8kSiK/prned/IvAgFNPUMNAkV zEMAVPWNRiMkSQLOOUajETjnSJIEaZqWeg6qiHaeaGPJ6+SuW/Smc0773Znq+nfVNkxQBSL6tuM4 33Jd948AHKtWPsYCIF+/L1390s2vuvodx+FVxB8EgVAT/OZM/KZjWawfGJO/tPrl0cUJ8TtCiAPr 8n+6YAXAU4jt7e3g8PDQAaq9AMBYBExr+Uu8/vrrUy3bUYUAUMwTkDkCqhCQ4QEZFpBiAIYlhCjm C3gA3DAMN9bX138qDMOfZIxdltcxDwGg16cRBE37ysYJIXIhIIUBMN7VUPUuqOQnhMjHtYXjOBOE 7ThOXpZWuzyqlnzbzzZLH1BP+HXnq2sHcJcx9nuu636TMbZDRAkUsteOMr6fBkGQx/cZY1wl/iAI UsdxxJTEr7v1Jcpc+3VJfkAx1i/j+gFOSB/QtvWVLv8kST7vdDqfWZf/0wUrAJ5esK2trYBzTmoe gMn6n0YASKu/icVfhl/6pV8SAPDLv/zLBIwFgckrIFcOZN4AfdWAuoxwIkQAZXMhKGJgZWXl5aWl pR/3ff8niWi9bZy46Ri1XhcymIcAqGuvK7c99zTlafvanqNNGKBJ3dC3B+D3Hcf5A8/z/l9G+jnR YywA1FcqrX6Z0c8Y49LVL9fxq8v5ZHJfS+JXYYrv6/2mo7qbX1msX1r9alue8BfHsQMg9jzvI5vl /3TCCoCnHNvb28Hx8TEDgDAMOQBsbW1Rp9MRn3zySUEEXLlyhT766KPSMIAe65+G/CXpm9BUCKh5 AobQQB4iQBYeQLlXwAHgra2tfb3X6/2453k/QkTL8nrmLQD0epts9SZ9z7oAqLvmNudp2mYYc5Ct 2/99z/P+BCckrxO+FAKpfDHGUsp27ZOk7zhObvGXEb+M8Q8GA/T7fbG6uioaEn+Tepm1rx514q+y +l1p9XPOH2Yb+0znYrI4c1gB8GzAuXz5sgeMPQBSAACAFAHXrl3LB+/s7HCgPrO/qQCoIn0T6oSA njAoJvcSUEVAvpoARa9A/kTCrOwBcDc2Nn6g0+l8w/f9vwJgXb2ueQsAvS7LpvDBLAQ8C1nPSwDM a1zTedPUK9r2ieiPiOiPPc/7P8iIHpqFr9RTJb6fZq5+YXLzq/F913XF+vq68H2/sJxvTsRftqyP af26AFAf3iMwJn811g9oy/sA8MzqfzDxZVo8VbAC4BnC9vZ2MBgMWBAEQgoAiV6vJwBgdXU1b794 8aIACpsF5agj/7akb0ITIWDaS0BoKwfUXQYx6RXIj9BWE6ysrLzS6/V+2PO8bzDGXpjSYpyatPRy 2dr+eVv4iyi36auK189i5bf0AuwQ0R8C+BPP876DE9JPNcLPY/q6pU9EvNPp8GzLbi736ZfWvhrf X15exoKJX28TmHxoD1B09wsUn9qnHk2xfkcIsZ8l+p08T9viqYUVAM8Y3njjDWdnZ8cDACkCXnjh BWMSnxQAElIIXL9+nWB4wuA8SN+EMiEAAOpeAnqegFCSBtUXTkSAmjOQ7zGA7LGlqhiIouji8vLy N3zf/yHHcV7N2k9VADQ9Z9WYRQiAJueX5bYehVn66sZrbRzAe0T0fwH8IRHdcV2XA1BJP0XR6k/J 4OIPw1BI0letfcaYqIrvz4n41bYmWf1SCABF8lctfsAc6wcAJ0kSTwiRxnF8u9vt3jFcj8VTCisA nlHcuHHDO3fuHAPGAuDixYt0584doY3B3bt3J0TA9evX6dq1a+KNN94QQKtHCs8EXQgA5SsH9PCA 7hVQxIAeIpAxT9UzUAgZOI4TrKys3AjD8DXXdX+QMXZJXuOiBEBV31l7AJqc/yz66upEdBfAuwBu AvguxvH9BEAqyV9a90pZf/GM+HkYhsIU22eMCZObX03sk6QPjL1wp0D8pqPq7geKsX51Yx+BLNZP 44f4PMqs/mZbW1o8NbAC4BnGm2++yW7evOkCJ9sD37lzR0jL/8KFC/nfXwqBa9euCQDIyF+FvEkt XBCoQgCo3k9AhgfKvAIASAsRTHgJMBkmyIUBxssL1/v9/mu+73/ddd1XiegrhS/mCRIATcqzeiHm 4cWY13emtgkh7gH4UwDfAfBdIrqPsXWfAsitewBptoeG6trnVaRPREISvxrbdxxHOI4jpJu/1+tx 1drvdrtic3MzD71pxD/xWVCezW/qa0r8LlBYv69b/epufoBi9Xue90kmpCyeQVgB8Bzg9ddfd195 5RUHOLkB3b17V0gB8LWvfS2/q+7s7IjBYEAN1v6fqRAAAJNXQGS5ApoQKHgHMCkG8oRCnIgBo6cA Y0Gw1u12X/F9/y+6rvs1xtj3ZeNbeQimIcV5WPizWvdPkNX/5wA+APCnnPP3iOhLnBB+buEjs/gV Nz8vs/Il6UsXv0r60sWvxvY9zxMrKytQ3fyDwYADgLqUDwAWQPxlCX76sj7V4gfKid+N4xhE5HLO d33f/9DG+p9tWAHwnODNN99Un92NH/3RH+X9fp/29/fzu+nrr79usvqroLou1bFz9xTUhQf0XQYr QgQTYgBFIaCHCkziQH0xjBMKr/m+f9VxnO9zXfcKEW3lX9KMVrZaf1YEwBRj7wL4HoAPOecfAPgz jNfkS7JPoVj7GeHndcXCV4+yLEyWfra/RiGhz3Vd4bquiKKI+74v1tbWoFr78sl8nU6HGrj5gXLi V+syll9H/EAz8ve0PheAyKz+ked5HxPRjuFaLZ4xWAHwnOHNN990peV/48YNZMd5Wvv6jW5hQgA4 8QoAQF2IoEwMYOwR0EUAE0LIzGc1VJCXcSIOCh4DAMxxnKDb7X5fEAQvOY5zxXGcl7LQQVj4ss5A AExTbnINs/Qp9ZEQ4jMhxPcAfAzgY875xwAOMLbcJdlLF75073PVuvc8T47VCX/CymeM8U6ngzJL X5K+53mi2+3yIAjExsYGJOkDldZ+U+I3jdGJXk/uA4q79wGTG/aEKLr9J6z+JEkIgJOm6efZuv7Z Hkph8dTACoDnEEIIevvttxkA58qVK+LGjRvyZiKPJqu+cIpZ3n6GuTmkEADqvQIA0FIMyHKVl0AS fh5OQIlIgCIWoija9DzvBc/zLnme9wIRbRHRBhGdm9UCX6RImMc4rf5ACPEl5/xTAJ8R0e00TW8L IT4HIBTLXr5SSegYu/bzPoX4OQDu+z7XCV9a+SrpM8YEEQnXdXkURSgjfc/zRL/f591ul5pY+0Ct m7+qDFQTvz6mzuIvI34v2yLaFUIceJ73Adnd/J47WAHwHEMIwd599918c3dFCEwMrTvVNG+P8vBB q3OavALA1GKAcOIRKHgIlGOhrLQZ61qb47ouS5Jkoq/b7b7ked45x3HWGGNfIaIOY+wlIooAnM+/ uDkLgCZzm5ZlXQixA+Ax5/wTAIdCiNtCiD0AO2mafojx31eStoBC9oqVL1Akfm4q+74vqgifiPKj dO0zxmQmv+j1ejCRfpmLHxhn8m9tjaM8Laz9qjIwHfGrCX7AZJxfjfeLbDySJPEAxHEcf2L38H9+ YQWABd566y3nypUrDKgUASoW4RmQ8/X/yTKhYESbEAEwFgOmBELlJUMBE6IAijDASciA6WXP8xxh 8CRAExIYP1RFzlPHEgByHMcLw/BFIQR5nvdVIgoAhI7jfEWOJ6LLwAkpE9ESgI38y2wnEnaFEA/V MUKITwDEWflzIcQhgDRN048ZY4jj+FMAw+xvJRSCly9J4EIlc4wJ3SQECmMzsi8QPgARhqFQiV6W JdFLa9/zPM4YE/1+H47jCJN7HxhvnR1Fkdjc3IRK+nL3TGnhK0/kA6rJvayfGdqaEj9QbvGbntwn kiTxAQjF3W+f3PccwwoACwDjsMA777zj9Pt96nQ6dO3atTZPANSJedHWhEkUFBIPsxCHLAMAVldX 2bvvvgugKAYAQE8gVL0D8sU5Z91uNxcIBwcHJISgTqfDhBB0dHREACgIgpy4j4+Pyff9giioEBB5 O4riIK9nblt1HCnnUglEvqC1Ac1/92poSGjteZvrunqbUMhcJX6hWfyqSND7hWLZ5+2qdS+JXiV+ nfBlPD+KIiqz8tuSflY+beLPl+hlR93iD3CCiSS/7P/GE0LsZw822jdcp8VzBisALAoQQtC7777r djodAgBFCDTJ9j9tIdAIb7/9dv5//t577xEA3Llzhx4+fEgA8PjxYwKADz74AIPBgI1GI7p7d7z0 eXV1lSVJQg8ePADnnJaWlqT7HtnzCQoiQXoLOOdqPkGB7MvqKBI+aYJA1oHiOu+cPEoEQP7ZlccC txIAGcGrbRPCICNo2SbLXOlTxYFK8lDIPe9XyhNkr1r3kuR1wgcA3/c5AARBwFdWVgAAKulLwgeA MtLf2tqS3wFVkH7Zd2oSXGXiDDD/XfUYvyR+NZnU5O4HFOIHcOy67sd2Tb+FCisALIx46623nOvX r+f5AXKDIAW6u95E9kIbe+aCoEwMAMDDhw9JioGjoyMaDocEAKPRiOI4pjRNc4+B9BSoL8VTYBQF FeX8hq+GHICCOIA+VhsDvV2ZU2eVlqHw95KkrPSpZbU/b/d9v9BXdZQiotPpmAjfSPaO4+RH+ZJW fq/XoyorHxhn78tNenTSB4Dt7e0m31ldjF9t0+P8apuJ+NVH8wJFS9+0rl/IYxbnT5Mk+V4Yhp8o Is3CAoAVABY1+OY3v+meO3eO+b5P29vbuivYROpVQkBvO1NRUCcGgBPvgBQEo9GIAEAKAmAcPjAJ AmDsUakQBYAmBoCxZwEngqBgMaoCQs7X+mSbegTKhUAtJEl7nkdKHSgSP3BC6Go5H2OqqwKg0+mA MZb3l5E9AJgI3/M80ev1yET48mFYS0tLotvtUgvS179HU1tTAaBb/jrxO0qfTvyqxV8W5/cAIEkS FwA453eyLXxtnN/CCCsALGohwwLLy8sMABQhUOUBaCoE9L4zEwXTCALgxEMAjD0DJi8BME44lEIA GH+vqjCQbSXiAFCI3tSm1qH9tivIX28XQRCYxpq8AaViQCH3Qp/azhgTURRBliXRA2OCl6Qv65Ls gfFjr2UcHwA2NsZ5jibCB8Zu/W63SyWEr/8vV30/dRZ+WVkP36hlNcZSRfzqmn4B7QE+CvHf833/ IyI60D+MhYUKKwAsGsMgBAAz8eskrrc1JfszEwWqGACaCQJgvD2x6iUAJkUBcCIG9LJK7qY2/Zih qi/vNyEMw/zcDZaCVYoAdb5qycuj3iaz8YETgpdlYEzykvBVsg+CQPT7fVJj+G0IH8hJv+y7qfv+ TPUqd786Rm1ztSNwQuqd7Ghy+RfW9EviF0I8yNbz2wQ/i0awAsCiNaQQWF9fd4A8I7osNGAi8bbe gVnGzgVNBQFQLQqAyfABUBQGVUdgkuhNfWo9iqKm3oACygSBiejVdrVNtei73S6ZSF49SpJXyR4Y W/adTkcsLS2RTvYA8oftbG5uCgB4+eWXC9esEH5+uTX1sr4yD0CdANCT+YAT4ldJPszOUUX8BVe/ EGLX87wPafwsBAuLxrACwGJqCCHYe++950ZRxICCEDCFBkwC4KkTAhJlggBoLgqAcfhAjlE9BsCJ OFDbALMo0OtqudfrlY6rgkrkOiSBm8bpJA8Aq6ureX8ZyQNjogfGiYAAcPHiRQDVZA80InygmbVv amsjAIDqpD6g6OaX/aF2DJQ+lfjztfxCiL3M4n9g+AwWFrWwAsBiZhiEANDMta+HCcrGtQ0BqCLk 1ERCE1EAmIUBMCkOALNAAIB+v88AYHd3VwBFsbCysjIhIMqgCgugSNplkNa6qW1paYmAE3IHzAQP nJC83E9/eXmZTEQPFMn+0qVLhfdXElR11H3+MmKv6iuz8Ms27ZHjTW7+EJMCQFr7BC27P01TX4yx 63ne+9bit5gVVgBYzA1SCCwtLTlAHndtSsCmJUqzegjaYO7n1QUBUBQFQFEYBEGQk8jnn38uVHEA AL1eL++Xj0SWUEWDDlVEzAK5pE/F8vIyAUViB07IHTgheGVOob62tib6/T4BRaIHJskeyJektiH3 Nm0mV75e1sfosf2qbH7CpLWvltVxHgCkaeoDEJzzB9bVbzFPWAFgMXfoQgCYSMJq4h1Qy2XjF2nd 60lipqQx0xjTb6qQH/HOO+8Yf3fvv/9+of3u3bsT4x48eDDRJrc6NuHg4GCuv3FJ5qurqxPn1Ykd GJO73nb+/Pm8rdfrkYnkgYm9J6Yh/Lq+Mnd+WR9gtvSlAKiz9uVY1b1v3Ls/SRIiIh8YL+fzPO8j +7Aei3nDCgCLhUEIQe+9954XRRGT1u2FCxeaWvpqu2lFQd28Uw8BzIoyYaBCFwkSJrFQBpOIULG+ vk6AmbzLoJK6iitXrqguf+P7GjaZUjENsZf1N3Hz1yXz1Vn6wAmZA2ZrX3fz59a+JH4hBOecf+b7 /sd2OZ/FomAFgMXCIVcNbG5uuo7jEHDyBDU5xDSt5HQcZnJvQlZPjRgoQxORUIYy8QCYLXoJlcTb Qnm4VJPrbvPZ6si9yZimAsCpKecEnqGptS/nUbZrHwEYpWn6SRAEn9gNfCwWDSsALE4VQgjn1q1b nhrv1sRAPrTsFA3LbT0AT704qEKZcJCx9zrUPCVyHveRJm76Jv1NE/v0OtP6TJY+oSgAVEvfRPSq ha+OzwVARvwA8Nh13VsAPrdb9lqcFqwAsDgTCCHYhx9+6HW73fyGmgmBJu59vayPnUfOQJscgLOA /tttEy9f1DXMa2yTebNY92q7bNMFQBNLX1r4QFEAqBa+KhLy+H52HiGE2PE873tEtAsLi1OGFQAW ZwqZJ7C0tOQ4jkOMMdIzwfUp2lGW5f+y/vTCMmuqbL+CWVDm7i4j57rNaer6TxuzvP+0SXzTCgC9 jQxj9J36ytbte8oYoNzCVzfsIaUMFN38wzRNPwuC4LZ181ucJc76hmJhkUOGBzqdTn7zzcRAnVeg LC9Ar7fJGXimQwIlWKQrv82YOtJvEu8Hqt36QJHk1TrhJKlPJ/kyt34ez8/qMqkv78+26v3Ubtxj 8aTACgCLJw7ZVrXu3bt3PcYYMcYIOHlym2mKoWzyAFQJgDKXf1m/aczTgHn95tueZ54eAJ3Im4wj Q10XAKp737QVr5w34dbHiWiQz33wAUAIcZim6edhGN6x1r7FkwYrACyeaAgh2K1bt/xut6sus8Jg MCgMM5QJ1d4APTQwL4+AaS+AKld+Vex+mhBAk01y2mIeZF91jrZ9JgFgaiuz8OV5Xa3ftAtfmaUP tV2J6wNAmqbpF0EQ3LVr9y2eZFgBYPHUQAjh3r592wuCwCEiAoCNjY2mCYB6nz6uLHegKvzwrHgF JJreD+Zp/Zti82VzTSGAsiQ+wEz46twmJK+69Kvi+pxz/tD3/c8BfGkz+S2eBlgBYPHUQQ0ReJ6X 3+SzZ8K32XqYtDowKQDytzVdijanbpzELImAZeOqxs/6O581rl8330TeVX16m57AJ9GU8GWbieRl X34uNa6fkf4OgPtElFR8DguLJw5WAFg81VDFQBAEBZeuYSc7PaGwjQDQ+8vaTvP5BfPAvGP5pjHT CICmlr2ETvZAMVlP1vV+9f1U0s/LcRwzIpLnF5zzPd/37wN4QESx4VosLJ4KWAFg8cxAFwMyTADk T5YzrShosnoAqBYAVfPK2prirPIA2iTl1Y2pywloIwBMsXtgkuxlm6leZuXnT+9TrHwIIbgQQpL+ Q2vpWzwrsALA4pmFEMK9e/eur4oBIqKVlRUpBgCzACDU5wSUtaWY/F3pQqFNzsC0O/DNcw8BU+y9 zbXUZe3r2fkqdLLXLXW1Tc8N0L0Cely/0B/HsQeM/0eEECPO+cMgCB4C2LMxfYtnEVYAWDwXkHsM dLtd1/O8nFSIiLKn2OkCoE4QoKYNFW114/WxXKs3wTwEgMmSb+sBqCJ3CZNFb7LSZbtO9uo4td3V 2lTCpziOCwJACLGfpumjTqfz0D6Ax+J5gBUAFs8d1FBBGIYeY6xgoS4vLwPVgiA/ldIvYSJ0ncRV tBUAdWNVNA09NLkPNCFy0zn1eL1pronQgUkXvjpeP1etANAInzDekW8vDMM9WCvf4jmEFQAWzz2E EAyAe+/ePc/3fddxnAJpLS0tAeb1+ibLvCwLv8yKbyIA0oq+qnlQ5jb9rZvGNSHxsnaTBd90jB6j l9Ate2ObdOnLNiHEkHP+OCP8x3ZjHovnHVYAWFho0AWB67oTceh+v28KGwDmsABQ7pKvCg/I+jwE QBXqCN0Uh687T5O5dWN0YSBRRfZ5uxDiKE3Tx51O5zHGhG8z9i0sFFgBYGHRAEIIF4B7//59z/d9 j4gKYQMiol6vp4uCKswjEbDpcjtTYmKTeTIzXh/TRgA4Je1Nzm8UBnrsHgCEEDHn/DBN08Nut3sA 4ICInuTllxYWZw4rACwspkDmJXDkZkS+73uMMX3nOQBAiTCoEgAmYm+aCFhGtlUioGyOKTmvavw0 892SdhqNRgWilys5Mlf+cZqmR91u9xDAkV2aZ2HRHlYAWFjMCVlyoYPMU+C6ruM4jkNEjronQQYC gG63WycOZL1MADT1AsDwPmXzyizzqvGmslEQqeXRaFQW5ycAMed8yDkfRlF0DOAIwNAm61lYzAdW AFhYLBiqMLh3757jeZ7jeZ5HRKxKHEhEUQTMRwCoQqJqXi1x11wDgFpyBwAIIRIASZqmx5zzuNfr jQAMAYws0VtYLBZWAFhYnDGy/AIC4O3s7DDP89zMc8CIiDHGmiTSTaBMWIRhaAoH0PHxMQFg2rxZ yokQIs1eSZqmcb/fTzAmeE5Ew7Jrt7CwWDysALCweAog9y7Iqi6ydfm7u7ueJGw2Rm51K+2mNfKl HgA5j3OuL5MjzvlICCGIiDjnab/fl2MEAFke2QQ8CwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsL CwsLCwsLCwsLCwsLCwsLCwsLCwsLC4t54f8D2brgF/Lp4R8AAAAASUVORK5CYII= " + id="image4549" + x="162.0482" + y="122.71503" /> + <rect + y="120.0357" + x="203.07843" + height="40" + width="48" + id="rect3861" + style="opacity:0.79620852;fill:#deded0;fill-opacity:1;stroke:none" /> + <image + y="122.71503" + x="210.03737" + id="image3863" + xlink:href="data:image/png;base64,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 " + height="35.911209" + width="35.911209" /> + <path + sodipodi:type="arc" + style="fill:url(#radialGradient3838);fill-opacity:1;stroke:none" + id="path3813" + sodipodi:cx="223.62251" + sodipodi:cy="147.08873" + sodipodi:rx="11.136931" + sodipodi:ry="9.0156116" + d="m 234.75944,147.08873 a 11.136931,9.0156116 0 1 1 -22.27386,0 11.136931,9.0156116 0 1 1 22.27386,0 z" + transform="matrix(1.2054549,0,0,1.1341085,-41.21305,-21.172626)" /> + <rect + ry="4.1932693" + y="467.85327" + x="215.2729" + height="43.25" + width="200.58887" + id="rect4912" + style="fill:#c9dbdf;fill-opacity:1;stroke:none" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + id="path4914" + d="m 219.19773,467.616 c -2.3021,0 -4.1543,2.0202 -4.1543,4.5312 l 0,17.9688 200.5856,0 0,-17.9688 c 0,-2.511 -1.8521,-4.5312 -4.1543,-4.5312 l -192.277,0 z" + style="fill:#d6e5e8;fill-opacity:1;stroke:none" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + transform="matrix(0.91683189,0,0,1,2564.1856,-830.04452)" + style="fill:#555753;fill-opacity:0.68306011;stroke:none;filter:url(#filter4997-0)" + id="rect4917" + width="218.78479" + height="43.25" + x="-2560" + y="1248.6122" + ry="4.1932693" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + ry="4.1932693" + y="417.31763" + x="216.40852" + height="43.25" + width="200.58887" + id="rect4919" + style="fill:#c9dbdf;fill-opacity:1;stroke:none" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + id="path4921" + d="m 220.33333,417.0805 c -2.3021,0 -4.1543,2.0202 -4.1543,4.5312 l 0,17.9688 200.5856,0 0,-17.9688 c 0,-2.511 -1.8521,-4.5312 -4.1543,-4.5312 l -192.277,0 z" + style="fill:#d6e5e8;fill-opacity:1;stroke:none" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + style="fill:url(#linearGradient5710);fill-opacity:1;stroke:none" + id="rect5702" + width="200.58887" + height="42.75" + x="216.40852" + y="417.31763" + ry="4.1447921" /> + <text + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + xml:space="preserve" + style="font-size:18.32528687px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#c6d9dd;fill-opacity:1;stroke:none;font-family:Arial Rounded MT Bold;-inkscape-font-specification:Arial Rounded MT Bold" + x="258.99481" + y="445.8772" + id="text5782" + sodipodi:linespacing="125%"><tspan + sodipodi:role="line" + id="tspan5784" + x="258.99481" + y="445.8772" + style="font-size:23px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#c6d9dd;fill-opacity:1;font-family:Yanone Kaffeesatz;-inkscape-font-specification:Yanone Kaffeesatz">ASK A QUESTION</tspan></text> + <text + sodipodi:linespacing="125%" + id="text4923" + y="444.99341" + x="258.99481" + style="font-size:18.32528687px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#314e55;fill-opacity:1;stroke:none;font-family:Arial Rounded MT Bold;-inkscape-font-specification:Arial Rounded MT Bold" + xml:space="preserve" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"><tspan + style="font-size:23px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#314e55;fill-opacity:1;font-family:Yanone Kaffeesatz;-inkscape-font-specification:Yanone Kaffeesatz" + y="444.99341" + x="258.99481" + id="tspan4926" + sodipodi:role="line">ASK A QUESTION</tspan></text> + <g + id="g5771" + clip-path="url(#clipPath5776)" + transform="matrix(0.95652174,0,0,0.9658003,1661.0255,-3400.1079)" + inkscape:export-filename="/home/bcorrales/personal/askbot/bigbutton.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="4.1932693" + y="4000.7271" + x="-1346.1777" + height="43.25" + width="200.58887" + id="rect5712" + style="fill:#c9dbdf;fill-opacity:1;stroke:none" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + id="path5714" + d="m -1342.2529,4000.4898 c -2.3021,0 -4.1543,2.0202 -4.1543,4.5312 l 0,17.9688 200.5856,0 0,-17.9688 c 0,-2.511 -1.8521,-4.5312 -4.1543,-4.5312 l -192.277,0 z" + style="fill:#d6e5e8;fill-opacity:1;stroke:none" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> + <g + id="g5728" + clip-path="url(#clipPath5733)" + transform="matrix(1,0,0,0.96580351,1721.4506,-3395.7266)" + inkscape:export-filename="/home/bcorrales/personal/askbot/bigbutton.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <rect + ry="4.1932693" + y="3952.6914" + x="-1345.0421" + height="43.25" + width="200.58887" + id="rect5718" + style="fill:#c9dbdf;fill-opacity:1;stroke:none" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <path + inkscape:connector-curvature="0" + id="path5720" + d="m -1341.1173,3952.4543 c -2.3021,0 -4.1543,2.0202 -4.1543,4.5312 l 0,17.9688 200.5856,0 0,-17.9688 c 0,-2.511 -1.8521,-4.5312 -4.1543,-4.5312 l -192.277,0 z" + style="fill:#d6e5e8;fill-opacity:1;stroke:none" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + <rect + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + style="fill:url(#linearGradient5765);fill-opacity:1;stroke:none" + id="rect5722" + width="200.58887" + height="42.75" + x="-1345.0421" + y="3952.6914" + ry="4.1447921" /> + </g> + <rect + inkscape:export-ydpi="90" + inkscape:export-xdpi="90" + inkscape:export-filename="/home/bcorrales/personal/askbot/templates/question_page_20_oct.png" + style="fill:#eceeeb;fill-opacity:1;stroke:none" + id="rect8138" + width="200" + height="34" + x="208.43501" + y="563.99463" /> + <path + style="fill:#cfcdcb;fill-opacity:1;stroke:none" + d="m 237.10314,570.64836 c -4.1222,0 -7.6717,2.6492 -9.375,6.5 -0.6289,-0.2342 -1.2957,-0.375 -2,-0.375 -1.9564,0 -3.7033,0.9745 -4.8125,2.5 l -11.8437,0.125 0,7.3125 11.5312,-0.094 c 1.0734,1.8106 2.9601,3.0313 5.125,3.0313 1.022,0 1.9677,-0.2764 2.8125,-0.75 1.8902,3.0125 5.0068,4.9687 8.5625,4.9687 3.7337,0 7.0246,-2.1669 8.875,-5.4374 l -4.8125,0 c -1.0612,0.806 -2.5249,0.8124 -3.9063,0.8124 -3.6563,0 -4.8124,-2.9663 -4.8124,-7.0312 0,-4.0647 1.4686,-6.625 5.125,-6.625 1.7505,0 3.2224,0.1762 4.4062,1.4062 l 4.4688,0 c -1.7287,-3.7705 -5.2744,-6.3437 -9.3438,-6.3437 z" + id="rect5882" + inkscape:connector-curvature="0" + inkscape:export-filename="/home/bcorrales/personal/askbot/contributorsback.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90" /> + </g> +</svg> diff --git a/askbot/skins/default/media/images/summary-background.png b/askbot/skins/default/media/images/summary-background.png Binary files differnew file mode 100644 index 00000000..58c3855a --- /dev/null +++ b/askbot/skins/default/media/images/summary-background.png diff --git a/askbot/skins/default/media/js/less.min.js b/askbot/skins/default/media/js/less.min.js new file mode 100644 index 00000000..6e4d5cff --- /dev/null +++ b/askbot/skins/default/media/js/less.min.js @@ -0,0 +1,16 @@ +// +// LESS - Leaner CSS v1.1.3 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +// +// LESS - Leaner CSS v1.1.3 +// http://lesscss.org +// +// Copyright (c) 2009-2011, Alexis Sellier +// Licensed under the Apache 2.0 License. +// +(function(a,b){function v(a,b){var c="less-error-message:"+p(b),e=["<ul>",'<li><label>[-1]</label><pre class="ctx">{0}</pre></li>',"<li><label>[0]</label><pre>{current}</pre></li>",'<li><label>[1]</label><pre class="ctx">{2}</pre></li>',"</ul>"].join("\n"),f=document.createElement("div"),g,h;f.id=c,f.className="less-error-message",h="<h3>"+(a.message||"There is an error in your .less file")+"</h3>"+'<p><a href="'+b+'">'+b+"</a> ",a.extract&&(h+="on line "+a.line+", column "+(a.column+1)+":</p>"+e.replace(/\[(-?\d)\]/g,function(b,c){return parseInt(a.line)+parseInt(c)||""}).replace(/\{(\d)\}/g,function(b,c){return a.extract[parseInt(c)]||""}).replace(/\{current\}/,a.extract[1].slice(0,a.column)+'<span class="error">'+a.extract[1].slice(a.column)+"</span>")),f.innerHTML=h,q([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #ee4444;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.ctx {","color: #dd4444;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}function u(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function t(a){return a&&a.parentNode.removeChild(a)}function s(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){u("browser doesn't support AJAX.");return null}}function r(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var f=s(),h=g?!1:d.async;typeof f.overrideMimeType=="function"&&f.overrideMimeType("text/css"),f.open("GET",a,h),f.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),f.send(null),g?f.status===0?c(f.responseText):e(f.status,a):h?f.onreadystatechange=function(){f.readyState==4&&i(f,c,e)}:i(f,c,e)}function q(a,b,c){var d,e=b.href?b.href.replace(/\?.*$/,""):"",f="less:"+(b.title||p(e));(d=document.getElementById(f))===null&&(d=document.createElement("style"),d.type="text/css",d.media=b.media||"screen",d.id=f,document.getElementsByTagName("head")[0].appendChild(d));if(d.styleSheet)try{d.styleSheet.cssText=a}catch(g){throw new Error("Couldn't reassign styleSheet.cssText.")}else(function(a){d.childNodes.length>0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&h&&(u("saving "+e+" to cache."),h.setItem(e,a),h.setItem(e+":timestamp",c))}function p(a){return a.replace(/^[a-z]+:\/\/?[^\/]+/,"").replace(/^\//,"").replace(/\?.*$/,"").replace(/\.[^\.\/]+$/,"").replace(/[^\.\w-]+/g,"-").replace(/\./g,":")}function o(b,c,e,f){var g=a.location.href.replace(/[#?].*$/,""),i=b.href.replace(/\?.*$/,""),j=h&&h.getItem(i),k=h&&h.getItem(i+":timestamp"),l={css:j,timestamp:k};/^(https?|file):/.test(i)||(i.charAt(0)=="/"?i=a.location.protocol+"//"+a.location.host+i:i=g.slice(0,g.lastIndexOf("/")+1)+i),r(b.href,b.type,function(a,g){if(!e&&l&&g&&(new Date(g)).valueOf()===(new Date(l.timestamp)).valueOf())q(l.css,b),c(null,b,{local:!0,remaining:f});else try{(new d.Parser({optimization:d.optimization,paths:[i.replace(/[\w\.-]+$/,"")],mime:b.type})).parse(a,function(a,d){if(a)return v(a,i);try{c(d,b,{local:!1,lastModified:g,remaining:f}),t(document.getElementById("less-error-message:"+p(i)))}catch(a){v(a,i)}})}catch(h){v(h,i)}},function(a,b){throw new Error("Couldn't load "+b+" ("+a+")")})}function n(a,b){for(var c=0;c<d.sheets.length;c++)o(d.sheets[c],a,b,d.sheets.length-(c+1))}function m(){var a=document.getElementsByTagName("style");for(var b=0;b<a.length;b++)a[b].type.match(k)&&(new d.Parser).parse(a[b].innerHTML||"",function(c,d){a[b].type="text/css",a[b].innerHTML=d.toCSS()})}function c(b){return a.less[b.split("/")[1]]}Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d<c;d++)d in this&&a.call(b,this[d],d,this)}),Array.prototype.map||(Array.prototype.map=function(a){var b=this.length>>>0,c=Array(b),d=arguments[1];for(var e=0;e<b;e++)e in this&&(c[e]=a.call(d,this[e],e,this));return c}),Array.prototype.filter||(Array.prototype.filter=function(a){var b=[],c=arguments[1];for(var d=0;d<this.length;d++)a.call(c,this[d])&&b.push(this[d]);return b}),Array.prototype.reduce||(Array.prototype.reduce=function(a){var b=this.length>>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else for(;;){if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}for(;c<b;c++)c in this&&(d=a.call(null,d,this[c],c,this));return d}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){var b=this.length,c=arguments[1]||0;if(!b)return-1;if(c>=b)return-1;c<0&&(c+=b);for(;c<b;c++){if(!Object.prototype.hasOwnProperty.call(this,c))continue;if(a===this[c])return c}return-1}),Object.keys||(Object.keys=function(a){var b=[];for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&b.push(c);return b}),String.prototype.trim||(String.prototype.trim=function(){return String(this).replace(/^\s\s*/,"").replace(/\s\s*$/,"")});var d,e;typeof a=="undefined"?(d=exports,e=c("less/tree")):(typeof a.less=="undefined"&&(a.less={}),d=a.less,e=a.less.tree={}),d.Parser=function(a){function t(a){return typeof a=="string"?b.charAt(c)===a:a.test(j[f])?!0:!1}function s(a){var d,e,g,h,i,m,n,o;if(a instanceof Function)return a.call(l.parsers);if(typeof a=="string")d=b.charAt(c)===a?a:null,g=1,r();else{r();if(d=a.exec(j[f]))g=d[0].length;else return null}if(d){o=c+=g,m=c+j[f].length-g;while(c<m){h=b.charCodeAt(c);if(h!==32&&h!==10&&h!==9)break;c++}j[f]=j[f].slice(g+(c-o)),k=c,j[f].length===0&&f<j.length-1&&f++;return typeof d=="string"?d:d.length===1?d[0]:d}}function r(){c>k&&(j[f]=j[f].slice(c-k),k=c)}function q(){j[f]=g,c=h,k=c}function p(){g=j[f],h=c,k=c}var b,c,f,g,h,i,j,k,l,m=this,n=function(){},o=this.imports={paths:a&&a.paths||[],queue:[],files:{},mime:a&&a.mime,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=a,c(a),e.queue.length===0&&n()},a)}};this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null;return l={imports:o,parse:function(d,g){var h,l,m,o,p,q,r=[],t,u=null;c=f=k=i=0,j=[],b=d.replace(/\r\n/g,"\n"),j=function(c){var d=0,e=/[^"'`\{\}\/\(\)]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=0,h,i=c[0],j,k;for(var l=0,m,n;l<b.length;l++){e.lastIndex=l,(h=e.exec(b))&&h.index===l&&(l+=h[0].length,i.push(h[0])),m=b.charAt(l),f.lastIndex=l,!k&&!j&&m==="/"&&(n=b.charAt(l+1),(n==="/"||n==="*")&&(h=f.exec(b))&&h.index===l&&(l+=h[0].length,i.push(h[0]),m=b.charAt(l)));if(m==="{"&&!k&&!j)g++,i.push(m);else if(m==="}"&&!k&&!j)g--,i.push(m),c[++d]=i=[];else if(m==="("&&!k&&!j)i.push(m),j=!0;else if(m===")"&&!k&&j)i.push(m),j=!1;else{if(m==='"'||m==="'"||m==="`")k?k=k===m?!1:k:k=m;i.push(m)}}if(g>0)throw{type:"Syntax",message:"Missing closing `}`",filename:a.filename};return c.map(function(a){return a.join("")})}([[]]),h=new e.Ruleset([],s(this.parsers.primary)),h.root=!0,h.toCSS=function(c){var d,f,g;return function(g,h){function n(a){return a?(b.slice(0,a).match(/\n/g)||"").length:null}var i=[];g=g||{},typeof h=="object"&&!Array.isArray(h)&&(h=Object.keys(h).map(function(a){var b=h[a];b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b]));return new e.Rule("@"+a,b,!1,0)}),i=[new e.Ruleset(null,h)]);try{var j=c.call(this,{frames:i}).toCSS([],{compress:g.compress||!1})}catch(k){f=b.split("\n"),d=n(k.index);for(var l=k.index,m=-1;l>=0&&b.charAt(l)!=="\n";l--)m++;throw{type:k.type,message:k.message,filename:a.filename,index:k.index,line:typeof d=="number"?d+1:null,callLine:k.call&&n(k.call)+1,callExtract:f[n(k.call)],stack:k.stack,column:m,extract:[f[d-1],f[d],f[d+1]]}}return g.compress?j.replace(/(\s)+/g,"$1"):j}}(h.eval);if(c<b.length-1){c=i,q=b.split("\n"),p=(b.slice(0,c).match(/\n/g)||"").length+1;for(var v=c,w=-1;v>=0&&b.charAt(v)!=="\n";v--)w++;u={name:"ParseError",message:"Syntax Error on line "+p,index:c,filename:a.filename,line:p,column:w,extract:[q[p-2],q[p-1],q[p]]}}this.imports.queue.length>0?n=function(){g(u,h)}:g(u,h)},parsers:{primary:function(){var a,b=[];while((a=s(this.mixin.definition)||s(this.rule)||s(this.ruleset)||s(this.mixin.call)||s(this.comment)||s(this.directive))||s(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(c)==="/"){if(b.charAt(c+1)==="/")return new e.Comment(s(/^\/\/.*/),!0);if(a=s(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)}},entities:{quoted:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==='"'||b.charAt(d)==="'"){f&&s("~");if(a=s(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],f)}},keyword:function(){var a;if(a=s(/^[A-Za-z-]+/))return new e.Keyword(a)},call:function(){var a,b,d=c;if(!!(a=/^([\w-]+|%)\(/.exec(j[f]))){a=a[1].toLowerCase();if(a==="url")return null;c+=a.length;if(a==="alpha")return s(this.alpha);s("("),b=s(this.entities.arguments);if(!s(")"))return;if(a)return new e.Call(a,b,d)}},arguments:function(){var a=[],b;while(b=s(this.expression)){a.push(b);if(!s(","))break}return a},literal:function(){return s(this.entities.dimension)||s(this.entities.color)||s(this.entities.quoted)},url:function(){var a;if(b.charAt(c)==="u"&&!!s(/^url\(/)){a=s(this.entities.quoted)||s(this.entities.variable)||s(this.entities.dataURI)||s(/^[-\w%@$\/.&=:;#+?~]+/)||"";if(!s(")"))throw new Error("missing closing ) for url()");return new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),o.paths)}},dataURI:function(){var a;if(s(/^data:/)){a={},a.mime=s(/^[^\/]+\/[^,;)]+/)||"",a.charset=s(/^;\s*charset=[^,;)]+/)||"",a.base64=s(/^;\s*base64/)||"",a.data=s(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var a,d=c;if(b.charAt(c)==="@"&&(a=s(/^@@?[\w-]+/)))return new e.Variable(a,d)},color:function(){var a;if(b.charAt(c)==="#"&&(a=s(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,d=b.charCodeAt(c);if(!(d>57||d<45||d===47))if(a=s(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,d=c,f;b.charAt(d)==="~"&&(d++,f=!0);if(b.charAt(d)==="`"){f&&s("~");if(a=s(/^`([^`]*)`/))return new e.JavaScript(a[1],c,f)}}},variable:function(){var a;if(b.charAt(c)==="@"&&(a=s(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!!t(/^[@\w.%-]+\/[@\w.-]+/)&&(a=s(this.entity))&&s("/")&&(b=s(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var a=[],d,f,g,h=c,i=b.charAt(c);if(i==="."||i==="#"){while(d=s(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))a.push(new e.Element(f,d)),f=s(">");s("(")&&(g=s(this.entities.arguments))&&s(")");if(a.length>0&&(s(";")||t("}")))return new e.mixin.Call(a,g,h)}},definition:function(){var a,d=[],f,g,h,i;if(!(b.charAt(c)!=="."&&b.charAt(c)!=="#"||t(/^[^{]*(;|})/)))if(f=s(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=f[1];while(h=s(this.entities.variable)||s(this.entities.literal)||s(this.entities.keyword)){if(h instanceof e.Variable)if(s(":"))if(i=s(this.expression))d.push({name:h.name,value:i});else throw new Error("Expected value");else d.push({name:h.name});else d.push({value:h});if(!s(","))break}if(!s(")"))throw new Error("Expected )");g=s(this.block);if(g)return new e.mixin.Definition(a,d,g)}}},entity:function(){return s(this.entities.literal)||s(this.entities.variable)||s(this.entities.url)||s(this.entities.call)||s(this.entities.keyword)||s(this.entities.javascript)||s(this.comment)},end:function(){return s(";")||t("}")},alpha:function(){var a;if(!!s(/^\(opacity=/i))if(a=s(/^\d+/)||s(this.entities.variable)){if(!s(")"))throw new Error("missing closing ) for alpha()");return new e.Alpha(a)}},element:function(){var a,b,c;c=s(this.combinator),a=s(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||s("*")||s(this.attribute)||s(/^\([^)@]+\)/);if(a)return new e.Element(c,a)},combinator:function(){var a,d=b.charAt(c);if(d===">"||d==="&"||d==="+"||d==="~"){c++;while(b.charAt(c)===" ")c++;return new e.Combinator(d)}if(d===":"&&b.charAt(c+1)===":"){c+=2;while(b.charAt(c)===" ")c++;return new e.Combinator("::")}return b.charAt(c-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,d,f=[],g,h;while(d=s(this.element)){g=b.charAt(c),f.push(d);if(g==="{"||g==="}"||g===";"||g===",")break}if(f.length>0)return new e.Selector(f)},tag:function(){return s(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||s("*")},attribute:function(){var a="",b,c,d;if(!!s("[")){if(b=s(/^[a-zA-Z-]+/)||s(this.entities.quoted))(d=s(/^[|~*$^]?=/))&&(c=s(this.entities.quoted)||s(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!s("]"))return;if(a)return"["+a+"]"}},block:function(){var a;if(s("{")&&(a=s(this.primary))&&s("}"))return a},ruleset:function(){var a=[],b,d,g;p();if(g=/^([.#: \w-]+)[\s\n]*\{/.exec(j[f]))c+=g[0].length-1,a=[new e.Selector([new e.Element(null,g[1])])];else while(b=s(this.selector)){a.push(b),s(this.comment);if(!s(","))break;s(this.comment)}if(a.length>0&&(d=s(this.block)))return new e.Ruleset(a,d);i=c,q()},rule:function(){var a,d,g=b.charAt(c),k,l;p();if(g!=="."&&g!=="#"&&g!=="&")if(a=s(this.variable)||s(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(j[f]))?(c+=l[0].length-1,d=new e.Anonymous(l[1])):a==="font"?d=s(this.font):d=s(this.value),k=s(this.important);if(d&&s(this.end))return new e.Rule(a,d,k,h);i=c,q()}},"import":function(){var a;if(s(/^@import\s+/)&&(a=s(this.entities.quoted)||s(this.entities.url))&&s(";"))return new e.Import(a,o)},directive:function(){var a,d,f,g;if(b.charAt(c)==="@"){if(d=s(this["import"]))return d;if(a=s(/^@media|@page|@-[-a-z]+/)){g=(s(/^[^{]+/)||"").trim();if(f=s(this.block))return new e.Directive(a+" "+g,f)}else if(a=s(/^@[-a-z]+/))if(a==="@font-face"){if(f=s(this.block))return new e.Directive(a,f)}else if((d=s(this.entity))&&s(";"))return new e.Directive(a,d)}},font:function(){var a=[],b=[],c,d,f,g;while(g=s(this.shorthand)||s(this.entity))b.push(g);a.push(new e.Expression(b));if(s(","))while(g=s(this.expression)){a.push(g);if(!s(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=s(this.expression)){b.push(a);if(!s(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(c)==="!")return s(/^! *important/)},sub:function(){var a;if(s("(")&&(a=s(this.expression))&&s(")"))return a},multiplication:function(){var a,b,c,d;if(a=s(this.operand)){while((c=s("/")||s("*"))&&(b=s(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,d,f,g;if(a=s(this.multiplication)){while((f=s(/^[-+]\s+/)||b.charAt(c-1)!=" "&&(s("+")||s("-")))&&(d=s(this.multiplication)))g=new e.Operation(f,[g||a,d]);return g||a}},operand:function(){var a,d=b.charAt(c+1);b.charAt(c)==="-"&&(d==="@"||d==="(")&&(a=s("-"));var f=s(this.sub)||s(this.entities.dimension)||s(this.entities.color)||s(this.entities.variable)||s(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),f]):f},expression:function(){var a,b,c=[],d;while(a=s(this.addition)||s(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=s(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}},typeof a!="undefined"&&(d.Parser.importer=function(a,b,c,d){a.charAt(0)!=="/"&&b.length>0&&(a=b[0]+a),o({href:a,title:a,type:d.mime},c,!0)}),function(a){function d(a){return Math.min(1,Math.max(0,a))}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){a=a<0?a+1:a>1?a-1:a;return a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();e.s+=c.value/100,e.s=d(e.s);return b(e)},desaturate:function(a,c){var e=a.toHSL();e.s-=c.value/100,e.s=d(e.s);return b(e)},lighten:function(a,c){var e=a.toHSL();e.l+=c.value/100,e.l=d(e.l);return b(e)},darken:function(a,c){var e=a.toHSL();e.l-=c.value/100,e.l=d(e.l);return b(e)},fadein:function(a,c){var e=a.toHSL();e.a+=c.value/100,e.a=d(e.a);return b(e)},fadeout:function(a,c){var e=a.toHSL();e.a-=c.value/100,e.a=d(e.a);return b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;d.h=e<0?360+e:e;return b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e<c.length;e++)d=d.replace(/%[sda]/i,function(a){var b=a.match(/s/i)?c[e].value:c[e].toCSS();return a.match(/[A-Z]$/)?encodeURIComponent(b):b});d=d.replace(/%%/g,"%");return new a.Quoted('"'+d+'"',d)},round:function(b){if(b instanceof a.Dimension)return new a.Dimension(Math.round(c(b)),b.unit);if(typeof b=="number")return Math.round(b);throw{error:"RuntimeError",message:"math functions take numbers as parameters"}}}}(c("less/tree")),function(a){a.Alpha=function(a){this.value=a},a.Alpha.prototype={toCSS:function(){return"alpha(opacity="+(this.value.toCSS?this.value.toCSS():this.value)+")"},eval:function(a){this.value.eval&&(this.value=this.value.eval(a));return this}}}(c("less/tree")),function(a){a.Anonymous=function(a){this.value=a.value||a},a.Anonymous.prototype={toCSS:function(){return this.value},eval:function(){return this}}}(c("less/tree")),function(a){a.Call=function(a,b,c){this.name=a,this.args=b,this.index=c},a.Call.prototype={eval:function(b){var c=this.args.map(function(a){return a.eval(b)});if(!(this.name in a.functions))return new a.Anonymous(this.name+"("+c.map(function(a){return a.toCSS()}).join(", ")+")");try{return a.functions[this.name].apply(a.functions,c)}catch(d){throw{message:"error evaluating function `"+this.name+"`",index:this.index}}},toCSS:function(a){return this.eval(a).toCSS()}}}(c("less/tree")),function(a){a.Color=function(a,b){Array.isArray(a)?this.rgb=a:a.length==6?this.rgb=a.match(/.{2}/g).map(function(a){return parseInt(a,16)}):a.length==8?(this.alpha=parseInt(a.substring(0,2),16)/255,this.rgb=a.substr(2).match(/.{2}/g).map(function(a){return parseInt(a,16)})):this.rgb=a.split("").map(function(a){return parseInt(a+a,16)}),this.alpha=typeof b=="number"?b:1},a.Color.prototype={eval:function(){return this},toCSS:function(){return this.alpha<1?"rgba("+this.rgb.map(function(a){return Math.round(a)}).concat(this.alpha).join(", ")+")":"#"+this.rgb.map(function(a){a=Math.round(a),a=(a>255?255:a<0?0:a).toString(16);return a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b<c?6:0);break;case b:g=(c-a)/j+2;break;case c:g=(a-b)/j+4}g/=6}return{h:g*360,s:h,l:i,a:d}}}}(c("less/tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("less/tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)}}}(c("less/tree")),function(a){a.Directive=function(b,c){this.name=b,Array.isArray(c)?this.ruleset=new a.Ruleset([],c):this.value=c},a.Directive.prototype={toCSS:function(a,b){if(this.ruleset){this.ruleset.root=!0;return this.name+(b.compress?"{":" {\n ")+this.ruleset.toCSS(a,b).trim().replace(/\n/g,"\n ")+(b.compress?"}":"\n}\n")}return this.name+" "+this.value.toCSS()+";\n"},eval:function(a){a.frames.unshift(this),this.ruleset=this.ruleset&&this.ruleset.eval(a),a.frames.shift();return this},variable:function(b){return a.Ruleset.prototype.variable.call(this.ruleset,b)},find:function(){return a.Ruleset.prototype.find.apply(this.ruleset,arguments)},rulesets:function(){return a.Ruleset.prototype.rulesets.apply(this.ruleset)}}}(c("less/tree")),function(a){a.Element=function(b,c){this.combinator=b instanceof a.Combinator?b:new a.Combinator(b),this.value=c.trim()},a.Element.prototype.toCSS=function(a){return this.combinator.toCSS(a||{})+this.value},a.Combinator=function(a){a===" "?this.value=" ":this.value=a?a.trim():""},a.Combinator.prototype.toCSS=function(a){return{"":""," ":" ","&":"",":":" :","::":"::","+":a.compress?"+":" + ","~":a.compress?"~":" ~ ",">":a.compress?">":" > "}[this.value]}}(c("less/tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(" ")}}}(c("less/tree")),function(a){a.Import=function(b,c){var d=this;this._path=b,b instanceof a.Quoted?this.path=/\.(le?|c)ss$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css$/.test(this.path),this.css||c.push(this.path,function(a){if(!a)throw new Error("Error parsing "+d.path);d.root=a})},a.Import.prototype={toCSS:function(){return this.css?"@import "+this._path.toCSS()+";\n":""},eval:function(b){var c;if(this.css)return this;c=new a.Ruleset(null,this.root.rules.slice(0));for(var d=0;d<c.rules.length;d++)c.rules[d]instanceof a.Import&&Array.prototype.splice.apply(c.rules,[d,1].concat(c.rules[d].eval(b)));return c.rules}}}(c("less/tree")),function(a){a.JavaScript=function(a,b,c){this.escaped=c,this.expression=a,this.index=b},a.JavaScript.prototype={eval:function(b){var c,d=this,e={},f=this.expression.replace(/@\{([\w-]+)\}/g,function(c,e){return a.jsify((new a.Variable("@"+e,d.index)).eval(b))});try{f=new Function("return ("+f+")")}catch(g){throw{message:"JavaScript evaluation error: `"+f+"`",index:this.index}}for(var h in b.frames[0].variables())e[h.slice(1)]={value:b.frames[0].variables()[h].value,toJS:function(){return this.value.eval(b).toCSS()}};try{c=f.call(e)}catch(g){throw{message:"JavaScript evaluation error: '"+g.name+": "+g.message+"'",index:this.index}}return typeof c=="string"?new a.Quoted('"'+c+'"',c,this.escaped,this.index):Array.isArray(c)?new a.Anonymous(c.join(", ")):new a.Anonymous(c)}}}(c("less/tree")),function(a){a.Keyword=function(a){this.value=a},a.Keyword.prototype={eval:function(){return this},toCSS:function(){return this.value}}}(c("less/tree")),function(a){a.mixin={},a.mixin.Call=function(b,c,d){this.selector=new a.Selector(b),this.arguments=c,this.index=d},a.mixin.Call.prototype={eval:function(a){var b,c,d=[],e=!1;for(var f=0;f<a.frames.length;f++)if((b=a.frames[f].find(this.selector)).length>0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;g<b.length;g++)if(b[g].match(c,a))try{Array.prototype.push.apply(d,b[g].eval(a,this.arguments).rules),e=!0}catch(h){throw{message:h.message,index:h.index,stack:h.stack,call:this.index}}if(e)return d;throw{message:"No matching definition was found for `"+this.selector.toCSS().trim()+"("+this.arguments.map(function(a){return a.toCSS()}).join(", ")+")`",index:this.index}}throw{message:this.selector.toCSS().trim()+" is undefined",index:this.index}}},a.mixin.Definition=function(b,c,d){this.name=b,this.selectors=[new a.Selector([new a.Element(null,b)])],this.params=c,this.arity=c.length,this.rules=d,this._lookups={},this.required=c.reduce(function(a,b){return!b.name||b.name&&!b.value?a+1:a},0),this.parent=a.Ruleset.prototype,this.frames=[]},a.mixin.Definition.prototype={toCSS:function(){return""},variable:function(a){return this.parent.variable.call(this,a)},variables:function(){return this.parent.variables.call(this)},find:function(){return this.parent.find.apply(this,arguments)},rulesets:function(){return this.parent.rulesets.apply(this)},eval:function(b,c){var d=new a.Ruleset(null,[]),e,f=[];for(var g=0,h;g<this.params.length;g++)if(this.params[g].name)if(h=c&&c[g]||this.params[g].value)d.rules.unshift(new a.Rule(this.params[g].name,h.eval(b)));else throw{message:"wrong number of arguments for "+this.name+" ("+c.length+" for "+this.arity+")"};for(var g=0;g<Math.max(this.params.length,c&&c.length);g++)f.push(c[g]||this.params[g].value);d.rules.unshift(new a.Rule("@arguments",(new a.Expression(f)).eval(b)));return(new a.Ruleset(null,this.rules.slice(0))).eval({frames:[this,d].concat(this.frames,b.frames)})},match:function(a,b){var c=a&&a.length||0,d;if(c<this.required)return!1;if(this.required>0&&c>this.params.length)return!1;d=Math.min(c,this.arity);for(var e=0;e<d;e++)if(!this.params[e].name&&a[e].eval(b).toCSS()!=this.params[e].value.eval(b).toCSS())return!1;return!0}}}(c("less/tree")),function(a){a.Operation=function(a,b){this.op=a.trim(),this.operands=b},a.Operation.prototype.eval=function(b){var c=this.operands[0].eval(b),d=this.operands[1].eval(b),e;if(c instanceof a.Dimension&&d instanceof a.Color)if(this.op==="*"||this.op==="+")e=d,d=c,c=e;else throw{name:"OperationError",message:"Can't substract or divide a color from a number"};return c.operate(this.op,d)},a.operate=function(a,b,c){switch(a){case"+":return b+c;case"-":return b-c;case"*":return b*c;case"/":return b/c}}}(c("less/tree")),function(a){a.Quoted=function(a,b,c,d){this.escaped=c,this.value=b||"",this.quote=a.charAt(0),this.index=d},a.Quoted.prototype={toCSS:function(){return this.escaped?this.value:this.quote+this.value+this.quote},eval:function(b){var c=this,d=this.value.replace(/`([^`]+)`/g,function(d,e){return(new a.JavaScript(e,c.index,!0)).eval(b).value}).replace(/@\{([\w-]+)\}/g,function(d,e){var f=(new a.Variable("@"+e,c.index)).eval(b);return f.value||f.toCSS()});return new a.Quoted(this.quote+d+this.quote,d,this.escaped,this.index)}}}(c("less/tree")),function(a){a.Rule=function(b,c,d,e){this.name=b,this.value=c instanceof a.Value?c:new a.Value([c]),this.important=d?" "+d.trim():"",this.index=e,b.charAt(0)==="@"?this.variable=!0:this.variable=!1},a.Rule.prototype.toCSS=function(a){return this.variable?"":this.name+(a.compress?":":": ")+this.value.toCSS(a)+this.important+";"},a.Rule.prototype.eval=function(b){return new a.Rule(this.name,this.value.eval(b),this.important,this.index)},a.Shorthand=function(a,b){this.a=a,this.b=b},a.Shorthand.prototype={toCSS:function(a){return this.a.toCSS(a)+"/"+this.b.toCSS(a)},eval:function(){return this}}}(c("less/tree")),function(a){a.Ruleset=function(a,b){this.selectors=a,this.rules=b,this._lookups={}},a.Ruleset.prototype={eval:function(b){var c=new a.Ruleset(this.selectors,this.rules.slice(0));c.root=this.root,b.frames.unshift(c);if(c.root)for(var d=0;d<c.rules.length;d++)c.rules[d]instanceof a.Import&&Array.prototype.splice.apply(c.rules,[d,1].concat(c.rules[d].eval(b)));for(var d=0;d<c.rules.length;d++)c.rules[d]instanceof a.mixin.Definition&&(c.rules[d].frames=b.frames.slice(0));for(var d=0;d<c.rules.length;d++)c.rules[d]instanceof a.mixin.Call&&Array.prototype.splice.apply(c.rules,[d,1].concat(c.rules[d].eval(b)));for(var d=0,e;d<c.rules.length;d++)e=c.rules[d],e instanceof a.mixin.Definition||(c.rules[d]=e.eval?e.eval(b):e);b.frames.shift();return c},match:function(a){return!a||a.length===0},variables:function(){return this._variables?this._variables:this._variables=this.rules.reduce(function(b,c){c instanceof a.Rule&&c.variable===!0&&(b[c.name]=c);return b},{})},variable:function(a){return this.variables()[a]},rulesets:function(){return this._rulesets?this._rulesets:this._rulesets=this.rules.filter(function(b){return b instanceof a.Ruleset||b instanceof a.mixin.Definition})},find:function(b,c){c=c||this;var d=[],e,f,g=b.toCSS();if(g in this._lookups)return this._lookups[g];this.rulesets().forEach(function(e){if(e!==c)for(var g=0;g<e.selectors.length;g++)if(f=b.match(e.selectors[g])){b.elements.length>1?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}});return this._lookups[g]=d},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;if(!this.root)if(b.length===0)g=this.selectors.map(function(a){return[a]});else for(var j=0;j<this.selectors.length;j++)for(var k=0;k<b.length;k++)g.push(b[k].concat([this.selectors[j]]));for(var l=0;l<this.rules.length;l++)i=this.rules[l],i.rules||i instanceof a.Directive?f.push(i.toCSS(g,c)):i instanceof a.Comment?i.silent||(this.root?f.push(i.toCSS(c)):e.push(i.toCSS(c))):i.toCSS&&!i.variable?e.push(i.toCSS(c)):i.value&&!i.variable&&e.push(i.value.toString());f=f.join(""),this.root?d.push(e.join(c.compress?"":"\n")):e.length>0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":g.length>3?",\n":", "),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f);return d.join("")+(c.compress?"\n":"")}}}(c("less/tree")),function(a){a.Selector=function(a){this.elements=a,this.elements[0].combinator.value===""&&(this.elements[0].combinator.value=" ")},a.Selector.prototype.match=function(a){return this.elements[0].value===a.elements[0].value?!0:!1},a.Selector.prototype.toCSS=function(a){if(this._css)return this._css;return this._css=this.elements.map(function(b){return typeof b=="string"?" "+b.trim():b.toCSS(a)}).join("")}}(c("less/tree")),function(b){b.URL=function(b,c){b.data?this.attrs=b:(!/^(?:https?:\/|file:\/|data:\/)?\//.test(b.value)&&c.length>0&&typeof a!="undefined"&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("less/tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("less/tree")),function(a){a.Variable=function(a,b){this.name=a,this +.index=b},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{message:"variable "+e+" is undefined",index:this.index}}}}(c("less/tree")),c("less/tree").find=function(a,b){for(var c=0,d;c<a.length;c++)if(d=b.call(a,a[c]))return d;return null},c("less/tree").jsify=function(a){return Array.isArray(a.value)&&a.value.length>1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)};var g=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||g?"development":"production"),d.async=!1,d.poll=d.poll||(g?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&n(function(a,b,c){a&&q(a.toCSS(),b,c.lastModified)})},d.poll)):d.optimization=3;var h;try{h=typeof a.localStorage=="undefined"?null:a.localStorage}catch(i){h=null}var j=document.getElementsByTagName("link"),k=/^text\/(x-)?less$/;d.sheets=[];for(var l=0;l<j.length;l++)(j[l].rel==="stylesheet/less"||j[l].rel.match(/stylesheet/)&&j[l].type.match(k))&&d.sheets.push(j[l]);d.refresh=function(a){var b,c;b=c=new Date,n(function(a,d,e){e.local?u("loading "+d.href+" from cache."):(u("parsed "+d.href+" successfully."),q(a.toCSS(),d,e.lastModified)),u("css for "+d.href+" generated in "+(new Date-c)+"ms"),e.remaining===0&&u("css generated in "+(new Date-b)+"ms"),c=new Date},a),m()},d.refreshStyles=m,d.refresh(d.env==="development")})(window)
\ No newline at end of file diff --git a/askbot/skins/default/media/js/live_search.js b/askbot/skins/default/media/js/live_search.js index f9f03453..1a46e338 100644 --- a/askbot/skins/default/media/js/live_search.js +++ b/askbot/skins/default/media/js/live_search.js @@ -15,7 +15,7 @@ var liveSearch = function(){ query.attr('class', 'searchInputCancelable'); x_button = $('<input class="cancelSearchBtn" type="button" name="reset_query"/>'); //x_button.click(reset_query); - x_button.val('x'); + x_button.val('X'); x_button.click( function(){ query.val(''); diff --git a/askbot/skins/default/media/style/lib_style.less b/askbot/skins/default/media/style/lib_style.less new file mode 100644 index 00000000..d1424137 --- /dev/null +++ b/askbot/skins/default/media/style/lib_style.less @@ -0,0 +1,38 @@ +/* General Predifined classes, read more in lesscss.org */ + +/* Variables for Colors*/ + +@header-color:#16160f; + +@link:#1b79bd; +@question-link:#464646; +@button-label:#4a757f; + +/* Receive exactly positions for background Sprite */ + +.sprites(@hor,@vert,@back:url(../images/sprites.png)){ + background:@hor @vert @back; +} + + +/* CSS3 Elements */ + +.box-shadow (@hor: 0px, @vert: 0px, @blur: 5px, @shadow: #929292){ + -webkit-box-shadow: @arguments; + -moz-box-shadow: @arguments; + box-shadow: @arguments; +} + +.text-shadow(@hor: 0px, @vert: 0px, @blur: 5px, @shadow: #929292){ + text-shadow: @arguments; + -moz-text-shadow: @arguments; + -webkit-text-shadow: @arguments; +} + +.rounded-corners(@radio: 5px){ + border-radius: @radio; + -ms-border-radius: @radio; + -moz-border-radius: @radio; + -webkit-border-radius: @radio; + -khtml-border-radius: @radio; +} diff --git a/askbot/skins/default/media/style/style.css b/askbot/skins/default/media/style/style.css index 6297721b..8e757d14 100644 --- a/askbot/skins/default/media/style/style.css +++ b/askbot/skins/default/media/style/style.css @@ -1,4 +1,7 @@ @import url(jquery.autocomplete.css); +@import "lib_style.less"; /* Library of predifined less functions styles */ + +/* ----- General HTML Styles----- */ body { background: #FFF; @@ -7,7 +10,7 @@ body { margin: 0; padding: 0; color: #000; - font-family: sans-serif; + font-family: 'Yanone Kaffeesatz', sans-serif; } div { @@ -32,7 +35,7 @@ hr { input, select { vertical-align: middle; - font-family: Trebuchet MS, "segoe ui", Helvetica, "Microsoft YaHei", 宋 体, Tahoma, Verdana, MingLiu, PMingLiu, Arial, sans-serif; + font-family: Trebuchet MS, "segoe ui", Helvetica, Tahoma, Verdana, MingLiu, PMingLiu, Arial, sans-serif; } p { @@ -43,57 +46,11 @@ p { } a { - color: #333333; + color:@link; text-decoration: none; cursor: pointer; } -/* http://pathfindersoftware.com/2007/09/developers-note-2/ */ -* html .clearfix, -* html .paginator { - height: 1; - overflow: visible; -} -+ html .clearfix, -+ html .paginator { - min-height: 1%; -} -.clearfix:after, -.paginator:after { - clear: both; - content:"."; - display:block; - height: 0; - visibility: hidden; -} - -.badges a { - color: #763333; - text-decoration: underline; -} - -a:hover { - text-decoration: underline; -} - -.badge-context-toggle.active { - cursor: pointer; - text-decoration: underline; -} - -h1 { - font-size: 160%; - padding: 10px 0 5px 5px; -} - -.users-page h1, .tags-page h1 { - float: left; -} - -.main-page h1 { - margin-right: 5px; -} - h2 { font-size: 140%; padding: 3px 0 3px 5px; @@ -151,237 +108,405 @@ blockquote { background-color: #F5F5F5; } -.content-wrapper {/* wrapper positioning class */ - width: 960px; - margin: auto; - position:relative; +/* http://pathfindersoftware.com/2007/09/developers-note-2/ */ +* html .clearfix, +* html .paginator { + height: 1; + overflow: visible; } - -#ab-header { - margin-top: 0px; - background: #FFF; ++ html .clearfix, ++ html .paginator { + min-height: 1%; } - -#ab-header .content-wrapper { - height: 90px;/* same as logo height */ +.clearfix:after, +.paginator:after { + clear: both; + content:"."; + display:block; + height: 0; + visibility: hidden; } -#CALeft { - width: 710px; - float: left; - position: relative; - padding: 0 5px 10px 5px; +.badges a { + color: #763333; + text-decoration: underline; } -#CARight { - width: 230px; - float: right; - padding: 0 5px 10px 5px; +a:hover { + text-decoration: underline; } -#CAFull { - float: left; - padding: 0 5px 10px 5px; - width: 950px; +.badge-context-toggle.active { + cursor: pointer; + text-decoration: underline; } -#ground { - width: 100%; - clear: both; - border-top: 1px solid #000; - padding: 6px 0 0 0; - text-align: center; - background: #777; +h1 { + font-size: 160%; + padding: 10px 0 5px 5px; } -#ground p { - margin-bottom:0; -} +/* ----- Custom positions ----- */ -#ab-logo { - padding: 0px 0px 0px 10px; - position: absolute; - bottom: 0; - left: 0; - height: 90px; - width: 70px; -} +.left{float:left} +.right{float:right} +.clean{clear:both} -img.license-logo { - margin: 6px 0 10px 0; -} -#ab-meta-nav, -#ab-main-nav { - position: absolute; - left: 100px; -} +/* ----- Notify message bar ----- */ -#ab-meta-nav { +.notify { + position: fixed; top: 0px; - height: 20px; - padding: 3px; - margin: 0; -} + left: 0px; + width: 100%; + z-index: 100; + padding: 0; + text-align: center; + background-color: #f5dd69; + border-top:#fff 1px solid; -#ab-meta-nav a { - height: 35px; - text-align: right; - margin-left: 20px; - text-decoration: underline; - color: #555555; + p { + margin-top: 6px; + margin-bottom: 6px; + font-size: 16px; + color:#424242 + } } -#ab-meta-nav a:first-child { - margin-left: 0; +#close-notify { + position: absolute; + right: 5px; + top: 7px; + color: #735005; + text-decoration: none; + line-height: 18px; + .sprites(-6px,-5px); + cursor: pointer; + width:20px; + height:20px; } -#ab-meta-nav a#ab-responses { - margin-left: 3px; -} -#ab-meta-nav a img { - vertical-align:middle; - margin-bottom:2px; +#close-notify:hover { + .sprites(-26px,-5px); } -#ab-meta-nav .user-info a { - margin: 0; - text-decoration: none; -} +/* ----- Header ----- */ -#ab-main-nav { - bottom: 0; +#header { + margin-top: 0px; + background: @header-color; } -#ab-main-nav a { - color: #333333; - background-color: #fff0e0; - border: 1px solid #888888; - border-bottom: none; - padding: 0px 12px 3px 12px; - height: 25px; - line-height: 30px; - margin-right: 10px; - font-size: 18px; - font-weight: 100; - text-decoration: none; - display: block; - float: left; +.content-wrapper {/* wrapper positioning class */ + width: 960px; + margin: auto; + position:relative; } -#ab-main-nav a:hover { - text-decoration: underline; +#logo img{ + padding: 5px 0px 5px 0px; } -#ab-main-nav a.on { - height: 24px; - line-height: 28px; - border-bottom: 1px solid #a40000; - border-right: 1px solid #820000; - border-top: 1px solid #d40000; - border-left: 1px solid #d40000; /*background:#A31E39; */ - background: #b03a48; - color: #FFF; - font-weight: 800; - text-decoration: none -} +#user-tools-nav { + height: 20px; + position:absolute; + bottom: 0; + right:0px; + padding-bottom:5px; + + a { + height: 35px; + text-align: right; + margin-left: 20px; + text-decoration: underline; + color:#d0e296; + font-size:16px; + } + + a:first-child { + margin-left: 0; + } + + a#ab-responses { + margin-left: 3px; + } + + .user-info,.user-micro-info{ + color:#b5b593; + } + + a img { + vertical-align:middle; + margin-bottom:2px; + } + + .user-info a { + margin: 0; + text-decoration: none; + } +} + +#meta-nav { + float:right; -#ab-main-nav a.special { - font-size: 18px; - color: #B02B2C; - font-weight: bold; - text-decoration: none; -} + a { + color: #e2e2ae; + padding: 0px 0px 0px 35px; + height: 25px; + line-height: 30px; + margin:5px 0px 0px 10px; + font-size: 18px; + font-weight: 100; + text-decoration: none; + display: block; + float: left; + } + + a:hover { + text-decoration: underline; + } + + a.on { + font-weight:bold; + color: #FFF; + text-decoration: none; + } + + a.special { + font-size: 18px; + color: #B02B2C; + font-weight: bold; + text-decoration: none; + } + + a.special:hover { + text-decoration: underline; + } + + #nav_tags{ + .sprites(-50px,-5px) + } + + #nav_users{ + .sprites(-125px,-5px) + } + + #nav_badges{ + .sprites(-210px,-5px) + } +} + +#secundary-header{ + height:55px; + background:#e9e9e1; + border-bottom:#d3d3c2 1px solid; + margin-bottom:10px; -#ab-main-nav a.special:hover { - text-decoration: underline; + #home-button{ + border-right:#afaf9e 1px solid; + .sprites(-6px,-36px); + height:55px; + width:43px; + display:block; + float:left; + } + + #home-button:hover{ + .sprites(-6px-45,-36px); + } + + #scope-wrapper{ + width:688px; + float:left; + + a{ + display:block; + float:left; + } + + .scope-selector{ + font-size:21px; + color:#5a5a4b; + height:55px; + line-height:55px; + margin-left:24px + } + .on{ + background:url(../images/scopearrow.png) no-repeat center bottom; + } + } } #searchBar { display:inline-block; - background-color: #cccccc;/*888a85; /*#e9b96e;*/ - width:700px; - border: 1px solid #aaaaaa; - padding: 4px 5px 4px 4px; + background-color: #fff; + width:412px; + border: 1px solid #c9c9b5; + float:right; + height:42px; + margin:6px 0px 0px 15px; + + .searchInput, .searchInputCancelable { + font-size: 18px; + height: 40px; + background:#FFF; + border:0px; + color:#c2c2c2; + padding-left:10px; + font-family: 'Yanone Kaffeesatz', sans-serif; + } + + .searchInput, .searchInputCancelable { + width: 352px; + } + + .searchInputCancelable { + width: 317px; + } + + .searchBtn { + font-size: 10px; + color: #666; + background-color: #eee; + height: 42px; + border:#FFF 1px solid; + line-height: 22px; + text-align: center; + float:right; + margin: 0px; + width:48px; + .sprites(-98px,-36px); + cursor:pointer; + } + + .searchBtn:hover { + .sprites(-98px-48,-36px); + } + + .cancelSearchBtn { + font-size: 30px; + color: #ce8888; + background:#fff; + height: 42px; + border:0px; + border-left:#deded0 1px solid; + text-align: center; + width: 35px; + cursor:pointer; + } + + .cancelSearchBtn:hover { + color: #d84040; + } +} + +#ask-button{ + background: url(../images/bigbutton.png) repeat-x bottom; + line-height:44px; + text-align:center; + width:200px; + height:42px; + font-size:23px; + color:@button-label; + margin-top:7px; + float:right; + text-transform:uppercase; + .rounded-corners(5px); + .box-shadow(1px, 1px, 2px, #636363) } -#searchBar .searchInput, #searchBar .searchInputCancelable { - font-size: 24px; - line-height: 24px; - height: 31px; - margin: 0px 4px 0px 0px; - padding: 5px 0 0 5px; +#ask-button:hover{ + text-decoration:none; + background: url(../images/bigbutton.png) repeat-x top; + .text-shadow(0px, 1px, 0px, #c6d9dd) } -#searchBar .searchInput, #searchBar .searchInputCancelable { - width: 607px; -} +/* ----- Content layout ----- */ -#searchBar .searchInputCancelable { - width: 564px; +#ContentLeft { + width: 730px; + float: left; + position: relative; } -#searchBar .searchBtn, #searchBar .cancelSearchBtn { - font-size: 20px; - color: #666; - background-color: #eee; - height: 40px; - border: 1px solid #aaa; - line-height: 22px; - text-align: center; - padding-bottom: 4px; +#ContentRight { + width: 200px; + float: right; + padding: 0 0px 10px 0px; } -#searchBar .searchBtn { - margin: 0px; - width: 78px; +#ContentFull { + float: left; + width: 950px; } -#searchBar .cancelSearchBtn { - width: 40px; - margin: 0px 3px 0px 0px; -} +/* ----- Sidebar Widgets Box ----- */ -#askFormBar { - display:inline-block; - background-color: #e3e3e3;/*888a85; /*#e9b96e;*/ - border: 1px solid #aaaaaa; - padding: 4px 7px 5px 5px; -} -#askFormBar p { - width: 685px; - margin:0 0 5px 0; -} -#askFormBar .questionTitleInput { - font-size: 24px; - line-height: 24px; - height: 36px; - width: 680px; - margin: 0px; - padding: 5px 0 0 5px; +.box { + background: #fff; + padding: 10px 0px 0px 0px; + + + p { + margin-bottom: 4px; + } + + p.info-box-follow-up-links { + text-align: right; + margin: 0; + } + + h2 { + padding-left: 0; + background:#eceeeb; + height:30px; + line-height:30px; + text-align:right; + font-size:24px; + font-weight:normal; + color:#656565; + padding-right:10px; + margin-bottom:10px; + } + h3{ + color:#4a757f; + font-size:18px; + text-align:left; + font-weight:normal; + } + .contributorback{ + background: #eceeeb url(../images/contributorsback.png) no-repeat center left; + } + + label { + color: #333; + } + + ul { + margin-left: 15px; + } + + li { + list-style-type: disc; + font-size: 13px; + line-height: 20px; + margin-bottom: 10px; + } + ul.tags { + list-style: none; + margin: 0; + padding: 0; + line-height: 170%; + display: block; + } } -#question-list { - float: left; - position: relative; - background-color: #FFF; - padding: 0; - width: 100%; +img.gravatar { + margin:1px; } -.ask-page div#question-list { - float: none; - width: 706px; -} -.ask-page div#question-list h2 { - font-size: 14px; - padding-bottom: 0; -} -.ask-page div#question-list span { - padding: 3px 7px; - margin-right: 5px; - background: #ccc; -} +/* ----- Tags Styles ----- */ /* tag formatting is also copy-pasted in template because it must be the same in the emails @@ -422,7 +547,6 @@ img.license-logo { } ul.tags, -.boxC ul.tags, ul.tags.marked-tags, ul#related-tags { list-style: none; @@ -451,6 +575,7 @@ ul.tags.marked-tags li, #tagSelector div.inputs { clear: both; float: none; + margin-bottom:10px; } .tags-page ul.tags li, @@ -512,6 +637,78 @@ ul#related-tags li { text-decoration: none; } + +.users-page h1, .tags-page h1 { + float: left; +} + +.main-page h1 { + margin-right: 5px; +} + +#ground { + width: 100%; + clear: both; + border-top: 1px solid #000; + padding: 6px 0 0 0; + text-align: center; + background: #777; +} + +#ground p { + margin-bottom:0; +} + + + +img.license-logo { + margin: 6px 0 10px 0; +} + + +#askFormBar { + display:inline-block; + background-color: #e3e3e3;/*888a85; /*#e9b96e;*/ + border: 1px solid #aaaaaa; + padding: 4px 7px 5px 5px; +} +#askFormBar p { + width: 685px; + margin:0 0 5px 0; +} +#askFormBar .questionTitleInput { + font-size: 24px; + line-height: 24px; + height: 36px; + width: 680px; + margin: 0px; + padding: 5px 0 0 5px; +} + +#question-list { + float: left; + position: relative; + background-color: #FFF; + padding: 0; + width: 100%; +} + +.ask-page div#question-list { + float: none; + width: 706px; +} +.ask-page div#question-list h2 { + font-size: 14px; + padding-bottom: 0; +} +.ask-page div#question-list span { + padding: 3px 7px; + margin-right: 5px; + background: #ccc; +} + + + span.delete-icon { padding-left: 13px; vertical-align: bottom; @@ -546,21 +743,117 @@ ul#search-tags { padding-top: 3px; } +/* ----- Sorting top Tab ------*/ + +.tabBar { + background-color: #eff5f6; + height: 30px; + width: 412px; + clear: both; + margin-bottom: 3px; + margin-top: 3px; + float:right; + font-family:Georgia; + font-size:16px; + .rounded-corners(5px); +} + +.tabBar h2 { + float: left; +} + +.tabsA, .tabsC { + float: right; + position: relative; + display: block; + height: 20px; +} + +/* tabsA - used for sorting */ +.tabsA { float: right; } +.tabsC { float: left; } + +.tabsA a, .tabsC a{ + + border-left: 1px solid #d0e1e4; + color: #8b1717; + display: block; + float: left; + height: 20px; + line-height: 20px; + padding:4px 7px 4px 7px; + text-decoration: none; +} + +.tabsA a.on, .tabsC a.on, .tabsA a:hover, .tabsC a:hover { + color: #C22828; +} + +.tabsA a.rev.on, tabsA a.rev.on:hover { +} + + + +.tabsA .label, .tabsC .label { + float: left; + color: #646464; + margin-top:4px; + margin-right:5px; +} + +.tabsB a { + background: #eee; + border: 1px solid #eee; + color: #777; + display: block; + float: left; + height: 22px; + line-height: 28px; + margin: 5px 0px 0 4px; + padding: 0 11px 0 11px; + text-decoration: none; +} + +.rss { + float: right; + font-size: 16px; + color: #f57900 !important; + margin: 1px 8px 0 0; + width:45px; + padding-left: 16px; + padding-top:3px; + background: url(../images/feed-icon-small.png) no-repeat center right; +} + +.rss:hover { + color: #F4A731 !important; +} + + +/* ----- Question list ----- */ + .short-summary { position: relative; filter: inherit; - padding: 5px 2px 5px 2px; - border-top: 1px dashed #ccccce; + padding: 10px; + border-bottom: 1px solid #DDDBCE; + margin-bottom:1px; overflow: hidden; - width: 702px; + width: 710px; float: left; + background: url(../images/summary-background.png) repeat-x; } .short-summary h2 { - font-size: 16px; - font-family: "Trebuchet MS", "segoe ui", arial, sans-serif; + font-size: 22px; + font-weight:normal; +} + +.short-summary a { + color:@question-link; } + .short-summary .userinfo .relativetime, .short-summary .userinfo a, .short-summary span.anonymous { @@ -684,29 +977,7 @@ ul#search-tags { text-decoration: underline; } -.boxC { - background: white /*#cacdc6; /*f9f7ed;*/ - padding: 10px 10px 10px 15px; - margin-bottom: 12px; -} - -.boxC p { - margin-bottom: 4px; -} - -.boxC p.info-box-follow-up-links { - text-align: right; - margin: 0; -} - -.boxC h2, -.boxC h3 { - padding-left: 0; -} -.boxC label { - color: #333; -} .pager { clear:both; @@ -780,17 +1051,6 @@ ul#search-tags { padding: 5px 0 10px 0; } -p.rss { - float: right; - font-size: 12px; - color: #666; - margin: 0 2px 0 0; -} - -p.rss a { - padding-left: 16px; - background: url(../images/feed-icon-small.png) no-repeat; -} .question-page p.rss { float:none; @@ -829,87 +1089,6 @@ a:hover.medal { border-right: 1px solid #D1CA3D; } -/*Tabs*/ -.tabBar { - background-color: #FFF; - border-bottom: 1px solid white; - height: 30px; - width: 100%; - clear: both; - margin-bottom: 3px; - margin-top: 3px; -} - -.tabBar h2 { - float: left; -} - -.tabsA, .tabsC { - background-color: #FFF; - float: right; - position: relative; - display: block; - font-weight: bold; - height: 20px; -} - -/* tabsA - used for sorting */ -.tabsA { float: right; } -.tabsC { float: left; } - -.tabsA a.on, .tabsC a.on, .tabsA a:hover, .tabsC a:hover { - background: #fff; - color: #a40000; - border-top: 1px solid #babdb6; - border-left: 1px solid #babdb6; - border-right: 1px solid #888a85; - border-bottom: 1px solid #888a85; - height: 24px; - line-height: 26px; - margin-top: 3px; -} - -.tabsA a.rev.on, tabsA a.rev.on:hover { - padding: 0px 2px 0px 7px; -} - -.tabsA a, .tabsC a{ - background: #f9f7eb; - border-top: 1px solid #eeeeec; - border-left: 1px solid #eeeeec; - border-right: 1px solid #a9aca5; - border-bottom: 1px solid #888a85; - color: #888a85; - display: block; - float: left; - height: 20px; - line-height: 22px; - margin: 5px 0 0 4px; - padding: 0 2px; - text-decoration: none; - font-size: 12.5px; -} - -.tabsA .label, .tabsC .label { - float: left; - font-weight: bold; - color: #777; - margin: 8px 0 0 0px; -} - -.tabsB a { - background: #eee; - border: 1px solid #eee; - color: #777; - display: block; - float: left; - height: 22px; - line-height: 28px; - margin: 5px 0px 0 4px; - padding: 0 11px 0 11px; - text-decoration: none; -} - .questions-related { font-weight: 700; word-wrap: break-word; @@ -1308,16 +1487,7 @@ div.comments { } -.boxC ul { - margin-left: 15px; -} -.boxC li { - list-style-type: disc; - font-size: 13px; - line-height: 20px; - margin-bottom: 10px; -} /* openid styles */ .form-row { @@ -1852,9 +2022,7 @@ p.space-above { color: red; } -.darkred { - color: darkred; -} + button::-moz-focus-inner { padding:0; @@ -1895,42 +2063,6 @@ button::-moz-focus-inner { padding-right: 10px; } -.notify { - position: fixed; - top: 0px; - left: 0px; - width: 100%; - z-index: 100; - padding: 0; - text-align: center; - font-weight: Bold; - color: #444; - background-color: #F4A83D; -} - -.notify p { - margin-top: 5px; - margin-bottom: 5px; - font-size: 16px; -} - -#close-notify { - position: absolute; - right: 5px; - top: 5px; - padding: 0 3px 0 3px; - color: #735005; - text-decoration: none; - font-size: 14px; - line-height: 18px; - background-color: #FAD163; - border: 2px #735005 solid; - cursor: pointer; -} - -#close-notify:hover { - text-decoration: none; -} .noscript { position: fixed; @@ -2210,7 +2342,7 @@ p.signup_p { .question-body li { margin-bottom:0.7em; } -.answer-body li {$ +.answer-body li { margin-bottom:0.7em; } .wmd-preview a { @@ -2288,9 +2420,7 @@ p.signup_p { padding-right:5px; } -img.gravatar { - margin:2px; -} + .user-info-table .gravatar { margin:0; } diff --git a/askbot/skins/default/templates/base.html b/askbot/skins/default/templates/base.html index 9f779945..636d42a6 100644 --- a/askbot/skins/default/templates/base.html +++ b/askbot/skins/default/templates/base.html @@ -13,7 +13,8 @@ <meta name="google-site-verification" content="{{settings.GOOGLE_SITEMAP_CODE}}" /> {% endif %} <link rel="shortcut icon" href="{{ settings.SITE_FAVICON|media }}" /> - <link href="{{"/style/style.css"|media }}" rel="stylesheet" type="text/css" /> + <link href="{{"/style/style.css"|media }}" rel="stylesheet/less" type="text/css" /> + <script type="text/javascript" src="{{"/js/less.min.js"|media}}"></script> {{ skin.get_extra_css_link() }} {% if settings.USE_CUSTOM_CSS %} <link @@ -46,7 +47,8 @@ <body class="{% block body_class %}{% endblock %}{% if page_class %} {{page_class}}{% endif %}"> {% include "blocks/system_messages.html" %} {% include "custom_header.html" ignore missing %} - {% include "blocks/header.html" %} + {% include "blocks/header.html" %} {# Logo, user tool navigation and meta navitation #} + {% include "blocks/secundary_header.html" %} {# Scope selector, search input and ask button #} <div class="content-wrapper"> {% block body %} {% endblock %} diff --git a/askbot/skins/default/templates/blocks/bottom_scripts.html b/askbot/skins/default/templates/blocks/bottom_scripts.html index 771c13a4..34b7b7ce 100644 --- a/askbot/skins/default/templates/blocks/bottom_scripts.html +++ b/askbot/skins/default/templates/blocks/bottom_scripts.html @@ -41,6 +41,7 @@ <script type='text/javascript' src="{{"/js/jquery.i18n.js"|media }}"></script> <script type='text/javascript' src="{% url "askbot_jsi18n" %}"></script> <script type='text/javascript' src="{{"/js/utils.js"|media }}"></script> +<link href='http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:300,400,700' rel='stylesheet' type='text/css'> {% if settings.ENABLE_MATHJAX %} <script type='text/javascript' src="{{settings.MATHJAX_BASE_URL}}/MathJax.js"> MathJax.Hub.Config({ diff --git a/askbot/skins/default/templates/blocks/header.html b/askbot/skins/default/templates/blocks/header.html index d7359007..340b9ef2 100644 --- a/askbot/skins/default/templates/blocks/header.html +++ b/askbot/skins/default/templates/blocks/header.html @@ -1,23 +1,19 @@ <!-- template header.html --> {% import "macros.html" as macros %} -<div id="ab-header"> +<div id="header"> <div class="content-wrapper"> {% if settings.SHOW_LOGO %} - <a id="ab-logo" href="{% url questions %}?start_over=true"><img + <a id="logo" href="{% url questions %}?start_over=true"><img src="{{ settings.SITE_LOGO_URL|media }}" title="{% trans %}back to home page{% endtrans %}" alt="{% trans site=settings.APP_SHORT_NAME %}{{site}} logo{% endtrans %}"/></a> {% endif %} - <div id="ab-meta-nav"> - {% include "blocks/header_meta_links.html" %} + <div id="user-tools-nav"> + {% include "blocks/user_navigation.html" %} {{settings.CUSTOM_HEADER}} </div> - <div id="ab-main-nav"> - <a - id="nav_questions" - href="{% url questions %}" - {% if active_tab == 'questions' %}class="on"{% endif %} - >{% trans %}questions{% endtrans %}</a> + + <div id="meta-nav"> <a id="nav_tags" href="{% url tags %}" @@ -33,12 +29,15 @@ href="{% url badges %}" {% if active_tab == 'badges' %}class="on"{% endif %} >{% trans %}badges{% endtrans %}</a> + <!-- <a id="nav_ask" href="{% url ask %}" class="{% if active_tab == 'ask' %}on{% else %}special{% endif %}" >{% trans %}ask a question{% endtrans %}</a> + --> </div> + <div class="clean"></div> </div> </div> <!-- end template header.html --> diff --git a/askbot/skins/default/templates/blocks/input_bar.html b/askbot/skins/default/templates/blocks/input_bar.html index bed97eb4..55917fbc 100644 --- a/askbot/skins/default/templates/blocks/input_bar.html +++ b/askbot/skins/default/templates/blocks/input_bar.html @@ -11,6 +11,14 @@ action="{% url questions %}" {% endif %} method="get"> + <input type="submit" value="" name="search" class="searchBtn" /> + {% if active_tab == "tags" %} + <input type="hidden" name="t" value="tag"/> + {% else %} + {% if active_tab == "users" %} + <input type="hidden" name="t" value="user"/> + {% endif %} + {% endif %} {# class was searchInput #} <input {% if query %} @@ -25,20 +33,13 @@ id="keywords"/> {% if query %}{# query is only defined by questions view #} <input type="button" - value="x" + value="X" name="reset_query" {# todo - make sure it works on Enter keypress #} onclick="window.location.href='{% url questions %}?reset_query=true'" class="cancelSearchBtn"/> {% endif %} - <input type="submit" value="{% trans %}search{% endtrans %}" name="search" class="searchBtn" /> - {% if active_tab == "tags" %} - <input type="hidden" name="t" value="tag"/> - {% else %} - {% if active_tab == "users" %} - <input type="hidden" name="t" value="user"/> - {% endif %} - {% endif %} + </form> </div> {% endspaceless %} diff --git a/askbot/skins/default/templates/blocks/secundary_header.html b/askbot/skins/default/templates/blocks/secundary_header.html new file mode 100644 index 00000000..0d588627 --- /dev/null +++ b/askbot/skins/default/templates/blocks/secundary_header.html @@ -0,0 +1,22 @@ +<!-- template secundary_header.html --> + +<div id="secundary-header"> + <div class="content-wrapper"> + + <a id="home-button" href="{% url questions %}"></a> + <div id="scope-wrapper"> + <a class="scope-selector {% if scope == 'all' %}on{% endif %}" + href="?scope=all" title="{% trans %}see all questions{% endtrans %}">ALL</a> + <a class="scope-selector {% if scope == 'unanswered' %}on{% endif %}" + href="?scope=unanswered&sort=answers-asc" title="{% trans %}see unanswered questions{% endtrans %}">UNANSWERED</a> + {% if request.user.is_authenticated() %} + <a class="scope-selector {% if scope == 'favorite' %}on{% endif %}" + href="?scope=favorite" title="{% trans %}see your followed questions{% endtrans %}">FOLLOWED</a> + {% endif %} + + {% include "blocks/input_bar.html" %} {# include search form block #} + </div> + <a id="ask-button" href="{% url ask %}">{% trans %}ask a question{% endtrans %}</a> + <div class="clean"></div> + </div> +</div> diff --git a/askbot/skins/default/templates/blocks/system_messages.html b/askbot/skins/default/templates/blocks/system_messages.html index 18ba03d7..97bb4b51 100644 --- a/askbot/skins/default/templates/blocks/system_messages.html +++ b/askbot/skins/default/templates/blocks/system_messages.html @@ -1,8 +1,8 @@ <div class="notify" style="display:none"> {% if user_messages %} {% for message in user_messages %} - <p class="darkred">{{ message }}</p> + <p>{{ message }}</p> {% endfor %} {% endif %} - <a id="close-notify" onclick="notify.close(true)">×</a> + <a id="close-notify" onclick="notify.close(true)"></a> </div> diff --git a/askbot/skins/default/templates/blocks/tag_selector.html b/askbot/skins/default/templates/blocks/tag_selector.html index c3626be9..be456ad1 100644 --- a/askbot/skins/default/templates/blocks/tag_selector.html +++ b/askbot/skins/default/templates/blocks/tag_selector.html @@ -1,6 +1,6 @@ {# todo - maybe disable navigation from ignored tags here when "hide" is on - with js? #} {% import "macros.html" as macros %} -<div id="tagSelector" class="boxC"> +<div id="tagSelector" class="box"> <h2>{% trans %}Interesting tags{% endtrans %}</h2> {{ macros.tag_list_widget( diff --git a/askbot/skins/default/templates/blocks/user_navigation.html b/askbot/skins/default/templates/blocks/user_navigation.html new file mode 100644 index 00000000..2324291d --- /dev/null +++ b/askbot/skins/default/templates/blocks/user_navigation.html @@ -0,0 +1,15 @@ +{% if request.user.is_authenticated() %} + <a href="{{ request.user.get_absolute_url() }}">{{ request.user.username }}</a> + <span class="user-info"> + {{ macros.inbox_link(request.user) }} + {{ macros.moderation_items_link(request.user, moderation_items) }} + ({{ macros.user_long_score_and_badge_summary(user) }}) + </span> + <a href="{{ settings.LOGOUT_URL }}?next={{ settings.LOGOUT_REDIRECT_URL }}">{% trans %}logout{% endtrans %}</a> +{% else %} + <a href="{{ settings.LOGIN_URL }}">{% trans %}login{% endtrans %}</a> +{% endif %} + +{% if request.user.is_authenticated() and request.user.is_administrator() %} + <a href="{% url site_settings %}">{% trans %}settings{% endtrans %}</a> +{% endif %} diff --git a/askbot/skins/default/templates/main_page/headline.html b/askbot/skins/default/templates/main_page/headline.html index 130a9bd9..62d67ebb 100644 --- a/askbot/skins/default/templates/main_page/headline.html +++ b/askbot/skins/default/templates/main_page/headline.html @@ -1,12 +1,6 @@ {% import "macros.html" as macros %} {% if questions_count > 0 %} <div style="clear:both"> - <p class="rss"> - (<a - href="{{settings.APP_URL}}/feeds/rss/" - title="{% trans %}subscribe to the questions feed{% endtrans %}" - >{% trans %}rss feed{% endtrans %}</a>) - </p> <h1 id="question-count" class="search-result-summary"> {% if search_tags %} {% trans cnt=questions_count, q_num=questions_count|intcomma %}{{q_num}} question, tagged{% pluralize %}{{q_num}} questions, tagged{% endtrans %} diff --git a/askbot/skins/default/templates/main_page/sidebar.html b/askbot/skins/default/templates/main_page/sidebar.html index 6abc0492..57267ea3 100644 --- a/askbot/skins/default/templates/main_page/sidebar.html +++ b/askbot/skins/default/templates/main_page/sidebar.html @@ -4,8 +4,8 @@ {% if contributors and settings.SIDEBAR_MAIN_SHOW_AVATARS %} {% cache 600 "contributors" contributors search_tags scope sort query context.page context.page_size language_code %} - <div id="contrib-users" class="boxC"> - <h2>{% trans %}Contributors{% endtrans %}</h2> + <div id="contrib-users" class="box"> + <h2 class="contributorback">{% trans %}Contributors{% endtrans %}</h2> {% spaceless %} {% for person in contributors %} {{ macros.gravatar(person,48) }} @@ -21,7 +21,7 @@ {% if tags and settings.SIDEBAR_MAIN_SHOW_TAGS %} {% cache 0 "tags" tags search_tags scope sort query context.page context.page_size language_code %} - <div class="boxC"> + <div class="box"> <h2>{% trans %}Related tags{% endtrans %}</h2> {% if tag_list_type == 'list' %} <ul id="related-tags" class="tags"> diff --git a/askbot/skins/default/templates/main_page/tab_bar.html b/askbot/skins/default/templates/main_page/tab_bar.html index 1b27ab3a..49e12204 100644 --- a/askbot/skins/default/templates/main_page/tab_bar.html +++ b/askbot/skins/default/templates/main_page/tab_bar.html @@ -1,28 +1,8 @@ {% import "macros.html" as macros %} -{% cache 600 "scope_sort_tabs" search_tags request.user scope sort query context.page context.page_size language_code %} +{% cache 0 "scope_sort_tabs" search_tags request.user scope sort query context.page context.page_size language_code %} <div class="tabBar"> - <div class="tabsC"> - <span class="label">{% trans %}In:{% endtrans %}</span> - <a id="all" - class="{% if scope == 'all' %}on{% else %}off{% endif %}" - href="?scope=all" - title="{% trans %}see all questions{% endtrans %}" - ><span>{% trans %}all{% endtrans %}</span></a> - <a id="unanswered" - class="{% if scope == 'unanswered' %}on{% else %}off{% endif %}" - href="?scope=unanswered&sort=answers-asc" - title="{% trans %}see unanswered questions{% endtrans %}" - ><span>{% trans %}unanswered{% endtrans %}</span></a> - {% if request.user.is_authenticated() %} - <a id="favorite" - class="{% if scope == 'favorite' %}on{% else %}off{% endif %}" - href="?scope=favorite" - title="{% trans %}see your followed questions{% endtrans %}" - ><span>{% trans %}followed{% endtrans %}</span></a> - {% endif %} - </div> <div id="sort_tabs" class="tabsA"> - <span class="label">{% trans %}Sort by:{% endtrans %}</span> + <span class="label">{% trans %}Sort by »{% endtrans %}</span> {% if show_sort_by_relevance %} {% set asc_relevance_tooltip = gettext('most relevant questions') %} {% set desc_relevance_tooltip = gettext('click to see most relevant questions') %} @@ -81,6 +61,11 @@ current_sort_method = sort ) }} + <a class="rss" + href="{{settings.APP_URL}}/feeds/rss/" + title="{% trans %}subscribe to the questions feed{% endtrans %}" + >{% trans %}RSS{% endtrans %} + </a> </div> </div> {% endcache %} diff --git a/askbot/skins/default/templates/one_column_body.html b/askbot/skins/default/templates/one_column_body.html index e97de505..852f8fe5 100644 --- a/askbot/skins/default/templates/one_column_body.html +++ b/askbot/skins/default/templates/one_column_body.html @@ -1,8 +1,7 @@ {% extends "base.html" %} {% block body_class %}one-col{% endblock %} {% block body %} -<div id="CAFull"> - {% include "blocks/input_bar.html" %} +<div id="ContentFull"> {% block content%} {% endblock%} </div> diff --git a/askbot/skins/default/templates/two_column_body.html b/askbot/skins/default/templates/two_column_body.html index a284744e..4c3193be 100644 --- a/askbot/skins/default/templates/two_column_body.html +++ b/askbot/skins/default/templates/two_column_body.html @@ -1,12 +1,11 @@ {% extends "base.html" %} {% block body_class %}two-col{% endblock %} {% block body %} -<div id="CALeft"> - {% include "blocks/input_bar.html" %} +<div id="ContentLeft"> {% block content%} {% endblock%} </div> -<div id="CARight"> +<div id="ContentRight"> {% block sidebar%} {% endblock%} </div> diff --git a/askbot/skins/old/media/images/anon.png b/askbot/skins/old/media/images/anon.png Binary files differnew file mode 100644 index 00000000..a2041590 --- /dev/null +++ b/askbot/skins/old/media/images/anon.png diff --git a/askbot/skins/old/media/images/blue-up-arrow-h18px.png b/askbot/skins/old/media/images/blue-up-arrow-h18px.png Binary files differnew file mode 100755 index 00000000..e1f29e86 --- /dev/null +++ b/askbot/skins/old/media/images/blue-up-arrow-h18px.png diff --git a/askbot/skins/old/media/images/box-arrow.gif b/askbot/skins/old/media/images/box-arrow.gif Binary files differnew file mode 100755 index 00000000..89dcf5b3 --- /dev/null +++ b/askbot/skins/old/media/images/box-arrow.gif diff --git a/askbot/skins/old/media/images/bullet_green.gif b/askbot/skins/old/media/images/bullet_green.gif Binary files differnew file mode 100755 index 00000000..fa530910 --- /dev/null +++ b/askbot/skins/old/media/images/bullet_green.gif diff --git a/askbot/skins/old/media/images/cc-88x31.png b/askbot/skins/old/media/images/cc-88x31.png Binary files differnew file mode 100755 index 00000000..0f2a0f10 --- /dev/null +++ b/askbot/skins/old/media/images/cc-88x31.png diff --git a/askbot/skins/old/media/images/cc-by-sa.png b/askbot/skins/old/media/images/cc-by-sa.png Binary files differnew file mode 100644 index 00000000..f0a944e0 --- /dev/null +++ b/askbot/skins/old/media/images/cc-by-sa.png diff --git a/askbot/skins/old/media/images/close-small-dark.png b/askbot/skins/old/media/images/close-small-dark.png Binary files differnew file mode 100755 index 00000000..280c1fc7 --- /dev/null +++ b/askbot/skins/old/media/images/close-small-dark.png diff --git a/askbot/skins/old/media/images/close-small-hover.png b/askbot/skins/old/media/images/close-small-hover.png Binary files differnew file mode 100755 index 00000000..7899aec7 --- /dev/null +++ b/askbot/skins/old/media/images/close-small-hover.png diff --git a/askbot/skins/old/media/images/close-small.png b/askbot/skins/old/media/images/close-small.png Binary files differnew file mode 100755 index 00000000..5a99d31f --- /dev/null +++ b/askbot/skins/old/media/images/close-small.png diff --git a/askbot/skins/old/media/images/dash.gif b/askbot/skins/old/media/images/dash.gif Binary files differnew file mode 100755 index 00000000..d1ddc507 --- /dev/null +++ b/askbot/skins/old/media/images/dash.gif diff --git a/askbot/skins/old/media/images/dialog-warning-off.png b/askbot/skins/old/media/images/dialog-warning-off.png Binary files differnew file mode 100644 index 00000000..258e4d86 --- /dev/null +++ b/askbot/skins/old/media/images/dialog-warning-off.png diff --git a/askbot/skins/old/media/images/dialog-warning.png b/askbot/skins/old/media/images/dialog-warning.png Binary files differnew file mode 100644 index 00000000..a9e4ff39 --- /dev/null +++ b/askbot/skins/old/media/images/dialog-warning.png diff --git a/askbot/skins/old/media/images/djangomade124x25_grey.gif b/askbot/skins/old/media/images/djangomade124x25_grey.gif Binary files differnew file mode 100755 index 00000000..d34bb311 --- /dev/null +++ b/askbot/skins/old/media/images/djangomade124x25_grey.gif diff --git a/askbot/skins/old/media/images/dot-g.gif b/askbot/skins/old/media/images/dot-g.gif Binary files differnew file mode 100755 index 00000000..5d6bb28e --- /dev/null +++ b/askbot/skins/old/media/images/dot-g.gif diff --git a/askbot/skins/old/media/images/dot-list.gif b/askbot/skins/old/media/images/dot-list.gif Binary files differnew file mode 100755 index 00000000..f6a6b865 --- /dev/null +++ b/askbot/skins/old/media/images/dot-list.gif diff --git a/askbot/skins/old/media/images/edit.png b/askbot/skins/old/media/images/edit.png Binary files differnew file mode 100755 index 00000000..dcb09be0 --- /dev/null +++ b/askbot/skins/old/media/images/edit.png diff --git a/askbot/skins/old/media/images/expander-arrow-hide.gif b/askbot/skins/old/media/images/expander-arrow-hide.gif Binary files differnew file mode 100755 index 00000000..feb6a618 --- /dev/null +++ b/askbot/skins/old/media/images/expander-arrow-hide.gif diff --git a/askbot/skins/old/media/images/expander-arrow-show.gif b/askbot/skins/old/media/images/expander-arrow-show.gif Binary files differnew file mode 100755 index 00000000..6825c56e --- /dev/null +++ b/askbot/skins/old/media/images/expander-arrow-show.gif diff --git a/askbot/skins/old/media/images/favicon.gif b/askbot/skins/old/media/images/favicon.gif Binary files differnew file mode 100644 index 00000000..f7f9061b --- /dev/null +++ b/askbot/skins/old/media/images/favicon.gif diff --git a/askbot/skins/old/media/images/favicon.ico b/askbot/skins/old/media/images/favicon.ico Binary files differnew file mode 100644 index 00000000..51a57bed --- /dev/null +++ b/askbot/skins/old/media/images/favicon.ico diff --git a/askbot/skins/old/media/images/feed-icon-small.png b/askbot/skins/old/media/images/feed-icon-small.png Binary files differnew file mode 100755 index 00000000..b3c949d2 --- /dev/null +++ b/askbot/skins/old/media/images/feed-icon-small.png diff --git a/askbot/skins/old/media/images/flags/ad.gif b/askbot/skins/old/media/images/flags/ad.gif Binary files differnew file mode 100755 index 00000000..57b49973 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ad.gif diff --git a/askbot/skins/old/media/images/flags/ae.gif b/askbot/skins/old/media/images/flags/ae.gif Binary files differnew file mode 100755 index 00000000..78d15b67 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ae.gif diff --git a/askbot/skins/old/media/images/flags/af.gif b/askbot/skins/old/media/images/flags/af.gif Binary files differnew file mode 100755 index 00000000..98894082 --- /dev/null +++ b/askbot/skins/old/media/images/flags/af.gif diff --git a/askbot/skins/old/media/images/flags/ag.gif b/askbot/skins/old/media/images/flags/ag.gif Binary files differnew file mode 100755 index 00000000..48f8e7bc --- /dev/null +++ b/askbot/skins/old/media/images/flags/ag.gif diff --git a/askbot/skins/old/media/images/flags/ai.gif b/askbot/skins/old/media/images/flags/ai.gif Binary files differnew file mode 100755 index 00000000..1cbc5795 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ai.gif diff --git a/askbot/skins/old/media/images/flags/al.gif b/askbot/skins/old/media/images/flags/al.gif Binary files differnew file mode 100755 index 00000000..c44fe0a0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/al.gif diff --git a/askbot/skins/old/media/images/flags/am.gif b/askbot/skins/old/media/images/flags/am.gif Binary files differnew file mode 100755 index 00000000..2915e30c --- /dev/null +++ b/askbot/skins/old/media/images/flags/am.gif diff --git a/askbot/skins/old/media/images/flags/an.gif b/askbot/skins/old/media/images/flags/an.gif Binary files differnew file mode 100755 index 00000000..cb570c67 --- /dev/null +++ b/askbot/skins/old/media/images/flags/an.gif diff --git a/askbot/skins/old/media/images/flags/ao.gif b/askbot/skins/old/media/images/flags/ao.gif Binary files differnew file mode 100644 index 00000000..8c854fa1 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ao.gif diff --git a/askbot/skins/old/media/images/flags/ar.gif b/askbot/skins/old/media/images/flags/ar.gif Binary files differnew file mode 100755 index 00000000..a9f71f7d --- /dev/null +++ b/askbot/skins/old/media/images/flags/ar.gif diff --git a/askbot/skins/old/media/images/flags/as.gif b/askbot/skins/old/media/images/flags/as.gif Binary files differnew file mode 100755 index 00000000..d776ec27 --- /dev/null +++ b/askbot/skins/old/media/images/flags/as.gif diff --git a/askbot/skins/old/media/images/flags/at.gif b/askbot/skins/old/media/images/flags/at.gif Binary files differnew file mode 100755 index 00000000..87e12173 --- /dev/null +++ b/askbot/skins/old/media/images/flags/at.gif diff --git a/askbot/skins/old/media/images/flags/au.gif b/askbot/skins/old/media/images/flags/au.gif Binary files differnew file mode 100755 index 00000000..5269c6a0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/au.gif diff --git a/askbot/skins/old/media/images/flags/aw.gif b/askbot/skins/old/media/images/flags/aw.gif Binary files differnew file mode 100755 index 00000000..27fdb4d1 --- /dev/null +++ b/askbot/skins/old/media/images/flags/aw.gif diff --git a/askbot/skins/old/media/images/flags/ax.gif b/askbot/skins/old/media/images/flags/ax.gif Binary files differnew file mode 100755 index 00000000..0ceb6849 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ax.gif diff --git a/askbot/skins/old/media/images/flags/az.gif b/askbot/skins/old/media/images/flags/az.gif Binary files differnew file mode 100755 index 00000000..d7716184 --- /dev/null +++ b/askbot/skins/old/media/images/flags/az.gif diff --git a/askbot/skins/old/media/images/flags/ba.gif b/askbot/skins/old/media/images/flags/ba.gif Binary files differnew file mode 100755 index 00000000..9bf5f0ac --- /dev/null +++ b/askbot/skins/old/media/images/flags/ba.gif diff --git a/askbot/skins/old/media/images/flags/bb.gif b/askbot/skins/old/media/images/flags/bb.gif Binary files differnew file mode 100755 index 00000000..b7d08e57 --- /dev/null +++ b/askbot/skins/old/media/images/flags/bb.gif diff --git a/askbot/skins/old/media/images/flags/bd.gif b/askbot/skins/old/media/images/flags/bd.gif Binary files differnew file mode 100755 index 00000000..0fd27eca --- /dev/null +++ b/askbot/skins/old/media/images/flags/bd.gif diff --git a/askbot/skins/old/media/images/flags/be.gif b/askbot/skins/old/media/images/flags/be.gif Binary files differnew file mode 100755 index 00000000..ae09bfbe --- /dev/null +++ b/askbot/skins/old/media/images/flags/be.gif diff --git a/askbot/skins/old/media/images/flags/bf.gif b/askbot/skins/old/media/images/flags/bf.gif Binary files differnew file mode 100755 index 00000000..9d6772cd --- /dev/null +++ b/askbot/skins/old/media/images/flags/bf.gif diff --git a/askbot/skins/old/media/images/flags/bg.gif b/askbot/skins/old/media/images/flags/bg.gif Binary files differnew file mode 100755 index 00000000..11cf8ff3 --- /dev/null +++ b/askbot/skins/old/media/images/flags/bg.gif diff --git a/askbot/skins/old/media/images/flags/bh.gif b/askbot/skins/old/media/images/flags/bh.gif Binary files differnew file mode 100755 index 00000000..56aa72b2 --- /dev/null +++ b/askbot/skins/old/media/images/flags/bh.gif diff --git a/askbot/skins/old/media/images/flags/bi.gif b/askbot/skins/old/media/images/flags/bi.gif Binary files differnew file mode 100755 index 00000000..6e2cbe12 --- /dev/null +++ b/askbot/skins/old/media/images/flags/bi.gif diff --git a/askbot/skins/old/media/images/flags/bj.gif b/askbot/skins/old/media/images/flags/bj.gif Binary files differnew file mode 100755 index 00000000..e676116f --- /dev/null +++ b/askbot/skins/old/media/images/flags/bj.gif diff --git a/askbot/skins/old/media/images/flags/bm.gif b/askbot/skins/old/media/images/flags/bm.gif Binary files differnew file mode 100755 index 00000000..9feb87bc --- /dev/null +++ b/askbot/skins/old/media/images/flags/bm.gif diff --git a/askbot/skins/old/media/images/flags/bn.gif b/askbot/skins/old/media/images/flags/bn.gif Binary files differnew file mode 100755 index 00000000..b7b6b0f9 --- /dev/null +++ b/askbot/skins/old/media/images/flags/bn.gif diff --git a/askbot/skins/old/media/images/flags/bo.gif b/askbot/skins/old/media/images/flags/bo.gif Binary files differnew file mode 100755 index 00000000..4844f856 --- /dev/null +++ b/askbot/skins/old/media/images/flags/bo.gif diff --git a/askbot/skins/old/media/images/flags/br.gif b/askbot/skins/old/media/images/flags/br.gif Binary files differnew file mode 100755 index 00000000..8c866162 --- /dev/null +++ b/askbot/skins/old/media/images/flags/br.gif diff --git a/askbot/skins/old/media/images/flags/bs.gif b/askbot/skins/old/media/images/flags/bs.gif Binary files differnew file mode 100755 index 00000000..c0a741e5 --- /dev/null +++ b/askbot/skins/old/media/images/flags/bs.gif diff --git a/askbot/skins/old/media/images/flags/bt.gif b/askbot/skins/old/media/images/flags/bt.gif Binary files differnew file mode 100755 index 00000000..abe2f3cc --- /dev/null +++ b/askbot/skins/old/media/images/flags/bt.gif diff --git a/askbot/skins/old/media/images/flags/bv.gif b/askbot/skins/old/media/images/flags/bv.gif Binary files differnew file mode 100755 index 00000000..6202d1f3 --- /dev/null +++ b/askbot/skins/old/media/images/flags/bv.gif diff --git a/askbot/skins/old/media/images/flags/bw.gif b/askbot/skins/old/media/images/flags/bw.gif Binary files differnew file mode 100755 index 00000000..986ab63c --- /dev/null +++ b/askbot/skins/old/media/images/flags/bw.gif diff --git a/askbot/skins/old/media/images/flags/by.gif b/askbot/skins/old/media/images/flags/by.gif Binary files differnew file mode 100755 index 00000000..43ffcd4c --- /dev/null +++ b/askbot/skins/old/media/images/flags/by.gif diff --git a/askbot/skins/old/media/images/flags/bz.gif b/askbot/skins/old/media/images/flags/bz.gif Binary files differnew file mode 100755 index 00000000..791737f0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/bz.gif diff --git a/askbot/skins/old/media/images/flags/ca.gif b/askbot/skins/old/media/images/flags/ca.gif Binary files differnew file mode 100755 index 00000000..457d9662 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ca.gif diff --git a/askbot/skins/old/media/images/flags/catalonia.gif b/askbot/skins/old/media/images/flags/catalonia.gif Binary files differnew file mode 100644 index 00000000..73df9a04 --- /dev/null +++ b/askbot/skins/old/media/images/flags/catalonia.gif diff --git a/askbot/skins/old/media/images/flags/cc.gif b/askbot/skins/old/media/images/flags/cc.gif Binary files differnew file mode 100755 index 00000000..3f783270 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cc.gif diff --git a/askbot/skins/old/media/images/flags/cd.gif b/askbot/skins/old/media/images/flags/cd.gif Binary files differnew file mode 100644 index 00000000..1df717ae --- /dev/null +++ b/askbot/skins/old/media/images/flags/cd.gif diff --git a/askbot/skins/old/media/images/flags/cf.gif b/askbot/skins/old/media/images/flags/cf.gif Binary files differnew file mode 100755 index 00000000..35787ca4 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cf.gif diff --git a/askbot/skins/old/media/images/flags/cg.gif b/askbot/skins/old/media/images/flags/cg.gif Binary files differnew file mode 100755 index 00000000..e0a62a51 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cg.gif diff --git a/askbot/skins/old/media/images/flags/ch.gif b/askbot/skins/old/media/images/flags/ch.gif Binary files differnew file mode 100755 index 00000000..d5c0e5b7 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ch.gif diff --git a/askbot/skins/old/media/images/flags/ci.gif b/askbot/skins/old/media/images/flags/ci.gif Binary files differnew file mode 100755 index 00000000..844120a5 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ci.gif diff --git a/askbot/skins/old/media/images/flags/ck.gif b/askbot/skins/old/media/images/flags/ck.gif Binary files differnew file mode 100755 index 00000000..2edb7399 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ck.gif diff --git a/askbot/skins/old/media/images/flags/cl.gif b/askbot/skins/old/media/images/flags/cl.gif Binary files differnew file mode 100755 index 00000000..cbc370e6 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cl.gif diff --git a/askbot/skins/old/media/images/flags/cm.gif b/askbot/skins/old/media/images/flags/cm.gif Binary files differnew file mode 100755 index 00000000..1fb102b2 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cm.gif diff --git a/askbot/skins/old/media/images/flags/cn.gif b/askbot/skins/old/media/images/flags/cn.gif Binary files differnew file mode 100755 index 00000000..b0525309 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cn.gif diff --git a/askbot/skins/old/media/images/flags/co.gif b/askbot/skins/old/media/images/flags/co.gif Binary files differnew file mode 100755 index 00000000..d0e15caf --- /dev/null +++ b/askbot/skins/old/media/images/flags/co.gif diff --git a/askbot/skins/old/media/images/flags/cr.gif b/askbot/skins/old/media/images/flags/cr.gif Binary files differnew file mode 100755 index 00000000..0728dd6a --- /dev/null +++ b/askbot/skins/old/media/images/flags/cr.gif diff --git a/askbot/skins/old/media/images/flags/cs.gif b/askbot/skins/old/media/images/flags/cs.gif Binary files differnew file mode 100755 index 00000000..101db649 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cs.gif diff --git a/askbot/skins/old/media/images/flags/cu.gif b/askbot/skins/old/media/images/flags/cu.gif Binary files differnew file mode 100755 index 00000000..291255ca --- /dev/null +++ b/askbot/skins/old/media/images/flags/cu.gif diff --git a/askbot/skins/old/media/images/flags/cv.gif b/askbot/skins/old/media/images/flags/cv.gif Binary files differnew file mode 100755 index 00000000..43c6c6cb --- /dev/null +++ b/askbot/skins/old/media/images/flags/cv.gif diff --git a/askbot/skins/old/media/images/flags/cx.gif b/askbot/skins/old/media/images/flags/cx.gif Binary files differnew file mode 100755 index 00000000..a5b43089 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cx.gif diff --git a/askbot/skins/old/media/images/flags/cy.gif b/askbot/skins/old/media/images/flags/cy.gif Binary files differnew file mode 100755 index 00000000..35c661e1 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cy.gif diff --git a/askbot/skins/old/media/images/flags/cz.gif b/askbot/skins/old/media/images/flags/cz.gif Binary files differnew file mode 100755 index 00000000..0a605e58 --- /dev/null +++ b/askbot/skins/old/media/images/flags/cz.gif diff --git a/askbot/skins/old/media/images/flags/de.gif b/askbot/skins/old/media/images/flags/de.gif Binary files differnew file mode 100755 index 00000000..75728ddf --- /dev/null +++ b/askbot/skins/old/media/images/flags/de.gif diff --git a/askbot/skins/old/media/images/flags/dj.gif b/askbot/skins/old/media/images/flags/dj.gif Binary files differnew file mode 100755 index 00000000..212406d9 --- /dev/null +++ b/askbot/skins/old/media/images/flags/dj.gif diff --git a/askbot/skins/old/media/images/flags/dk.gif b/askbot/skins/old/media/images/flags/dk.gif Binary files differnew file mode 100755 index 00000000..03e75bd2 --- /dev/null +++ b/askbot/skins/old/media/images/flags/dk.gif diff --git a/askbot/skins/old/media/images/flags/dm.gif b/askbot/skins/old/media/images/flags/dm.gif Binary files differnew file mode 100755 index 00000000..2f87f3ca --- /dev/null +++ b/askbot/skins/old/media/images/flags/dm.gif diff --git a/askbot/skins/old/media/images/flags/do.gif b/askbot/skins/old/media/images/flags/do.gif Binary files differnew file mode 100755 index 00000000..f7d0bad3 --- /dev/null +++ b/askbot/skins/old/media/images/flags/do.gif diff --git a/askbot/skins/old/media/images/flags/dz.gif b/askbot/skins/old/media/images/flags/dz.gif Binary files differnew file mode 100755 index 00000000..ed580a7c --- /dev/null +++ b/askbot/skins/old/media/images/flags/dz.gif diff --git a/askbot/skins/old/media/images/flags/ec.gif b/askbot/skins/old/media/images/flags/ec.gif Binary files differnew file mode 100755 index 00000000..9e41e0ec --- /dev/null +++ b/askbot/skins/old/media/images/flags/ec.gif diff --git a/askbot/skins/old/media/images/flags/ee.gif b/askbot/skins/old/media/images/flags/ee.gif Binary files differnew file mode 100755 index 00000000..9397a2d0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ee.gif diff --git a/askbot/skins/old/media/images/flags/eg.gif b/askbot/skins/old/media/images/flags/eg.gif Binary files differnew file mode 100755 index 00000000..6857c7dd --- /dev/null +++ b/askbot/skins/old/media/images/flags/eg.gif diff --git a/askbot/skins/old/media/images/flags/eh.gif b/askbot/skins/old/media/images/flags/eh.gif Binary files differnew file mode 100755 index 00000000..dd0391c2 --- /dev/null +++ b/askbot/skins/old/media/images/flags/eh.gif diff --git a/askbot/skins/old/media/images/flags/england.gif b/askbot/skins/old/media/images/flags/england.gif Binary files differnew file mode 100755 index 00000000..933a4f0b --- /dev/null +++ b/askbot/skins/old/media/images/flags/england.gif diff --git a/askbot/skins/old/media/images/flags/er.gif b/askbot/skins/old/media/images/flags/er.gif Binary files differnew file mode 100755 index 00000000..3d4d612c --- /dev/null +++ b/askbot/skins/old/media/images/flags/er.gif diff --git a/askbot/skins/old/media/images/flags/es.gif b/askbot/skins/old/media/images/flags/es.gif Binary files differnew file mode 100755 index 00000000..c27d65e5 --- /dev/null +++ b/askbot/skins/old/media/images/flags/es.gif diff --git a/askbot/skins/old/media/images/flags/et.gif b/askbot/skins/old/media/images/flags/et.gif Binary files differnew file mode 100755 index 00000000..f77995d0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/et.gif diff --git a/askbot/skins/old/media/images/flags/europeanunion.gif b/askbot/skins/old/media/images/flags/europeanunion.gif Binary files differnew file mode 100644 index 00000000..28a762a5 --- /dev/null +++ b/askbot/skins/old/media/images/flags/europeanunion.gif diff --git a/askbot/skins/old/media/images/flags/fam.gif b/askbot/skins/old/media/images/flags/fam.gif Binary files differnew file mode 100755 index 00000000..7d528852 --- /dev/null +++ b/askbot/skins/old/media/images/flags/fam.gif diff --git a/askbot/skins/old/media/images/flags/fi.gif b/askbot/skins/old/media/images/flags/fi.gif Binary files differnew file mode 100755 index 00000000..8d3a1918 --- /dev/null +++ b/askbot/skins/old/media/images/flags/fi.gif diff --git a/askbot/skins/old/media/images/flags/fj.gif b/askbot/skins/old/media/images/flags/fj.gif Binary files differnew file mode 100755 index 00000000..486151cb --- /dev/null +++ b/askbot/skins/old/media/images/flags/fj.gif diff --git a/askbot/skins/old/media/images/flags/fk.gif b/askbot/skins/old/media/images/flags/fk.gif Binary files differnew file mode 100755 index 00000000..37b5ecf3 --- /dev/null +++ b/askbot/skins/old/media/images/flags/fk.gif diff --git a/askbot/skins/old/media/images/flags/fm.gif b/askbot/skins/old/media/images/flags/fm.gif Binary files differnew file mode 100755 index 00000000..7f8723b7 --- /dev/null +++ b/askbot/skins/old/media/images/flags/fm.gif diff --git a/askbot/skins/old/media/images/flags/fo.gif b/askbot/skins/old/media/images/flags/fo.gif Binary files differnew file mode 100755 index 00000000..4a90fc04 --- /dev/null +++ b/askbot/skins/old/media/images/flags/fo.gif diff --git a/askbot/skins/old/media/images/flags/fr.gif b/askbot/skins/old/media/images/flags/fr.gif Binary files differnew file mode 100755 index 00000000..43d0b801 --- /dev/null +++ b/askbot/skins/old/media/images/flags/fr.gif diff --git a/askbot/skins/old/media/images/flags/ga.gif b/askbot/skins/old/media/images/flags/ga.gif Binary files differnew file mode 100755 index 00000000..23fd5f0d --- /dev/null +++ b/askbot/skins/old/media/images/flags/ga.gif diff --git a/askbot/skins/old/media/images/flags/gb.gif b/askbot/skins/old/media/images/flags/gb.gif Binary files differnew file mode 100644 index 00000000..3c6bce15 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gb.gif diff --git a/askbot/skins/old/media/images/flags/gd.gif b/askbot/skins/old/media/images/flags/gd.gif Binary files differnew file mode 100755 index 00000000..25ea3123 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gd.gif diff --git a/askbot/skins/old/media/images/flags/ge.gif b/askbot/skins/old/media/images/flags/ge.gif Binary files differnew file mode 100755 index 00000000..faa7f126 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ge.gif diff --git a/askbot/skins/old/media/images/flags/gf.gif b/askbot/skins/old/media/images/flags/gf.gif Binary files differnew file mode 100755 index 00000000..43d0b801 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gf.gif diff --git a/askbot/skins/old/media/images/flags/gh.gif b/askbot/skins/old/media/images/flags/gh.gif Binary files differnew file mode 100755 index 00000000..273fb7d1 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gh.gif diff --git a/askbot/skins/old/media/images/flags/gi.gif b/askbot/skins/old/media/images/flags/gi.gif Binary files differnew file mode 100755 index 00000000..7b1984bc --- /dev/null +++ b/askbot/skins/old/media/images/flags/gi.gif diff --git a/askbot/skins/old/media/images/flags/gl.gif b/askbot/skins/old/media/images/flags/gl.gif Binary files differnew file mode 100755 index 00000000..ef445be0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gl.gif diff --git a/askbot/skins/old/media/images/flags/gm.gif b/askbot/skins/old/media/images/flags/gm.gif Binary files differnew file mode 100755 index 00000000..6847c5a8 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gm.gif diff --git a/askbot/skins/old/media/images/flags/gn.gif b/askbot/skins/old/media/images/flags/gn.gif Binary files differnew file mode 100755 index 00000000..a982ac6f --- /dev/null +++ b/askbot/skins/old/media/images/flags/gn.gif diff --git a/askbot/skins/old/media/images/flags/gp.gif b/askbot/skins/old/media/images/flags/gp.gif Binary files differnew file mode 100755 index 00000000..31166db6 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gp.gif diff --git a/askbot/skins/old/media/images/flags/gq.gif b/askbot/skins/old/media/images/flags/gq.gif Binary files differnew file mode 100755 index 00000000..8b4e0cc4 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gq.gif diff --git a/askbot/skins/old/media/images/flags/gr.gif b/askbot/skins/old/media/images/flags/gr.gif Binary files differnew file mode 100755 index 00000000..b4c8c04e --- /dev/null +++ b/askbot/skins/old/media/images/flags/gr.gif diff --git a/askbot/skins/old/media/images/flags/gs.gif b/askbot/skins/old/media/images/flags/gs.gif Binary files differnew file mode 100755 index 00000000..ccc96ec0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gs.gif diff --git a/askbot/skins/old/media/images/flags/gt.gif b/askbot/skins/old/media/images/flags/gt.gif Binary files differnew file mode 100755 index 00000000..7e94d1dd --- /dev/null +++ b/askbot/skins/old/media/images/flags/gt.gif diff --git a/askbot/skins/old/media/images/flags/gu.gif b/askbot/skins/old/media/images/flags/gu.gif Binary files differnew file mode 100755 index 00000000..eafef683 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gu.gif diff --git a/askbot/skins/old/media/images/flags/gw.gif b/askbot/skins/old/media/images/flags/gw.gif Binary files differnew file mode 100755 index 00000000..55f75711 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gw.gif diff --git a/askbot/skins/old/media/images/flags/gy.gif b/askbot/skins/old/media/images/flags/gy.gif Binary files differnew file mode 100755 index 00000000..1cb4cd71 --- /dev/null +++ b/askbot/skins/old/media/images/flags/gy.gif diff --git a/askbot/skins/old/media/images/flags/hk.gif b/askbot/skins/old/media/images/flags/hk.gif Binary files differnew file mode 100755 index 00000000..798af96d --- /dev/null +++ b/askbot/skins/old/media/images/flags/hk.gif diff --git a/askbot/skins/old/media/images/flags/hm.gif b/askbot/skins/old/media/images/flags/hm.gif Binary files differnew file mode 100755 index 00000000..5269c6a0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/hm.gif diff --git a/askbot/skins/old/media/images/flags/hn.gif b/askbot/skins/old/media/images/flags/hn.gif Binary files differnew file mode 100755 index 00000000..6c4ffe8e --- /dev/null +++ b/askbot/skins/old/media/images/flags/hn.gif diff --git a/askbot/skins/old/media/images/flags/hr.gif b/askbot/skins/old/media/images/flags/hr.gif Binary files differnew file mode 100755 index 00000000..557c6602 --- /dev/null +++ b/askbot/skins/old/media/images/flags/hr.gif diff --git a/askbot/skins/old/media/images/flags/ht.gif b/askbot/skins/old/media/images/flags/ht.gif Binary files differnew file mode 100755 index 00000000..059604ab --- /dev/null +++ b/askbot/skins/old/media/images/flags/ht.gif diff --git a/askbot/skins/old/media/images/flags/hu.gif b/askbot/skins/old/media/images/flags/hu.gif Binary files differnew file mode 100755 index 00000000..6142d868 --- /dev/null +++ b/askbot/skins/old/media/images/flags/hu.gif diff --git a/askbot/skins/old/media/images/flags/id.gif b/askbot/skins/old/media/images/flags/id.gif Binary files differnew file mode 100755 index 00000000..865161b0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/id.gif diff --git a/askbot/skins/old/media/images/flags/ie.gif b/askbot/skins/old/media/images/flags/ie.gif Binary files differnew file mode 100755 index 00000000..506ad285 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ie.gif diff --git a/askbot/skins/old/media/images/flags/il.gif b/askbot/skins/old/media/images/flags/il.gif Binary files differnew file mode 100755 index 00000000..c8483ae5 --- /dev/null +++ b/askbot/skins/old/media/images/flags/il.gif diff --git a/askbot/skins/old/media/images/flags/in.gif b/askbot/skins/old/media/images/flags/in.gif Binary files differnew file mode 100755 index 00000000..1cd80272 --- /dev/null +++ b/askbot/skins/old/media/images/flags/in.gif diff --git a/askbot/skins/old/media/images/flags/io.gif b/askbot/skins/old/media/images/flags/io.gif Binary files differnew file mode 100755 index 00000000..de7e7ab3 --- /dev/null +++ b/askbot/skins/old/media/images/flags/io.gif diff --git a/askbot/skins/old/media/images/flags/iq.gif b/askbot/skins/old/media/images/flags/iq.gif Binary files differnew file mode 100755 index 00000000..c34fe3c4 --- /dev/null +++ b/askbot/skins/old/media/images/flags/iq.gif diff --git a/askbot/skins/old/media/images/flags/ir.gif b/askbot/skins/old/media/images/flags/ir.gif Binary files differnew file mode 100755 index 00000000..156040fc --- /dev/null +++ b/askbot/skins/old/media/images/flags/ir.gif diff --git a/askbot/skins/old/media/images/flags/is.gif b/askbot/skins/old/media/images/flags/is.gif Binary files differnew file mode 100755 index 00000000..b42502de --- /dev/null +++ b/askbot/skins/old/media/images/flags/is.gif diff --git a/askbot/skins/old/media/images/flags/it.gif b/askbot/skins/old/media/images/flags/it.gif Binary files differnew file mode 100755 index 00000000..d79e90e9 --- /dev/null +++ b/askbot/skins/old/media/images/flags/it.gif diff --git a/askbot/skins/old/media/images/flags/jm.gif b/askbot/skins/old/media/images/flags/jm.gif Binary files differnew file mode 100755 index 00000000..0bed67c2 --- /dev/null +++ b/askbot/skins/old/media/images/flags/jm.gif diff --git a/askbot/skins/old/media/images/flags/jo.gif b/askbot/skins/old/media/images/flags/jo.gif Binary files differnew file mode 100755 index 00000000..03daf8af --- /dev/null +++ b/askbot/skins/old/media/images/flags/jo.gif diff --git a/askbot/skins/old/media/images/flags/jp.gif b/askbot/skins/old/media/images/flags/jp.gif Binary files differnew file mode 100755 index 00000000..444c1d05 --- /dev/null +++ b/askbot/skins/old/media/images/flags/jp.gif diff --git a/askbot/skins/old/media/images/flags/ke.gif b/askbot/skins/old/media/images/flags/ke.gif Binary files differnew file mode 100755 index 00000000..c2b5d45c --- /dev/null +++ b/askbot/skins/old/media/images/flags/ke.gif diff --git a/askbot/skins/old/media/images/flags/kg.gif b/askbot/skins/old/media/images/flags/kg.gif Binary files differnew file mode 100755 index 00000000..72a4d412 --- /dev/null +++ b/askbot/skins/old/media/images/flags/kg.gif diff --git a/askbot/skins/old/media/images/flags/kh.gif b/askbot/skins/old/media/images/flags/kh.gif Binary files differnew file mode 100755 index 00000000..30a18315 --- /dev/null +++ b/askbot/skins/old/media/images/flags/kh.gif diff --git a/askbot/skins/old/media/images/flags/ki.gif b/askbot/skins/old/media/images/flags/ki.gif Binary files differnew file mode 100755 index 00000000..4a0751a2 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ki.gif diff --git a/askbot/skins/old/media/images/flags/km.gif b/askbot/skins/old/media/images/flags/km.gif Binary files differnew file mode 100755 index 00000000..5859595e --- /dev/null +++ b/askbot/skins/old/media/images/flags/km.gif diff --git a/askbot/skins/old/media/images/flags/kn.gif b/askbot/skins/old/media/images/flags/kn.gif Binary files differnew file mode 100755 index 00000000..bb9cc34a --- /dev/null +++ b/askbot/skins/old/media/images/flags/kn.gif diff --git a/askbot/skins/old/media/images/flags/kp.gif b/askbot/skins/old/media/images/flags/kp.gif Binary files differnew file mode 100755 index 00000000..6e0ca09e --- /dev/null +++ b/askbot/skins/old/media/images/flags/kp.gif diff --git a/askbot/skins/old/media/images/flags/kr.gif b/askbot/skins/old/media/images/flags/kr.gif Binary files differnew file mode 100755 index 00000000..1cddbe75 --- /dev/null +++ b/askbot/skins/old/media/images/flags/kr.gif diff --git a/askbot/skins/old/media/images/flags/kw.gif b/askbot/skins/old/media/images/flags/kw.gif Binary files differnew file mode 100755 index 00000000..1efc7347 --- /dev/null +++ b/askbot/skins/old/media/images/flags/kw.gif diff --git a/askbot/skins/old/media/images/flags/ky.gif b/askbot/skins/old/media/images/flags/ky.gif Binary files differnew file mode 100755 index 00000000..d3d02ee4 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ky.gif diff --git a/askbot/skins/old/media/images/flags/kz.gif b/askbot/skins/old/media/images/flags/kz.gif Binary files differnew file mode 100755 index 00000000..24baebe0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/kz.gif diff --git a/askbot/skins/old/media/images/flags/la.gif b/askbot/skins/old/media/images/flags/la.gif Binary files differnew file mode 100755 index 00000000..d14cf4d8 --- /dev/null +++ b/askbot/skins/old/media/images/flags/la.gif diff --git a/askbot/skins/old/media/images/flags/lb.gif b/askbot/skins/old/media/images/flags/lb.gif Binary files differnew file mode 100755 index 00000000..003d83af --- /dev/null +++ b/askbot/skins/old/media/images/flags/lb.gif diff --git a/askbot/skins/old/media/images/flags/lc.gif b/askbot/skins/old/media/images/flags/lc.gif Binary files differnew file mode 100644 index 00000000..f5fe5bff --- /dev/null +++ b/askbot/skins/old/media/images/flags/lc.gif diff --git a/askbot/skins/old/media/images/flags/li.gif b/askbot/skins/old/media/images/flags/li.gif Binary files differnew file mode 100755 index 00000000..713c58e1 --- /dev/null +++ b/askbot/skins/old/media/images/flags/li.gif diff --git a/askbot/skins/old/media/images/flags/lk.gif b/askbot/skins/old/media/images/flags/lk.gif Binary files differnew file mode 100755 index 00000000..1b3ee7f5 --- /dev/null +++ b/askbot/skins/old/media/images/flags/lk.gif diff --git a/askbot/skins/old/media/images/flags/lr.gif b/askbot/skins/old/media/images/flags/lr.gif Binary files differnew file mode 100755 index 00000000..435af9e5 --- /dev/null +++ b/askbot/skins/old/media/images/flags/lr.gif diff --git a/askbot/skins/old/media/images/flags/ls.gif b/askbot/skins/old/media/images/flags/ls.gif Binary files differnew file mode 100755 index 00000000..427ae957 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ls.gif diff --git a/askbot/skins/old/media/images/flags/lt.gif b/askbot/skins/old/media/images/flags/lt.gif Binary files differnew file mode 100755 index 00000000..dee9c601 --- /dev/null +++ b/askbot/skins/old/media/images/flags/lt.gif diff --git a/askbot/skins/old/media/images/flags/lu.gif b/askbot/skins/old/media/images/flags/lu.gif Binary files differnew file mode 100755 index 00000000..7d7293ed --- /dev/null +++ b/askbot/skins/old/media/images/flags/lu.gif diff --git a/askbot/skins/old/media/images/flags/lv.gif b/askbot/skins/old/media/images/flags/lv.gif Binary files differnew file mode 100755 index 00000000..17e71b7e --- /dev/null +++ b/askbot/skins/old/media/images/flags/lv.gif diff --git a/askbot/skins/old/media/images/flags/ly.gif b/askbot/skins/old/media/images/flags/ly.gif Binary files differnew file mode 100755 index 00000000..a654c30a --- /dev/null +++ b/askbot/skins/old/media/images/flags/ly.gif diff --git a/askbot/skins/old/media/images/flags/ma.gif b/askbot/skins/old/media/images/flags/ma.gif Binary files differnew file mode 100755 index 00000000..fc784119 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ma.gif diff --git a/askbot/skins/old/media/images/flags/mc.gif b/askbot/skins/old/media/images/flags/mc.gif Binary files differnew file mode 100755 index 00000000..02a7c8e1 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mc.gif diff --git a/askbot/skins/old/media/images/flags/md.gif b/askbot/skins/old/media/images/flags/md.gif Binary files differnew file mode 100755 index 00000000..e4b8a7e3 --- /dev/null +++ b/askbot/skins/old/media/images/flags/md.gif diff --git a/askbot/skins/old/media/images/flags/me.gif b/askbot/skins/old/media/images/flags/me.gif Binary files differnew file mode 100644 index 00000000..a260453c --- /dev/null +++ b/askbot/skins/old/media/images/flags/me.gif diff --git a/askbot/skins/old/media/images/flags/mg.gif b/askbot/skins/old/media/images/flags/mg.gif Binary files differnew file mode 100755 index 00000000..a91b577d --- /dev/null +++ b/askbot/skins/old/media/images/flags/mg.gif diff --git a/askbot/skins/old/media/images/flags/mh.gif b/askbot/skins/old/media/images/flags/mh.gif Binary files differnew file mode 100755 index 00000000..92f5f485 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mh.gif diff --git a/askbot/skins/old/media/images/flags/mk.gif b/askbot/skins/old/media/images/flags/mk.gif Binary files differnew file mode 100755 index 00000000..7aeb8311 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mk.gif diff --git a/askbot/skins/old/media/images/flags/ml.gif b/askbot/skins/old/media/images/flags/ml.gif Binary files differnew file mode 100755 index 00000000..53d6f490 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ml.gif diff --git a/askbot/skins/old/media/images/flags/mm.gif b/askbot/skins/old/media/images/flags/mm.gif Binary files differnew file mode 100755 index 00000000..9e0a2756 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mm.gif diff --git a/askbot/skins/old/media/images/flags/mn.gif b/askbot/skins/old/media/images/flags/mn.gif Binary files differnew file mode 100755 index 00000000..dff8ea5a --- /dev/null +++ b/askbot/skins/old/media/images/flags/mn.gif diff --git a/askbot/skins/old/media/images/flags/mo.gif b/askbot/skins/old/media/images/flags/mo.gif Binary files differnew file mode 100755 index 00000000..66cf5b4f --- /dev/null +++ b/askbot/skins/old/media/images/flags/mo.gif diff --git a/askbot/skins/old/media/images/flags/mp.gif b/askbot/skins/old/media/images/flags/mp.gif Binary files differnew file mode 100755 index 00000000..73b7147e --- /dev/null +++ b/askbot/skins/old/media/images/flags/mp.gif diff --git a/askbot/skins/old/media/images/flags/mq.gif b/askbot/skins/old/media/images/flags/mq.gif Binary files differnew file mode 100755 index 00000000..570bc5dd --- /dev/null +++ b/askbot/skins/old/media/images/flags/mq.gif diff --git a/askbot/skins/old/media/images/flags/mr.gif b/askbot/skins/old/media/images/flags/mr.gif Binary files differnew file mode 100755 index 00000000..f52fcf09 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mr.gif diff --git a/askbot/skins/old/media/images/flags/ms.gif b/askbot/skins/old/media/images/flags/ms.gif Binary files differnew file mode 100755 index 00000000..5e5a67aa --- /dev/null +++ b/askbot/skins/old/media/images/flags/ms.gif diff --git a/askbot/skins/old/media/images/flags/mt.gif b/askbot/skins/old/media/images/flags/mt.gif Binary files differnew file mode 100755 index 00000000..45c709f2 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mt.gif diff --git a/askbot/skins/old/media/images/flags/mu.gif b/askbot/skins/old/media/images/flags/mu.gif Binary files differnew file mode 100755 index 00000000..081ab453 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mu.gif diff --git a/askbot/skins/old/media/images/flags/mv.gif b/askbot/skins/old/media/images/flags/mv.gif Binary files differnew file mode 100755 index 00000000..46b63875 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mv.gif diff --git a/askbot/skins/old/media/images/flags/mw.gif b/askbot/skins/old/media/images/flags/mw.gif Binary files differnew file mode 100755 index 00000000..ad045a09 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mw.gif diff --git a/askbot/skins/old/media/images/flags/mx.gif b/askbot/skins/old/media/images/flags/mx.gif Binary files differnew file mode 100755 index 00000000..ddc75d04 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mx.gif diff --git a/askbot/skins/old/media/images/flags/my.gif b/askbot/skins/old/media/images/flags/my.gif Binary files differnew file mode 100755 index 00000000..fc7d5236 --- /dev/null +++ b/askbot/skins/old/media/images/flags/my.gif diff --git a/askbot/skins/old/media/images/flags/mz.gif b/askbot/skins/old/media/images/flags/mz.gif Binary files differnew file mode 100755 index 00000000..7d635082 --- /dev/null +++ b/askbot/skins/old/media/images/flags/mz.gif diff --git a/askbot/skins/old/media/images/flags/na.gif b/askbot/skins/old/media/images/flags/na.gif Binary files differnew file mode 100755 index 00000000..c0babe72 --- /dev/null +++ b/askbot/skins/old/media/images/flags/na.gif diff --git a/askbot/skins/old/media/images/flags/nc.gif b/askbot/skins/old/media/images/flags/nc.gif Binary files differnew file mode 100755 index 00000000..b1e91b9a --- /dev/null +++ b/askbot/skins/old/media/images/flags/nc.gif diff --git a/askbot/skins/old/media/images/flags/ne.gif b/askbot/skins/old/media/images/flags/ne.gif Binary files differnew file mode 100755 index 00000000..ff4eaf07 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ne.gif diff --git a/askbot/skins/old/media/images/flags/nf.gif b/askbot/skins/old/media/images/flags/nf.gif Binary files differnew file mode 100755 index 00000000..c83424c2 --- /dev/null +++ b/askbot/skins/old/media/images/flags/nf.gif diff --git a/askbot/skins/old/media/images/flags/ng.gif b/askbot/skins/old/media/images/flags/ng.gif Binary files differnew file mode 100755 index 00000000..bdde7cb3 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ng.gif diff --git a/askbot/skins/old/media/images/flags/ni.gif b/askbot/skins/old/media/images/flags/ni.gif Binary files differnew file mode 100755 index 00000000..d05894d0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ni.gif diff --git a/askbot/skins/old/media/images/flags/nl.gif b/askbot/skins/old/media/images/flags/nl.gif Binary files differnew file mode 100755 index 00000000..c1c8f46d --- /dev/null +++ b/askbot/skins/old/media/images/flags/nl.gif diff --git a/askbot/skins/old/media/images/flags/no.gif b/askbot/skins/old/media/images/flags/no.gif Binary files differnew file mode 100755 index 00000000..6202d1f3 --- /dev/null +++ b/askbot/skins/old/media/images/flags/no.gif diff --git a/askbot/skins/old/media/images/flags/np.gif b/askbot/skins/old/media/images/flags/np.gif Binary files differnew file mode 100755 index 00000000..1096893a --- /dev/null +++ b/askbot/skins/old/media/images/flags/np.gif diff --git a/askbot/skins/old/media/images/flags/nr.gif b/askbot/skins/old/media/images/flags/nr.gif Binary files differnew file mode 100755 index 00000000..2e4c0c5c --- /dev/null +++ b/askbot/skins/old/media/images/flags/nr.gif diff --git a/askbot/skins/old/media/images/flags/nu.gif b/askbot/skins/old/media/images/flags/nu.gif Binary files differnew file mode 100755 index 00000000..618210a7 --- /dev/null +++ b/askbot/skins/old/media/images/flags/nu.gif diff --git a/askbot/skins/old/media/images/flags/nz.gif b/askbot/skins/old/media/images/flags/nz.gif Binary files differnew file mode 100755 index 00000000..028a5dc6 --- /dev/null +++ b/askbot/skins/old/media/images/flags/nz.gif diff --git a/askbot/skins/old/media/images/flags/om.gif b/askbot/skins/old/media/images/flags/om.gif Binary files differnew file mode 100755 index 00000000..2b8c7750 --- /dev/null +++ b/askbot/skins/old/media/images/flags/om.gif diff --git a/askbot/skins/old/media/images/flags/pa.gif b/askbot/skins/old/media/images/flags/pa.gif Binary files differnew file mode 100755 index 00000000..d518b2f9 --- /dev/null +++ b/askbot/skins/old/media/images/flags/pa.gif diff --git a/askbot/skins/old/media/images/flags/pe.gif b/askbot/skins/old/media/images/flags/pe.gif Binary files differnew file mode 100755 index 00000000..3bc76390 --- /dev/null +++ b/askbot/skins/old/media/images/flags/pe.gif diff --git a/askbot/skins/old/media/images/flags/pf.gif b/askbot/skins/old/media/images/flags/pf.gif Binary files differnew file mode 100755 index 00000000..849297a5 --- /dev/null +++ b/askbot/skins/old/media/images/flags/pf.gif diff --git a/askbot/skins/old/media/images/flags/pg.gif b/askbot/skins/old/media/images/flags/pg.gif Binary files differnew file mode 100755 index 00000000..2d20b078 --- /dev/null +++ b/askbot/skins/old/media/images/flags/pg.gif diff --git a/askbot/skins/old/media/images/flags/ph.gif b/askbot/skins/old/media/images/flags/ph.gif Binary files differnew file mode 100755 index 00000000..12b380ac --- /dev/null +++ b/askbot/skins/old/media/images/flags/ph.gif diff --git a/askbot/skins/old/media/images/flags/pk.gif b/askbot/skins/old/media/images/flags/pk.gif Binary files differnew file mode 100755 index 00000000..f3f62c2e --- /dev/null +++ b/askbot/skins/old/media/images/flags/pk.gif diff --git a/askbot/skins/old/media/images/flags/pl.gif b/askbot/skins/old/media/images/flags/pl.gif Binary files differnew file mode 100755 index 00000000..bf106463 --- /dev/null +++ b/askbot/skins/old/media/images/flags/pl.gif diff --git a/askbot/skins/old/media/images/flags/pm.gif b/askbot/skins/old/media/images/flags/pm.gif Binary files differnew file mode 100755 index 00000000..99bf6fdb --- /dev/null +++ b/askbot/skins/old/media/images/flags/pm.gif diff --git a/askbot/skins/old/media/images/flags/pn.gif b/askbot/skins/old/media/images/flags/pn.gif Binary files differnew file mode 100755 index 00000000..4bc86a1d --- /dev/null +++ b/askbot/skins/old/media/images/flags/pn.gif diff --git a/askbot/skins/old/media/images/flags/pr.gif b/askbot/skins/old/media/images/flags/pr.gif Binary files differnew file mode 100755 index 00000000..6d5d5896 --- /dev/null +++ b/askbot/skins/old/media/images/flags/pr.gif diff --git a/askbot/skins/old/media/images/flags/ps.gif b/askbot/skins/old/media/images/flags/ps.gif Binary files differnew file mode 100755 index 00000000..6afa3b71 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ps.gif diff --git a/askbot/skins/old/media/images/flags/pt.gif b/askbot/skins/old/media/images/flags/pt.gif Binary files differnew file mode 100755 index 00000000..e735f740 --- /dev/null +++ b/askbot/skins/old/media/images/flags/pt.gif diff --git a/askbot/skins/old/media/images/flags/pw.gif b/askbot/skins/old/media/images/flags/pw.gif Binary files differnew file mode 100755 index 00000000..5854510f --- /dev/null +++ b/askbot/skins/old/media/images/flags/pw.gif diff --git a/askbot/skins/old/media/images/flags/py.gif b/askbot/skins/old/media/images/flags/py.gif Binary files differnew file mode 100755 index 00000000..f2e66af7 --- /dev/null +++ b/askbot/skins/old/media/images/flags/py.gif diff --git a/askbot/skins/old/media/images/flags/qa.gif b/askbot/skins/old/media/images/flags/qa.gif Binary files differnew file mode 100755 index 00000000..2e843ff9 --- /dev/null +++ b/askbot/skins/old/media/images/flags/qa.gif diff --git a/askbot/skins/old/media/images/flags/re.gif b/askbot/skins/old/media/images/flags/re.gif Binary files differnew file mode 100755 index 00000000..43d0b801 --- /dev/null +++ b/askbot/skins/old/media/images/flags/re.gif diff --git a/askbot/skins/old/media/images/flags/ro.gif b/askbot/skins/old/media/images/flags/ro.gif Binary files differnew file mode 100755 index 00000000..f5d5f125 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ro.gif diff --git a/askbot/skins/old/media/images/flags/rs.gif b/askbot/skins/old/media/images/flags/rs.gif Binary files differnew file mode 100644 index 00000000..3bd1fb2f --- /dev/null +++ b/askbot/skins/old/media/images/flags/rs.gif diff --git a/askbot/skins/old/media/images/flags/ru.gif b/askbot/skins/old/media/images/flags/ru.gif Binary files differnew file mode 100755 index 00000000..b525c462 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ru.gif diff --git a/askbot/skins/old/media/images/flags/rw.gif b/askbot/skins/old/media/images/flags/rw.gif Binary files differnew file mode 100755 index 00000000..0d095f7a --- /dev/null +++ b/askbot/skins/old/media/images/flags/rw.gif diff --git a/askbot/skins/old/media/images/flags/sa.gif b/askbot/skins/old/media/images/flags/sa.gif Binary files differnew file mode 100755 index 00000000..179961b6 --- /dev/null +++ b/askbot/skins/old/media/images/flags/sa.gif diff --git a/askbot/skins/old/media/images/flags/sb.gif b/askbot/skins/old/media/images/flags/sb.gif Binary files differnew file mode 100755 index 00000000..8f5ff837 --- /dev/null +++ b/askbot/skins/old/media/images/flags/sb.gif diff --git a/askbot/skins/old/media/images/flags/sc.gif b/askbot/skins/old/media/images/flags/sc.gif Binary files differnew file mode 100755 index 00000000..31b47677 --- /dev/null +++ b/askbot/skins/old/media/images/flags/sc.gif diff --git a/askbot/skins/old/media/images/flags/scotland.gif b/askbot/skins/old/media/images/flags/scotland.gif Binary files differnew file mode 100755 index 00000000..03f3f1de --- /dev/null +++ b/askbot/skins/old/media/images/flags/scotland.gif diff --git a/askbot/skins/old/media/images/flags/sd.gif b/askbot/skins/old/media/images/flags/sd.gif Binary files differnew file mode 100755 index 00000000..53ae214f --- /dev/null +++ b/askbot/skins/old/media/images/flags/sd.gif diff --git a/askbot/skins/old/media/images/flags/se.gif b/askbot/skins/old/media/images/flags/se.gif Binary files differnew file mode 100755 index 00000000..80f62852 --- /dev/null +++ b/askbot/skins/old/media/images/flags/se.gif diff --git a/askbot/skins/old/media/images/flags/sg.gif b/askbot/skins/old/media/images/flags/sg.gif Binary files differnew file mode 100755 index 00000000..5663d39f --- /dev/null +++ b/askbot/skins/old/media/images/flags/sg.gif diff --git a/askbot/skins/old/media/images/flags/sh.gif b/askbot/skins/old/media/images/flags/sh.gif Binary files differnew file mode 100755 index 00000000..dcc7f3bc --- /dev/null +++ b/askbot/skins/old/media/images/flags/sh.gif diff --git a/askbot/skins/old/media/images/flags/si.gif b/askbot/skins/old/media/images/flags/si.gif Binary files differnew file mode 100755 index 00000000..23852b50 --- /dev/null +++ b/askbot/skins/old/media/images/flags/si.gif diff --git a/askbot/skins/old/media/images/flags/sj.gif b/askbot/skins/old/media/images/flags/sj.gif Binary files differnew file mode 100755 index 00000000..6202d1f3 --- /dev/null +++ b/askbot/skins/old/media/images/flags/sj.gif diff --git a/askbot/skins/old/media/images/flags/sk.gif b/askbot/skins/old/media/images/flags/sk.gif Binary files differnew file mode 100755 index 00000000..1b3f22ba --- /dev/null +++ b/askbot/skins/old/media/images/flags/sk.gif diff --git a/askbot/skins/old/media/images/flags/sl.gif b/askbot/skins/old/media/images/flags/sl.gif Binary files differnew file mode 100755 index 00000000..f0f34923 --- /dev/null +++ b/askbot/skins/old/media/images/flags/sl.gif diff --git a/askbot/skins/old/media/images/flags/sm.gif b/askbot/skins/old/media/images/flags/sm.gif Binary files differnew file mode 100755 index 00000000..04d98de5 --- /dev/null +++ b/askbot/skins/old/media/images/flags/sm.gif diff --git a/askbot/skins/old/media/images/flags/sn.gif b/askbot/skins/old/media/images/flags/sn.gif Binary files differnew file mode 100755 index 00000000..6dac8709 --- /dev/null +++ b/askbot/skins/old/media/images/flags/sn.gif diff --git a/askbot/skins/old/media/images/flags/so.gif b/askbot/skins/old/media/images/flags/so.gif Binary files differnew file mode 100755 index 00000000..f1961694 --- /dev/null +++ b/askbot/skins/old/media/images/flags/so.gif diff --git a/askbot/skins/old/media/images/flags/sr.gif b/askbot/skins/old/media/images/flags/sr.gif Binary files differnew file mode 100755 index 00000000..0f7499ad --- /dev/null +++ b/askbot/skins/old/media/images/flags/sr.gif diff --git a/askbot/skins/old/media/images/flags/st.gif b/askbot/skins/old/media/images/flags/st.gif Binary files differnew file mode 100755 index 00000000..4f1e6e09 --- /dev/null +++ b/askbot/skins/old/media/images/flags/st.gif diff --git a/askbot/skins/old/media/images/flags/sv.gif b/askbot/skins/old/media/images/flags/sv.gif Binary files differnew file mode 100755 index 00000000..2d7b159a --- /dev/null +++ b/askbot/skins/old/media/images/flags/sv.gif diff --git a/askbot/skins/old/media/images/flags/sy.gif b/askbot/skins/old/media/images/flags/sy.gif Binary files differnew file mode 100755 index 00000000..dc8bd509 --- /dev/null +++ b/askbot/skins/old/media/images/flags/sy.gif diff --git a/askbot/skins/old/media/images/flags/sz.gif b/askbot/skins/old/media/images/flags/sz.gif Binary files differnew file mode 100755 index 00000000..f37aaf80 --- /dev/null +++ b/askbot/skins/old/media/images/flags/sz.gif diff --git a/askbot/skins/old/media/images/flags/tc.gif b/askbot/skins/old/media/images/flags/tc.gif Binary files differnew file mode 100755 index 00000000..11a8c232 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tc.gif diff --git a/askbot/skins/old/media/images/flags/td.gif b/askbot/skins/old/media/images/flags/td.gif Binary files differnew file mode 100755 index 00000000..7aa8a10d --- /dev/null +++ b/askbot/skins/old/media/images/flags/td.gif diff --git a/askbot/skins/old/media/images/flags/tf.gif b/askbot/skins/old/media/images/flags/tf.gif Binary files differnew file mode 100755 index 00000000..51a43250 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tf.gif diff --git a/askbot/skins/old/media/images/flags/tg.gif b/askbot/skins/old/media/images/flags/tg.gif Binary files differnew file mode 100755 index 00000000..ca6b4e77 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tg.gif diff --git a/askbot/skins/old/media/images/flags/th.gif b/askbot/skins/old/media/images/flags/th.gif Binary files differnew file mode 100755 index 00000000..01307924 --- /dev/null +++ b/askbot/skins/old/media/images/flags/th.gif diff --git a/askbot/skins/old/media/images/flags/tj.gif b/askbot/skins/old/media/images/flags/tj.gif Binary files differnew file mode 100755 index 00000000..2fe38d4a --- /dev/null +++ b/askbot/skins/old/media/images/flags/tj.gif diff --git a/askbot/skins/old/media/images/flags/tk.gif b/askbot/skins/old/media/images/flags/tk.gif Binary files differnew file mode 100755 index 00000000..3d3a727f --- /dev/null +++ b/askbot/skins/old/media/images/flags/tk.gif diff --git a/askbot/skins/old/media/images/flags/tl.gif b/askbot/skins/old/media/images/flags/tl.gif Binary files differnew file mode 100755 index 00000000..df22d582 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tl.gif diff --git a/askbot/skins/old/media/images/flags/tm.gif b/askbot/skins/old/media/images/flags/tm.gif Binary files differnew file mode 100755 index 00000000..36d0994f --- /dev/null +++ b/askbot/skins/old/media/images/flags/tm.gif diff --git a/askbot/skins/old/media/images/flags/tn.gif b/askbot/skins/old/media/images/flags/tn.gif Binary files differnew file mode 100755 index 00000000..917d4288 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tn.gif diff --git a/askbot/skins/old/media/images/flags/to.gif b/askbot/skins/old/media/images/flags/to.gif Binary files differnew file mode 100755 index 00000000..d7ed4d11 --- /dev/null +++ b/askbot/skins/old/media/images/flags/to.gif diff --git a/askbot/skins/old/media/images/flags/tr.gif b/askbot/skins/old/media/images/flags/tr.gif Binary files differnew file mode 100755 index 00000000..e407d553 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tr.gif diff --git a/askbot/skins/old/media/images/flags/tt.gif b/askbot/skins/old/media/images/flags/tt.gif Binary files differnew file mode 100755 index 00000000..47d3b806 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tt.gif diff --git a/askbot/skins/old/media/images/flags/tv.gif b/askbot/skins/old/media/images/flags/tv.gif Binary files differnew file mode 100755 index 00000000..3c338277 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tv.gif diff --git a/askbot/skins/old/media/images/flags/tw.gif b/askbot/skins/old/media/images/flags/tw.gif Binary files differnew file mode 100755 index 00000000..cacfd9b7 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tw.gif diff --git a/askbot/skins/old/media/images/flags/tz.gif b/askbot/skins/old/media/images/flags/tz.gif Binary files differnew file mode 100755 index 00000000..82b52ca2 --- /dev/null +++ b/askbot/skins/old/media/images/flags/tz.gif diff --git a/askbot/skins/old/media/images/flags/ua.gif b/askbot/skins/old/media/images/flags/ua.gif Binary files differnew file mode 100755 index 00000000..5d6cd83f --- /dev/null +++ b/askbot/skins/old/media/images/flags/ua.gif diff --git a/askbot/skins/old/media/images/flags/ug.gif b/askbot/skins/old/media/images/flags/ug.gif Binary files differnew file mode 100755 index 00000000..58b731ad --- /dev/null +++ b/askbot/skins/old/media/images/flags/ug.gif diff --git a/askbot/skins/old/media/images/flags/um.gif b/askbot/skins/old/media/images/flags/um.gif Binary files differnew file mode 100755 index 00000000..3b4c8483 --- /dev/null +++ b/askbot/skins/old/media/images/flags/um.gif diff --git a/askbot/skins/old/media/images/flags/us.gif b/askbot/skins/old/media/images/flags/us.gif Binary files differnew file mode 100755 index 00000000..8f198f73 --- /dev/null +++ b/askbot/skins/old/media/images/flags/us.gif diff --git a/askbot/skins/old/media/images/flags/uy.gif b/askbot/skins/old/media/images/flags/uy.gif Binary files differnew file mode 100755 index 00000000..12848c74 --- /dev/null +++ b/askbot/skins/old/media/images/flags/uy.gif diff --git a/askbot/skins/old/media/images/flags/uz.gif b/askbot/skins/old/media/images/flags/uz.gif Binary files differnew file mode 100755 index 00000000..dc9daeca --- /dev/null +++ b/askbot/skins/old/media/images/flags/uz.gif diff --git a/askbot/skins/old/media/images/flags/va.gif b/askbot/skins/old/media/images/flags/va.gif Binary files differnew file mode 100755 index 00000000..2bd74468 --- /dev/null +++ b/askbot/skins/old/media/images/flags/va.gif diff --git a/askbot/skins/old/media/images/flags/vc.gif b/askbot/skins/old/media/images/flags/vc.gif Binary files differnew file mode 100755 index 00000000..48213816 --- /dev/null +++ b/askbot/skins/old/media/images/flags/vc.gif diff --git a/askbot/skins/old/media/images/flags/ve.gif b/askbot/skins/old/media/images/flags/ve.gif Binary files differnew file mode 100755 index 00000000..19ce6c14 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ve.gif diff --git a/askbot/skins/old/media/images/flags/vg.gif b/askbot/skins/old/media/images/flags/vg.gif Binary files differnew file mode 100755 index 00000000..1fc0f96e --- /dev/null +++ b/askbot/skins/old/media/images/flags/vg.gif diff --git a/askbot/skins/old/media/images/flags/vi.gif b/askbot/skins/old/media/images/flags/vi.gif Binary files differnew file mode 100755 index 00000000..66f9e746 --- /dev/null +++ b/askbot/skins/old/media/images/flags/vi.gif diff --git a/askbot/skins/old/media/images/flags/vn.gif b/askbot/skins/old/media/images/flags/vn.gif Binary files differnew file mode 100755 index 00000000..f1e20c94 --- /dev/null +++ b/askbot/skins/old/media/images/flags/vn.gif diff --git a/askbot/skins/old/media/images/flags/vu.gif b/askbot/skins/old/media/images/flags/vu.gif Binary files differnew file mode 100755 index 00000000..8a8b2b06 --- /dev/null +++ b/askbot/skins/old/media/images/flags/vu.gif diff --git a/askbot/skins/old/media/images/flags/wales.gif b/askbot/skins/old/media/images/flags/wales.gif Binary files differnew file mode 100755 index 00000000..901d1750 --- /dev/null +++ b/askbot/skins/old/media/images/flags/wales.gif diff --git a/askbot/skins/old/media/images/flags/wf.gif b/askbot/skins/old/media/images/flags/wf.gif Binary files differnew file mode 100755 index 00000000..eaa954b1 --- /dev/null +++ b/askbot/skins/old/media/images/flags/wf.gif diff --git a/askbot/skins/old/media/images/flags/ws.gif b/askbot/skins/old/media/images/flags/ws.gif Binary files differnew file mode 100755 index 00000000..a51f939e --- /dev/null +++ b/askbot/skins/old/media/images/flags/ws.gif diff --git a/askbot/skins/old/media/images/flags/ye.gif b/askbot/skins/old/media/images/flags/ye.gif Binary files differnew file mode 100755 index 00000000..7b0183d0 --- /dev/null +++ b/askbot/skins/old/media/images/flags/ye.gif diff --git a/askbot/skins/old/media/images/flags/yt.gif b/askbot/skins/old/media/images/flags/yt.gif Binary files differnew file mode 100755 index 00000000..a2267c05 --- /dev/null +++ b/askbot/skins/old/media/images/flags/yt.gif diff --git a/askbot/skins/old/media/images/flags/za.gif b/askbot/skins/old/media/images/flags/za.gif Binary files differnew file mode 100755 index 00000000..ede52589 --- /dev/null +++ b/askbot/skins/old/media/images/flags/za.gif diff --git a/askbot/skins/old/media/images/flags/zm.gif b/askbot/skins/old/media/images/flags/zm.gif Binary files differnew file mode 100755 index 00000000..b2851d2b --- /dev/null +++ b/askbot/skins/old/media/images/flags/zm.gif diff --git a/askbot/skins/old/media/images/flags/zw.gif b/askbot/skins/old/media/images/flags/zw.gif Binary files differnew file mode 100755 index 00000000..02901f62 --- /dev/null +++ b/askbot/skins/old/media/images/flags/zw.gif diff --git a/askbot/skins/old/media/images/go-up-grey.png b/askbot/skins/old/media/images/go-up-grey.png Binary files differnew file mode 100644 index 00000000..763bb799 --- /dev/null +++ b/askbot/skins/old/media/images/go-up-grey.png diff --git a/askbot/skins/old/media/images/go-up-orange.png b/askbot/skins/old/media/images/go-up-orange.png Binary files differnew file mode 100644 index 00000000..eca3579d --- /dev/null +++ b/askbot/skins/old/media/images/go-up-orange.png diff --git a/askbot/skins/old/media/images/gray-up-arrow-h18px.png b/askbot/skins/old/media/images/gray-up-arrow-h18px.png Binary files differnew file mode 100755 index 00000000..78767445 --- /dev/null +++ b/askbot/skins/old/media/images/gray-up-arrow-h18px.png diff --git a/askbot/skins/old/media/images/grippie.png b/askbot/skins/old/media/images/grippie.png Binary files differnew file mode 100755 index 00000000..6524d416 --- /dev/null +++ b/askbot/skins/old/media/images/grippie.png diff --git a/askbot/skins/old/media/images/indicator.gif b/askbot/skins/old/media/images/indicator.gif Binary files differnew file mode 100755 index 00000000..1c72ebb5 --- /dev/null +++ b/askbot/skins/old/media/images/indicator.gif diff --git a/askbot/skins/old/media/images/logo.gif b/askbot/skins/old/media/images/logo.gif Binary files differnew file mode 100644 index 00000000..03eb79f4 --- /dev/null +++ b/askbot/skins/old/media/images/logo.gif diff --git a/askbot/skins/old/media/images/logo.png b/askbot/skins/old/media/images/logo.png Binary files differnew file mode 100644 index 00000000..10559161 --- /dev/null +++ b/askbot/skins/old/media/images/logo.png diff --git a/askbot/skins/old/media/images/logo1.png b/askbot/skins/old/media/images/logo1.png Binary files differnew file mode 100755 index 00000000..d79a6271 --- /dev/null +++ b/askbot/skins/old/media/images/logo1.png diff --git a/askbot/skins/old/media/images/logo2.png b/askbot/skins/old/media/images/logo2.png Binary files differnew file mode 100755 index 00000000..bd3cccd9 --- /dev/null +++ b/askbot/skins/old/media/images/logo2.png diff --git a/askbot/skins/old/media/images/mail-envelope-empty.png b/askbot/skins/old/media/images/mail-envelope-empty.png Binary files differnew file mode 100644 index 00000000..0fde87dc --- /dev/null +++ b/askbot/skins/old/media/images/mail-envelope-empty.png diff --git a/askbot/skins/old/media/images/mail-envelope-full.png b/askbot/skins/old/media/images/mail-envelope-full.png Binary files differnew file mode 100644 index 00000000..2277e919 --- /dev/null +++ b/askbot/skins/old/media/images/mail-envelope-full.png diff --git a/askbot/skins/old/media/images/medala.gif b/askbot/skins/old/media/images/medala.gif Binary files differnew file mode 100755 index 00000000..93dd1a39 --- /dev/null +++ b/askbot/skins/old/media/images/medala.gif diff --git a/askbot/skins/old/media/images/medala_on.gif b/askbot/skins/old/media/images/medala_on.gif Binary files differnew file mode 100755 index 00000000..a18f9e85 --- /dev/null +++ b/askbot/skins/old/media/images/medala_on.gif diff --git a/askbot/skins/old/media/images/new.gif b/askbot/skins/old/media/images/new.gif Binary files differnew file mode 100755 index 00000000..8a220b53 --- /dev/null +++ b/askbot/skins/old/media/images/new.gif diff --git a/askbot/skins/old/media/images/nophoto.png b/askbot/skins/old/media/images/nophoto.png Binary files differnew file mode 100755 index 00000000..2daf0ffd --- /dev/null +++ b/askbot/skins/old/media/images/nophoto.png diff --git a/askbot/skins/old/media/images/openid.gif b/askbot/skins/old/media/images/openid.gif Binary files differnew file mode 100755 index 00000000..8540e12b --- /dev/null +++ b/askbot/skins/old/media/images/openid.gif diff --git a/askbot/skins/old/media/images/openid/aol.gif b/askbot/skins/old/media/images/openid/aol.gif Binary files differnew file mode 100755 index 00000000..decc4f12 --- /dev/null +++ b/askbot/skins/old/media/images/openid/aol.gif diff --git a/askbot/skins/old/media/images/openid/blogger.ico b/askbot/skins/old/media/images/openid/blogger.ico Binary files differnew file mode 100755 index 00000000..1b9730b0 --- /dev/null +++ b/askbot/skins/old/media/images/openid/blogger.ico diff --git a/askbot/skins/old/media/images/openid/claimid.ico b/askbot/skins/old/media/images/openid/claimid.ico Binary files differnew file mode 100755 index 00000000..2b80f491 --- /dev/null +++ b/askbot/skins/old/media/images/openid/claimid.ico diff --git a/askbot/skins/old/media/images/openid/facebook.gif b/askbot/skins/old/media/images/openid/facebook.gif Binary files differnew file mode 100755 index 00000000..b997b358 --- /dev/null +++ b/askbot/skins/old/media/images/openid/facebook.gif diff --git a/askbot/skins/old/media/images/openid/flickr.ico b/askbot/skins/old/media/images/openid/flickr.ico Binary files differnew file mode 100755 index 00000000..11f6e07f --- /dev/null +++ b/askbot/skins/old/media/images/openid/flickr.ico diff --git a/askbot/skins/old/media/images/openid/google.gif b/askbot/skins/old/media/images/openid/google.gif Binary files differnew file mode 100755 index 00000000..1b6cd07b --- /dev/null +++ b/askbot/skins/old/media/images/openid/google.gif diff --git a/askbot/skins/old/media/images/openid/livejournal.ico b/askbot/skins/old/media/images/openid/livejournal.ico Binary files differnew file mode 100755 index 00000000..f3d21ec5 --- /dev/null +++ b/askbot/skins/old/media/images/openid/livejournal.ico diff --git a/askbot/skins/old/media/images/openid/myopenid.ico b/askbot/skins/old/media/images/openid/myopenid.ico Binary files differnew file mode 100755 index 00000000..ceb06e6a --- /dev/null +++ b/askbot/skins/old/media/images/openid/myopenid.ico diff --git a/askbot/skins/old/media/images/openid/openid-inputicon.gif b/askbot/skins/old/media/images/openid/openid-inputicon.gif Binary files differnew file mode 100755 index 00000000..cde836c8 --- /dev/null +++ b/askbot/skins/old/media/images/openid/openid-inputicon.gif diff --git a/askbot/skins/old/media/images/openid/openid.gif b/askbot/skins/old/media/images/openid/openid.gif Binary files differnew file mode 100755 index 00000000..c718b0e6 --- /dev/null +++ b/askbot/skins/old/media/images/openid/openid.gif diff --git a/askbot/skins/old/media/images/openid/technorati.ico b/askbot/skins/old/media/images/openid/technorati.ico Binary files differnew file mode 100755 index 00000000..fa1083c1 --- /dev/null +++ b/askbot/skins/old/media/images/openid/technorati.ico diff --git a/askbot/skins/old/media/images/openid/twitter.png b/askbot/skins/old/media/images/openid/twitter.png Binary files differnew file mode 100755 index 00000000..9a6552d1 --- /dev/null +++ b/askbot/skins/old/media/images/openid/twitter.png diff --git a/askbot/skins/old/media/images/openid/verisign.ico b/askbot/skins/old/media/images/openid/verisign.ico Binary files differnew file mode 100755 index 00000000..3953af93 --- /dev/null +++ b/askbot/skins/old/media/images/openid/verisign.ico diff --git a/askbot/skins/old/media/images/openid/vidoop.ico b/askbot/skins/old/media/images/openid/vidoop.ico Binary files differnew file mode 100755 index 00000000..bbd9a0d5 --- /dev/null +++ b/askbot/skins/old/media/images/openid/vidoop.ico diff --git a/askbot/skins/old/media/images/openid/wordpress.ico b/askbot/skins/old/media/images/openid/wordpress.ico Binary files differnew file mode 100755 index 00000000..31b7d2c2 --- /dev/null +++ b/askbot/skins/old/media/images/openid/wordpress.ico diff --git a/askbot/skins/old/media/images/openid/yahoo.gif b/askbot/skins/old/media/images/openid/yahoo.gif Binary files differnew file mode 100755 index 00000000..0f0eb8ef --- /dev/null +++ b/askbot/skins/old/media/images/openid/yahoo.gif diff --git a/askbot/skins/old/media/images/print.png b/askbot/skins/old/media/images/print.png Binary files differnew file mode 100644 index 00000000..37bf88af --- /dev/null +++ b/askbot/skins/old/media/images/print.png diff --git a/askbot/skins/old/media/images/pw-login.gif b/askbot/skins/old/media/images/pw-login.gif Binary files differnew file mode 100644 index 00000000..f88b1bcf --- /dev/null +++ b/askbot/skins/old/media/images/pw-login.gif diff --git a/askbot/skins/old/media/images/quest-bg.gif b/askbot/skins/old/media/images/quest-bg.gif Binary files differnew file mode 100755 index 00000000..b7540238 --- /dev/null +++ b/askbot/skins/old/media/images/quest-bg.gif diff --git a/askbot/skins/old/media/images/sprite.png b/askbot/skins/old/media/images/sprite.png Binary files differnew file mode 100644 index 00000000..1a0fbc78 --- /dev/null +++ b/askbot/skins/old/media/images/sprite.png diff --git a/askbot/skins/old/media/images/tag-left.png b/askbot/skins/old/media/images/tag-left.png Binary files differnew file mode 100644 index 00000000..5a9d8a0d --- /dev/null +++ b/askbot/skins/old/media/images/tag-left.png diff --git a/askbot/skins/old/media/images/tag-right.png b/askbot/skins/old/media/images/tag-right.png Binary files differnew file mode 100644 index 00000000..871664c3 --- /dev/null +++ b/askbot/skins/old/media/images/tag-right.png diff --git a/askbot/skins/old/media/images/vote-accepted-on.png b/askbot/skins/old/media/images/vote-accepted-on.png Binary files differnew file mode 100755 index 00000000..2026f3bc --- /dev/null +++ b/askbot/skins/old/media/images/vote-accepted-on.png diff --git a/askbot/skins/old/media/images/vote-accepted.png b/askbot/skins/old/media/images/vote-accepted.png Binary files differnew file mode 100755 index 00000000..ecd18551 --- /dev/null +++ b/askbot/skins/old/media/images/vote-accepted.png diff --git a/askbot/skins/old/media/images/vote-arrow-down-on.png b/askbot/skins/old/media/images/vote-arrow-down-on.png Binary files differnew file mode 100755 index 00000000..048dbb44 --- /dev/null +++ b/askbot/skins/old/media/images/vote-arrow-down-on.png diff --git a/askbot/skins/old/media/images/vote-arrow-down.png b/askbot/skins/old/media/images/vote-arrow-down.png Binary files differnew file mode 100755 index 00000000..e4fdec0a --- /dev/null +++ b/askbot/skins/old/media/images/vote-arrow-down.png diff --git a/askbot/skins/old/media/images/vote-arrow-up-on.png b/askbot/skins/old/media/images/vote-arrow-up-on.png Binary files differnew file mode 100755 index 00000000..56ad0c25 --- /dev/null +++ b/askbot/skins/old/media/images/vote-arrow-up-on.png diff --git a/askbot/skins/old/media/images/vote-arrow-up.png b/askbot/skins/old/media/images/vote-arrow-up.png Binary files differnew file mode 100755 index 00000000..6e9a51c7 --- /dev/null +++ b/askbot/skins/old/media/images/vote-arrow-up.png diff --git a/askbot/skins/old/media/images/vote-favorite-off.png b/askbot/skins/old/media/images/vote-favorite-off.png Binary files differnew file mode 100755 index 00000000..c1bef074 --- /dev/null +++ b/askbot/skins/old/media/images/vote-favorite-off.png diff --git a/askbot/skins/old/media/images/vote-favorite-on.png b/askbot/skins/old/media/images/vote-favorite-on.png Binary files differnew file mode 100755 index 00000000..1f9c14ab --- /dev/null +++ b/askbot/skins/old/media/images/vote-favorite-on.png diff --git a/askbot/skins/old/media/images/wiki.png b/askbot/skins/old/media/images/wiki.png Binary files differnew file mode 100644 index 00000000..06d487f3 --- /dev/null +++ b/askbot/skins/old/media/images/wiki.png diff --git a/askbot/skins/old/media/jquery-openid/images/aol.gif b/askbot/skins/old/media/jquery-openid/images/aol.gif Binary files differnew file mode 100755 index 00000000..24d1e152 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/aol.gif diff --git a/askbot/skins/old/media/jquery-openid/images/blogger-1.png b/askbot/skins/old/media/jquery-openid/images/blogger-1.png Binary files differnew file mode 100755 index 00000000..8b360ea5 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/blogger-1.png diff --git a/askbot/skins/old/media/jquery-openid/images/blogger.ico b/askbot/skins/old/media/jquery-openid/images/blogger.ico Binary files differnew file mode 100755 index 00000000..1b9730b0 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/blogger.ico diff --git a/askbot/skins/old/media/jquery-openid/images/claimid-0.png b/askbot/skins/old/media/jquery-openid/images/claimid-0.png Binary files differnew file mode 100755 index 00000000..4a0ea1b3 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/claimid-0.png diff --git a/askbot/skins/old/media/jquery-openid/images/claimid.ico b/askbot/skins/old/media/jquery-openid/images/claimid.ico Binary files differnew file mode 100755 index 00000000..2b80f491 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/claimid.ico diff --git a/askbot/skins/old/media/jquery-openid/images/facebook.gif b/askbot/skins/old/media/jquery-openid/images/facebook.gif Binary files differnew file mode 100755 index 00000000..c5586455 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/facebook.gif diff --git a/askbot/skins/old/media/jquery-openid/images/flickr.ico b/askbot/skins/old/media/jquery-openid/images/flickr.ico Binary files differnew file mode 100755 index 00000000..11f6e07f --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/flickr.ico diff --git a/askbot/skins/old/media/jquery-openid/images/flickr.png b/askbot/skins/old/media/jquery-openid/images/flickr.png Binary files differnew file mode 100755 index 00000000..142405a6 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/flickr.png diff --git a/askbot/skins/old/media/jquery-openid/images/google.gif b/askbot/skins/old/media/jquery-openid/images/google.gif Binary files differnew file mode 100755 index 00000000..65395365 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/google.gif diff --git a/askbot/skins/old/media/jquery-openid/images/identica.png b/askbot/skins/old/media/jquery-openid/images/identica.png Binary files differnew file mode 100644 index 00000000..2b607db1 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/identica.png diff --git a/askbot/skins/old/media/jquery-openid/images/linkedin.gif b/askbot/skins/old/media/jquery-openid/images/linkedin.gif Binary files differnew file mode 100644 index 00000000..36e049ac --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/linkedin.gif diff --git a/askbot/skins/old/media/jquery-openid/images/livejournal-1.png b/askbot/skins/old/media/jquery-openid/images/livejournal-1.png Binary files differnew file mode 100755 index 00000000..e6436081 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/livejournal-1.png diff --git a/askbot/skins/old/media/jquery-openid/images/livejournal.ico b/askbot/skins/old/media/jquery-openid/images/livejournal.ico Binary files differnew file mode 100755 index 00000000..f3d21ec5 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/livejournal.ico diff --git a/askbot/skins/old/media/jquery-openid/images/myopenid-2.png b/askbot/skins/old/media/jquery-openid/images/myopenid-2.png Binary files differnew file mode 100755 index 00000000..f64fb8e8 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/myopenid-2.png diff --git a/askbot/skins/old/media/jquery-openid/images/myopenid.ico b/askbot/skins/old/media/jquery-openid/images/myopenid.ico Binary files differnew file mode 100755 index 00000000..ceb06e6a --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/myopenid.ico diff --git a/askbot/skins/old/media/jquery-openid/images/openid-inputicon.gif b/askbot/skins/old/media/jquery-openid/images/openid-inputicon.gif Binary files differnew file mode 100755 index 00000000..cde836c8 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/openid-inputicon.gif diff --git a/askbot/skins/old/media/jquery-openid/images/openid.gif b/askbot/skins/old/media/jquery-openid/images/openid.gif Binary files differnew file mode 100755 index 00000000..19eb7c6f --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/openid.gif diff --git a/askbot/skins/old/media/jquery-openid/images/openidico.png b/askbot/skins/old/media/jquery-openid/images/openidico.png Binary files differnew file mode 100755 index 00000000..ab622669 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/openidico.png diff --git a/askbot/skins/old/media/jquery-openid/images/openidico16.png b/askbot/skins/old/media/jquery-openid/images/openidico16.png Binary files differnew file mode 100755 index 00000000..ad718ac5 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/openidico16.png diff --git a/askbot/skins/old/media/jquery-openid/images/technorati-1.png b/askbot/skins/old/media/jquery-openid/images/technorati-1.png Binary files differnew file mode 100755 index 00000000..f7195240 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/technorati-1.png diff --git a/askbot/skins/old/media/jquery-openid/images/technorati.ico b/askbot/skins/old/media/jquery-openid/images/technorati.ico Binary files differnew file mode 100755 index 00000000..fa1083c1 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/technorati.ico diff --git a/askbot/skins/old/media/jquery-openid/images/twitter.gif b/askbot/skins/old/media/jquery-openid/images/twitter.gif Binary files differnew file mode 100644 index 00000000..173cace1 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/twitter.gif diff --git a/askbot/skins/old/media/jquery-openid/images/verisign-2.png b/askbot/skins/old/media/jquery-openid/images/verisign-2.png Binary files differnew file mode 100755 index 00000000..c1467008 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/verisign-2.png diff --git a/askbot/skins/old/media/jquery-openid/images/verisign.ico b/askbot/skins/old/media/jquery-openid/images/verisign.ico Binary files differnew file mode 100755 index 00000000..3953af93 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/verisign.ico diff --git a/askbot/skins/old/media/jquery-openid/images/vidoop.ico b/askbot/skins/old/media/jquery-openid/images/vidoop.ico Binary files differnew file mode 100755 index 00000000..bbd9a0d5 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/vidoop.ico diff --git a/askbot/skins/old/media/jquery-openid/images/vidoop.png b/askbot/skins/old/media/jquery-openid/images/vidoop.png Binary files differnew file mode 100755 index 00000000..032c9e98 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/vidoop.png diff --git a/askbot/skins/old/media/jquery-openid/images/wordpress.ico b/askbot/skins/old/media/jquery-openid/images/wordpress.ico Binary files differnew file mode 100755 index 00000000..31b7d2c2 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/wordpress.ico diff --git a/askbot/skins/old/media/jquery-openid/images/wordpress.png b/askbot/skins/old/media/jquery-openid/images/wordpress.png Binary files differnew file mode 100755 index 00000000..ee29f0cf --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/wordpress.png diff --git a/askbot/skins/old/media/jquery-openid/images/yahoo.gif b/askbot/skins/old/media/jquery-openid/images/yahoo.gif Binary files differnew file mode 100755 index 00000000..614910a9 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/images/yahoo.gif diff --git a/askbot/skins/old/media/jquery-openid/jquery.openid.js b/askbot/skins/old/media/jquery-openid/jquery.openid.js new file mode 100644 index 00000000..7ba9adce --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/jquery.openid.js @@ -0,0 +1,447 @@ +$.fn.authenticator = function() { + var signin_page = $(this); + var signin_form = $('#signin-form'); + var openid_login_token_input = $('input[name=openid_login_token]'); + var openid_login_token_input_fields = $('#openid-fs'); + var provider_name_input = $('input[name=login_provider_name]'); + var email_input_fields = $('#email-input-fs'); + var account_recovery_heading = $('#account-recovery-heading'); + var account_recovery_hint = $('#account-recovery-form>.hint'); + var account_recovery_link = $('#account-recovery-form>.hint>span.link'); + var account_recovery_text_span = $('#account-recovery-form>.hint>span.text'); + var password_input_fields = $('#password-fs'); + var existing_login_methods_div = $('#existing-login-methods'); + var openid_submit_button = $('input[name=openid_login_with_extra_token]'); + var existing_login_methods = {}; + + var account_recovery_question_text = account_recovery_heading.html(); + var account_recovery_prompt_text = account_recovery_text_span.html(); + + var setup_click_handler = function(elements, handler_function){ + elements.unbind('click').click(handler_function); + }; + + var setup_enter_key_handler = function(elements, handler_function){ + elements.each( + function(index, element){ + $(element).unbind('keypress').keypress( + function(e){ + if ((e.which && e.which == 13)||(e.keyCode && e.keyCode == 13)){ + if (handler_function){ + return handler_function(); + } + else { + element.click(); + return false; + } + } + } + ); + } + ); + }; + + var setup_event_handlers = function(elements, handler_function){ + setup_click_handler(elements, handler_function); + setup_enter_key_handler(elements); + }; + + var get_provider_name = function(row_el){ + var row = $(row_el); + var name_span = row.find('.ab-provider-name'); + return provider_name = $.trim(name_span.html()); + }; + + var read_existing_login_methods = function(){ + $('.ab-provider-row').each( + function(i, provider_row){ + var provider_name = get_provider_name(provider_row); + existing_login_methods[provider_name] = true; + } + ); + }; + + var setup_login_method_deleters = function(){ + $('.ab-provider-row').each( + function(i, provider_row){ + var provider_name = get_provider_name(provider_row); + var remove_button = $( + provider_row + ).find('button'); + remove_button.click( + function(){ + var message = $.i18n._( + 'Are you sure you want to remove ' + + 'your {provider} login?' + ).replace( + '{provider}', + provider_name + ); + if (confirm(message)){ + $.ajax({ + type: 'POST', + url: authUrl + 'delete_login_method/',//url!!! + data: {provider_name: provider_name}, + success: function(data, text_status, xhr){ + $(provider_row).remove(); + delete existing_login_methods[provider_name]; + provider_count -=1; + if (provider_count < 0){ + provider_count === 0; + } + if (provider_count === 0){ + $('#ab-existing-login-methods').remove(); + $('#ab-show-login-methods').remove(); + $('h1').html( + $.i18n._("Please add one or more login methods.") + ); + $('#login-intro').html( + $.i18n._("You don\'t have a method to log in right now, please add one or more by clicking any of the icons below.") + ); + existing_login_methods = null; + } + } + }); + } + } + ); + } + ); + } + + var submit_login_with_password = function(){ + var username = $('#id_username'); + var password = $('#id_password'); + + if (username.val().length < 1){ + username.focus(); + return false; + } + if (password.val().length < 1){ + password.focus(); + return false; + } + return true; + }; + + var submit_change_password = function(){ + var newpass = $('#id_new_password'); + var newpass_retyped = $('#id_new_password_retyped'); + if (newpass.val().length < 1){ + newpass.focus(); + return false + } + if (newpass_retyped.val().length < 1){ + newpass_retyped.focus(); + return false; + } + if (newpass.val() !== newpass_retyped.val()){ + newpass_retyped.after( + '<span class="error">' + + $.i18n._('passwords do not match') + + '</span>' + ); + newpass.val('').focus(); + newpass_retyped.val(''); + return false; + } + return true; + }; + + //validator, may be extended to check url for openid + var submit_with_extra_openid_token = function() { + if (openid_login_token_input.val().length < 1) { + openid_login_token_input.focus(); + return false; + } + return true; + }; + + var insert_login_list_enabler = function(){ + var enabler = $('#login-list-enabler'); + if (enabler.is('p#login-list-enabler')){ + enabler.show(); + } + else { + enabler = $( + '<p id="login-list-enabler"><a href="#">' + + $.i18n._('Show/change current login methods') + + '</a></p>'); + setup_event_handlers( + enabler, + function(){ + if (askbot['settings']['signin_always_show_local_login'] === false){ + password_input_fields.hide(); + } + openid_login_token_input_fields.hide(); + enabler.hide(); + existing_login_methods_div.show(); + } + ); + existing_login_methods_div.after(enabler); + } + }; + + var reset_password_input_fields = function(){ + if (userIsAuthenticated){ + $('#id_new_password').val(''); + $('#id_new_password_retyped').val(''); + } + else { + $('#id_username').val(''); + $('#id_password').val(''); + } + }; + + var reset_form = function(){ + openid_login_token_input_fields.hide(); + if (askbot['settings']['signin_always_show_local_login'] === false){ + password_input_fields.hide(); + } + reset_password_input_fields(); + $('.error').remove(); + if (userIsAuthenticated === false){ + email_input_fields.hide(); + account_recovery_heading.hide(); + account_recovery_link.show(); + account_recovery_hint.show(); + $('#account-recovery-form>p.hint').css('margin-top','10px'); + account_recovery_text_span.html(account_recovery_question_text).show(); + } + else { + if (existing_login_methods !== null){ + existing_login_methods_div.hide(); + insert_login_list_enabler(); + } + } + }; + + var set_provider_name = function(element){ + var provider_name = element.attr('name'); + provider_name_input.val(provider_name); + }; + + var show_openid_input_fields = function(provider_name){ + reset_form(); + var token_name = extra_token_name[provider_name] + if (userIsAuthenticated){ + var heading_text = $.i18n._( + 'Please enter your {token_name}, then proceed' + ); + $('#openid-heading').html( + heading_text.replace('{token_name}', token_name) + ); + var button_text = $.i18n._('Connect your {provider_name} account to {site}'); + button_text = button_text.replace( + '{provider_name}', provider_name + ).replace( + '{site}', siteName + ); + openid_submit_button.val(button_text); + } + else { + $('#openid-heading>span').html(token_name); + } + openid_login_token_input_fields.show(); + openid_login_token_input.focus(); + }; + + var start_simple_login = function() { + //$('#openid_form .providers td').removeClass('highlight'); + //$li.addClass('highlight'); + set_provider_name($(this)); + signin_form.submit(); + return true; + }; + + var start_login_with_extra_openid_token = function() { + show_openid_input_fields($(this).attr('name')); + set_provider_name($(this)); + + setup_enter_key_handler( + openid_login_token_input, + function(){ + openid_submit_button.click(); + return false; + } + ); + + setup_event_handlers( + openid_submit_button, + function(){ + signin_form.unbind( + 'submit' + ).submit( + submit_with_extra_openid_token + ); + } + ); + return false; + }; + + var start_facebook_login = function(){ + set_provider_name($(this)); + if (typeof FB != 'undefined'){ + FB.getLoginStatus(function(response){ + if (response.authResponse){ + signin_form.submit(); + } + else { + if (FB.getSession()){ + signin_form.submit(); + } + FB.login(); + } + }); + } + return false; + }; + + var start_password_login_or_change = function(){ + //called upon clicking on one of the password login buttons + reset_form(); + set_provider_name($(this)); + var provider_name = $(this).attr('name'); + return setup_password_login_or_change(provider_name); + }; + + var init_always_visible_password_login = function(){ + reset_form(); + //will break wordpress and ldap + provider_name_input.val('local'); + setup_password_login_or_change('local'); + }; + + var setup_password_login_or_change = function(provider_name){ + var token_name = extra_token_name[provider_name] + var password_action_input = $('input[name=password_action]'); + if (userIsAuthenticated === true){ + var password_button = $('input[name=change_password]'); + var submit_action = submit_change_password; + if (existing_login_methods && existing_login_methods[provider_name]){ + var change_pw_heading = 'Change your {provider} password'; + var password_heading_text = $.i18n._(change_pw_heading); + var password_button_text = $.i18n._('Change password'); + } + else { + var create_pw_heading = 'Create a password for {provider}'; + var password_heading_text = $.i18n._(create_pw_heading); + var password_button_text = $.i18n._('Create password'); + } + if (provider_name === 'local'){ + var provider_cleaned_name = siteName; + } + else { + var provider_cleaned_name = provider_name; + } + $('#password-heading').html( + password_heading_text.replace('{provider}', provider_cleaned_name) + ) + password_button.val(password_button_text); + password_action_input.val('change_password'); + var focus_input = $('#id_new_password'); + var submittable_input = $('#id_new_password_retyped'); + } + else{ + $('#password-heading>span').html(token_name); + var password_button = $('input[name=login_with_password]'); + var submit_action = submit_login_with_password; + var create_pw_link = $('a.create-password-account') + if (create_pw_link.length > 0){ + create_pw_link.html($.i18n._('Create a password-protected account')); + var url = create_pw_link.attr('href'); + if (url.indexOf('?') !== -1){ + url = url.replace(/\?.*$/,'?login_provider=' + provider_name); + } + else{ + url += '?login_provider=' + provider_name; + } + create_pw_link.attr('href', url); + } + password_action_input.val('login'); + var focus_input = $('#id_username'); + var submittable_input = $('#id_password'); + } + password_input_fields.show(); + focus_input.focus(); + + var submit_password_login = function(){ + signin_form.unbind('submit').submit(submit_action); + }; + + setup_enter_key_handler( + submittable_input, + function() { + password_button.click(); + return false; + } + ); + setup_event_handlers(password_button, submit_password_login); + return false; + }; + + var start_account_recovery = function(){ + reset_form(); + account_recovery_hint.hide(); + account_recovery_heading.css('margin-bottom', '0px'); + account_recovery_heading.html(account_recovery_prompt_text).show(); + email_input_fields.show(); + $('#id_email').focus(); + }; + + var clear_password_fields = function(){ + $('#id_password').val(''); + $('#id_new_password').val(''); + $('#id_new_password_retyped').val(''); + }; + + var setup_default_handlers = function(){ + setup_event_handlers( + signin_page.find('input.openid-direct'), + start_simple_login + ); + + setup_event_handlers( + signin_page.find('input.openid-username'), + start_login_with_extra_openid_token + ); + + setup_event_handlers( + signin_page.find('input.openid-generic'), + start_login_with_extra_openid_token + ); + + setup_event_handlers( + signin_page.find('input.facebook'), + start_facebook_login + ); + + setup_event_handlers( + signin_page.find('input.oauth'), + start_simple_login + ); + + setup_event_handlers( + signin_page.find('input.password'), + start_password_login_or_change + ); + setup_event_handlers( + signin_page.find('input.wordpress_site'), + start_password_login_or_change + ); + + setup_event_handlers(account_recovery_link, start_account_recovery); + + if (userIsAuthenticated){ + read_existing_login_methods(); + setup_login_method_deleters(); + } + }; + + setup_default_handlers(); + if (askbot['settings']['signin_always_show_local_login'] === true){ + init_always_visible_password_login(); + } + clear_password_fields(); + return this; +}; diff --git a/askbot/skins/old/media/jquery-openid/openid.css b/askbot/skins/old/media/jquery-openid/openid.css new file mode 100644 index 00000000..da541e45 --- /dev/null +++ b/askbot/skins/old/media/jquery-openid/openid.css @@ -0,0 +1,38 @@ +div#login-icons {margin:10px 0 0 0;padding:0} +ul.login-icons {width: 450px; margin:0;padding:0;text-align:left; list-style-type:none; display:block;} +ul.login-icons li {display:inline;} +ul.large input {height: 40px; width: 90px;border:1px solid #ccc;margin:0 5px 5px 0;} +.openid-signin h2 {margin-top:15px;} +.openid-signin h2#account-recovery-heading {margin-bottom:2px;} +#account-recovery-form p.hint a {color:blue; text-decoration: underline;} +.openid-signin fieldset { border-style:none;margin:0;padding:0;} +.openid-signin p {margin:0;padding:0}; +.openid-signin p.hint {color: #555;} +.openid-signin #password-fs label {width:100px;margin-top:5px;text-align:left;} +.openid-signin #password-fs .hint {margin-bottom:5px} +#password-fs a {padding-left:5px;} +/*#signin-form #account-recovery-form input {cursor:pointer;} +#signin-form #account-recovery-form input.text {cursor:default;}*/ + +table.login { text-align: right;} + +.openid-signin .submit-b { + cursor: pointer; /*letter-spacing:1px;*/ + margin: 0 0 2px 0; + vertical-align: middle; +} + +.openid-signin .highlight { -moz-border-radius:4px; -webkit-border-radius:4px; background-color: #FD6} + +ul.providers { + display: block; +} + +.openid-signin th { + color: #555; + font-weight: normal; +} + +.openid-signin .ab-provider-name { + font-weight: bold; +} diff --git a/askbot/skins/old/media/js/autocompleter.js b/askbot/skins/old/media/js/autocompleter.js new file mode 100644 index 00000000..a7c54315 --- /dev/null +++ b/askbot/skins/old/media/js/autocompleter.js @@ -0,0 +1,766 @@ +/** + * AutoCompleter Object, refactored closure style from + * jQuery autocomplete plugin + * @param {Object=} options Settings + * @constructor + */ +var AutoCompleter = function(options) { + + /** + * Default options for autocomplete plugin + */ + var defaults = { + autocompleteMultiple: true, + multipleSeparator: ' ',//a single character + inputClass: 'acInput', + loadingClass: 'acLoading', + resultsClass: 'acResults', + selectClass: 'acSelect', + queryParamName: 'q', + limitParamName: 'limit', + extraParams: {}, + lineSeparator: '\n', + cellSeparator: '|', + minChars: 2, + maxItemsToShow: 10, + delay: 400, + useCache: true, + maxCacheLength: 10, + matchSubset: true, + matchCase: false, + matchInside: true, + mustMatch: false, + preloadData: false, + selectFirst: false, + stopCharRegex: /\s+/, + selectOnly: false, + formatItem: null, // TBD + onItemSelect: false, + autoFill: false, + filterResults: true, + sortResults: true, + sortFunction: false, + onNoMatch: false + }; + + /** + * Options dictionary + * @type Object + * @private + */ + this.options = $.extend({}, defaults, options); + + /** + * Cached data + * @type Object + * @private + */ + this.cacheData_ = {}; + + /** + * Number of cached data items + * @type number + * @private + */ + this.cacheLength_ = 0; + + /** + * Class name to mark selected item + * @type string + * @private + */ + this.selectClass_ = 'jquery-autocomplete-selected-item'; + + /** + * Handler to activation timeout + * @type ?number + * @private + */ + this.keyTimeout_ = null; + + /** + * Last key pressed in the input field (store for behavior) + * @type ?number + * @private + */ + this.lastKeyPressed_ = null; + + /** + * Last value processed by the autocompleter + * @type ?string + * @private + */ + this.lastProcessedValue_ = null; + + /** + * Last value selected by the user + * @type ?string + * @private + */ + this.lastSelectedValue_ = null; + + /** + * Is this autocompleter active? + * @type boolean + * @private + */ + this.active_ = false; + + /** + * Is it OK to finish on blur? + * @type boolean + * @private + */ + this.finishOnBlur_ = true; + + this.options.minChars = parseInt(this.options.minChars, 10); + if (isNaN(this.options.minChars) || this.options.minChars < 1) { + this.options.minChars = 2; + } + + this.options.maxItemsToShow = parseInt(this.options.maxItemsToShow, 10); + if (isNaN(this.options.maxItemsToShow) || this.options.maxItemsToShow < 1) { + this.options.maxItemsToShow = 10; + } + + this.options.maxCacheLength = parseInt(this.options.maxCacheLength, 10); + if (isNaN(this.options.maxCacheLength) || this.options.maxCacheLength < 1) { + this.options.maxCacheLength = 10; + } + + if (this.options['preloadData'] === true){ + this.fetchRemoteData('', function(){}); + } +}; +inherits(AutoCompleter, WrappedElement); + +AutoCompleter.prototype.decorate = function(element){ + + /** + * Init DOM elements repository + */ + this._element = element; + + /** + * Switch off the native autocomplete + */ + this._element.attr('autocomplete', 'off'); + + /** + * Create DOM element to hold results + */ + this._results = $('<div></div>').hide(); + if (this.options.resultsClass) { + this._results.addClass(this.options.resultsClass); + } + this._results.css({ + position: 'absolute' + }); + $('body').append(this._results); + + this.setEventHandlers(); +}; + +AutoCompleter.prototype.setEventHandlers = function(){ + /** + * Shortcut to self + */ + var self = this; + + /** + * Attach keyboard monitoring to $elem + */ + self._element.keydown(function(e) { + self.lastKeyPressed_ = e.keyCode; + switch(self.lastKeyPressed_) { + + case 38: // up + e.preventDefault(); + if (self.active_) { + self.focusPrev(); + } else { + self.activate(); + } + return false; + break; + + case 40: // down + e.preventDefault(); + if (self.active_) { + self.focusNext(); + } else { + self.activate(); + } + return false; + break; + + case 9: // tab + case 13: // return + if (self.active_) { + e.preventDefault(); + self.selectCurrent(); + return false; + } + break; + + case 27: // escape + if (self.active_) { + e.preventDefault(); + self.finish(); + return false; + } + break; + + default: + self.activate(); + + } + }); + self._element.blur(function() { + if (self.finishOnBlur_) { + setTimeout(function() { self.finish(); }, 200); + } + }); +}; + +AutoCompleter.prototype.position = function() { + var offset = this._element.offset(); + this._results.css({ + top: offset.top + this._element.outerHeight(), + left: offset.left + }); +}; + +AutoCompleter.prototype.cacheRead = function(filter) { + var filterLength, searchLength, search, maxPos, pos; + if (this.options.useCache) { + filter = String(filter); + filterLength = filter.length; + if (this.options.matchSubset) { + searchLength = 1; + } else { + searchLength = filterLength; + } + while (searchLength <= filterLength) { + if (this.options.matchInside) { + maxPos = filterLength - searchLength; + } else { + maxPos = 0; + } + pos = 0; + while (pos <= maxPos) { + search = filter.substr(0, searchLength); + if (this.cacheData_[search] !== undefined) { + return this.cacheData_[search]; + } + pos++; + } + searchLength++; + } + } + return false; +}; + +AutoCompleter.prototype.cacheWrite = function(filter, data) { + if (this.options.useCache) { + if (this.cacheLength_ >= this.options.maxCacheLength) { + this.cacheFlush(); + } + filter = String(filter); + if (this.cacheData_[filter] !== undefined) { + this.cacheLength_++; + } + return this.cacheData_[filter] = data; + } + return false; +}; + +AutoCompleter.prototype.cacheFlush = function() { + this.cacheData_ = {}; + this.cacheLength_ = 0; +}; + +AutoCompleter.prototype.callHook = function(hook, data) { + var f = this.options[hook]; + if (f && $.isFunction(f)) { + return f(data, this); + } + return false; +}; + +AutoCompleter.prototype.activate = function() { + var self = this; + var activateNow = function() { + self.activateNow(); + }; + var delay = parseInt(this.options.delay, 10); + if (isNaN(delay) || delay <= 0) { + delay = 250; + } + if (this.keyTimeout_) { + clearTimeout(this.keyTimeout_); + } + this.keyTimeout_ = setTimeout(activateNow, delay); +}; + +AutoCompleter.prototype.activateNow = function() { + var value = this.getValue(); + if (value !== this.lastProcessedValue_ && value !== this.lastSelectedValue_) { + if (value.length >= this.options.minChars) { + this.active_ = true; + this.lastProcessedValue_ = value; + this.fetchData(value); + } + } +}; + +AutoCompleter.prototype.fetchData = function(value) { + if (this.options.data) { + this.filterAndShowResults(this.options.data, value); + } else { + var self = this; + this.fetchRemoteData(value, function(remoteData) { + self.filterAndShowResults(remoteData, value); + }); + } +}; + +AutoCompleter.prototype.fetchRemoteData = function(filter, callback) { + var data = this.cacheRead(filter); + if (data) { + callback(data); + } else { + var self = this; + if (this._element){ + this._element.addClass(this.options.loadingClass); + } + var ajaxCallback = function(data) { + var parsed = false; + if (data !== false) { + parsed = self.parseRemoteData(data); + self.options.data = parsed;//cache data forever - E.F. + self.cacheWrite(filter, parsed); + } + if (self._element){ + self._element.removeClass(self.options.loadingClass); + } + callback(parsed); + }; + $.ajax({ + url: this.makeUrl(filter), + success: ajaxCallback, + error: function() { + ajaxCallback(false); + } + }); + } +}; + +AutoCompleter.prototype.setOption = function(name, value){ + this.options[name] = value; +}; + +AutoCompleter.prototype.setExtraParam = function(name, value) { + var index = $.trim(String(name)); + if (index) { + if (!this.options.extraParams) { + this.options.extraParams = {}; + } + if (this.options.extraParams[index] !== value) { + this.options.extraParams[index] = value; + this.cacheFlush(); + } + } +}; + +AutoCompleter.prototype.makeUrl = function(param) { + var self = this; + var url = this.options.url; + var params = $.extend({}, this.options.extraParams); + // If options.queryParamName === false, append query to url + // instead of using a GET parameter + if (this.options.queryParamName === false) { + url += encodeURIComponent(param); + } else { + params[this.options.queryParamName] = param; + } + + if (this.options.limitParamName && this.options.maxItemsToShow) { + params[this.options.limitParamName] = this.options.maxItemsToShow; + } + + var urlAppend = []; + $.each(params, function(index, value) { + urlAppend.push(self.makeUrlParam(index, value)); + }); + if (urlAppend.length) { + url += url.indexOf('?') == -1 ? '?' : '&'; + url += urlAppend.join('&'); + } + return url; +}; + +AutoCompleter.prototype.makeUrlParam = function(name, value) { + return String(name) + '=' + encodeURIComponent(value); +}; + +/** + * Sanitize CR and LF, then split into lines + */ +AutoCompleter.prototype.splitText = function(text) { + return String(text).replace(/(\r\n|\r|\n)/g, '\n').split(this.options.lineSeparator); +}; + +AutoCompleter.prototype.parseRemoteData = function(remoteData) { + var value, lines, i, j, data; + var results = []; + var lines = this.splitText(remoteData); + for (i = 0; i < lines.length; i++) { + var line = lines[i].split(this.options.cellSeparator); + data = []; + for (j = 0; j < line.length; j++) { + data.push(unescape(line[j])); + } + value = data.shift(); + results.push({ value: unescape(value), data: data }); + } + return results; +}; + +AutoCompleter.prototype.filterAndShowResults = function(results, filter) { + this.showResults(this.filterResults(results, filter), filter); +}; + +AutoCompleter.prototype.filterResults = function(results, filter) { + + var filtered = []; + var value, data, i, result, type, include; + var regex, pattern, testValue; + + for (i = 0; i < results.length; i++) { + result = results[i]; + type = typeof result; + if (type === 'string') { + value = result; + data = {}; + } else if ($.isArray(result)) { + value = result[0]; + data = result.slice(1); + } else if (type === 'object') { + value = result.value; + data = result.data; + } + value = String(value); + if (value > '') { + if (typeof data !== 'object') { + data = {}; + } + if (this.options.filterResults) { + pattern = String(filter); + testValue = String(value); + if (!this.options.matchCase) { + pattern = pattern.toLowerCase(); + testValue = testValue.toLowerCase(); + } + include = testValue.indexOf(pattern); + if (this.options.matchInside) { + include = include > -1; + } else { + include = include === 0; + } + } else { + include = true; + } + if (include) { + filtered.push({ value: value, data: data }); + } + } + } + + if (this.options.sortResults) { + filtered = this.sortResults(filtered, filter); + } + + if (this.options.maxItemsToShow > 0 && this.options.maxItemsToShow < filtered.length) { + filtered.length = this.options.maxItemsToShow; + } + + return filtered; + +}; + +AutoCompleter.prototype.sortResults = function(results, filter) { + var self = this; + var sortFunction = this.options.sortFunction; + if (!$.isFunction(sortFunction)) { + sortFunction = function(a, b, f) { + return self.sortValueAlpha(a, b, f); + }; + } + results.sort(function(a, b) { + return sortFunction(a, b, filter); + }); + return results; +}; + +AutoCompleter.prototype.sortValueAlpha = function(a, b, filter) { + a = String(a.value); + b = String(b.value); + if (!this.options.matchCase) { + a = a.toLowerCase(); + b = b.toLowerCase(); + } + if (a > b) { + return 1; + } + if (a < b) { + return -1; + } + return 0; +}; + +AutoCompleter.prototype.showResults = function(results, filter) { + var self = this; + var $ul = $('<ul></ul>'); + var i, result, $li, extraWidth, first = false, $first = false; + var numResults = results.length; + for (i = 0; i < numResults; i++) { + result = results[i]; + $li = $('<li>' + this.showResult(result.value, result.data) + '</li>'); + $li.data('value', result.value); + $li.data('data', result.data); + $li.click(function() { + var $this = $(this); + self.selectItem($this); + }).mousedown(function() { + self.finishOnBlur_ = false; + }).mouseup(function() { + self.finishOnBlur_ = true; + }); + $ul.append($li); + if (first === false) { + first = String(result.value); + $first = $li; + $li.addClass(this.options.firstItemClass); + } + if (i == numResults - 1) { + $li.addClass(this.options.lastItemClass); + } + } + + // Alway recalculate position before showing since window size or + // input element location may have changed. This fixes #14 + this.position(); + + this._results.html($ul).show(); + extraWidth = this._results.outerWidth() - this._results.width(); + this._results.width(this._element.outerWidth() - extraWidth); + $('li', this._results).hover( + function() { self.focusItem(this); }, + function() { /* void */ } + ); + if (this.autoFill(first, filter)) { + this.focusItem($first); + } +}; + +AutoCompleter.prototype.showResult = function(value, data) { + if ($.isFunction(this.options.showResult)) { + return this.options.showResult(value, data); + } else { + return value; + } +}; + +AutoCompleter.prototype.autoFill = function(value, filter) { + var lcValue, lcFilter, valueLength, filterLength; + if (this.options.autoFill && this.lastKeyPressed_ != 8) { + lcValue = String(value).toLowerCase(); + lcFilter = String(filter).toLowerCase(); + valueLength = value.length; + filterLength = filter.length; + if (lcValue.substr(0, filterLength) === lcFilter) { + this._element.val(value); + this.selectRange(filterLength, valueLength); + return true; + } + } + return false; +}; + +AutoCompleter.prototype.focusNext = function() { + this.focusMove(+1); +}; + +AutoCompleter.prototype.focusPrev = function() { + this.focusMove(-1); +}; + +AutoCompleter.prototype.focusMove = function(modifier) { + var i, $items = $('li', this._results); + modifier = parseInt(modifier, 10); + for (var i = 0; i < $items.length; i++) { + if ($($items[i]).hasClass(this.selectClass_)) { + this.focusItem(i + modifier); + return; + } + } + this.focusItem(0); +}; + +AutoCompleter.prototype.focusItem = function(item) { + var $item, $items = $('li', this._results); + if ($items.length) { + $items.removeClass(this.selectClass_).removeClass(this.options.selectClass); + if (typeof item === 'number') { + item = parseInt(item, 10); + if (item < 0) { + item = 0; + } else if (item >= $items.length) { + item = $items.length - 1; + } + $item = $($items[item]); + } else { + $item = $(item); + } + if ($item) { + $item.addClass(this.selectClass_).addClass(this.options.selectClass); + } + } +}; + +AutoCompleter.prototype.selectCurrent = function() { + var $item = $('li.' + this.selectClass_, this._results); + if ($item.length == 1) { + this.selectItem($item); + } else { + this.finish(); + } +}; + +AutoCompleter.prototype.selectItem = function($li) { + var value = $li.data('value'); + var data = $li.data('data'); + var displayValue = this.displayValue(value, data); + this.lastProcessedValue_ = displayValue; + this.lastSelectedValue_ = displayValue; + + this.setValue(displayValue); + + this.setCaret(displayValue.length); + this.callHook('onItemSelect', { value: value, data: data }); + this.finish(); +}; + +/** + * @return {boolean} true if the symbol matches something that is + * considered content and false otherwise + * @param {string} symbol - a single char string + */ +AutoCompleter.prototype.isContentChar = function(symbol){ + if (symbol.match(this.options['stopCharRegex'])){ + return false; + } else if (symbol === this.options['multipleSeparator']){ + return false; + } else { + return true; + } +}; + +/** + * takes value from the input box + * and saves _selection_start and _selection_end coordinates + * respects settings autocompleteMultiple and + * multipleSeparator + * @return {string} the current word in the + * autocompletable word + */ +AutoCompleter.prototype.getValue = function(){ + var sel = this._element.getSelection(); + var text = this._element.val(); + var pos = sel.start;//estimated start + //find real start + var start = pos; + for (cpos = pos; cpos >= 0; cpos = cpos - 1){ + if (cpos === text.length){ + continue; + } + var symbol = text.charAt(cpos); + if (!this.isContentChar(symbol)){ + break; + } + start = cpos; + } + //find real end + var end = pos; + for (cpos = pos; cpos < text.length; cpos = cpos + 1){ + if (cpos === 0){ + continue; + } + var symbol = text.charAt(cpos); + if (!this.isContentChar(symbol)){ + break; + } + end = cpos; + } + this._selection_start = start; + this._selection_end = end; + return text.substring(start, end); +} + +/** + * sets value of the input box + * by replacing the previous selection + * with the value from the autocompleter + */ +AutoCompleter.prototype.setValue = function(val){ + var prefix = this._element.val().substring(0, this._selection_start); + var postfix = this._element.val().substring(this._selection_end + 1); + this._element.val(prefix + val + postfix); +}; + +AutoCompleter.prototype.displayValue = function(value, data) { + if ($.isFunction(this.options.displayValue)) { + return this.options.displayValue(value, data); + } else { + return value; + } +}; + +AutoCompleter.prototype.finish = function() { + if (this.keyTimeout_) { + clearTimeout(this.keyTimeout_); + } + if (this._element.val() !== this.lastSelectedValue_) { + if (this.options.mustMatch) { + this._element.val(''); + } + this.callHook('onNoMatch'); + } + this._results.hide(); + this.lastKeyPressed_ = null; + this.lastProcessedValue_ = null; + if (this.active_) { + this.callHook('onFinish'); + } + this.active_ = false; +}; + +AutoCompleter.prototype.selectRange = function(start, end) { + var input = this._element.get(0); + if (input.setSelectionRange) { + input.focus(); + input.setSelectionRange(start, end); + } else if (this.createTextRange) { + var range = this.createTextRange(); + range.collapse(true); + range.moveEnd('character', end); + range.moveStart('character', start); + range.select(); + } +}; + +AutoCompleter.prototype.setCaret = function(pos) { + this.selectRange(pos, pos); +}; + diff --git a/askbot/skins/old/media/js/compress.bat b/askbot/skins/old/media/js/compress.bat new file mode 100644 index 00000000..53d72588 --- /dev/null +++ b/askbot/skins/old/media/js/compress.bat @@ -0,0 +1,5 @@ +#java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 wmd\wmd.js -o wmd\wmd-min.js +#java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 wmd\showdown.js -o wmd\showdown-min.js +#java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 post.js -o post.pack.js +java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 se_hilite_src.js -o se_hilite.js +pause diff --git a/askbot/skins/old/media/js/editor.js b/askbot/skins/old/media/js/editor.js new file mode 100644 index 00000000..f5b1e2af --- /dev/null +++ b/askbot/skins/old/media/js/editor.js @@ -0,0 +1,75 @@ +/* + jQuery TextAreaResizer plugin + Created on 17th January 2008 by Ryan O'Dell + Version 1.0.4 +*/(function($){var textarea,staticOffset;var iLastMousePos=0;var iMin=32;var grip;$.fn.TextAreaResizer=function(){return this.each(function(){textarea=$(this).addClass('processed'),staticOffset=null;$(this).wrap('<div class="resizable-textarea"><span></span></div>').parent().append($('<div class="grippie"></div>').bind("mousedown",{el:this},startDrag));var grippie=$('div.grippie',$(this).parent())[0];grippie.style.marginRight=(grippie.offsetWidth-$(this)[0].offsetWidth)+'px'})};function startDrag(e){textarea=$(e.data.el);textarea.blur();iLastMousePos=mousePosition(e).y;staticOffset=textarea.height()-iLastMousePos;textarea.css('opacity',0.25);$(document).mousemove(performDrag).mouseup(endDrag);return false}function performDrag(e){var iThisMousePos=mousePosition(e).y;var iMousePos=staticOffset+iThisMousePos;if(iLastMousePos>=(iThisMousePos)){iMousePos-=5}iLastMousePos=iThisMousePos;iMousePos=Math.max(iMin,iMousePos);textarea.height(iMousePos+'px');if(iMousePos<iMin){endDrag(e)}return false}function endDrag(e){$(document).unbind('mousemove',performDrag).unbind('mouseup',endDrag);textarea.css('opacity',1);textarea.focus();textarea=null;staticOffset=null;iLastMousePos=0}function mousePosition(e){return{x:e.clientX+document.documentElement.scrollLeft,y:e.clientY+document.documentElement.scrollTop}}})(jQuery); +/* + * TypeWatch 2.0 - Original by Denny Ferrassoli / Refactored by Charles Christolini + * Copyright(c) 2007 Denny Ferrassoli - DennyDotNet.com + * Coprright(c) 2008 Charles Christolini - BinaryPie.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html +*/(function(jQuery){jQuery.fn.typeWatch=function(o){var options=jQuery.extend({wait:750,callback:function(){},highlight:true,captureLength:2},o);function checkElement(timer,override){var elTxt=jQuery(timer.el).val();if((elTxt.length>options.captureLength&&elTxt.toUpperCase()!=timer.text)||(override&&elTxt.length>options.captureLength)){timer.text=elTxt.toUpperCase();timer.cb(elTxt)}};function watchElement(elem){if(elem.type.toUpperCase()=="TEXT"||elem.nodeName.toUpperCase()=="TEXTAREA"){var timer={timer:null,text:jQuery(elem).val().toUpperCase(),cb:options.callback,el:elem,wait:options.wait};if(options.highlight){jQuery(elem).focus(function(){this.select()})}var startWatch=function(evt){var timerWait=timer.wait;var overrideBool=false;if(evt.keyCode==13&&this.type.toUpperCase()=="TEXT"){timerWait=1;overrideBool=true}var timerCallbackFx=function(){checkElement(timer,overrideBool)};clearTimeout(timer.timer);timer.timer=setTimeout(timerCallbackFx,timerWait)};jQuery(elem).keydown(startWatch)}};return this.each(function(index){watchElement(this)})}})(jQuery); +/* +Ajax upload +*/jQuery.extend({createUploadIframe:function(d,b){var a="jUploadFrame"+d;if(window.ActiveXObject){var c=document.createElement('<iframe id="'+a+'" name="'+a+'" />');if(typeof b=="boolean"){c.src="javascript:false"}else{if(typeof b=="string"){c.src=b}}}else{var c=document.createElement("iframe");c.id=a;c.name=a}c.style.position="absolute";c.style.top="-1000px";c.style.left="-1000px";document.body.appendChild(c);return c},createUploadForm:function(g,b){var e="jUploadForm"+g;var a="jUploadFile"+g;var d=$('<form action="" method="POST" name="'+e+'" id="'+e+'" enctype="multipart/form-data"></form>');var c=$("#"+b);var f=$(c).clone();$(c).attr("id",a);$(c).before(f);$(c).appendTo(d);$(d).css("position","absolute");$(d).css("top","-1200px");$(d).css("left","-1200px");$(d).appendTo("body");return d},ajaxFileUpload:function(k){k=jQuery.extend({},jQuery.ajaxSettings,k);var a=new Date().getTime();var b=jQuery.createUploadForm(a,k.fileElementId);var i=jQuery.createUploadIframe(a,k.secureuri);var h="jUploadFrame"+a;var j="jUploadForm"+a;if(k.global&&!jQuery.active++){jQuery.event.trigger("ajaxStart")}var c=false;var f={};if(k.global){jQuery.event.trigger("ajaxSend",[f,k])}var d=function(l){var p=document.getElementById(h);try{if(p.contentWindow){f.responseText=p.contentWindow.document.body?p.contentWindow.document.body.innerText:null;f.responseXML=p.contentWindow.document.XMLDocument?p.contentWindow.document.XMLDocument:p.contentWindow.document}else{if(p.contentDocument){f.responseText=p.contentDocument.document.body?p.contentDocument.document.body.textContent||document.body.innerText:null;f.responseXML=p.contentDocument.document.XMLDocument?p.contentDocument.document.XMLDocument:p.contentDocument.document}}}catch(o){jQuery.handleError(k,f,null,o)}if(f||l=="timeout"){c=true;var m;try{m=l!="timeout"?"success":"error";if(m!="error"){var n=jQuery.uploadHttpData(f,k.dataType);if(k.success){k.success(n,m)}if(k.global){jQuery.event.trigger("ajaxSuccess",[f,k])}}else{jQuery.handleError(k,f,m)}}catch(o){m="error";jQuery.handleError(k,f,m,o)}if(k.global){jQuery.event.trigger("ajaxComplete",[f,k])}if(k.global&&!--jQuery.active){jQuery.event.trigger("ajaxStop")}if(k.complete){k.complete(f,m)}jQuery(p).unbind();setTimeout(function(){try{$(p).remove();$(b).remove()}catch(q){jQuery.handleError(k,f,null,q)}},100);f=null}};if(k.timeout>0){setTimeout(function(){if(!c){d("timeout")}},k.timeout)}try{var b=$("#"+j);$(b).attr("action",k.url);$(b).attr("method","POST");$(b).attr("target",h);if(b.encoding){b.encoding="multipart/form-data"}else{b.enctype="multipart/form-data"}$(b).submit()}catch(g){jQuery.handleError(k,f,null,g)}if(window.attachEvent){document.getElementById(h).attachEvent("onload",d)}else{document.getElementById(h).addEventListener("load",d,false)}return{abort:function(){}}},uploadHttpData:function(r,type){var data=!type;data=type=="xml"||data?r.responseXML:r.responseText;if(type=="script"){jQuery.globalEval(data)}if(type=="json"){eval("data = "+data)}if(type=="html"){jQuery("<div>").html(data).evalScripts()}return data}}); +/** + * Upload call. Used only once in the wmd file upload + * this is "tightly coupled" with the wmd file uploader + * @param {Object} jquery object imageUrl - where the + * uploaded url must be inserted on successful upload + * @param {Function} handler that is run upon change + * of the file upload field + */ +function ajaxFileUpload(imageUrl, startUploadHandler) +{ + $("#loading").ajaxStart(function(){ + $(this).show(); + }).ajaxComplete(function(){ + $(this).hide(); + }); + + $("#upload").ajaxStart(function(){ + $(this).hide(); + }).ajaxComplete(function(){ + $(this).show(); + }); + + $.ajaxFileUpload + ( + { + url: askbot['urls']['upload'], + secureuri:false, + fileElementId:'file-upload', + dataType: 'xml', + success: function (data, status) + { + var fileURL = $(data).find('file_url').text(); + var error = $(data).find('error').text(); + if(error != ''){ + alert(error); + if (startUploadHandler){ + /* re-install this as the upload extension + * will remove the handler to prevent double uploading */ + $('#file-upload').change(startUploadHandler); + } + }else{ + imageUrl.attr('value', fileURL); + } + + }, + error: function (data, status, e) + { + alert(e); + if (startUploadHandler){ + /* re-install this as the upload extension + * will remove the handler to prevent double uploading */ + $('#file-upload').change(startUploadHandler); + } + } + } + ) + + return false; +} diff --git a/askbot/skins/old/media/js/excanvas.min.js b/askbot/skins/old/media/js/excanvas.min.js new file mode 100644 index 00000000..12c74f7b --- /dev/null +++ b/askbot/skins/old/media/js/excanvas.min.js @@ -0,0 +1 @@ +if(!document.createElement("canvas").getContext){(function(){var z=Math;var K=z.round;var J=z.sin;var U=z.cos;var b=z.abs;var k=z.sqrt;var D=10;var F=D/2;function T(){return this.context_||(this.context_=new W(this))}var O=Array.prototype.slice;function G(i,j,m){var Z=O.call(arguments,2);return function(){return i.apply(j,Z.concat(O.call(arguments)))}}function AD(Z){return String(Z).replace(/&/g,"&").replace(/"/g,""")}function r(i){if(!i.namespaces.g_vml_){i.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML")}if(!i.namespaces.g_o_){i.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML")}if(!i.styleSheets.ex_canvas_){var Z=i.createStyleSheet();Z.owningElement.id="ex_canvas_";Z.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}r(document);var E={init:function(Z){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var i=Z||document;i.createElement("canvas");i.attachEvent("onreadystatechange",G(this.init_,this,i))}},init_:function(m){var j=m.getElementsByTagName("canvas");for(var Z=0;Z<j.length;Z++){this.initElement(j[Z])}},initElement:function(i){if(!i.getContext){i.getContext=T;r(i.ownerDocument);i.innerHTML="";i.attachEvent("onpropertychange",S);i.attachEvent("onresize",w);var Z=i.attributes;if(Z.width&&Z.width.specified){i.style.width=Z.width.nodeValue+"px"}else{i.width=i.clientWidth}if(Z.height&&Z.height.specified){i.style.height=Z.height.nodeValue+"px"}else{i.height=i.clientHeight}}return i}};function S(i){var Z=i.srcElement;switch(i.propertyName){case"width":Z.getContext().clearRect();Z.style.width=Z.attributes.width.nodeValue+"px";Z.firstChild.style.width=Z.clientWidth+"px";break;case"height":Z.getContext().clearRect();Z.style.height=Z.attributes.height.nodeValue+"px";Z.firstChild.style.height=Z.clientHeight+"px";break}}function w(i){var Z=i.srcElement;if(Z.firstChild){Z.firstChild.style.width=Z.clientWidth+"px";Z.firstChild.style.height=Z.clientHeight+"px"}}E.init();var I=[];for(var AC=0;AC<16;AC++){for(var AB=0;AB<16;AB++){I[AC*16+AB]=AC.toString(16)+AB.toString(16)}}function V(){return[[1,0,0],[0,1,0],[0,0,1]]}function d(m,j){var i=V();for(var Z=0;Z<3;Z++){for(var AF=0;AF<3;AF++){var p=0;for(var AE=0;AE<3;AE++){p+=m[Z][AE]*j[AE][AF]}i[Z][AF]=p}}return i}function Q(i,Z){Z.fillStyle=i.fillStyle;Z.lineCap=i.lineCap;Z.lineJoin=i.lineJoin;Z.lineWidth=i.lineWidth;Z.miterLimit=i.miterLimit;Z.shadowBlur=i.shadowBlur;Z.shadowColor=i.shadowColor;Z.shadowOffsetX=i.shadowOffsetX;Z.shadowOffsetY=i.shadowOffsetY;Z.strokeStyle=i.strokeStyle;Z.globalAlpha=i.globalAlpha;Z.font=i.font;Z.textAlign=i.textAlign;Z.textBaseline=i.textBaseline;Z.arcScaleX_=i.arcScaleX_;Z.arcScaleY_=i.arcScaleY_;Z.lineScale_=i.lineScale_}var B={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"};function g(i){var m=i.indexOf("(",3);var Z=i.indexOf(")",m+1);var j=i.substring(m+1,Z).split(",");if(j.length==4&&i.substr(3,1)=="a"){alpha=Number(j[3])}else{j[3]=1}return j}function C(Z){return parseFloat(Z)/100}function N(i,j,Z){return Math.min(Z,Math.max(j,i))}function c(AF){var j,i,Z;h=parseFloat(AF[0])/360%360;if(h<0){h++}s=N(C(AF[1]),0,1);l=N(C(AF[2]),0,1);if(s==0){j=i=Z=l}else{var m=l<0.5?l*(1+s):l+s-l*s;var AE=2*l-m;j=A(AE,m,h+1/3);i=A(AE,m,h);Z=A(AE,m,h-1/3)}return"#"+I[Math.floor(j*255)]+I[Math.floor(i*255)]+I[Math.floor(Z*255)]}function A(i,Z,j){if(j<0){j++}if(j>1){j--}if(6*j<1){return i+(Z-i)*6*j}else{if(2*j<1){return Z}else{if(3*j<2){return i+(Z-i)*(2/3-j)*6}else{return i}}}}function Y(Z){var AE,p=1;Z=String(Z);if(Z.charAt(0)=="#"){AE=Z}else{if(/^rgb/.test(Z)){var m=g(Z);var AE="#",AF;for(var j=0;j<3;j++){if(m[j].indexOf("%")!=-1){AF=Math.floor(C(m[j])*255)}else{AF=Number(m[j])}AE+=I[N(AF,0,255)]}p=m[3]}else{if(/^hsl/.test(Z)){var m=g(Z);AE=c(m);p=m[3]}else{AE=B[Z]||Z}}}return{color:AE,alpha:p}}var L={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};var f={};function X(Z){if(f[Z]){return f[Z]}var m=document.createElement("div");var j=m.style;try{j.font=Z}catch(i){}return f[Z]={style:j.fontStyle||L.style,variant:j.fontVariant||L.variant,weight:j.fontWeight||L.weight,size:j.fontSize||L.size,family:j.fontFamily||L.family}}function P(j,i){var Z={};for(var AF in j){Z[AF]=j[AF]}var AE=parseFloat(i.currentStyle.fontSize),m=parseFloat(j.size);if(typeof j.size=="number"){Z.size=j.size}else{if(j.size.indexOf("px")!=-1){Z.size=m}else{if(j.size.indexOf("em")!=-1){Z.size=AE*m}else{if(j.size.indexOf("%")!=-1){Z.size=(AE/100)*m}else{if(j.size.indexOf("pt")!=-1){Z.size=m/0.75}else{Z.size=AE}}}}}Z.size*=0.981;return Z}function AA(Z){return Z.style+" "+Z.variant+" "+Z.weight+" "+Z.size+"px "+Z.family}function t(Z){switch(Z){case"butt":return"flat";case"round":return"round";case"square":default:return"square"}}function W(i){this.m_=V();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=D*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=i;var Z=i.ownerDocument.createElement("div");Z.style.width=i.clientWidth+"px";Z.style.height=i.clientHeight+"px";Z.style.overflow="hidden";Z.style.position="absolute";i.appendChild(Z);this.element_=Z;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var M=W.prototype;M.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};M.beginPath=function(){this.currentPath_=[]};M.moveTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"moveTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.lineTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"lineTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.bezierCurveTo=function(j,i,AI,AH,AG,AE){var Z=this.getCoords_(AG,AE);var AF=this.getCoords_(j,i);var m=this.getCoords_(AI,AH);e(this,AF,m,Z)};function e(Z,m,j,i){Z.currentPath_.push({type:"bezierCurveTo",cp1x:m.x,cp1y:m.y,cp2x:j.x,cp2y:j.y,x:i.x,y:i.y});Z.currentX_=i.x;Z.currentY_=i.y}M.quadraticCurveTo=function(AG,j,i,Z){var AF=this.getCoords_(AG,j);var AE=this.getCoords_(i,Z);var AH={x:this.currentX_+2/3*(AF.x-this.currentX_),y:this.currentY_+2/3*(AF.y-this.currentY_)};var m={x:AH.x+(AE.x-this.currentX_)/3,y:AH.y+(AE.y-this.currentY_)/3};e(this,AH,m,AE)};M.arc=function(AJ,AH,AI,AE,i,j){AI*=D;var AN=j?"at":"wa";var AK=AJ+U(AE)*AI-F;var AM=AH+J(AE)*AI-F;var Z=AJ+U(i)*AI-F;var AL=AH+J(i)*AI-F;if(AK==Z&&!j){AK+=0.125}var m=this.getCoords_(AJ,AH);var AG=this.getCoords_(AK,AM);var AF=this.getCoords_(Z,AL);this.currentPath_.push({type:AN,x:m.x,y:m.y,radius:AI,xStart:AG.x,yStart:AG.y,xEnd:AF.x,yEnd:AF.y})};M.rect=function(j,i,Z,m){this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath()};M.strokeRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.stroke();this.currentPath_=p};M.fillRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.fill();this.currentPath_=p};M.createLinearGradient=function(i,m,Z,j){var p=new v("gradient");p.x0_=i;p.y0_=m;p.x1_=Z;p.y1_=j;return p};M.createRadialGradient=function(m,AE,j,i,p,Z){var AF=new v("gradientradial");AF.x0_=m;AF.y0_=AE;AF.r0_=j;AF.x1_=i;AF.y1_=p;AF.r1_=Z;return AF};M.drawImage=function(AO,j){var AH,AF,AJ,AV,AM,AK,AQ,AX;var AI=AO.runtimeStyle.width;var AN=AO.runtimeStyle.height;AO.runtimeStyle.width="auto";AO.runtimeStyle.height="auto";var AG=AO.width;var AT=AO.height;AO.runtimeStyle.width=AI;AO.runtimeStyle.height=AN;if(arguments.length==3){AH=arguments[1];AF=arguments[2];AM=AK=0;AQ=AJ=AG;AX=AV=AT}else{if(arguments.length==5){AH=arguments[1];AF=arguments[2];AJ=arguments[3];AV=arguments[4];AM=AK=0;AQ=AG;AX=AT}else{if(arguments.length==9){AM=arguments[1];AK=arguments[2];AQ=arguments[3];AX=arguments[4];AH=arguments[5];AF=arguments[6];AJ=arguments[7];AV=arguments[8]}else{throw Error("Invalid number of arguments")}}}var AW=this.getCoords_(AH,AF);var m=AQ/2;var i=AX/2;var AU=[];var Z=10;var AE=10;AU.push(" <g_vml_:group",' coordsize="',D*Z,",",D*AE,'"',' coordorigin="0,0"',' style="width:',Z,"px;height:",AE,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var p=[];p.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",K(AW.x/D),",","Dy=",K(AW.y/D),"");var AS=AW;var AR=this.getCoords_(AH+AJ,AF);var AP=this.getCoords_(AH,AF+AV);var AL=this.getCoords_(AH+AJ,AF+AV);AS.x=z.max(AS.x,AR.x,AP.x,AL.x);AS.y=z.max(AS.y,AR.y,AP.y,AL.y);AU.push("padding:0 ",K(AS.x/D),"px ",K(AS.y/D),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",p.join(""),", sizingmethod='clip');")}else{AU.push("top:",K(AW.y/D),"px;left:",K(AW.x/D),"px;")}AU.push(' ">','<g_vml_:image src="',AO.src,'"',' style="width:',D*AJ,"px;"," height:",D*AV,'px"',' cropleft="',AM/AG,'"',' croptop="',AK/AT,'"',' cropright="',(AG-AM-AQ)/AG,'"',' cropbottom="',(AT-AK-AX)/AT,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",AU.join(""))};M.stroke=function(AM){var m=10;var AN=10;var AE=5000;var AG={x:null,y:null};var AL={x:null,y:null};for(var AH=0;AH<this.currentPath_.length;AH+=AE){var AK=[];var AF=false;AK.push("<g_vml_:shape",' filled="',!!AM,'"',' style="position:absolute;width:',m,"px;height:",AN,'px;"',' coordorigin="0,0"',' coordsize="',D*m,",",D*AN,'"',' stroked="',!AM,'"',' path="');var AO=false;for(var AI=AH;AI<Math.min(AH+AE,this.currentPath_.length);AI++){if(AI%AE==0&&AI>0){AK.push(" m ",K(this.currentPath_[AI-1].x),",",K(this.currentPath_[AI-1].y))}var Z=this.currentPath_[AI];var AJ;switch(Z.type){case"moveTo":AJ=Z;AK.push(" m ",K(Z.x),",",K(Z.y));break;case"lineTo":AK.push(" l ",K(Z.x),",",K(Z.y));break;case"close":AK.push(" x ");Z=null;break;case"bezierCurveTo":AK.push(" c ",K(Z.cp1x),",",K(Z.cp1y),",",K(Z.cp2x),",",K(Z.cp2y),",",K(Z.x),",",K(Z.y));break;case"at":case"wa":AK.push(" ",Z.type," ",K(Z.x-this.arcScaleX_*Z.radius),",",K(Z.y-this.arcScaleY_*Z.radius)," ",K(Z.x+this.arcScaleX_*Z.radius),",",K(Z.y+this.arcScaleY_*Z.radius)," ",K(Z.xStart),",",K(Z.yStart)," ",K(Z.xEnd),",",K(Z.yEnd));break}if(Z){if(AG.x==null||Z.x<AG.x){AG.x=Z.x}if(AL.x==null||Z.x>AL.x){AL.x=Z.x}if(AG.y==null||Z.y<AG.y){AG.y=Z.y}if(AL.y==null||Z.y>AL.y){AL.y=Z.y}}}AK.push(' ">');if(!AM){R(this,AK)}else{a(this,AK,AG,AL)}AK.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",AK.join(""))}};function R(j,AE){var i=Y(j.strokeStyle);var m=i.color;var p=i.alpha*j.globalAlpha;var Z=j.lineScale_*j.lineWidth;if(Z<1){p*=Z}AE.push("<g_vml_:stroke",' opacity="',p,'"',' joinstyle="',j.lineJoin,'"',' miterlimit="',j.miterLimit,'"',' endcap="',t(j.lineCap),'"',' weight="',Z,'px"',' color="',m,'" />')}function a(AO,AG,Ah,AP){var AH=AO.fillStyle;var AY=AO.arcScaleX_;var AX=AO.arcScaleY_;var Z=AP.x-Ah.x;var m=AP.y-Ah.y;if(AH instanceof v){var AL=0;var Ac={x:0,y:0};var AU=0;var AK=1;if(AH.type_=="gradient"){var AJ=AH.x0_/AY;var j=AH.y0_/AX;var AI=AH.x1_/AY;var Aj=AH.y1_/AX;var Ag=AO.getCoords_(AJ,j);var Af=AO.getCoords_(AI,Aj);var AE=Af.x-Ag.x;var p=Af.y-Ag.y;AL=Math.atan2(AE,p)*180/Math.PI;if(AL<0){AL+=360}if(AL<0.000001){AL=0}}else{var Ag=AO.getCoords_(AH.x0_,AH.y0_);Ac={x:(Ag.x-Ah.x)/Z,y:(Ag.y-Ah.y)/m};Z/=AY*D;m/=AX*D;var Aa=z.max(Z,m);AU=2*AH.r0_/Aa;AK=2*AH.r1_/Aa-AU}var AS=AH.colors_;AS.sort(function(Ak,i){return Ak.offset-i.offset});var AN=AS.length;var AR=AS[0].color;var AQ=AS[AN-1].color;var AW=AS[0].alpha*AO.globalAlpha;var AV=AS[AN-1].alpha*AO.globalAlpha;var Ab=[];for(var Ae=0;Ae<AN;Ae++){var AM=AS[Ae];Ab.push(AM.offset*AK+AU+" "+AM.color)}AG.push('<g_vml_:fill type="',AH.type_,'"',' method="none" focus="100%"',' color="',AR,'"',' color2="',AQ,'"',' colors="',Ab.join(","),'"',' opacity="',AV,'"',' g_o_:opacity2="',AW,'"',' angle="',AL,'"',' focusposition="',Ac.x,",",Ac.y,'" />')}else{if(AH instanceof u){if(Z&&m){var AF=-Ah.x;var AZ=-Ah.y;AG.push("<g_vml_:fill",' position="',AF/Z*AY*AY,",",AZ/m*AX*AX,'"',' type="tile"',' src="',AH.src_,'" />')}}else{var Ai=Y(AO.fillStyle);var AT=Ai.color;var Ad=Ai.alpha*AO.globalAlpha;AG.push('<g_vml_:fill color="',AT,'" opacity="',Ad,'" />')}}}M.fill=function(){this.stroke(true)};M.closePath=function(){this.currentPath_.push({type:"close"})};M.getCoords_=function(j,i){var Z=this.m_;return{x:D*(j*Z[0][0]+i*Z[1][0]+Z[2][0])-F,y:D*(j*Z[0][1]+i*Z[1][1]+Z[2][1])-F}};M.save=function(){var Z={};Q(this,Z);this.aStack_.push(Z);this.mStack_.push(this.m_);this.m_=d(V(),this.m_)};M.restore=function(){if(this.aStack_.length){Q(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function H(Z){return isFinite(Z[0][0])&&isFinite(Z[0][1])&&isFinite(Z[1][0])&&isFinite(Z[1][1])&&isFinite(Z[2][0])&&isFinite(Z[2][1])}function y(i,Z,j){if(!H(Z)){return }i.m_=Z;if(j){var p=Z[0][0]*Z[1][1]-Z[0][1]*Z[1][0];i.lineScale_=k(b(p))}}M.translate=function(j,i){var Z=[[1,0,0],[0,1,0],[j,i,1]];y(this,d(Z,this.m_),false)};M.rotate=function(i){var m=U(i);var j=J(i);var Z=[[m,j,0],[-j,m,0],[0,0,1]];y(this,d(Z,this.m_),false)};M.scale=function(j,i){this.arcScaleX_*=j;this.arcScaleY_*=i;var Z=[[j,0,0],[0,i,0],[0,0,1]];y(this,d(Z,this.m_),true)};M.transform=function(p,m,AF,AE,i,Z){var j=[[p,m,0],[AF,AE,0],[i,Z,1]];y(this,d(j,this.m_),true)};M.setTransform=function(AE,p,AG,AF,j,i){var Z=[[AE,p,0],[AG,AF,0],[j,i,1]];y(this,Z,true)};M.drawText_=function(AK,AI,AH,AN,AG){var AM=this.m_,AQ=1000,i=0,AP=AQ,AF={x:0,y:0},AE=[];var Z=P(X(this.font),this.element_);var j=AA(Z);var AR=this.element_.currentStyle;var p=this.textAlign.toLowerCase();switch(p){case"left":case"center":case"right":break;case"end":p=AR.direction=="ltr"?"right":"left";break;case"start":p=AR.direction=="rtl"?"right":"left";break;default:p="left"}switch(this.textBaseline){case"hanging":case"top":AF.y=Z.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":AF.y=-Z.size/2.25;break}switch(p){case"right":i=AQ;AP=0.05;break;case"center":i=AP=AQ/2;break}var AO=this.getCoords_(AI+AF.x,AH+AF.y);AE.push('<g_vml_:line from="',-i,' 0" to="',AP,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!AG,'" stroked="',!!AG,'" style="position:absolute;width:1px;height:1px;">');if(AG){R(this,AE)}else{a(this,AE,{x:-i,y:0},{x:AP,y:Z.size})}var AL=AM[0][0].toFixed(3)+","+AM[1][0].toFixed(3)+","+AM[0][1].toFixed(3)+","+AM[1][1].toFixed(3)+",0,0";var AJ=K(AO.x/D)+","+K(AO.y/D);AE.push('<g_vml_:skew on="t" matrix="',AL,'" ',' offset="',AJ,'" origin="',i,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',AD(AK),'" style="v-text-align:',p,";font:",AD(j),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",AE.join(""))};M.fillText=function(j,Z,m,i){this.drawText_(j,Z,m,i,false)};M.strokeText=function(j,Z,m,i){this.drawText_(j,Z,m,i,true)};M.measureText=function(j){if(!this.textMeasureEl_){var Z='<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",Z);this.textMeasureEl_=this.element_.lastChild}var i=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(i.createTextNode(j));return{width:this.textMeasureEl_.offsetWidth}};M.clip=function(){};M.arcTo=function(){};M.createPattern=function(i,Z){return new u(i,Z)};function v(Z){this.type_=Z;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}v.prototype.addColorStop=function(i,Z){Z=Y(Z);this.colors_.push({offset:i,color:Z.color,alpha:Z.alpha})};function u(i,Z){q(i);switch(Z){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=Z;break;default:n("SYNTAX_ERR")}this.src_=i.src;this.width_=i.width;this.height_=i.height}function n(Z){throw new o(Z)}function q(Z){if(!Z||Z.nodeType!=1||Z.tagName!="IMG"){n("TYPE_MISMATCH_ERR")}if(Z.readyState!="complete"){n("INVALID_STATE_ERR")}}function o(Z){this.code=this[Z];this.message=Z+": DOM Exception "+this.code}var x=o.prototype=new Error;x.INDEX_SIZE_ERR=1;x.DOMSTRING_SIZE_ERR=2;x.HIERARCHY_REQUEST_ERR=3;x.WRONG_DOCUMENT_ERR=4;x.INVALID_CHARACTER_ERR=5;x.NO_DATA_ALLOWED_ERR=6;x.NO_MODIFICATION_ALLOWED_ERR=7;x.NOT_FOUND_ERR=8;x.NOT_SUPPORTED_ERR=9;x.INUSE_ATTRIBUTE_ERR=10;x.INVALID_STATE_ERR=11;x.SYNTAX_ERR=12;x.INVALID_MODIFICATION_ERR=13;x.NAMESPACE_ERR=14;x.INVALID_ACCESS_ERR=15;x.VALIDATION_ERR=16;x.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=E;CanvasRenderingContext2D=W;CanvasGradient=v;CanvasPattern=u;DOMException=o})()};
\ No newline at end of file diff --git a/askbot/skins/old/media/js/flot-build.bat b/askbot/skins/old/media/js/flot-build.bat new file mode 100644 index 00000000..f9f32cb7 --- /dev/null +++ b/askbot/skins/old/media/js/flot-build.bat @@ -0,0 +1,3 @@ +java -jar yuicompressor-2.4.2.jar --type js --charset utf-8 jquery.flot.js -o jquery.flot.pack.js + +pause diff --git a/askbot/skins/old/media/js/i18n.js b/askbot/skins/old/media/js/i18n.js new file mode 100644 index 00000000..192d335b --- /dev/null +++ b/askbot/skins/old/media/js/i18n.js @@ -0,0 +1,469 @@ +//var i18nLang; +var i18nZh = { + 'insufficient privilege':'用户æƒé™ä¸åœ¨æ“作范围', + 'cannot pick own answer as best':'ä¸èƒ½è®¾ç½®è‡ªå·±çš„回ç”为最佳ç”案', + 'anonymous users cannot select favorite questions':'匿å用户ä¸èƒ½æ”¶è—问题,请先', + 'please login':'注册或者登录', + 'daily vote cap exhausted':'对ä¸èµ·ï¼Œæ‚¨å·²ç”¨å®Œä»Šæ—¥æ‰€æœ‰çš„投票。', + 'please confirm offensive':"确定è¦å½’类该帖为广告ã€äººèº«æ”»å‡»ã€æ¶æ„言论å—?", + 'anonymous users cannot flag offensive posts':'匿å用户ä¸èƒ½æ“作,请先', + 'cannot flag message as offensive twice':'ä¸èƒ½é‡å¤æ“作。', + 'flag offensive cap exhausted':'对ä¸èµ·ï¼Œæ‚¨å·²ç”¨å®Œä»Šæ—¥æ‰€æœ‰çš„5次‘水帖’æ“作。', + 'confirm delete':"确定è¦åˆ 除/æ’¤é”€åˆ é™¤è¯¥å¸–å—?", + 'anonymous users cannot delete/undelete':"匿å用户ä¸èƒ½åˆ é™¤æˆ–æ’¤é”€åˆ é™¤å¸–å", + 'post recovered':"æ“作æˆåŠŸï¼è¯¥å¸–å已被æ¢å¤ã€‚", + 'post deleted':"æ“作æˆåŠŸï¼è¯¥å¸–åå·²åˆ é™¤ã€‚", + 'add comment':'æ·»åŠ è¯„è®º', + 'delete this comment':'åˆ é™¤æ¤è¯„论', + 'add a comment':"æ·»åŠ è¯„è®º", + 'comments':"评论", + 'confirm delete comment':"真è¦åˆ 除æ¤è¯„论å—?", + '{0} characters left': '还å¯å†™{0}å—符', + 'click to close':'点击消æ¯æ¡†å…³é—', + 'loading...':'读å–ä¸...', + 'tags cannot be empty':'æ ‡ç¾ä¸èƒ½ä¸ºç©ºã€‚', + 'content cannot be empty':'内容ä¸èƒ½ä¸ºç©ºã€‚', + 'content minchars': '请输入至少 {0} å—符。', + 'please enter title':'è¯·è¾“å…¥æ ‡é¢˜ã€‚', + 'title minchars':"请输入至少 {0} å—符。", + 'delete':'åˆ é™¤', + 'undelete':'å–消', + 'bold':'粗体', + 'italic':'斜体', + 'link':'超链接', + 'quote':'引用', + 'preformatted text':'代ç ', + 'image':'图片', + 'numbered list':'æ•°å—ç¼–å·åˆ—表', + 'bulleted list':'项目符å·åˆ—表', + 'heading':'æ ‡é¢˜', + 'horizontal bar':'水平线', + 'undo':'撤销', + 'redo':'é‡åš', + 'enter image url':'<b>输入图片地å€</b></p><p>示例:<br />http://www.example.com/image.jpg \"我的截图\"', + 'enter url':'<b>输入Web地å€</b></p><p>示例:<br />http://www.cnprog.com/ \"我的网站\"</p>"', + 'upload image':'æˆ–è€…ä¸Šä¼ æœ¬åœ°å›¾ç‰‡ï¼š' +}; + +var i18nZhtw = { + 'insufficient privilege':'權é™ä¸è¶³', + 'cannot pick own answer as best':'ä¸èƒ½è”½æŽƒè‡ªç', + 'anonymous users cannot select favorite questions':'匿å用戶ä¸èƒ½æ”¶è—å•é¡Œ', + 'please login':'請先登錄', + 'daily vote cap exhausted':'å°ä¸èµ·ï¼Œæ‚¨å·²ç”¨å®Œä»Šæ—¥æ‰€æœ‰çš„投票。', + 'please confirm offensive':"確定è¦æ¸é¡žè©²å¸–為廣告ã€äººèº«æ”»æ“Šã€æƒ¡æ„言論嗎?", + 'anonymous users cannot flag offensive posts':'匿å用戶ä¸èƒ½æ“作', + 'cannot flag message as offensive twice':'ä¸èƒ½é‡è¤‡æ“作。', + 'flag offensive cap exhausted':'å°ä¸èµ·ï¼Œæ‚¨å·²ç”¨å®Œä»Šæ—¥æ‰€æœ‰çš„5次『水帖ã€æ“作。', + 'confirm delete':"確定刪除", + 'anonymous users cannot delete/undelete':"匿å用戶ä¸èƒ½åˆªé™¤æˆ–æ¢å¾©å¸–å", + 'post recovered':"æ“作æˆåŠŸï¼è©²å¸–å已被æ¢è¤‡ã€‚", + 'post deleted':"æ“作æˆåŠŸï¼è©²å¸–å已刪除。", + 'add comment':'æ·»åŠ è©•è«–', + 'delete this comment':'刪除æ¤è©•è«–', + 'add a comment':"æ·»åŠ è©•è«–", + 'comments':"è©•è«–", + 'confirm delete comment':"刪除評論確èª", + '{0} characters left': 'é‚„å¯å¯«{0}å—', + 'click to close':'點擊消æ¯æ¡†é—œé–‰', + 'loading...':'讀å–ä¸...', + 'tags cannot be empty':'標籤ä¸èƒ½ç‚ºç©ºç™½', + 'content cannot be empty':'內容ä¸èƒ½ç‚ºç©ºç™½', + 'content minchars': '請輸入至少 {0} å—符。', + 'please enter title':'請輸入標題。', + 'title minchars':"請輸入至少 {0} å—符。", + 'delete':'刪除', + 'undelete':'å–消', + 'bold':'ç²—é«”', + 'italic':'斜體', + 'link':'超連接', + 'quote':'引用', + 'preformatted text':'代碼', + 'image':'圖片', + 'numbered list':'數å—編號列表', + 'bulleted list':'é …ç›®ç¬¦è™Ÿåˆ—è¡¨', + 'heading':'標題', + 'horizontal bar':'水平線', + 'undo':'撤銷', + 'redo':'é‡åš', + 'enter image url':'<b>輸入圖片地å€</b></p><p>示例:<br />http://www.example.com/image.jpg \"我的截圖\"', + 'enter url':'<b>輸入Web地å€</b></p><p>示例:<br />http://www.cnprog.com/ \"我的網站\"</p>"', + 'upload image':'或者上傳本地圖片:' +}; + + +var i18nEn = { + "anonymous users cannot vote": "sorry, anonymous users cannot vote ", + 'tags cannot be empty':'please enter at least one tag', + 'anonymous users cannot select favorite questions':'sorry, anonymous users cannot select favorite questions ', + 'upload image':'Upload image:', + 'enter image url':'enter URL of the image, e.g. http://www.example.com/image.jpg or upload an image file', + 'enter url':'enter Web address, e.g. http://www.example.com \"page title\"', + 'upload file attachment':'Please choose and upload a file:', + 'daily vote cap exhausted':'sorry, you\'ve used up todays vote cap', + 'cannot pick own answer as best':'sorry, you cannot accept your own answer', + 'please confirm offensive':'are you sure this post is offensive, contains spam, advertising, malicious remarks, etc.?', + 'flag offensive cap exhausted':'sorry, you\'ve used up todays cap of flagging offensive messages ', + 'confirm delete':'are you sure you want to delete this?', + 'anonymous users cannot delete/undelete':'sorry, anonymous users cannot delete or undelete posts', + 'post recovered':'your post is now restored!', + 'post deleted':'your post has been deleted', + 'confirm delete comment':'do you really want to delete this comment?', + 'content minchars': 'please enter more than {0} characters', + 'title minchars':"please enter at least {0} characters", + 'characters':'characters left', + 'cannot flag message as offensive twice':'cannot flag message as offensive twice ', + 'edit':'edit', + 'click to edit this comment':'click to edit this comment', + 'confirm abandon comment':'Are you sure you do not want to post this comment?', + 'save comment': 'save comment', + 'enter more characters': 'please enter at least {0} more characters', + 'Follow': 'Follow', + '<b>Following</b><b class="unfollow">Unfollow</b>': '<b>Following</b><b class="unfollow">Unfollow</b>', +}; + +var i18nFi = { + "anonymous users cannot vote": "kirjaudu sisään, jotta voit käyttää tätä ominaisuutta ", + 'tags cannot be empty':'anna vähintään yksi tagi', + 'anonymous users cannot select favorite questions':'kirjaudu sisään, jotta voit käyttää tätä ominaisuutta', + 'upload image':'Lähetä kuva:', + 'enter image url':'Anna kuvan URL-osoite, esim. http://www.example.com/image.jpg \"kuvan otsikko\"', + 'enter url':'Anna URL-osoite, esim. http://www.example.com \"sivun otsikko\"', + 'daily vote cap exhausted':'olet käyttänyt tämän päivän osalta äänesi', + 'cannot pick own answer as best':'et voi hyväksyä omaa vastaustasi parhaaksi', + 'please confirm offensive':'oletko varma, että tämä on roskaposti, loukkaava tai muuta hyväksymätöntä?', + 'flag offensive cap exhausted':'olet käyttänyt tämän päivän merkkausmäärät ', + 'confirm delete':'oletko varma, että haluat poistaa tämän?', + 'anonymous users cannot delete/undelete':'kirjaudu sisään, jotta voit käyttää tätä ominaisuutta', + 'post recovered':'postauksesi on palautettu!', + 'post deleted':'postauksesi on poistettu', + 'confirm delete comment':'oletko varma, että haluat poistaa tämän kommentin?', + 'content minchars': 'syötä vähintään {0} merkkiä', + 'title minchars':"syötä vähintään {0} merkkiä", + '{0} characters left': '{0} merkkiä jäljellä', + 'cannot flag message as offensive twice':'ei voi merkata kahta kertaa ' +}; + +var i18nTr = { + "anonymous users cannot vote":"üye giriÅŸi yapmadan oy kullanamazsınız", + 'insufficient privilege':'buna yetkiniz yoktur', + 'cannot pick own answer as best':'en cevap olarak kendi cevabınızı seçemezsiniz', + 'anonymous users cannot select favorite questions':'üye giriÅŸi yapmadan favori seçemezsiniz', + 'please login':'lütfen üye giriÅŸi yapınız', + 'daily vote cap exhausted':'bugünlük oy verme kotanız doldu', + 'please confirm offensive':"ÅŸikayetinizi onaylayın", + 'anonymous users cannot flag offensive posts':'üye giriÅŸi yapmadan ÅŸikayet gönderemezsiniz', + 'cannot flag message as offensive twice':'ÅŸikayet mesajı olarak iki kez iÅŸaretlemelisiniz', + 'flag offensive cap exhausted':'ÅŸikayet kotası aşıldı', + 'confirm delete':"Bunu silmek istediÄŸinizden emin misiniz?", + 'anonymous users cannot delete/undelete':"üye giriÅŸi yapmadan yazı silemez yada geri alamazsınız", + 'post recovered':"yazı geri alındı", + 'post deleted':"yazı silindi", + 'add comment':'yorum ekle', + 'delete this comment':'bu yorumu sil', + 'add a comment':"yorum ekle", + 'comments':"yorumlar", + 'confirm delete comment':"yorumu silmek istediÄŸinizden emin misiniz?", + '{0} characters left': 'yazılabilir {0} karakter eksik', + 'click to close':'kapatmak için tıklayın', + 'loading...':'yükleniyor...', + 'tags cannot be empty':'etiketler boÅŸ olamaz', + 'content cannot be empty':'içerik boÅŸ olamaz', + 'content minchars': 'Lütfen en az (0) karakter girin', + 'please enter title':'lütfen bir baÅŸlık yazın', + 'title minchars':"Lütfen en az (0) karakter girin", + 'delete':'sil', + 'undelete':'geri al', + 'bold': 'kalın', + 'italic':'italik', + 'link':'link', + 'quote':'alıntı', + 'preformatted text':'hazır metin', + 'image':'resimler', + 'numbered list':'numaralı liste', + 'bulleted list':'iÅŸaretli liste', + 'heading':'BaÅŸlık', + 'horizontal bar':'yatay bar', + 'undo':'geri', + 'redo':'yeniden', + 'enter image url':'örnek resmin URLsini girin: <br />http://www.example.com/image.jpg \"resim baÅŸlığı\"', + 'enter url':'web adresini girin: <br />http://www.cnprog.com/ \"baÅŸlık baÄŸlantısı\"</p>"', + 'upload image':'resim yükle:' +}; + +var i18nEs = { + "anonymous users cannot vote":"usuarios anónimos no pueden votar", + 'insufficient privilege':'privilegio insuficiente', + 'cannot pick own answer as best':'no puede escoger su propia respuesta como la mejor', + 'anonymous users cannot select favorite questions':'usuarios anonimos no pueden seleccionar', + 'please login':'por favor inicie sesión', + 'daily vote cap exhausted':'cuota de votos diarios excedida', + 'please confirm offensive':"por favor confirme ofensiva", + 'anonymous users cannot flag offensive posts':'usuarios anónimos no pueden marcar publicaciones como ofensivas', + 'cannot flag message as offensive twice':'no puede marcar mensaje como ofensivo dos veces', + 'flag offensive cap exhausted':'cuota para marcar ofensivas ha sido excedida', + 'confirm delete':"¿Está seguro que desea borrar esto?", + 'anonymous users cannot delete/undelete':"usuarios anónimos no pueden borrar o recuperar publicaciones", + 'post recovered':"publicación recuperada", + 'post deleted':"publicación borrada。", + 'add comment':'agregar comentario', + 'delete this comment':'borrar este comentario', + 'add a comment':"agregar comentarios", + 'comments':"comentarios", + 'confirm delete comment':"¿Realmente desea borrar este comentario?", + '{0} characters left': '{0} caracteres faltantes', + 'click to close':'haga click para cerrar', + 'loading...':'cargando...', + 'tags cannot be empty':'las etiquetas no pueden estar vacÃas', + 'content cannot be empty':'el contenido no puede estar vacÃo', + 'content minchars': 'por favor introduzca mas de {0} caracteres', + 'please enter title':'por favor ingrese un tÃtulo', + 'title minchars':"por favor introduzca al menos {0} caracteres", + 'delete':'borrar', + 'undelete': 'recuperar', + 'bold': 'negrita', + 'italic':'cursiva', + 'link':'enlace', + 'quote':'citar', + 'preformatted text':'texto preformateado', + 'image':'imagen', + 'numbered list':'lista numerada', + 'bulleted list':'lista no numerada', + 'heading':'æ ‡é¢˜', + 'horizontal bar':'barra horizontal', + 'undo':'deshacer', + 'redo':'rehacer', + 'enter image url':'introduzca la URL de la imagen, por ejemplo:<br />http://www.example.com/image.jpg \"titulo de imagen\"', + 'enter url':'introduzca direcciones web, ejemplo:<br />http://www.cnprog.com/ \"titulo del enlace\"</p>"', + 'upload image':'cargar imagen:' +}; + +var i18nDe = { + "anonymous users cannot vote":"Gastbenutzer können nicht abstimmen ", + 'add a comment': 'Kommentar hinzufügen', + 'add comment': 'OK', + 'anonymous users cannot delete/undelete': 'Gastbenutzer können Beiträge nicht löschen oder wiederherstellen', + 'anonymous users cannot flag offensive posts': 'Gastbenutzer können Beiträge nicht melden', + 'anonymous users cannot select favorite questions': 'Gastbenutzer können keine Fragen als Favoriten markieren', + 'bold': 'Fett', + 'bulleted list': 'Liste', + '{0} characters left': '{0} characters left', + 'cannot flag message as offensive twice': 'Beiträge können nicht doppelt gemeldet werden', + 'cannot pick own answer as best': 'Eigene Antworten können nicht als die korrekte akzeptiert werden', + 'click to close': 'Schließen mit Klick', + 'comments': 'Kommentare', + 'confirm delete': 'Löschen bestätigen', + 'confirm delete comment': 'Löschen des Kommentars bestätigen', + 'content cannot be empty': 'Inhalt darf nicht leer sein', + 'content minchars': 'Bitte mindestens {0} Zeichen eingeben', + 'daily vote cap exhausted': 'Tägliches Abstimmungslimit erreicht', + 'delete': 'löschen', + 'delete this comment': 'Diesen Kommentar löschen', + 'enter image url': 'Bild-URL eingeben, zum Beispiel <br />http://www.ihredomain.de/bildname.jpg', + 'enter url': 'URL eingeben, zum Beispiel <br />http://www.askbot.org/ </p>', + 'flag offensive cap exhausted': 'Tägliches Limit zum Melden von Beiträgen erreicht', + 'heading': 'Titel', + 'horizontal bar': 'horizontaler Balken', + 'image': 'Bild', + 'insufficient privilege': 'nicht genügend Rechte', + 'italic': 'Kursiv', + 'link': 'Link', + 'loading...': 'Lade...', + 'numbered list': 'Nummerierte Liste', + 'please confirm offensive': 'Bitte beleidigenden/regelwidrigen Beitrag bestätigen', + 'please enter title': 'Bitte Titel eingeben', + 'please login': 'Bitte einloggen', + 'post deleted': 'Beitrag gelöscht', + 'post recovered': 'Beitrag wiederhergestellt', + 'preformatted text': 'Vorformatierter Text', + 'quote': 'Zitat', + 'redo': 'Wiederholen', + 'tags cannot be empty': 'Tags dürfen nicht leer sein', + 'title minchars': 'Bitte mindestens {0} Zeichen eingeben', + 'undelete': 'wiederherstellen', + 'undo': 'Rückgängig', + 'upload image': 'Bild hochladen' +}; + + +var i18nRu = { + "anonymous users cannot vote": "Извините, но Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы голоÑовать, ", + 'add a comment': 'добавить комментарий', + 'add comment': 'добавить комментарий', + 'save comment': 'Ñохранить комментарий', + 'anonymous users cannot delete/undelete': 'неавторизированные пользователи не могут воÑÑтанавливать и удалÑÑ‚ÑŒ ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ ', + 'anonymous users cannot flag offensive posts': 'Извините, но Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы пожаловатьÑÑ Ð½Ð° Ñообщение, ', + 'anonymous users cannot select favorite questions': 'Извините, но Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы добавть Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð² закладки, ', + 'Are you sure you want to remove your {provider} login?': 'Ð’Ñ‹ дейÑтвительно хотите удалить логин через {provider}?', + 'bold': 'жирный', + 'bulleted list': 'маркированный ÑпиÑок', + 'cancel': 'cancel', + '{0} characters left': 'оÑталоÑÑŒ меÑто Ð´Ð»Ñ {0} Ñимволов', + 'cannot flag message as offensive twice': 'Ð½ÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ð¼ÐµÑ‚Ð¸Ñ‚ÑŒ Ñообщение как Ñпам два раза', + 'cannot pick own answer as best': 'Извините, выбрать ÑобÑтвенный ответ в качеÑтве лучшего не разрешаетÑÑ', + 'Change password': 'Изменить пароль', + 'Change your {provider} password': 'Измените Ваш пароль Ð´Ð»Ñ {provider}', + 'click to close': 'нажмите, что бы закрыть', + 'Create a password for {provider}': 'Создать пароль Ð´Ð»Ñ {provider}', + 'Create password': 'Создать пароль', + 'Create a password-protected account': 'Создать аккаунт, защищенный паролем', + 'comments': 'комментарии', + 'confirm abandon comment': '', + 'Connect your {provider_name} account to {site}': 'Соедините {site} Ñ Ð’Ð°ÑˆÐ¸Ð¼ аккаунтом от {provider_name}', + 'confirm delete': 'Удалить?', + 'confirm delete comment': 'Удалить комментарий?', + 'content cannot be empty': 'пожалуйÑта, добавьте Ñодержание', + 'content minchars': 'Ñодержание должно быть более {0} Ñимволов', + 'daily vote cap exhausted': 'иÑчерпан доÑтупный на ÑÐµÐ³Ð¾Ð´Ð½Ñ Ð»Ð¸Ð¼Ð¸Ñ‚ голоÑований', + 'delete': 'удалить', + 'save tags': 'запомнить теги', + 'delete this comment': 'удалить Ñтот комментарий', + 'Delete this notification?': 'Удалить Ñто извещение?', + 'Delete these notifications?': 'Удалить Ñти извещениÑ?', + 'enter image url': 'введите url изображениÑ, например:<br /> http://www.domain.ru/kartinka.gif', + 'enter url': 'введите url, например:<br />http://www.domain.ru/ </p>', + 'flag offensive cap exhausted': 'иÑчерпан доÑтупный на ÑÐµÐ³Ð¾Ð´Ð½Ñ Ð»Ð¸Ð¼Ð¸Ñ‚ Ñообщений о Ñпаме', + 'file name': 'название файла', + 'heading': 'заголовок', + 'horizontal bar': 'Ð³Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ð»Ð¾Ñа', + 'image': 'изображение', + 'image description': 'опиÑание изображениÑ', + 'insufficient privilege': 'недоÑтаточно прав', + 'italic': 'курÑив', + 'link': 'ÑÑылка', + 'link text': 'текÑÑ‚ ÑÑылки', + 'loading...': 'загрузка...', + 'passwords do not match': 'пароли не Ñовпадают', + 'numbered list': 'пронумерованный ÑпиÑок', + 'Please add one or more login methods.': 'ПожалуйÑта, добавьте Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один поÑтоÑнный метод Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸.', + 'please confirm offensive': 'Ð’Ñ‹ уверены что Ñто Ñообщение неумеÑтно?', + 'please enter title': 'пожалуйÑта, введите заголовок', + 'Please enter your {token_name}, then proceed': 'Чтобы продолжить, пожалуйÑта введите {token_name}', + 'Please select at least one item': 'ПожалуйÑта, отметьте Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ одно извещение', + 'enter more characters': 'недоÑтаточно Ñимволов, пожалуйÑта, добавьте ещё {0}', + 'please login': 'введите логин', + 'post deleted': 'Ñообщение удалено', + 'post recovered': 'воÑÑтановить Ñообщение', + 'preformatted text': 'форматирование текÑта', + 'quote': 'цитата', + 'redo': 'повторить', + 'see questions tagged \'{tag}\'': 'Ñмотрите вопроÑÑ‹, помеченные \'{tag}\'', + 'Show/change current login methods': 'ПроÑмотреть, изменить ÑущеÑтвующие методы авторизации.', + 'tags cannot be empty': 'введите теги', + 'title minchars': 'заголовок должен быть более {0} Ñимволов', + 'undelete': 'воÑÑтановить', + 'click to edit this comment': 'нажмите здеÑÑŒ, чтобы отредактировать Ñтот комментарий', + 'edit': 'редактировать', + 'undo': 'отменить', + 'upload image': 'загрузить изображение', + 'upload file attachment': 'загрузить файл', + 'You don\'t have a method to log in right now, please add one or more by clicking any of the icons below.': 'У Ð’Ð°Ñ ÑÐµÐ¹Ñ‡Ð°Ñ Ð½ÐµÑ‚ поÑтоÑнного метода авторизации, пожалуйÑта выберите Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один, нажав на любую из предложеных ниже кнопок.' +}; + +var i18nFr = { + "anonymous users cannot vote":"les utilisateurs anonyment ne peuvent pas voter ", + 'add a comment': 'Ajouter un commentaire', + 'add comment': 'OK', + 'anonymous users cannot delete/undelete': 'Les utilisateurs anonymes ne peuvent pas supprimer/restaurer', + 'anonymous users cannot flag offensive posts': 'Les utilisateurs anonymes ne peuvent pas signaler les messages à contenu abusif', + 'anonymous users cannot select favorite questions': 'Les utilisateurs anonymes ne peuvent pas sélectionner leurs questions favorites', + 'bold': 'gras', + 'bulleted list': 'liste', + '{0} characters left': '{0} characters left', + 'cannot flag message as offensive twice': 'Vous ne pouvez pas signaler deux fois un message à contenu abusif', + 'cannot pick own answer as best': 'Vous ne pouvez pas désigner une de vos propres réponses comme étant la meilleure réponse', + 'click to close': 'cliquez pour fermer', + 'comments': 'commentaires', + 'confirm delete': 'Confirmer la suppression', + 'confirm delete comment': 'Confirmer la suppression du commentaire', + 'content cannot be empty': 'Le contenu ne doit pas être vide', + 'content minchars': 'Veuillez saisir au moins {0} caractères', + 'daily vote cap exhausted': 'Votre quota journalier de votes est atteint', + 'delete': 'supprimer', + 'delete this comment': 'supprimer ce commentaire', + 'enter image url': 'Veuillez saisir une URL menant à une image, par exemple <br />http://www.votre-domaine.com/nom-image.jpg', + 'enter url': 'Entrez une URL, par exemple <br />http://www.askbot.org/ </p>', + 'flag offensive cap exhausted': 'Votre quota journalier de signalements de contenus abusifs a été atteint', + 'heading': 'Titre', + 'horizontal bar': 'Barre horizontale', + 'image': 'Image', + 'insufficient privilege': 'Privilèges insuffisants', + 'italic': 'italique', + 'link': 'lien', + 'loading...': 'Chargement en cours...', + 'numbered list': 'liste numérotée', + 'please confirm offensive': 'Veuillez confirmer que le contenu est abusif', + 'please enter title': 'Veuillez saisir un titre', + 'please login': 'Veuillez vous authentifier', + 'post deleted': 'Message supprimé', + 'post recovered': 'Message restauré', + 'preformatted text': 'Texte préformaté', + 'quote': 'Citer', + 'redo': 'Rétablir', + 'tags cannot be empty': 'Les mots-clés ne doivent pas être vides', + 'title minchars': 'Veuillez saisir au moins {0} caractères', + 'undelete': 'Restaurer', + 'undo': 'Annuler', + 'upload image': 'Charger une image' +}; + +var i18nIt = { + "anonymous users cannot vote":"Gli utenti anonimi non possono votare ", + 'add a comment': 'Aggiungi un commento', + 'add comment': 'OK', + 'anonymous users cannot delete/undelete': 'Gli utenti anonimi non possono cancellare/annullare la cancellazione', + 'anonymous users cannot flag offensive posts': 'Gli utenti anonimi non possono flaggare come offensivo questo post', + 'anonymous users cannot select favorite questions': 'Gli utenti anonimi non possono aggiungere domande ai preferiti', + 'bold': 'grassetto', + 'bulleted list': 'Lista', + 'cannot flag message as offensive twice': 'non è possibile flaggare come offensivo più di una volta ', + 'cannot pick own answer as best': 'non è possibile assegnare come miglior risposta ad una propria domanda una propria risposta', + '{0} characters left': '{0} caratteri rimanenti', + 'click to close': 'clicca per chiudere', + 'comments': 'commenti', + 'confirm delete': 'conferma la cancellazione', + 'confirm delete comment': 'Vuoi davvero cancellare il commento?', + 'content cannot be empty': 'il contenuto non può essere vuoto', + 'content minchars': 'per favore inserisci più di {0} caratteri', + 'daily vote cap exhausted': 'Spiacente, hai raggiunto il limite odierno massimo di voti', + 'delete': 'elimina', + 'delete this comment': 'Elimina questo commento', + 'enter image url': 'inserisci l\'URL dell\'immagine, es. http://www.example.com/immagine.jpg \"titolo immagine\"', + 'enter url': 'inserisci l\'indirizzo web, e.g. <br />http://www.askbot.org/ </p>', + 'flag offensive cap exhausted': 'spiacente, hai raggiunto il limite odierno massimo di flag offensivi ', + 'heading': 'Titolo', + 'horizontal bar': 'barra orizzontale', + 'image': 'Immagine', + 'insufficient privilege': 'privilegi non sufficienti', + 'italic': 'corsivo', + 'link': 'Link', + 'loading...': 'Caricamento...', + 'numbered list': 'Lista numerata', + 'please confirm offensive': 'sei certo che questo post sia offensivo, contenga spam, pubblicità , osservazioni poco idonee, ecc.?', + 'please enter title': 'Per favore inserisci il titolo', + 'please login': 'Per favore effettua il login', + 'post deleted': 'Post eliminato', + 'post recovered': 'Post recuperato', + 'preformatted text': 'Testo preformattato', + 'quote': 'cita', + 'redo': 'Esegui nuovamente', + 'tags cannot be empty': 'Il campo Tags non può essere vuoto', + 'title minchars': 'per favore inserisci almeno {0} caratteri', + 'undelete': 'elimina', + 'undo': 'annulla', + 'upload image': 'carica immagine' +}; + +var i18n = { + 'en':i18nEn, + 'zh-cn':i18nZh, + 'es':i18nEs, + 'tr':i18nTr, + 'de':i18nDe, + 'ru':i18nRu, + 'fr':i18nFr, + 'it':i18nIt, + 'zh-tw':i18nZhtw +}; + +var i18n_dict = i18n[i18nLang]; diff --git a/askbot/skins/old/media/js/jquery-1.4.3.js b/askbot/skins/old/media/js/jquery-1.4.3.js new file mode 100644 index 00000000..ad9a79c4 --- /dev/null +++ b/askbot/skins/old/media/js/jquery-1.4.3.js @@ -0,0 +1,6883 @@ +/*! + * jQuery JavaScript Library v1.4.3 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Oct 14 23:10:06 2010 -0400 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, + + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + rwhite = /\s/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for non-word characters + rnonword = /\W/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $("TAG") + } else if ( !context && !rnonword.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.4.3", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || jQuery(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy, copyIsArray; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + // A third-party is pushing the ready event forwards + if ( wait === true ) { + jQuery.readyWait--; + } + + // Make sure that the DOM is not already loaded + if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, i = 0; + while ( (fn = readyList[ i++ ]) ) { + fn.call( document, jQuery ); + } + + // Reset the list of functions + readyList = null; + } + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test(data.replace(rvalidescape, "@") + .replace(rvalidtokens, "]") + .replace(rvalidbraces, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type(array); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can be optionally by executed if its a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// Verify that \s matches non-breaking spaces +// (IE fails on this test) +if ( !rwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +// Expose jQuery to the global object +return (window.jQuery = window.$ = jQuery); + +})(); + + +(function() { + + jQuery.support = {}; + + var root = document.documentElement, + script = document.createElement("script"), + div = document.createElement("div"), + id = "script" + jQuery.now(); + + div.style.display = "none"; + div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0], + select = document.createElement("select"), + opt = select.appendChild( document.createElement("option") ); + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: div.getElementsByTagName("input")[0].value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Will be defined later + optDisabled: false, + checkClone: false, + scriptEval: false, + noCloneEvent: true, + boxModel: null, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableHiddenOffsets: true + }; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as diabled) + select.disabled = true; + jQuery.support.optDisabled = !opt.disabled; + + script.type = "text/javascript"; + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + jQuery.support.scriptEval = true; + delete window[ id ]; + } + + root.removeChild( script ); + + if ( div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>"; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"); + div.style.width = div.style.paddingLeft = "1px"; + + document.body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "<div style='width:4px;'></div>"; + jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; + } + + div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>"; + var tds = div.getElementsByTagName("td"); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; + + tds[0].style.display = ""; + tds[1].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; + div.innerHTML = ""; + + document.body.removeChild( div ).style.display = "none"; + div = tds = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + root = script = div = all = a = null; +})(); + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; + + + + +var windowData = {}, + rbrace = /^(?:\{.*\}|\[.*\])$/; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + expando: "jQuery" + jQuery.now(), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + data: function( elem, name, data ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var isNode = elem.nodeType, + id = isNode ? elem[ jQuery.expando ] : null, + cache = jQuery.cache, thisCache; + + if ( isNode && !id && typeof name === "string" && data === undefined ) { + return; + } + + // Get the data from the object directly + if ( !isNode ) { + cache = elem; + + // Compute a unique ID for the element + } else if ( !id ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } + + // Avoid generating a new cache unless none exists and we + // want to manipulate it. + if ( typeof name === "object" ) { + if ( isNode ) { + cache[ id ] = jQuery.extend(cache[ id ], name); + + } else { + jQuery.extend( cache, name ); + } + + } else if ( isNode && !cache[ id ] ) { + cache[ id ] = {}; + } + + thisCache = isNode ? cache[ id ] : cache; + + // Prevent overriding the named cache with undefined values + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + return typeof name === "string" ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var isNode = elem.nodeType, + id = isNode ? elem[ jQuery.expando ] : elem, + cache = jQuery.cache, + thisCache = isNode ? cache[ id ] : id; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( thisCache ) { + // Remove the section of cache data + delete thisCache[ name ]; + + // If we've removed all the data, remove the element's cache + if ( isNode && jQuery.isEmptyObject(thisCache) ) { + jQuery.removeData( elem ); + } + } + + // Otherwise, we want to remove all of the element's data + } else { + if ( isNode && jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + + // Completely remove the data cache + } else if ( isNode ) { + delete cache[ id ]; + + // Remove all fields from the object + } else { + for ( var n in elem ) { + delete elem[ n ]; + } + } + } + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + if ( typeof key === "undefined" ) { + return this.length ? jQuery.data( this[0] ) : null; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && this[0].nodeType === 1 ) { + data = this[0].getAttribute( "data-" + key ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + } else { + data = undefined; + } + } + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + + + + +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); + + + + +var rclass = /[\n\t]/g, + rspaces = /\s+/, + rreturn = /\r/g, + rspecialurl = /^(?:href|src|style)$/, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rradiocheck = /^(?:radio|checkbox)$/i; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", setClass = elem.className; + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, i = 0, self = jQuery(this), + state = stateVal, + classNames = value.split( rspaces ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery.data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( !arguments.length ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray(val) ) { + val = jQuery.map(val, function (value) { + return value == null ? "" : value + ""; + }); + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't set attributes on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + // 'in' checks fail in Blackberry 4.7 #6931 + if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + if ( value === null ) { + if ( elem.nodeType === 1 ) { + elem.removeAttribute( name ); + } + + } else { + elem[ name ] = value; + } + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + // Ensure that missing attributes return undefined + // Blackberry 4.7 returns "" from getAttribute #6938 + if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { + return undefined; + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + } +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspace = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }, + focusCounts = { focusin: 0, focusout: 0 }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery.data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + // Use a key less likely to result in collisions for plain JS objects. + // Fixes bug #7150. + var eventKey = elem.nodeType ? "events" : "__events__", + events = elemData[ eventKey ], + eventHandle = elemData.handle; + + if ( typeof events === "function" ) { + // On plain objects events is a fn that holds the the data + // which prevents this data from being JSON serialized + // the function does not need to be called, it just contains the data + eventHandle = events.handle; + events = events.events; + + } else if ( !events ) { + if ( !elem.nodeType ) { + // On plain objects, create a fn that acts as the holder + // of the values to avoid JSON serialization of event data + elemData[ eventKey ] = elemData = function(){}; + } + + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + eventKey = elem.nodeType ? "events" : "__events__", + elemData = jQuery.data( elem ), + events = elemData && elemData[ eventKey ]; + + if ( !elemData || !events ) { + return; + } + + if ( typeof events === "function" ) { + elemData = events; + events = events.events; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( typeof elemData === "function" ) { + jQuery.removeData( elem, eventKey ); + + } else if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + jQuery.each( jQuery.cache, function() { + if ( this.events && this.events[type] ) { + jQuery.event.trigger( event, data, this.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = elem.nodeType ? + jQuery.data( elem, "handle" ) : + (jQuery.data( elem, "__events__" ) || {}).handle; + + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + event.preventDefault(); + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (inlineError) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var target = event.target, old, targetType = type.replace(rnamespaces, ""), + isClick = jQuery.nodeName(target, "a") && targetType === "click", + special = jQuery.event.special[ targetType ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ targetType ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + targetType ]; + + if ( old ) { + target[ "on" + targetType ] = null; + } + + jQuery.event.triggered = true; + target[ targetType ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (triggerError) {} + + if ( old ) { + target[ "on" + targetType ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace_sort = [], namespace_re, events, args = jQuery.makeArray( arguments ); + + event = args[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace_sort = namespaces.slice(0).sort(); + namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.namespace = event.namespace || namespace_sort.join("."); + + events = jQuery.data(this, this.nodeType ? "events" : "__events__"); + + if ( typeof events === "function" ) { + events = events.events; + } + + handlers = (events || {})[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, body = document.body; + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + e.liveFired = undefined; + return trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + e.liveFired = undefined; + return trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery.data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery.data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + return jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + return testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + return testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery.data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + args[0].type = type; + return jQuery.event.handle.apply( elem, args ); +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + if ( focusCounts[fix]++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --focusCounts[fix] === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.trigger( e, null, e.target ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) || data === false ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, elems = [], selectors = [], + related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + events = jQuery.data( this, this.nodeType ? "events" : "__events__" ); + + if ( typeof events === "function" ) { + events = events.events; + } + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) + if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + +// Prevent memory leaks in IE +// Window isn't included so as not to unbind existing unload events +// More info: +// - http://isaacschlueter.com/2006/10/msie-memory-leaks/ +if ( window.attachEvent && !window.addEventListener ) { + jQuery(window).bind("unload", function() { + for ( var id in jQuery.cache ) { + if ( jQuery.cache[ id ].handle ) { + // Try/Catch is to handle iframes being unloaded, see #4280 + try { + jQuery.event.remove( jQuery.cache[ id ].handle.elem ); + } catch(e) {} + } + } + }); +} + + +/*! + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function(){ + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function(selector, context, results, seed) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, extra, prune = true, contextXML = Sizzle.isXML(context), + soFar = selector, ret, cur, pop, i; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec(""); + m = chunker.exec(soFar); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function(results){ + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[i-1] ) { + results.splice(i--, 1); + } + } + } + } + + return results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.matchesSelector = function(node, expr){ + return Sizzle(expr, null, null, [node]).length > 0; +}; + +Sizzle.find = function(expr, context, isXML){ + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && Sizzle.isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var filter = Expr.filter[ type ], found, item, left = match[1]; + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.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(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part){ + var isPartStr = typeof part === "string", + elem, i = 0, l = checkSet.length; + + if ( isPartStr && !/\W/.test(part) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck, nodeCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck, nodeCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + NAME: function(match, context){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + return match[1].toLowerCase(); + }, + CHILD: function(match){ + if ( match[1] === "nth" ) { + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + PSEUDO: function(match, curLoop, inplace, result, not){ + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return (/h\d/i).test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input: function(elem){ + return (/input|select|textarea|button/i).test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 === i; + }, + eq: function(elem, i, match){ + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function(elem, match, i, array){ + var name = match[1], filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + } else { + Sizzle.error( "Syntax error, unrecognized expression: " + name ); + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + if ( type === "first" ) { + return true; + } + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first === 0 ) { + return diff === 0; + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch(e){ + makeArray = function(array, results) { + var ret = results || [], i = 0; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; +} else { + sortOrder = function( a, b ) { + var ap = [], bp = [], aup = a.parentNode, bup = b.parentNode, + cur = aup, al, bl; + + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // If the nodes are siblings (or identical) we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(); + form.innerHTML = "<a name='" + id + "'/>"; + + // Inject it into the root element, check its status, and remove it quickly + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function(match, context){ + var results = context.getElementsByTagName(match[1]); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = "<a href='#'></a>"; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "<p class='TEST'></p>"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + if ( context.nodeType === 9 ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var old = context.id, id = context.id = "__sizzle__"; + + try { + return makeArray( context.querySelectorAll( "#" + id + " " + query ), extra ); + + } catch(pseudoError) { + } finally { + if ( old ) { + context.id = old; + + } else { + context.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, ":sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + if ( matches ) { + Sizzle.matchesSelector = function( node, expr ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) ) { + return matches.call( node, expr ); + } + } catch(e) {} + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "<div class='test e'></div><div class='test'></div>"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +Sizzle.contains = document.documentElement.contains ? function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +} : function(a, b){ + return !!(a.compareDocumentPosition(b) & 16); +}; + +Sizzle.isXML = function(elem){ + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + if ( jQuery.isArray( selectors ) ) { + var match, matches = {}, selector, level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + var pos = POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique(ret) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context || this.context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call(arguments).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], cur = elem[dir]; + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /<tbody/i, + rhtml = /<|&#?\w+;/, + rnocache = /<(?:script|object|embed|option|style)/i, + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, // checked="checked" or checked (html5) + raction = /\=([^="'>\s]+\/)>/g, + wrapMap = { + 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, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize <link> and <script> tags normally +if ( !jQuery.support.htmlSerialize ) { + wrapMap._default = [ 1, "div<div>", "</div>" ]; +} + +jQuery.fn.extend({ + text: function( text ) { + if ( jQuery.isFunction(text) ) { + return this.each(function(i) { + var self = jQuery(this); + self.text( text.call(this, i, self.text()) ); + }); + } + + if ( typeof text !== "object" && text !== undefined ) { + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + } + + return jQuery.text( this ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append(this); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + return this.each(function() { + jQuery( this ).wrapAll( html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }, + + append: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }, + + before: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this ); + }); + } else if ( arguments.length ) { + var set = jQuery(arguments[0]); + set.push.apply( set, this.toArray() ); + return this.pushStack( set, "before", arguments ); + } + }, + + after: function() { + if ( this[0] && this[0].parentNode ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + } else if ( arguments.length ) { + var set = this.pushStack( this, "after", arguments ); + set.push.apply( set, jQuery(arguments[0]).toArray() ); + return set; + } + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( [ elem ] ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + return this; + }, + + clone: function( events ) { + // Do the clone + var ret = this.map(function() { + if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) { + // IE copies events bound via attachEvent when + // using cloneNode. Calling detachEvent on the + // clone will also remove the events from the orignal + // In order to get around this, we use innerHTML. + // Unfortunately, this means some modifications to + // attributes in IE that are actually only stored + // as properties will not be copied (such as the + // the name attribute on an input). + var html = this.outerHTML, ownerDocument = this.ownerDocument; + if ( !html ) { + var div = ownerDocument.createElement("div"); + div.appendChild( this.cloneNode(true) ); + html = div.innerHTML; + } + + return jQuery.clean([html.replace(rinlinejQuery, "") + // Handle the case in IE 8 where action=/test/> self-closes a tag + .replace(raction, '="$1">') + .replace(rleadingWhitespace, "")], ownerDocument)[0]; + } else { + return this.cloneNode(true); + } + }); + + // Copy the events from the original to the clone + if ( events === true ) { + cloneCopyEvent( this, ret ); + cloneCopyEvent( this.find("*"), ret.find("*") ); + } + + // Return the cloned set + return ret; + }, + + html: function( value ) { + if ( value === undefined ) { + return this[0] && this[0].nodeType === 1 ? + this[0].innerHTML.replace(rinlinejQuery, "") : + null; + + // See if we can take a shortcut and just use innerHTML + } else if ( typeof value === "string" && !rnocache.test( value ) && + (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && + !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { + + value = value.replace(rxhtmlTag, "<$1></$2>"); + + try { + for ( var i = 0, l = this.length; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + if ( this[i].nodeType === 1 ) { + jQuery.cleanData( this[i].getElementsByTagName("*") ); + this[i].innerHTML = value; + } + } + + // If using innerHTML throws an exception, use the fallback method + } catch(e) { + this.empty().append( value ); + } + + } else if ( jQuery.isFunction( value ) ) { + this.each(function(i){ + var self = jQuery(this); + self.html( value.call(this, i, self.html()) ); + }); + + } else { + this.empty().append( value ); + } + + return this; + }, + + replaceWith: function( value ) { + if ( this[0] && this[0].parentNode ) { + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this), old = self.html(); + self.replaceWith( value.call( this, i, old ) ); + }); + } + + if ( typeof value !== "string" ) { + value = jQuery(value).detach(); + } + + return this.each(function() { + var next = this.nextSibling, parent = this.parentNode; + + jQuery(this).remove(); + + if ( next ) { + jQuery(next).before( value ); + } else { + jQuery(parent).append( value ); + } + }); + } else { + return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ); + } + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + var results, first, value = args[0], scripts = [], fragment, parent; + + // We can't cloneNode fragments that contain checked, in WebKit + if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) { + return this.each(function() { + jQuery(this).domManip( args, table, callback, true ); + }); + } + + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + args[0] = value.call(this, i, table ? self.html() : undefined); + self.domManip( args, table, callback ); + }); + } + + if ( this[0] ) { + parent = value && value.parentNode; + + // If we're in a fragment, just use that instead of building a new one + if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) { + results = { fragment: parent }; + + } else { + results = jQuery.buildFragment( args, this, scripts ); + } + + fragment = results.fragment; + + if ( fragment.childNodes.length === 1 ) { + first = fragment = fragment.firstChild; + } else { + first = fragment.firstChild; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + callback.call( + table ? + root(this[i], first) : + this[i], + i > 0 || results.cacheable || this.length > 1 ? + fragment.cloneNode(true) : + fragment + ); + } + } + + if ( scripts.length ) { + jQuery.each( scripts, evalScript ); + } + } + + return this; + } +}); + +function root( elem, cur ) { + return jQuery.nodeName(elem, "table") ? + (elem.getElementsByTagName("tbody")[0] || + elem.appendChild(elem.ownerDocument.createElement("tbody"))) : + elem; +} + +function cloneCopyEvent(orig, ret) { + var i = 0; + + ret.each(function() { + if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) { + return; + } + + var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( var type in events ) { + for ( var handler in events[ type ] ) { + jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); + } + } + } + }); +} + +jQuery.buildFragment = function( args, nodes, scripts ) { + var fragment, cacheable, cacheresults, + doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); + + // Only cache "small" (1/2 KB) strings that are associated with the main document + // Cloning options loses the selected state, so don't cache them + // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment + // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache + if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && + !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { + + cacheable = true; + cacheresults = jQuery.fragments[ args[0] ]; + if ( cacheresults ) { + if ( cacheresults !== 1 ) { + fragment = cacheresults; + } + } + } + + if ( !fragment ) { + fragment = doc.createDocumentFragment(); + jQuery.clean( args, doc, fragment, scripts ); + } + + if ( cacheable ) { + jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1; + } + + return { fragment: fragment, cacheable: cacheable }; +}; + +jQuery.fragments = {}; + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var ret = [], insert = jQuery( selector ), + parent = this.length === 1 && this[0].parentNode; + + if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { + insert[ original ]( this[0] ); + return this; + + } else { + for ( var i = 0, l = insert.length; i < l; i++ ) { + var elems = (i > 0 ? this.clone(true) : this).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +}); + +jQuery.extend({ + clean: function( elems, context, fragment, scripts ) { + context = context || document; + + // !context.createElement fails in IE with an error but returns typeof 'object' + if ( typeof context.createElement === "undefined" ) { + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + } + + var ret = []; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( typeof elem === "number" ) { + elem += ""; + } + + if ( !elem ) { + continue; + } + + // Convert html string into DOM nodes + if ( typeof elem === "string" && !rhtml.test( elem ) ) { + elem = context.createTextNode( elem ); + + } else if ( typeof elem === "string" ) { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(rxhtmlTag, "<$1></$2>"); + + // Trim whitespace, otherwise indexOf won't work as expected + var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(), + wrap = wrapMap[ tag ] || wrapMap._default, + depth = wrap[0], + div = context.createElement("div"); + + // Go to html and back, then peel off extra wrappers + div.innerHTML = wrap[1] + elem + wrap[2]; + + // Move to the right depth + while ( depth-- ) { + div = div.lastChild; + } + + // Remove IE's autoinserted <tbody> from table fragments + if ( !jQuery.support.tbody ) { + + // String was a <table>, *may* have spurious <tbody> + var hasBody = rtbody.test(elem), + tbody = tag === "table" && !hasBody ? + div.firstChild && div.firstChild.childNodes : + + // String was a bare <thead> or <tfoot> + wrap[1] === "<table>" && !hasBody ? + div.childNodes : + []; + + for ( var j = tbody.length - 1; j >= 0 ; --j ) { + if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { + tbody[ j ].parentNode.removeChild( tbody[ j ] ); + } + } + + } + + // IE completely kills leading whitespace when innerHTML is used + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); + } + + elem = div.childNodes; + } + + if ( elem.nodeType ) { + ret.push( elem ); + } else { + ret = jQuery.merge( ret, elem ); + } + } + + if ( fragment ) { + for ( i = 0; ret[i]; i++ ) { + if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) { + scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] ); + + } else { + if ( ret[i].nodeType === 1 ) { + ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) ); + } + fragment.appendChild( ret[i] ); + } + } + } + + return ret; + }, + + cleanData: function( elems ) { + var data, id, cache = jQuery.cache, + special = jQuery.event.special, + deleteExpando = jQuery.support.deleteExpando; + + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + continue; + } + + id = elem[ jQuery.expando ]; + + if ( id ) { + data = cache[ id ]; + + if ( data && data.events ) { + for ( var type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + if ( deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + delete cache[ id ]; + } + } + } +}); + +function evalScript( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } +} + + + + +var ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity=([^)]*)/, + rdashAlpha = /-([a-z])/ig, + rupper = /([A-Z])/g, + rnumpx = /^-?\d+(?:px)?$/i, + rnum = /^-?\d/, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssWidth = [ "Left", "Right" ], + cssHeight = [ "Top", "Bottom" ], + curCSS, + + // cache check for defaultView.getComputedStyle + getComputedStyle = document.defaultView && document.defaultView.getComputedStyle, + + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn.css = function( name, value ) { + // Setting 'undefined' is a no-op + if ( arguments.length === 2 && value === undefined ) { + return this; + } + + return jQuery.access( this, name, value, true, function( elem, name, value ) { + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }); +}; + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity", "opacity" ); + return ret === "" ? "1" : ret; + + } else { + return elem.style.opacity; + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "zIndex": true, + "fontWeight": true, + "opacity": true, + "zoom": true, + "lineHeight": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, origName = jQuery.camelCase( name ), + style = elem.style, hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // Check if we're setting a value + if ( value !== undefined ) { + // Make sure that NaN and null values aren't set. See: #7116 + if ( typeof value === "number" && isNaN( value ) || value == null ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) { + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra ) { + // Make sure that we're working with the right name + var ret, origName = jQuery.camelCase( name ), + hooks = jQuery.cssHooks[ origName ]; + + name = jQuery.cssProps[ origName ] || origName; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) { + return ret; + + // Otherwise, if a way to get the computed value exists, use that + } else if ( curCSS ) { + return curCSS( elem, name, origName ); + } + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}; + + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + }, + + camelCase: function( string ) { + return string.replace( rdashAlpha, fcamelCase ); + } +}); + +// DEPRECATED, Use jQuery.css() instead +jQuery.curCSS = jQuery.css; + +jQuery.each(["height", "width"], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + var val; + + if ( computed ) { + if ( elem.offsetWidth !== 0 ) { + val = getWH( elem, name, extra ); + + } else { + jQuery.swap( elem, cssShow, function() { + val = getWH( elem, name, extra ); + }); + } + + return val + "px"; + } + }, + + set: function( elem, value ) { + if ( rnumpx.test( value ) ) { + // ignore negative width and height values #1599 + value = parseFloat(value); + + if ( value >= 0 ) { + return value + "px"; + } + + } else { + return value; + } + } + }; +}); + +if ( !jQuery.support.opacity ) { + jQuery.cssHooks.opacity = { + get: function( elem, computed ) { + // IE uses filters for opacity + return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ? + (parseFloat(RegExp.$1) / 100) + "" : + computed ? "1" : ""; + }, + + set: function( elem, value ) { + var style = elem.style; + + // IE has trouble with opacity if it does not have layout + // Force it by setting the zoom level + style.zoom = 1; + + // Set the alpha filter to set the opacity + var opacity = jQuery.isNaN(value) ? + "" : + "alpha(opacity=" + value * 100 + ")", + filter = style.filter || ""; + + style.filter = ralpha.test(filter) ? + filter.replace(ralpha, opacity) : + style.filter + ' ' + opacity; + } + }; +} + +if ( getComputedStyle ) { + curCSS = function( elem, newName, name ) { + var ret, defaultView, computedStyle; + + name = name.replace( rupper, "-$1" ).toLowerCase(); + + if ( !(defaultView = elem.ownerDocument.defaultView) ) { + return undefined; + } + + if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) { + ret = computedStyle.getPropertyValue( name ); + if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) { + ret = jQuery.style( elem, name ); + } + } + + return ret; + }; + +} else if ( document.documentElement.currentStyle ) { + curCSS = function( elem, name ) { + var left, rsLeft, ret = elem.currentStyle && elem.currentStyle[ name ], style = elem.style; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !rnumpx.test( ret ) && rnum.test( ret ) ) { + // Remember the original values + left = style.left; + rsLeft = elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + elem.runtimeStyle.left = elem.currentStyle.left; + style.left = name === "fontSize" ? "1em" : (ret || 0); + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + elem.runtimeStyle.left = rsLeft; + } + + return ret; + }; +} + +function getWH( elem, name, extra ) { + var which = name === "width" ? cssWidth : cssHeight, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight; + + if ( extra === "border" ) { + return val; + } + + jQuery.each( which, function() { + if ( !extra ) { + val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0; + } + + if ( extra === "margin" ) { + val += parseFloat(jQuery.css( elem, "margin" + this )) || 0; + + } else { + val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0; + } + }); + + return val; +} + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.hidden = function( elem ) { + var width = elem.offsetWidth, height = elem.offsetHeight; + + return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none"); + }; + + jQuery.expr.filters.visible = function( elem ) { + return !jQuery.expr.filters.hidden( elem ); + }; +} + + + + +var jsc = jQuery.now(), + rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, + rselectTextarea = /^(?:select|textarea)/i, + rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, + rnoContent = /^(?:GET|HEAD|DELETE)$/, + rbracket = /\[\]$/, + jsre = /\=\?(&|$)/, + rquery = /\?/, + rts = /([?&])_=[^&]*/, + rurl = /^(\w+:)?\/\/([^\/?#]+)/, + r20 = /%20/g, + rhash = /#.*$/, + + // Keep a copy of the old load method + _load = jQuery.fn.load; + +jQuery.fn.extend({ + load: function( url, params, callback ) { + if ( typeof url !== "string" && _load ) { + return _load.apply( this, arguments ); + + // Don't do a request if no elements are being requested + } else if ( !this.length ) { + return this; + } + + var off = url.indexOf(" "); + if ( off >= 0 ) { + var selector = url.slice(off, url.length); + url = url.slice(0, off); + } + + // Default to a GET request + var type = "GET"; + + // If the second parameter was provided + if ( params ) { + // If it's a function + if ( jQuery.isFunction( params ) ) { + // We assume that it's the callback + callback = params; + params = null; + + // Otherwise, build a param string + } else if ( typeof params === "object" ) { + params = jQuery.param( params, jQuery.ajaxSettings.traditional ); + type = "POST"; + } + } + + var self = this; + + // Request the remote document + jQuery.ajax({ + url: url, + type: type, + dataType: "html", + data: params, + complete: function( res, status ) { + // If successful, inject the HTML into all the matched elements + if ( status === "success" || status === "notmodified" ) { + // See if a selector was specified + self.html( selector ? + // Create a dummy div to hold the results + jQuery("<div>") + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append(res.responseText.replace(rscript, "")) + + // Locate the specified elements + .find(selector) : + + // If not, just inject the full result + res.responseText ); + } + + if ( callback ) { + self.each( callback, [res.responseText, status, res] ); + } + } + }); + + return this; + }, + + serialize: function() { + return jQuery.param(this.serializeArray()); + }, + + serializeArray: function() { + return this.map(function() { + return this.elements ? jQuery.makeArray(this.elements) : this; + }) + .filter(function() { + return this.name && !this.disabled && + (this.checked || rselectTextarea.test(this.nodeName) || + rinput.test(this.type)); + }) + .map(function( i, elem ) { + var val = jQuery(this).val(); + + return val == null ? + null : + jQuery.isArray(val) ? + jQuery.map( val, function( val, i ) { + return { name: elem.name, value: val }; + }) : + { name: elem.name, value: val }; + }).get(); + } +}); + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) { + jQuery.fn[o] = function( f ) { + return this.bind(o, f); + }; +}); + +jQuery.extend({ + get: function( url, data, callback, type ) { + // shift arguments if data argument was omited + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = null; + } + + return jQuery.ajax({ + type: "GET", + url: url, + data: data, + success: callback, + dataType: type + }); + }, + + getScript: function( url, callback ) { + return jQuery.get(url, null, callback, "script"); + }, + + getJSON: function( url, data, callback ) { + return jQuery.get(url, data, callback, "json"); + }, + + post: function( url, data, callback, type ) { + // shift arguments if data argument was omited + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = {}; + } + + return jQuery.ajax({ + type: "POST", + url: url, + data: data, + success: callback, + dataType: type + }); + }, + + ajaxSetup: function( settings ) { + jQuery.extend( jQuery.ajaxSettings, settings ); + }, + + ajaxSettings: { + url: location.href, + global: true, + type: "GET", + contentType: "application/x-www-form-urlencoded", + processData: true, + async: true, + /* + timeout: 0, + data: null, + username: null, + password: null, + traditional: false, + */ + // This function can be overriden by calling jQuery.ajaxSetup + xhr: function() { + return new window.XMLHttpRequest(); + }, + accepts: { + xml: "application/xml, text/xml", + html: "text/html", + script: "text/javascript, application/javascript", + json: "application/json, text/javascript", + text: "text/plain", + _default: "*/*" + } + }, + + ajax: function( origSettings ) { + var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings), + jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type); + + s.url = s.url.replace( rhash, "" ); + + // Use original (not extended) context object if it was provided + s.context = origSettings && origSettings.context != null ? origSettings.context : s; + + // convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Handle JSONP Parameter Callbacks + if ( s.dataType === "jsonp" ) { + if ( type === "GET" ) { + if ( !jsre.test( s.url ) ) { + s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?"; + } + } else if ( !s.data || !jsre.test(s.data) ) { + s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?"; + } + s.dataType = "json"; + } + + // Build temporary JSONP function + if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) { + jsonp = s.jsonpCallback || ("jsonp" + jsc++); + + // Replace the =? sequence both in the query string and the data + if ( s.data ) { + s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1"); + } + + s.url = s.url.replace(jsre, "=" + jsonp + "$1"); + + // We need to make sure + // that a JSONP style response is executed properly + s.dataType = "script"; + + // Handle JSONP-style loading + var customJsonp = window[ jsonp ]; + + window[ jsonp ] = function( tmp ) { + data = tmp; + jQuery.handleSuccess( s, xhr, status, data ); + jQuery.handleComplete( s, xhr, status, data ); + + if ( jQuery.isFunction( customJsonp ) ) { + customJsonp( tmp ); + + } else { + // Garbage collect + window[ jsonp ] = undefined; + + try { + delete window[ jsonp ]; + } catch( jsonpError ) {} + } + + if ( head ) { + head.removeChild( script ); + } + }; + } + + if ( s.dataType === "script" && s.cache === null ) { + s.cache = false; + } + + if ( s.cache === false && type === "GET" ) { + var ts = jQuery.now(); + + // try replacing _= if it is there + var ret = s.url.replace(rts, "$1_=" + ts); + + // if nothing was replaced, add timestamp to the end + s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : ""); + } + + // If data is available, append data to url for get requests + if ( s.data && type === "GET" ) { + s.url += (rquery.test(s.url) ? "&" : "?") + s.data; + } + + // Watch for a new set of requests + if ( s.global && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Matches an absolute URL, and saves the domain + var parts = rurl.exec( s.url ), + remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host); + + // If we're requesting a remote document + // and trying to load JSON or Script with a GET + if ( s.dataType === "script" && type === "GET" && remote ) { + var head = document.getElementsByTagName("head")[0] || document.documentElement; + var script = document.createElement("script"); + if ( s.scriptCharset ) { + script.charset = s.scriptCharset; + } + script.src = s.url; + + // Handle Script loading + if ( !jsonp ) { + var done = false; + + // Attach handlers for all browsers + script.onload = script.onreadystatechange = function() { + if ( !done && (!this.readyState || + this.readyState === "loaded" || this.readyState === "complete") ) { + done = true; + jQuery.handleSuccess( s, xhr, status, data ); + jQuery.handleComplete( s, xhr, status, data ); + + // Handle memory leak in IE + script.onload = script.onreadystatechange = null; + if ( head && script.parentNode ) { + head.removeChild( script ); + } + } + }; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709 and #4378). + head.insertBefore( script, head.firstChild ); + + // We handle everything using the script element injection + return undefined; + } + + var requestDone = false; + + // Create the request object + var xhr = s.xhr(); + + if ( !xhr ) { + return; + } + + // Open the socket + // Passing null username, generates a login popup on Opera (#2865) + if ( s.username ) { + xhr.open(type, s.url, s.async, s.username, s.password); + } else { + xhr.open(type, s.url, s.async); + } + + // Need an extra try/catch for cross domain requests in Firefox 3 + try { + // Set content-type if data specified and content-body is valid for this type + if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) { + xhr.setRequestHeader("Content-Type", s.contentType); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[s.url] ) { + xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]); + } + + if ( jQuery.etag[s.url] ) { + xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]); + } + } + + // Set header so the called script knows that it's an XMLHttpRequest + // Only send the header if it's not a remote XHR + if ( !remote ) { + xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); + } + + // Set the Accepts header for the server, depending on the dataType + xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ? + s.accepts[ s.dataType ] + ", */*; q=0.01" : + s.accepts._default ); + } catch( headerError ) {} + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false ) { + // Handle the global AJAX counter + if ( s.global && jQuery.active-- === 1 ) { + jQuery.event.trigger( "ajaxStop" ); + } + + // close opended socket + xhr.abort(); + return false; + } + + if ( s.global ) { + jQuery.triggerGlobal( s, "ajaxSend", [xhr, s] ); + } + + // Wait for a response to come back + var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) { + // The request was aborted + if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) { + // Opera doesn't call onreadystatechange before this point + // so we simulate the call + if ( !requestDone ) { + jQuery.handleComplete( s, xhr, status, data ); + } + + requestDone = true; + if ( xhr ) { + xhr.onreadystatechange = jQuery.noop; + } + + // The transfer is complete and the data is available, or the request timed out + } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) { + requestDone = true; + xhr.onreadystatechange = jQuery.noop; + + status = isTimeout === "timeout" ? + "timeout" : + !jQuery.httpSuccess( xhr ) ? + "error" : + s.ifModified && jQuery.httpNotModified( xhr, s.url ) ? + "notmodified" : + "success"; + + var errMsg; + + if ( status === "success" ) { + // Watch for, and catch, XML document parse errors + try { + // process the data (runs the xml through httpData regardless of callback) + data = jQuery.httpData( xhr, s.dataType, s ); + } catch( parserError ) { + status = "parsererror"; + errMsg = parserError; + } + } + + // Make sure that the request was successful or notmodified + if ( status === "success" || status === "notmodified" ) { + // JSONP handles its own success callback + if ( !jsonp ) { + jQuery.handleSuccess( s, xhr, status, data ); + } + } else { + jQuery.handleError( s, xhr, status, errMsg ); + } + + // Fire the complete handlers + if ( !jsonp ) { + jQuery.handleComplete( s, xhr, status, data ); + } + + if ( isTimeout === "timeout" ) { + xhr.abort(); + } + + // Stop memory leaks + if ( s.async ) { + xhr = null; + } + } + }; + + // Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK) + // Opera doesn't fire onreadystatechange at all on abort + try { + var oldAbort = xhr.abort; + xhr.abort = function() { + // xhr.abort in IE7 is not a native JS function + // and does not have a call property + if ( xhr && oldAbort.call ) { + oldAbort.call( xhr ); + } + + onreadystatechange( "abort" ); + }; + } catch( abortError ) {} + + // Timeout checker + if ( s.async && s.timeout > 0 ) { + setTimeout(function() { + // Check to see if the request is still happening + if ( xhr && !requestDone ) { + onreadystatechange( "timeout" ); + } + }, s.timeout); + } + + // Send the data + try { + xhr.send( noContent || s.data == null ? null : s.data ); + + } catch( sendError ) { + jQuery.handleError( s, xhr, null, sendError ); + + // Fire the complete handlers + jQuery.handleComplete( s, xhr, status, data ); + } + + // firefox 1.5 doesn't fire statechange for sync requests + if ( !s.async ) { + onreadystatechange(); + } + + // return XMLHttpRequest to allow aborting the request etc. + return xhr; + }, + + // Serialize an array of form elements or a set of + // key/values into a query string + param: function( a, traditional ) { + var s = [], add = function( key, value ) { + // If value is a function, invoke it and return its value + value = jQuery.isFunction(value) ? value() : value; + s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value); + }; + + // Set traditional to true for jQuery <= 1.3.2 behavior. + if ( traditional === undefined ) { + traditional = jQuery.ajaxSettings.traditional; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray(a) || a.jquery ) { + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + }); + + } else { + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( var prefix in a ) { + buildParams( prefix, a[prefix], traditional, add ); + } + } + + // Return the resulting serialization + return s.join("&").replace(r20, "+"); + } +}); + +function buildParams( prefix, obj, traditional, add ) { + if ( jQuery.isArray(obj) && obj.length ) { + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + // If array item is non-scalar (array or object), encode its + // numeric index to resolve deserialization ambiguity issues. + // Note that rack (as of 1.0.0) can't currently deserialize + // nested arrays properly, and attempting to do so may cause + // a server error. Possible fixes are to modify rack's + // deserialization algorithm or to provide an option or flag + // to force array serialization to be shallow. + buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add ); + } + }); + + } else if ( !traditional && obj != null && typeof obj === "object" ) { + if ( jQuery.isEmptyObject( obj ) ) { + add( prefix, "" ); + + // Serialize object item. + } else { + jQuery.each( obj, function( k, v ) { + buildParams( prefix + "[" + k + "]", v, traditional, add ); + }); + } + + } else { + // Serialize scalar item. + add( prefix, obj ); + } +} + +// This is still on the jQuery object... for now +// Want to move this to jQuery.ajax some day +jQuery.extend({ + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + handleError: function( s, xhr, status, e ) { + // If a local callback was specified, fire it + if ( s.error ) { + s.error.call( s.context, xhr, status, e ); + } + + // Fire the global callback + if ( s.global ) { + jQuery.triggerGlobal( s, "ajaxError", [xhr, s, e] ); + } + }, + + handleSuccess: function( s, xhr, status, data ) { + // If a local callback was specified, fire it and pass it the data + if ( s.success ) { + s.success.call( s.context, data, status, xhr ); + } + + // Fire the global callback + if ( s.global ) { + jQuery.triggerGlobal( s, "ajaxSuccess", [xhr, s] ); + } + }, + + handleComplete: function( s, xhr, status ) { + // Process result + if ( s.complete ) { + s.complete.call( s.context, xhr, status ); + } + + // The request was completed + if ( s.global ) { + jQuery.triggerGlobal( s, "ajaxComplete", [xhr, s] ); + } + + // Handle the global AJAX counter + if ( s.global && jQuery.active-- === 1 ) { + jQuery.event.trigger( "ajaxStop" ); + } + }, + + triggerGlobal: function( s, type, args ) { + (s.context && s.context.url == null ? jQuery(s.context) : jQuery.event).trigger(type, args); + }, + + // Determines if an XMLHttpRequest was successful or not + httpSuccess: function( xhr ) { + try { + // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450 + return !xhr.status && location.protocol === "file:" || + xhr.status >= 200 && xhr.status < 300 || + xhr.status === 304 || xhr.status === 1223; + } catch(e) {} + + return false; + }, + + // Determines if an XMLHttpRequest returns NotModified + httpNotModified: function( xhr, url ) { + var lastModified = xhr.getResponseHeader("Last-Modified"), + etag = xhr.getResponseHeader("Etag"); + + if ( lastModified ) { + jQuery.lastModified[url] = lastModified; + } + + if ( etag ) { + jQuery.etag[url] = etag; + } + + return xhr.status === 304; + }, + + httpData: function( xhr, type, s ) { + var ct = xhr.getResponseHeader("content-type") || "", + xml = type === "xml" || !type && ct.indexOf("xml") >= 0, + data = xml ? xhr.responseXML : xhr.responseText; + + if ( xml && data.documentElement.nodeName === "parsererror" ) { + jQuery.error( "parsererror" ); + } + + // Allow a pre-filtering function to sanitize the response + // s is checked to keep backwards compatibility + if ( s && s.dataFilter ) { + data = s.dataFilter( data, type ); + } + + // The filter can actually parse the response + if ( typeof data === "string" ) { + // Get the JavaScript object, if JSON is used. + if ( type === "json" || !type && ct.indexOf("json") >= 0 ) { + data = jQuery.parseJSON( data ); + + // If the type is "script", eval it in global context + } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) { + jQuery.globalEval( data ); + } + } + + return data; + } + +}); + +/* + * Create the request object; Microsoft failed to properly + * implement the XMLHttpRequest in IE7 (can't request local files), + * so we use the ActiveXObject when it is available + * Additionally XMLHttpRequest can be disabled in IE7/IE8 so + * we need a fallback. + */ +if ( window.ActiveXObject ) { + jQuery.ajaxSettings.xhr = function() { + if ( window.location.protocol !== "file:" ) { + try { + return new window.XMLHttpRequest(); + } catch(xhrError) {} + } + + try { + return new window.ActiveXObject("Microsoft.XMLHTTP"); + } catch(activeError) {} + }; +} + +// Does this browser support XHR requests? +jQuery.support.ajax = !!jQuery.ajaxSettings.xhr(); + + + + +var elemdisplay = {}, + rfxtypes = /^(?:toggle|show|hide)$/, + rfxnum = /^([+\-]=)?([\d+.\-]+)(.*)$/, + timerId, + fxAttrs = [ + // height animations + [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ], + // width animations + [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ], + // opacity animations + [ "opacity" ] + ]; + +jQuery.fn.extend({ + show: function( speed, easing, callback ) { + if ( speed || speed === 0 ) { + return this.animate( genFx("show", 3), speed, easing, callback); + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !jQuery.data(this[i], "olddisplay") && this[i].style.display === "none" ) { + this[i].style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( this[i].style.display === "" && jQuery.css( this[i], "display" ) === "none" ) { + jQuery.data(this[i], "olddisplay", defaultDisplay(this[i].nodeName)); + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + this[i].style.display = jQuery.data(this[i], "olddisplay") || ""; + } + + return this; + } + }, + + hide: function( speed, easing, callback ) { + if ( speed || speed === 0 ) { + return this.animate( genFx("hide", 3), speed, easing, callback); + + } else { + for ( var i = 0, j = this.length; i < j; i++ ) { + var display = jQuery.css( this[i], "display" ); + + if ( display !== "none" ) { + jQuery.data( this[i], "olddisplay", display ); + } + } + + // Set the display of the elements in a second loop + // to avoid the constant reflow + for ( i = 0; i < j; i++ ) { + this[i].style.display = "none"; + } + + return this; + } + }, + + // Save the old toggle function + _toggle: jQuery.fn.toggle, + + toggle: function( fn, fn2, callback ) { + var bool = typeof fn === "boolean"; + + if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) { + this._toggle.apply( this, arguments ); + + } else if ( fn == null || bool ) { + this.each(function() { + var state = bool ? fn : jQuery(this).is(":hidden"); + jQuery(this)[ state ? "show" : "hide" ](); + }); + + } else { + this.animate(genFx("toggle", 3), fn, fn2, callback); + } + + return this; + }, + + fadeTo: function( speed, to, easing, callback ) { + return this.filter(":hidden").css("opacity", 0).show().end() + .animate({opacity: to}, speed, easing, callback); + }, + + animate: function( prop, speed, easing, callback ) { + var optall = jQuery.speed(speed, easing, callback); + + if ( jQuery.isEmptyObject( prop ) ) { + return this.each( optall.complete ); + } + + return this[ optall.queue === false ? "each" : "queue" ](function() { + // XXX ‘this’ does not always have a nodeName when running the + // test suite + + var opt = jQuery.extend({}, optall), p, + isElement = this.nodeType === 1, + hidden = isElement && jQuery(this).is(":hidden"), + self = this; + + for ( p in prop ) { + var name = jQuery.camelCase( p ); + + if ( p !== name ) { + prop[ name ] = prop[ p ]; + delete prop[ p ]; + p = name; + } + + if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) { + return opt.complete.call(this); + } + + if ( isElement && ( p === "height" || p === "width" ) ) { + // Make sure that nothing sneaks out + // Record all 3 overflow attributes because IE does not + // change the overflow attribute when overflowX and + // overflowY are set to the same value + opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ]; + + // Set display property to inline-block for height/width + // animations on inline elements that are having width/height + // animated + if ( jQuery.css( this, "display" ) === "inline" && + jQuery.css( this, "float" ) === "none" ) { + if ( !jQuery.support.inlineBlockNeedsLayout ) { + this.style.display = "inline-block"; + + } else { + var display = defaultDisplay(this.nodeName); + + // inline-level elements accept inline-block; + // block-level elements need to be inline with layout + if ( display === "inline" ) { + this.style.display = "inline-block"; + + } else { + this.style.display = "inline"; + this.style.zoom = 1; + } + } + } + } + + if ( jQuery.isArray( prop[p] ) ) { + // Create (if needed) and add to specialEasing + (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1]; + prop[p] = prop[p][0]; + } + } + + if ( opt.overflow != null ) { + this.style.overflow = "hidden"; + } + + opt.curAnim = jQuery.extend({}, prop); + + jQuery.each( prop, function( name, val ) { + var e = new jQuery.fx( self, opt, name ); + + if ( rfxtypes.test(val) ) { + e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop ); + + } else { + var parts = rfxnum.exec(val), + start = e.cur(true) || 0; + + if ( parts ) { + var end = parseFloat( parts[2] ), + unit = parts[3] || "px"; + + // We need to compute starting value + if ( unit !== "px" ) { + jQuery.style( self, name, (end || 1) + unit); + start = ((end || 1) / e.cur(true)) * start; + jQuery.style( self, name, start + unit); + } + + // If a +=/-= token was provided, we're doing a relative animation + if ( parts[1] ) { + end = ((parts[1] === "-=" ? -1 : 1) * end) + start; + } + + e.custom( start, end, unit ); + + } else { + e.custom( start, val, "" ); + } + } + }); + + // For JS strict compliance + return true; + }); + }, + + stop: function( clearQueue, gotoEnd ) { + var timers = jQuery.timers; + + if ( clearQueue ) { + this.queue([]); + } + + this.each(function() { + // go in reverse order so anything added to the queue during the loop is ignored + for ( var i = timers.length - 1; i >= 0; i-- ) { + if ( timers[i].elem === this ) { + if (gotoEnd) { + // force the next step to be the last + timers[i](true); + } + + timers.splice(i, 1); + } + } + }); + + // start the next in the queue if the last step wasn't forced + if ( !gotoEnd ) { + this.dequeue(); + } + + return this; + } + +}); + +function genFx( type, num ) { + var obj = {}; + + jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() { + obj[ this ] = type; + }); + + return obj; +} + +// Generate shortcuts for custom animations +jQuery.each({ + slideDown: genFx("show", 1), + slideUp: genFx("hide", 1), + slideToggle: genFx("toggle", 1), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +}); + +jQuery.extend({ + speed: function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction(easing) && easing + }; + + opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : + opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default; + + // Queueing + opt.old = opt.complete; + opt.complete = function() { + if ( opt.queue !== false ) { + jQuery(this).dequeue(); + } + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + }; + + return opt; + }, + + easing: { + linear: function( p, n, firstNum, diff ) { + return firstNum + diff * p; + }, + swing: function( p, n, firstNum, diff ) { + return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum; + } + }, + + timers: [], + + fx: function( elem, options, prop ) { + this.options = options; + this.elem = elem; + this.prop = prop; + + if ( !options.orig ) { + options.orig = {}; + } + } + +}); + +jQuery.fx.prototype = { + // Simple function for setting a style value + update: function() { + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this ); + }, + + // Get the current size + cur: function() { + if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) { + return this.elem[ this.prop ]; + } + + var r = parseFloat( jQuery.css( this.elem, this.prop ) ); + return r && r > -10000 ? r : 0; + }, + + // Start an animation from one number to another + custom: function( from, to, unit ) { + this.startTime = jQuery.now(); + this.start = from; + this.end = to; + this.unit = unit || this.unit || "px"; + this.now = this.start; + this.pos = this.state = 0; + + var self = this, fx = jQuery.fx; + function t( gotoEnd ) { + return self.step(gotoEnd); + } + + t.elem = this.elem; + + if ( t() && jQuery.timers.push(t) && !timerId ) { + timerId = setInterval(fx.tick, fx.interval); + } + }, + + // Simple 'show' function + show: function() { + // Remember where we started, so that we can go back to it later + this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); + this.options.show = true; + + // Begin the animation + // Make sure that we start at a small width/height to avoid any + // flash of content + this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur()); + + // Start by showing the element + jQuery( this.elem ).show(); + }, + + // Simple 'hide' function + hide: function() { + // Remember where we started, so that we can go back to it later + this.options.orig[this.prop] = jQuery.style( this.elem, this.prop ); + this.options.hide = true; + + // Begin the animation + this.custom(this.cur(), 0); + }, + + // Each step of an animation + step: function( gotoEnd ) { + var t = jQuery.now(), done = true; + + if ( gotoEnd || t >= this.options.duration + this.startTime ) { + this.now = this.end; + this.pos = this.state = 1; + this.update(); + + this.options.curAnim[ this.prop ] = true; + + for ( var i in this.options.curAnim ) { + if ( this.options.curAnim[i] !== true ) { + done = false; + } + } + + if ( done ) { + // Reset the overflow + if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) { + var elem = this.elem, options = this.options; + jQuery.each( [ "", "X", "Y" ], function (index, value) { + elem.style[ "overflow" + value ] = options.overflow[index]; + } ); + } + + // Hide the element if the "hide" operation was done + if ( this.options.hide ) { + jQuery(this.elem).hide(); + } + + // Reset the properties, if the item has been hidden or shown + if ( this.options.hide || this.options.show ) { + for ( var p in this.options.curAnim ) { + jQuery.style( this.elem, p, this.options.orig[p] ); + } + } + + // Execute the complete function + this.options.complete.call( this.elem ); + } + + return false; + + } else { + var n = t - this.startTime; + this.state = n / this.options.duration; + + // Perform the easing function, defaults to swing + var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop]; + var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear"); + this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration); + this.now = this.start + ((this.end - this.start) * this.pos); + + // Perform the next step of the animation + this.update(); + } + + return true; + } +}; + +jQuery.extend( jQuery.fx, { + tick: function() { + var timers = jQuery.timers; + + for ( var i = 0; i < timers.length; i++ ) { + if ( !timers[i]() ) { + timers.splice(i--, 1); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + }, + + interval: 13, + + stop: function() { + clearInterval( timerId ); + timerId = null; + }, + + speeds: { + slow: 600, + fast: 200, + // Default speed + _default: 400 + }, + + step: { + opacity: function( fx ) { + jQuery.style( fx.elem, "opacity", fx.now ); + }, + + _default: function( fx ) { + if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) { + fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit; + } else { + fx.elem[ fx.prop ] = fx.now; + } + } + } +}); + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.animated = function( elem ) { + return jQuery.grep(jQuery.timers, function( fn ) { + return elem === fn.elem; + }).length; + }; +} + +function defaultDisplay( nodeName ) { + if ( !elemdisplay[ nodeName ] ) { + var elem = jQuery("<" + nodeName + ">").appendTo("body"), + display = elem.css("display"); + + elem.remove(); + + if ( display === "none" || display === "" ) { + display = "block"; + } + + elemdisplay[ nodeName ] = display; + } + + return elemdisplay[ nodeName ]; +} + + + + +var rtable = /^t(?:able|d|h)$/i, + rroot = /^(?:body|html)$/i; + +if ( "getBoundingClientRect" in document.documentElement ) { + jQuery.fn.offset = function( options ) { + var elem = this[0], box; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + try { + box = elem.getBoundingClientRect(); + } catch(e) {} + + var doc = elem.ownerDocument, + docElem = doc.documentElement; + + // Make sure we're not dealing with a disconnected DOM node + if ( !box || !jQuery.contains( docElem, elem ) ) { + return box || { top: 0, left: 0 }; + } + + var body = doc.body, + win = getWindow(doc), + clientTop = docElem.clientTop || body.clientTop || 0, + clientLeft = docElem.clientLeft || body.clientLeft || 0, + scrollTop = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ), + scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft), + top = box.top + scrollTop - clientTop, + left = box.left + scrollLeft - clientLeft; + + return { top: top, left: left }; + }; + +} else { + jQuery.fn.offset = function( options ) { + var elem = this[0]; + + if ( options ) { + return this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + if ( !elem || !elem.ownerDocument ) { + return null; + } + + if ( elem === elem.ownerDocument.body ) { + return jQuery.offset.bodyOffset( elem ); + } + + jQuery.offset.initialize(); + + var offsetParent = elem.offsetParent, prevOffsetParent = elem, + doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement, + body = doc.body, defaultView = doc.defaultView, + prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle, + top = elem.offsetTop, left = elem.offsetLeft; + + while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) { + if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { + break; + } + + computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle; + top -= elem.scrollTop; + left -= elem.scrollLeft; + + if ( elem === offsetParent ) { + top += elem.offsetTop; + left += elem.offsetLeft; + + if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevOffsetParent = offsetParent; + offsetParent = elem.offsetParent; + } + + if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) { + top += parseFloat( computedStyle.borderTopWidth ) || 0; + left += parseFloat( computedStyle.borderLeftWidth ) || 0; + } + + prevComputedStyle = computedStyle; + } + + if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) { + top += body.offsetTop; + left += body.offsetLeft; + } + + if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) { + top += Math.max( docElem.scrollTop, body.scrollTop ); + left += Math.max( docElem.scrollLeft, body.scrollLeft ); + } + + return { top: top, left: left }; + }; +} + +jQuery.offset = { + initialize: function() { + var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0, + html = "<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>"; + + jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } ); + + container.innerHTML = html; + body.insertBefore( container, body.firstChild ); + innerDiv = container.firstChild; + checkDiv = innerDiv.firstChild; + td = innerDiv.nextSibling.firstChild.firstChild; + + this.doesNotAddBorder = (checkDiv.offsetTop !== 5); + this.doesAddBorderForTableAndCells = (td.offsetTop === 5); + + checkDiv.style.position = "fixed"; + checkDiv.style.top = "20px"; + + // safari subtracts parent border width here which is 5px + this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15); + checkDiv.style.position = checkDiv.style.top = ""; + + innerDiv.style.overflow = "hidden"; + innerDiv.style.position = "relative"; + + this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5); + + this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop); + + body.removeChild( container ); + body = container = innerDiv = checkDiv = table = td = null; + jQuery.offset.initialize = jQuery.noop; + }, + + bodyOffset: function( body ) { + var top = body.offsetTop, left = body.offsetLeft; + + jQuery.offset.initialize(); + + if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) { + top += parseFloat( jQuery.css(body, "marginTop") ) || 0; + left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; + } + + return { top: top, left: left }; + }, + + setOffset: function( elem, options, i ) { + var position = jQuery.css( elem, "position" ); + + // set position first, in-case top/left are set even on static elem + if ( position === "static" ) { + elem.style.position = "relative"; + } + + var curElem = jQuery( elem ), + curOffset = curElem.offset(), + curCSSTop = jQuery.css( elem, "top" ), + curCSSLeft = jQuery.css( elem, "left" ), + calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1), + props = {}, curPosition = {}, curTop, curLeft; + + // need to be able to calculate position if either top or left is auto and position is absolute + if ( calculatePosition ) { + curPosition = curElem.position(); + } + + curTop = calculatePosition ? curPosition.top : parseInt( curCSSTop, 10 ) || 0; + curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0; + + if ( jQuery.isFunction( options ) ) { + options = options.call( elem, i, curOffset ); + } + + if (options.top != null) { + props.top = (options.top - curOffset.top) + curTop; + } + if (options.left != null) { + props.left = (options.left - curOffset.left) + curLeft; + } + + if ( "using" in options ) { + options.using.call( elem, props ); + } else { + curElem.css( props ); + } + } +}; + + +jQuery.fn.extend({ + position: function() { + if ( !this[0] ) { + return null; + } + + var elem = this[0], + + // Get *real* offsetParent + offsetParent = this.offsetParent(), + + // Get correct offsets + offset = this.offset(), + parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); + + // Subtract element margins + // note: when an element has margin: auto the offsetLeft and marginLeft + // are the same in Safari causing offset.left to incorrectly be 0 + offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; + offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; + + // Add offsetParent borders + parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; + parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; + + // Subtract the two offsets + return { + top: offset.top - parentOffset.top, + left: offset.left - parentOffset.left + }; + }, + + offsetParent: function() { + return this.map(function() { + var offsetParent = this.offsetParent || document.body; + while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent; + }); + } +}); + + +// Create scrollLeft and scrollTop methods +jQuery.each( ["Left", "Top"], function( i, name ) { + var method = "scroll" + name; + + jQuery.fn[ method ] = function(val) { + var elem = this[0], win; + + if ( !elem ) { + return null; + } + + if ( val !== undefined ) { + // Set the scroll offset + return this.each(function() { + win = getWindow( this ); + + if ( win ) { + win.scrollTo( + !i ? val : jQuery(win).scrollLeft(), + i ? val : jQuery(win).scrollTop() + ); + + } else { + this[ method ] = val; + } + }); + } else { + win = getWindow( elem ); + + // Return the scroll offset + return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] : + jQuery.support.boxModel && win.document.documentElement[ method ] || + win.document.body[ method ] : + elem[ method ]; + } + }; +}); + +function getWindow( elem ) { + return jQuery.isWindow( elem ) ? + elem : + elem.nodeType === 9 ? + elem.defaultView || elem.parentWindow : + false; +} + + + + +// Create innerHeight, innerWidth, outerHeight and outerWidth methods +jQuery.each([ "Height", "Width" ], function( i, name ) { + + var type = name.toLowerCase(); + + // innerHeight and innerWidth + jQuery.fn["inner" + name] = function() { + return this[0] ? + parseFloat( jQuery.css( this[0], type, "padding" ) ) : + null; + }; + + // outerHeight and outerWidth + jQuery.fn["outer" + name] = function( margin ) { + return this[0] ? + parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) : + null; + }; + + jQuery.fn[ type ] = function( size ) { + // Get window width or height + var elem = this[0]; + if ( !elem ) { + return size == null ? null : this; + } + + if ( jQuery.isFunction( size ) ) { + return this.each(function( i ) { + var self = jQuery( this ); + self[ type ]( size.call( this, i, self[ type ]() ) ); + }); + } + + return jQuery.isWindow( elem ) ? + // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode + elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] || + elem.document.body[ "client" + name ] : + + // Get document width or height + (elem.nodeType === 9) ? // is it a document + // Either scroll[Width/Height] or offset[Width/Height], whichever is greater + Math.max( + elem.documentElement["client" + name], + elem.body["scroll" + name], elem.documentElement["scroll" + name], + elem.body["offset" + name], elem.documentElement["offset" + name] + ) : + + // Get or set width or height on the element + size === undefined ? + // Get width or height on the element + parseFloat( jQuery.css( elem, type ) ) : + + // Set the width or height on the element (default to pixels if value is unitless) + this.css( type, typeof size === "string" ? size : size + "px" ); + }; + +}); + + +})(window); diff --git a/askbot/skins/old/media/js/jquery-fieldselection.js b/askbot/skins/old/media/js/jquery-fieldselection.js new file mode 100644 index 00000000..47f25a98 --- /dev/null +++ b/askbot/skins/old/media/js/jquery-fieldselection.js @@ -0,0 +1,83 @@ +/* + * jQuery plugin: fieldSelection - v0.1.0 - last change: 2006-12-16 + * (c) 2006 Alex Brem <alex@0xab.cd> - http://blog.0xab.cd + */ + +(function() { + + var fieldSelection = { + + getSelection: function() { + + var e = this.jquery ? this[0] : this; + + return ( + + /* mozilla / dom 3.0 */ + ('selectionStart' in e && function() { + var l = e.selectionEnd - e.selectionStart; + return { start: e.selectionStart, end: e.selectionEnd, length: l, text: e.value.substr(e.selectionStart, l) }; + }) || + + /* exploder */ + (document.selection && function() { + + e.focus(); + + var r = document.selection.createRange(); + if (r == null) { + return { start: 0, end: e.value.length, length: 0 } + } + + var re = e.createTextRange(); + var rc = re.duplicate(); + re.moveToBookmark(r.getBookmark()); + rc.setEndPoint('EndToStart', re); + + return { start: rc.text.length, end: rc.text.length + r.text.length, length: r.text.length, text: r.text }; + }) || + + /* browser not supported */ + function() { + return { start: 0, end: e.value.length, length: 0 }; + } + + )(); + + }, + + replaceSelection: function() { + + var e = this.jquery ? this[0] : this; + var text = arguments[0] || ''; + + return ( + + /* mozilla / dom 3.0 */ + ('selectionStart' in e && function() { + e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length); + return this; + }) || + + /* exploder */ + (document.selection && function() { + e.focus(); + document.selection.createRange().text = text; + return this; + }) || + + /* browser not supported */ + function() { + e.value += text; + return this; + } + + )(); + + } + + }; + + jQuery.each(fieldSelection, function(i) { jQuery.fn[i] = this; }); + +})(); diff --git a/askbot/skins/old/media/js/jquery-fieldselection.min.js b/askbot/skins/old/media/js/jquery-fieldselection.min.js new file mode 100644 index 00000000..c2abde0b --- /dev/null +++ b/askbot/skins/old/media/js/jquery-fieldselection.min.js @@ -0,0 +1 @@ +(function(){var a={getSelection:function(){var b=this.jquery?this[0]:this;return(("selectionStart" in b&&function(){var c=b.selectionEnd-b.selectionStart;return{start:b.selectionStart,end:b.selectionEnd,length:c,text:b.value.substr(b.selectionStart,c)}})||(document.selection&&function(){b.focus();var d=document.selection.createRange();if(d==null){return{start:0,end:b.value.length,length:0}}var c=b.createTextRange();var e=c.duplicate();c.moveToBookmark(d.getBookmark());e.setEndPoint("EndToStart",c);return{start:e.text.length,end:e.text.length+d.text.length,length:d.text.length,text:d.text}})||function(){return{start:0,end:b.value.length,length:0}})()},replaceSelection:function(){var b=this.jquery?this[0]:this;var c=arguments[0]||"";return(("selectionStart" in b&&function(){b.value=b.value.substr(0,b.selectionStart)+c+b.value.substr(b.selectionEnd,b.value.length);return this})||(document.selection&&function(){b.focus();document.selection.createRange().text=c;return this})||function(){b.value+=c;return this})()}};jQuery.each(a,function(b){jQuery.fn[b]=this})})();
\ No newline at end of file diff --git a/askbot/skins/old/media/js/jquery.ajaxfileupload.js b/askbot/skins/old/media/js/jquery.ajaxfileupload.js new file mode 100644 index 00000000..75292776 --- /dev/null +++ b/askbot/skins/old/media/js/jquery.ajaxfileupload.js @@ -0,0 +1,195 @@ +jQuery.extend({ + createUploadIframe: function(id, uri){ + //create frame + var frameId = 'jUploadFrame' + id; + if(window.ActiveXObject) { + var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />'); + if(typeof uri== 'boolean'){ + io.src = 'javascript:false'; + } + else if(typeof uri== 'string'){ + io.src = uri; + } + } + else { + var io = document.createElement('iframe'); + io.id = frameId; + io.name = frameId; + } + io.style.position = 'absolute'; + io.style.top = '-1000px'; + io.style.left = '-1000px'; + + document.body.appendChild(io); + return io; + }, + createUploadForm: function(id, fileElementId) + { + //create form + var formId = 'jUploadForm' + id; + var fileId = 'jUploadFile' + id; + var form = $('<form action="" method="POST" name="' + formId + '" id="' + formId + + '" enctype="multipart/form-data"></form>'); + var oldElement = $('#' + fileElementId); + var newElement = $(oldElement).clone(); + $(oldElement).attr('id', fileId); + $(oldElement).before(newElement); + $(oldElement).appendTo(form); + //set attributes + $(form).css('position', 'absolute'); + $(form).css('top', '-1200px'); + $(form).css('left', '-1200px'); + $(form).appendTo('body'); + return form; + }, + + ajaxFileUpload: function(s) { + // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout + s = jQuery.extend({}, jQuery.ajaxSettings, s); + var id = new Date().getTime() + var form = jQuery.createUploadForm(id, s.fileElementId); + var io = jQuery.createUploadIframe(id, s.secureuri); + var frameId = 'jUploadFrame' + id; + var formId = 'jUploadForm' + id; + // Watch for a new set of requests + if ( s.global && ! jQuery.active++ ) + { + jQuery.event.trigger( "ajaxStart" ); + } + var requestDone = false; + // Create the request object + var xml = {} + if ( s.global ) + jQuery.event.trigger("ajaxSend", [xml, s]); + // Wait for a response to come back + var uploadCallback = function(isTimeout) + { + var io = document.getElementById(frameId); + try { + if(io.contentWindow){ + xml.responseText = io.contentWindow.document.body ? + io.contentWindow.document.body.innerText : null; + xml.responseXML = io.contentWindow.document.XMLDocument ? + io.contentWindow.document.XMLDocument : io.contentWindow.document; + + } + else if(io.contentDocument) + { + xml.responseText = io.contentDocument.document.body ? + io.contentDocument.document.body.textContent || document.body.innerText : null; + xml.responseXML = io.contentDocument.document.XMLDocument ? + io.contentDocument.document.XMLDocument : io.contentDocument.document; + } + } + catch(e) + { + jQuery.handleError(s, xml, null, e); + } + if ( xml || isTimeout == "timeout") + { + requestDone = true; + var status; + try { + status = isTimeout != "timeout" ? "success" : "error"; + // Make sure that the request was successful or notmodified + if ( status != "error" ) + { + // process the data (runs the xml through httpData regardless of callback) + var data = jQuery.uploadHttpData( xml, s.dataType ); + // If a local callback was specified, fire it and pass it the data + if ( s.success ) + s.success( data, status ); + + // Fire the global callback + if( s.global ) + jQuery.event.trigger( "ajaxSuccess", [xml, s] ); + } else + jQuery.handleError(s, xml, status); + } catch(e) + { + status = "error"; + jQuery.handleError(s, xml, status, e); + } + + // The request was completed + if( s.global ) + jQuery.event.trigger( "ajaxComplete", [xml, s] ); + + // Handle the global AJAX counter + if ( s.global && ! --jQuery.active ) + jQuery.event.trigger( "ajaxStop" ); + + // Process result + if ( s.complete ) + s.complete(xml, status); + + jQuery(io).unbind(); + + setTimeout(function() + { try + { + $(io).remove(); + $(form).remove(); + + } catch(e) { + jQuery.handleError(s, xml, null, e); + } + }, 100) + xml = null; + } + } + // Timeout checker + if ( s.timeout > 0 ) { + setTimeout(function(){ + // Check to see if the request is still happening + if( !requestDone ) uploadCallback( "timeout" ); + }, s.timeout); + } + try + { + // var io = $('#' + frameId); + var form = $('#' + formId); + $(form).attr('action', s.url); + $(form).attr('method', 'POST'); + $(form).attr('target', frameId); + if(form.encoding) + { + form.encoding = 'multipart/form-data'; + } + else + { + form.enctype = 'multipart/form-data'; + } + $(form).submit(); + + } catch(e) + { + jQuery.handleError(s, xml, null, e); + } + if(window.attachEvent){ + document.getElementById(frameId).attachEvent('onload', uploadCallback); + } + else{ + document.getElementById(frameId).addEventListener('load', uploadCallback, false); + } + return {abort: function () {}}; + + }, + + uploadHttpData: function( r, type ) { + var data = !type; + data = type == "xml" || data ? r.responseXML : r.responseText; + // If the type is "script", eval it in global context + if ( type == "script" ) + jQuery.globalEval( data ); + // Get the JavaScript object, if JSON is used. + if ( type == "json" ) + eval( "data = " + data ); + // evaluate scripts within html + if ( type == "html" ) + jQuery("<div>").html(data).evalScripts(); + //alert($('param', data).each(function(){alert($(this).attr('value'));})); + return data; + } +}) + diff --git a/askbot/skins/old/media/js/jquery.flot.js b/askbot/skins/old/media/js/jquery.flot.js new file mode 100644 index 00000000..6534a468 --- /dev/null +++ b/askbot/skins/old/media/js/jquery.flot.js @@ -0,0 +1,2119 @@ +/* Javascript plotting library for jQuery, v. 0.6. + * + * Released under the MIT license by IOLA, December 2007. + * + */ + +// first an inline dependency, jquery.colorhelpers.js, we inline it here +// for convenience + +/* Plugin for jQuery for working with colors. + * + * Version 1.0. + * + * Inspiration from jQuery color animation plugin by John Resig. + * + * Released under the MIT license by Ole Laursen, October 2009. + * + * Examples: + * + * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() + * var c = $.color.extract($("#mydiv"), 'background-color'); + * console.log(c.r, c.g, c.b, c.a); + * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" + * + * Note that .scale() and .add() work in-place instead of returning + * new objects. + */ +(function(){jQuery.color={};jQuery.color.make=function(E,D,B,C){var F={};F.r=E||0;F.g=D||0;F.b=B||0;F.a=C!=null?C:1;F.add=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]+=H}return F.normalize()};F.scale=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]*=H}return F.normalize()};F.toString=function(){if(F.a>=1){return"rgb("+[F.r,F.g,F.b].join(",")+")"}else{return"rgba("+[F.r,F.g,F.b,F.a].join(",")+")"}};F.normalize=function(){function G(I,J,H){return J<I?I:(J>H?H:J)}F.r=G(0,parseInt(F.r),255);F.g=G(0,parseInt(F.g),255);F.b=G(0,parseInt(F.b),255);F.a=G(0,F.a,1);return F};F.clone=function(){return jQuery.color.make(F.r,F.b,F.g,F.a)};return F.normalize()};jQuery.color.extract=function(C,B){var D;do{D=C.css(B).toLowerCase();if(D!=""&&D!="transparent"){break}C=C.parent()}while(!jQuery.nodeName(C.get(0),"body"));if(D=="rgba(0, 0, 0, 0)"){D="transparent"}return jQuery.color.parse(D)};jQuery.color.parse=function(E){var D,B=jQuery.color.make;if(D=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10))}if(D=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10),parseFloat(D[4]))}if(D=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55)}if(D=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55,parseFloat(D[4]))}if(D=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(E)){return B(parseInt(D[1],16),parseInt(D[2],16),parseInt(D[3],16))}if(D=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(E)){return B(parseInt(D[1]+D[1],16),parseInt(D[2]+D[2],16),parseInt(D[3]+D[3],16))}var C=jQuery.trim(E).toLowerCase();if(C=="transparent"){return B(255,255,255,0)}else{D=A[C];return B(D[0],D[1],D[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(); + +// the actual Flot code +(function($) { + function Plot(placeholder, data_, options_, plugins) { + // data is on the form: + // [ series1, series2 ... ] + // where series is either just the data as [ [x1, y1], [x2, y2], ... ] + // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... } + + var series = [], + options = { + // the color theme used for graphs + colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"], + legend: { + show: true, + noColumns: 1, // number of colums in legend table + labelFormatter: null, // fn: string -> string + labelBoxBorderColor: "#ccc", // border color for the little label boxes + container: null, // container (as jQuery object) to put legend in, null means default on top of graph + position: "ne", // position of default legend container within plot + margin: 5, // distance from grid edge to default legend container within plot + backgroundColor: null, // null means auto-detect + backgroundOpacity: 0.85 // set to 0 to avoid background + }, + xaxis: { + mode: null, // null or "time" + transform: null, // null or f: number -> number to transform axis + inverseTransform: null, // if transform is set, this should be the inverse function + min: null, // min. value to show, null means set automatically + max: null, // max. value to show, null means set automatically + autoscaleMargin: null, // margin in % to add if auto-setting min/max + ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks + tickFormatter: null, // fn: number -> string + labelWidth: null, // size of tick labels in pixels + labelHeight: null, + + // mode specific options + tickDecimals: null, // no. of decimals, null means auto + tickSize: null, // number or [number, "unit"] + minTickSize: null, // number or [number, "unit"] + monthNames: null, // list of names of months + timeformat: null, // format string to use + twelveHourClock: false // 12 or 24 time in time mode + }, + yaxis: { + autoscaleMargin: 0.02 + }, + x2axis: { + autoscaleMargin: null + }, + y2axis: { + autoscaleMargin: 0.02 + }, + series: { + points: { + show: false, + radius: 3, + lineWidth: 2, // in pixels + fill: true, + fillColor: "#ffffff" + }, + lines: { + // we don't put in show: false so we can see + // whether lines were actively disabled + lineWidth: 2, // in pixels + fill: false, + fillColor: null, + steps: false + }, + bars: { + show: false, + lineWidth: 2, // in pixels + barWidth: 1, // in units of the x axis + fill: true, + fillColor: null, + align: "left", // or "center" + horizontal: false // when horizontal, left is now top + }, + shadowSize: 3 + }, + grid: { + show: true, + aboveData: false, + color: "#545454", // primary color used for outline and labels + backgroundColor: null, // null for transparent, else color + tickColor: "rgba(0,0,0,0.15)", // color used for the ticks + labelMargin: 5, // in pixels + borderWidth: 2, // in pixels + borderColor: null, // set if different from the grid color + markings: null, // array of ranges or fn: axes -> array of ranges + markingsColor: "#f4f4f4", + markingsLineWidth: 2, + // interactive stuff + clickable: false, + hoverable: false, + autoHighlight: true, // highlight in case mouse is near + mouseActiveRadius: 10 // how far the mouse can be away to activate an item + }, + hooks: {} + }, + canvas = null, // the canvas for the plot itself + overlay = null, // canvas for interactive stuff on top of plot + eventHolder = null, // jQuery object that events should be bound to + ctx = null, octx = null, + axes = { xaxis: {}, yaxis: {}, x2axis: {}, y2axis: {} }, + plotOffset = { left: 0, right: 0, top: 0, bottom: 0}, + canvasWidth = 0, canvasHeight = 0, + plotWidth = 0, plotHeight = 0, + hooks = { + processOptions: [], + processRawData: [], + processDatapoints: [], + draw: [], + bindEvents: [], + drawOverlay: [] + }, + plot = this; + + // public functions + plot.setData = setData; + plot.setupGrid = setupGrid; + plot.draw = draw; + plot.getPlaceholder = function() { return placeholder; }; + plot.getCanvas = function() { return canvas; }; + plot.getPlotOffset = function() { return plotOffset; }; + plot.width = function () { return plotWidth; }; + plot.height = function () { return plotHeight; }; + plot.offset = function () { + var o = eventHolder.offset(); + o.left += plotOffset.left; + o.top += plotOffset.top; + return o; + }; + plot.getData = function() { return series; }; + plot.getAxes = function() { return axes; }; + plot.getOptions = function() { return options; }; + plot.highlight = highlight; + plot.unhighlight = unhighlight; + plot.triggerRedrawOverlay = triggerRedrawOverlay; + plot.pointOffset = function(point) { + return { left: parseInt(axisSpecToRealAxis(point, "xaxis").p2c(+point.x) + plotOffset.left), + top: parseInt(axisSpecToRealAxis(point, "yaxis").p2c(+point.y) + plotOffset.top) }; + }; + + + // public attributes + plot.hooks = hooks; + + // initialize + initPlugins(plot); + parseOptions(options_); + constructCanvas(); + setData(data_); + setupGrid(); + draw(); + bindEvents(); + + + function executeHooks(hook, args) { + args = [plot].concat(args); + for (var i = 0; i < hook.length; ++i) + hook[i].apply(this, args); + } + + function initPlugins() { + for (var i = 0; i < plugins.length; ++i) { + var p = plugins[i]; + p.init(plot); + if (p.options) + $.extend(true, options, p.options); + } + } + + function parseOptions(opts) { + $.extend(true, options, opts); + if (options.grid.borderColor == null) + options.grid.borderColor = options.grid.color; + // backwards compatibility, to be removed in future + if (options.xaxis.noTicks && options.xaxis.ticks == null) + options.xaxis.ticks = options.xaxis.noTicks; + if (options.yaxis.noTicks && options.yaxis.ticks == null) + options.yaxis.ticks = options.yaxis.noTicks; + if (options.grid.coloredAreas) + options.grid.markings = options.grid.coloredAreas; + if (options.grid.coloredAreasColor) + options.grid.markingsColor = options.grid.coloredAreasColor; + if (options.lines) + $.extend(true, options.series.lines, options.lines); + if (options.points) + $.extend(true, options.series.points, options.points); + if (options.bars) + $.extend(true, options.series.bars, options.bars); + if (options.shadowSize) + options.series.shadowSize = options.shadowSize; + + for (var n in hooks) + if (options.hooks[n] && options.hooks[n].length) + hooks[n] = hooks[n].concat(options.hooks[n]); + + executeHooks(hooks.processOptions, [options]); + } + + function setData(d) { + series = parseData(d); + fillInSeriesOptions(); + processData(); + } + + function parseData(d) { + var res = []; + for (var i = 0; i < d.length; ++i) { + var s = $.extend(true, {}, options.series); + + if (d[i].data) { + s.data = d[i].data; // move the data instead of deep-copy + delete d[i].data; + + $.extend(true, s, d[i]); + + d[i].data = s.data; + } + else + s.data = d[i]; + res.push(s); + } + + return res; + } + + function axisSpecToRealAxis(obj, attr) { + var a = obj[attr]; + if (!a || a == 1) + return axes[attr]; + if (typeof a == "number") + return axes[attr.charAt(0) + a + attr.slice(1)]; + return a; // assume it's OK + } + + function fillInSeriesOptions() { + var i; + + // collect what we already got of colors + var neededColors = series.length, + usedColors = [], + assignedColors = []; + for (i = 0; i < series.length; ++i) { + var sc = series[i].color; + if (sc != null) { + --neededColors; + if (typeof sc == "number") + assignedColors.push(sc); + else + usedColors.push($.color.parse(series[i].color)); + } + } + + // we might need to generate more colors if higher indices + // are assigned + for (i = 0; i < assignedColors.length; ++i) { + neededColors = Math.max(neededColors, assignedColors[i] + 1); + } + + // produce colors as needed + var colors = [], variation = 0; + i = 0; + while (colors.length < neededColors) { + var c; + if (options.colors.length == i) // check degenerate case + c = $.color.make(100, 100, 100); + else + c = $.color.parse(options.colors[i]); + + // vary color if needed + var sign = variation % 2 == 1 ? -1 : 1; + c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2) + + // FIXME: if we're getting to close to something else, + // we should probably skip this one + colors.push(c); + + ++i; + if (i >= options.colors.length) { + i = 0; + ++variation; + } + } + + // fill in the options + var colori = 0, s; + for (i = 0; i < series.length; ++i) { + s = series[i]; + + // assign colors + if (s.color == null) { + s.color = colors[colori].toString(); + ++colori; + } + else if (typeof s.color == "number") + s.color = colors[s.color].toString(); + + // turn on lines automatically in case nothing is set + if (s.lines.show == null) { + var v, show = true; + for (v in s) + if (s[v].show) { + show = false; + break; + } + if (show) + s.lines.show = true; + } + + // setup axes + s.xaxis = axisSpecToRealAxis(s, "xaxis"); + s.yaxis = axisSpecToRealAxis(s, "yaxis"); + } + } + + function processData() { + var topSentry = Number.POSITIVE_INFINITY, + bottomSentry = Number.NEGATIVE_INFINITY, + i, j, k, m, length, + s, points, ps, x, y, axis, val, f, p; + + for (axis in axes) { + axes[axis].datamin = topSentry; + axes[axis].datamax = bottomSentry; + axes[axis].used = false; + } + + function updateAxis(axis, min, max) { + if (min < axis.datamin) + axis.datamin = min; + if (max > axis.datamax) + axis.datamax = max; + } + + for (i = 0; i < series.length; ++i) { + s = series[i]; + s.datapoints = { points: [] }; + + executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]); + } + + // first pass: clean and copy data + for (i = 0; i < series.length; ++i) { + s = series[i]; + + var data = s.data, format = s.datapoints.format; + + if (!format) { + format = []; + // find out how to copy + format.push({ x: true, number: true, required: true }); + format.push({ y: true, number: true, required: true }); + + if (s.bars.show) + format.push({ y: true, number: true, required: false, defaultValue: 0 }); + + s.datapoints.format = format; + } + + if (s.datapoints.pointsize != null) + continue; // already filled in + + if (s.datapoints.pointsize == null) + s.datapoints.pointsize = format.length; + + ps = s.datapoints.pointsize; + points = s.datapoints.points; + + insertSteps = s.lines.show && s.lines.steps; + s.xaxis.used = s.yaxis.used = true; + + for (j = k = 0; j < data.length; ++j, k += ps) { + p = data[j]; + + var nullify = p == null; + if (!nullify) { + for (m = 0; m < ps; ++m) { + val = p[m]; + f = format[m]; + + if (f) { + if (f.number && val != null) { + val = +val; // convert to number + if (isNaN(val)) + val = null; + } + + if (val == null) { + if (f.required) + nullify = true; + + if (f.defaultValue != null) + val = f.defaultValue; + } + } + + points[k + m] = val; + } + } + + if (nullify) { + for (m = 0; m < ps; ++m) { + val = points[k + m]; + if (val != null) { + f = format[m]; + // extract min/max info + if (f.x) + updateAxis(s.xaxis, val, val); + if (f.y) + updateAxis(s.yaxis, val, val); + } + points[k + m] = null; + } + } + else { + // a little bit of line specific stuff that + // perhaps shouldn't be here, but lacking + // better means... + if (insertSteps && k > 0 + && points[k - ps] != null + && points[k - ps] != points[k] + && points[k - ps + 1] != points[k + 1]) { + // copy the point to make room for a middle point + for (m = 0; m < ps; ++m) + points[k + ps + m] = points[k + m]; + + // middle point has same y + points[k + 1] = points[k - ps + 1]; + + // we've added a point, better reflect that + k += ps; + } + } + } + } + + // give the hooks a chance to run + for (i = 0; i < series.length; ++i) { + s = series[i]; + + executeHooks(hooks.processDatapoints, [ s, s.datapoints]); + } + + // second pass: find datamax/datamin for auto-scaling + for (i = 0; i < series.length; ++i) { + s = series[i]; + points = s.datapoints.points, + ps = s.datapoints.pointsize; + + var xmin = topSentry, ymin = topSentry, + xmax = bottomSentry, ymax = bottomSentry; + + for (j = 0; j < points.length; j += ps) { + if (points[j] == null) + continue; + + for (m = 0; m < ps; ++m) { + val = points[j + m]; + f = format[m]; + if (!f) + continue; + + if (f.x) { + if (val < xmin) + xmin = val; + if (val > xmax) + xmax = val; + } + if (f.y) { + if (val < ymin) + ymin = val; + if (val > ymax) + ymax = val; + } + } + } + + if (s.bars.show) { + // make sure we got room for the bar on the dancing floor + var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2; + if (s.bars.horizontal) { + ymin += delta; + ymax += delta + s.bars.barWidth; + } + else { + xmin += delta; + xmax += delta + s.bars.barWidth; + } + } + + updateAxis(s.xaxis, xmin, xmax); + updateAxis(s.yaxis, ymin, ymax); + } + + for (axis in axes) { + if (axes[axis].datamin == topSentry) + axes[axis].datamin = null; + if (axes[axis].datamax == bottomSentry) + axes[axis].datamax = null; + } + } + + function constructCanvas() { + function makeCanvas(width, height) { + var c = document.createElement('canvas'); + c.width = width; + c.height = height; + if ($.browser.msie) // excanvas hack + c = window.G_vmlCanvasManager.initElement(c); + return c; + } + + canvasWidth = placeholder.width(); + canvasHeight = placeholder.height(); + placeholder.html(""); // clear placeholder + if (placeholder.css("position") == 'static') + placeholder.css("position", "relative"); // for positioning labels and overlay + + if (canvasWidth <= 0 || canvasHeight <= 0) + throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight; + + if ($.browser.msie) // excanvas hack + window.G_vmlCanvasManager.init_(document); // make sure everything is setup + + // the canvas + canvas = $(makeCanvas(canvasWidth, canvasHeight)).appendTo(placeholder).get(0); + ctx = canvas.getContext("2d"); + + // overlay canvas for interactive features + overlay = $(makeCanvas(canvasWidth, canvasHeight)).css({ position: 'absolute', left: 0, top: 0 }).appendTo(placeholder).get(0); + octx = overlay.getContext("2d"); + octx.stroke(); + } + + function bindEvents() { + // we include the canvas in the event holder too, because IE 7 + // sometimes has trouble with the stacking order + eventHolder = $([overlay, canvas]); + + // bind events + if (options.grid.hoverable) + eventHolder.mousemove(onMouseMove); + + if (options.grid.clickable) + eventHolder.click(onClick); + + executeHooks(hooks.bindEvents, [eventHolder]); + } + + function setupGrid() { + function setTransformationHelpers(axis, o) { + function identity(x) { return x; } + + var s, m, t = o.transform || identity, + it = o.inverseTransform; + + // add transformation helpers + if (axis == axes.xaxis || axis == axes.x2axis) { + // precompute how much the axis is scaling a point + // in canvas space + s = axis.scale = plotWidth / (t(axis.max) - t(axis.min)); + m = t(axis.min); + + // data point to canvas coordinate + if (t == identity) // slight optimization + axis.p2c = function (p) { return (p - m) * s; }; + else + axis.p2c = function (p) { return (t(p) - m) * s; }; + // canvas coordinate to data point + if (!it) + axis.c2p = function (c) { return m + c / s; }; + else + axis.c2p = function (c) { return it(m + c / s); }; + } + else { + s = axis.scale = plotHeight / (t(axis.max) - t(axis.min)); + m = t(axis.max); + + if (t == identity) + axis.p2c = function (p) { return (m - p) * s; }; + else + axis.p2c = function (p) { return (m - t(p)) * s; }; + if (!it) + axis.c2p = function (c) { return m - c / s; }; + else + axis.c2p = function (c) { return it(m - c / s); }; + } + } + + function measureLabels(axis, axisOptions) { + var i, labels = [], l; + + axis.labelWidth = axisOptions.labelWidth; + axis.labelHeight = axisOptions.labelHeight; + + if (axis == axes.xaxis || axis == axes.x2axis) { + // to avoid measuring the widths of the labels, we + // construct fixed-size boxes and put the labels inside + // them, we don't need the exact figures and the + // fixed-size box content is easy to center + if (axis.labelWidth == null) + axis.labelWidth = canvasWidth / (axis.ticks.length > 0 ? axis.ticks.length : 1); + + // measure x label heights + if (axis.labelHeight == null) { + labels = []; + for (i = 0; i < axis.ticks.length; ++i) { + l = axis.ticks[i].label; + if (l) + labels.push('<div class="tickLabel" style="float:left;width:' + axis.labelWidth + 'px">' + l + '</div>'); + } + + if (labels.length > 0) { + var dummyDiv = $('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">' + + labels.join("") + '<div style="clear:left"></div></div>').appendTo(placeholder); + axis.labelHeight = dummyDiv.height(); + dummyDiv.remove(); + } + } + } + else if (axis.labelWidth == null || axis.labelHeight == null) { + // calculate y label dimensions + for (i = 0; i < axis.ticks.length; ++i) { + l = axis.ticks[i].label; + if (l) + labels.push('<div class="tickLabel">' + l + '</div>'); + } + + if (labels.length > 0) { + var dummyDiv = $('<div style="position:absolute;top:-10000px;font-size:smaller">' + + labels.join("") + '</div>').appendTo(placeholder); + if (axis.labelWidth == null) + axis.labelWidth = dummyDiv.width(); + if (axis.labelHeight == null) + axis.labelHeight = dummyDiv.find("div").height(); + dummyDiv.remove(); + } + + } + + if (axis.labelWidth == null) + axis.labelWidth = 0; + if (axis.labelHeight == null) + axis.labelHeight = 0; + } + + function setGridSpacing() { + // get the most space needed around the grid for things + // that may stick out + var maxOutset = options.grid.borderWidth; + for (i = 0; i < series.length; ++i) + maxOutset = Math.max(maxOutset, 2 * (series[i].points.radius + series[i].points.lineWidth/2)); + + plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = maxOutset; + + var margin = options.grid.labelMargin + options.grid.borderWidth; + + if (axes.xaxis.labelHeight > 0) + plotOffset.bottom = Math.max(maxOutset, axes.xaxis.labelHeight + margin); + if (axes.yaxis.labelWidth > 0) + plotOffset.left = Math.max(maxOutset, axes.yaxis.labelWidth + margin); + if (axes.x2axis.labelHeight > 0) + plotOffset.top = Math.max(maxOutset, axes.x2axis.labelHeight + margin); + if (axes.y2axis.labelWidth > 0) + plotOffset.right = Math.max(maxOutset, axes.y2axis.labelWidth + margin); + + plotWidth = canvasWidth - plotOffset.left - plotOffset.right; + plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top; + } + + var axis; + for (axis in axes) + setRange(axes[axis], options[axis]); + + if (options.grid.show) { + for (axis in axes) { + prepareTickGeneration(axes[axis], options[axis]); + setTicks(axes[axis], options[axis]); + measureLabels(axes[axis], options[axis]); + } + + setGridSpacing(); + } + else { + plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0; + plotWidth = canvasWidth; + plotHeight = canvasHeight; + } + + for (axis in axes) + setTransformationHelpers(axes[axis], options[axis]); + + if (options.grid.show) + insertLabels(); + + insertLegend(); + } + + function setRange(axis, axisOptions) { + var min = +(axisOptions.min != null ? axisOptions.min : axis.datamin), + max = +(axisOptions.max != null ? axisOptions.max : axis.datamax), + delta = max - min; + + if (delta == 0.0) { + // degenerate case + var widen = max == 0 ? 1 : 0.01; + + if (axisOptions.min == null) + min -= widen; + // alway widen max if we couldn't widen min to ensure we + // don't fall into min == max which doesn't work + if (axisOptions.max == null || axisOptions.min != null) + max += widen; + } + else { + // consider autoscaling + var margin = axisOptions.autoscaleMargin; + if (margin != null) { + if (axisOptions.min == null) { + min -= delta * margin; + // make sure we don't go below zero if all values + // are positive + if (min < 0 && axis.datamin != null && axis.datamin >= 0) + min = 0; + } + if (axisOptions.max == null) { + max += delta * margin; + if (max > 0 && axis.datamax != null && axis.datamax <= 0) + max = 0; + } + } + } + axis.min = min; + axis.max = max; + } + + function prepareTickGeneration(axis, axisOptions) { + // estimate number of ticks + var noTicks; + if (typeof axisOptions.ticks == "number" && axisOptions.ticks > 0) + noTicks = axisOptions.ticks; + else if (axis == axes.xaxis || axis == axes.x2axis) + // heuristic based on the model a*sqrt(x) fitted to + // some reasonable data points + noTicks = 0.3 * Math.sqrt(canvasWidth); + else + noTicks = 0.3 * Math.sqrt(canvasHeight); + + var delta = (axis.max - axis.min) / noTicks, + size, generator, unit, formatter, i, magn, norm; + + if (axisOptions.mode == "time") { + // pretty handling of time + + // map of app. size of time units in milliseconds + var timeUnitSize = { + "second": 1000, + "minute": 60 * 1000, + "hour": 60 * 60 * 1000, + "day": 24 * 60 * 60 * 1000, + "month": 30 * 24 * 60 * 60 * 1000, + "year": 365.2425 * 24 * 60 * 60 * 1000 + }; + + + // the allowed tick sizes, after 1 year we use + // an integer algorithm + var spec = [ + [1, "second"], [2, "second"], [5, "second"], [10, "second"], + [30, "second"], + [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"], + [30, "minute"], + [1, "hour"], [2, "hour"], [4, "hour"], + [8, "hour"], [12, "hour"], + [1, "day"], [2, "day"], [3, "day"], + [0.25, "month"], [0.5, "month"], [1, "month"], + [2, "month"], [3, "month"], [6, "month"], + [1, "year"] + ]; + + var minSize = 0; + if (axisOptions.minTickSize != null) { + if (typeof axisOptions.tickSize == "number") + minSize = axisOptions.tickSize; + else + minSize = axisOptions.minTickSize[0] * timeUnitSize[axisOptions.minTickSize[1]]; + } + + for (i = 0; i < spec.length - 1; ++i) + if (delta < (spec[i][0] * timeUnitSize[spec[i][1]] + + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2 + && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) + break; + size = spec[i][0]; + unit = spec[i][1]; + + // special-case the possibility of several years + if (unit == "year") { + magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10)); + norm = (delta / timeUnitSize.year) / magn; + if (norm < 1.5) + size = 1; + else if (norm < 3) + size = 2; + else if (norm < 7.5) + size = 5; + else + size = 10; + + size *= magn; + } + + if (axisOptions.tickSize) { + size = axisOptions.tickSize[0]; + unit = axisOptions.tickSize[1]; + } + + generator = function(axis) { + var ticks = [], + tickSize = axis.tickSize[0], unit = axis.tickSize[1], + d = new Date(axis.min); + + var step = tickSize * timeUnitSize[unit]; + + if (unit == "second") + d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize)); + if (unit == "minute") + d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize)); + if (unit == "hour") + d.setUTCHours(floorInBase(d.getUTCHours(), tickSize)); + if (unit == "month") + d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize)); + if (unit == "year") + d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize)); + + // reset smaller components + d.setUTCMilliseconds(0); + if (step >= timeUnitSize.minute) + d.setUTCSeconds(0); + if (step >= timeUnitSize.hour) + d.setUTCMinutes(0); + if (step >= timeUnitSize.day) + d.setUTCHours(0); + if (step >= timeUnitSize.day * 4) + d.setUTCDate(1); + if (step >= timeUnitSize.year) + d.setUTCMonth(0); + + + var carry = 0, v = Number.NaN, prev; + do { + prev = v; + v = d.getTime(); + ticks.push({ v: v, label: axis.tickFormatter(v, axis) }); + if (unit == "month") { + if (tickSize < 1) { + // a bit complicated - we'll divide the month + // up but we need to take care of fractions + // so we don't end up in the middle of a day + d.setUTCDate(1); + var start = d.getTime(); + d.setUTCMonth(d.getUTCMonth() + 1); + var end = d.getTime(); + d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize); + carry = d.getUTCHours(); + d.setUTCHours(0); + } + else + d.setUTCMonth(d.getUTCMonth() + tickSize); + } + else if (unit == "year") { + d.setUTCFullYear(d.getUTCFullYear() + tickSize); + } + else + d.setTime(v + step); + } while (v < axis.max && v != prev); + + return ticks; + }; + + formatter = function (v, axis) { + var d = new Date(v); + + // first check global format + if (axisOptions.timeformat != null) + return $.plot.formatDate(d, axisOptions.timeformat, axisOptions.monthNames); + + var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]]; + var span = axis.max - axis.min; + var suffix = (axisOptions.twelveHourClock) ? " %p" : ""; + + if (t < timeUnitSize.minute) + fmt = "%h:%M:%S" + suffix; + else if (t < timeUnitSize.day) { + if (span < 2 * timeUnitSize.day) + fmt = "%h:%M" + suffix; + else + fmt = "%b %d %h:%M" + suffix; + } + else if (t < timeUnitSize.month) + fmt = "%b %d"; + else if (t < timeUnitSize.year) { + if (span < timeUnitSize.year) + fmt = "%b"; + else + fmt = "%b %y"; + } + else + fmt = "%y"; + + return $.plot.formatDate(d, fmt, axisOptions.monthNames); + }; + } + else { + // pretty rounding of base-10 numbers + var maxDec = axisOptions.tickDecimals; + var dec = -Math.floor(Math.log(delta) / Math.LN10); + if (maxDec != null && dec > maxDec) + dec = maxDec; + + magn = Math.pow(10, -dec); + norm = delta / magn; // norm is between 1.0 and 10.0 + + if (norm < 1.5) + size = 1; + else if (norm < 3) { + size = 2; + // special case for 2.5, requires an extra decimal + if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) { + size = 2.5; + ++dec; + } + } + else if (norm < 7.5) + size = 5; + else + size = 10; + + size *= magn; + + if (axisOptions.minTickSize != null && size < axisOptions.minTickSize) + size = axisOptions.minTickSize; + + if (axisOptions.tickSize != null) + size = axisOptions.tickSize; + + axis.tickDecimals = Math.max(0, (maxDec != null) ? maxDec : dec); + + generator = function (axis) { + var ticks = []; + + // spew out all possible ticks + var start = floorInBase(axis.min, axis.tickSize), + i = 0, v = Number.NaN, prev; + do { + prev = v; + v = start + i * axis.tickSize; + ticks.push({ v: v, label: axis.tickFormatter(v, axis) }); + ++i; + } while (v < axis.max && v != prev); + return ticks; + }; + + formatter = function (v, axis) { + return v.toFixed(axis.tickDecimals); + }; + } + + axis.tickSize = unit ? [size, unit] : size; + axis.tickGenerator = generator; + if ($.isFunction(axisOptions.tickFormatter)) + axis.tickFormatter = function (v, axis) { return "" + axisOptions.tickFormatter(v, axis); }; + else + axis.tickFormatter = formatter; + } + + function setTicks(axis, axisOptions) { + axis.ticks = []; + + if (!axis.used) + return; + + if (axisOptions.ticks == null) + axis.ticks = axis.tickGenerator(axis); + else if (typeof axisOptions.ticks == "number") { + if (axisOptions.ticks > 0) + axis.ticks = axis.tickGenerator(axis); + } + else if (axisOptions.ticks) { + var ticks = axisOptions.ticks; + + if ($.isFunction(ticks)) + // generate the ticks + ticks = ticks({ min: axis.min, max: axis.max }); + + // clean up the user-supplied ticks, copy them over + var i, v; + for (i = 0; i < ticks.length; ++i) { + var label = null; + var t = ticks[i]; + if (typeof t == "object") { + v = t[0]; + if (t.length > 1) + label = t[1]; + } + else + v = t; + if (label == null) + label = axis.tickFormatter(v, axis); + axis.ticks[i] = { v: v, label: label }; + } + } + + if (axisOptions.autoscaleMargin != null && axis.ticks.length > 0) { + // snap to ticks + if (axisOptions.min == null) + axis.min = Math.min(axis.min, axis.ticks[0].v); + if (axisOptions.max == null && axis.ticks.length > 1) + axis.max = Math.max(axis.max, axis.ticks[axis.ticks.length - 1].v); + } + } + + function draw() { + ctx.clearRect(0, 0, canvasWidth, canvasHeight); + + var grid = options.grid; + + if (grid.show && !grid.aboveData) + drawGrid(); + + for (var i = 0; i < series.length; ++i) + drawSeries(series[i]); + + executeHooks(hooks.draw, [ctx]); + + if (grid.show && grid.aboveData) + drawGrid(); + } + + function extractRange(ranges, coord) { + var firstAxis = coord + "axis", + secondaryAxis = coord + "2axis", + axis, from, to, reverse; + + if (ranges[firstAxis]) { + axis = axes[firstAxis]; + from = ranges[firstAxis].from; + to = ranges[firstAxis].to; + } + else if (ranges[secondaryAxis]) { + axis = axes[secondaryAxis]; + from = ranges[secondaryAxis].from; + to = ranges[secondaryAxis].to; + } + else { + // backwards-compat stuff - to be removed in future + axis = axes[firstAxis]; + from = ranges[coord + "1"]; + to = ranges[coord + "2"]; + } + + // auto-reverse as an added bonus + if (from != null && to != null && from > to) + return { from: to, to: from, axis: axis }; + + return { from: from, to: to, axis: axis }; + } + + function drawGrid() { + var i; + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + + // draw background, if any + if (options.grid.backgroundColor) { + ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)"); + ctx.fillRect(0, 0, plotWidth, plotHeight); + } + + // draw markings + var markings = options.grid.markings; + if (markings) { + if ($.isFunction(markings)) + // xmin etc. are backwards-compatible, to be removed in future + markings = markings({ xmin: axes.xaxis.min, xmax: axes.xaxis.max, ymin: axes.yaxis.min, ymax: axes.yaxis.max, xaxis: axes.xaxis, yaxis: axes.yaxis, x2axis: axes.x2axis, y2axis: axes.y2axis }); + + for (i = 0; i < markings.length; ++i) { + var m = markings[i], + xrange = extractRange(m, "x"), + yrange = extractRange(m, "y"); + + // fill in missing + if (xrange.from == null) + xrange.from = xrange.axis.min; + if (xrange.to == null) + xrange.to = xrange.axis.max; + if (yrange.from == null) + yrange.from = yrange.axis.min; + if (yrange.to == null) + yrange.to = yrange.axis.max; + + // clip + if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max || + yrange.to < yrange.axis.min || yrange.from > yrange.axis.max) + continue; + + xrange.from = Math.max(xrange.from, xrange.axis.min); + xrange.to = Math.min(xrange.to, xrange.axis.max); + yrange.from = Math.max(yrange.from, yrange.axis.min); + yrange.to = Math.min(yrange.to, yrange.axis.max); + + if (xrange.from == xrange.to && yrange.from == yrange.to) + continue; + + // then draw + xrange.from = xrange.axis.p2c(xrange.from); + xrange.to = xrange.axis.p2c(xrange.to); + yrange.from = yrange.axis.p2c(yrange.from); + yrange.to = yrange.axis.p2c(yrange.to); + + if (xrange.from == xrange.to || yrange.from == yrange.to) { + // draw line + ctx.beginPath(); + ctx.strokeStyle = m.color || options.grid.markingsColor; + ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth; + //ctx.moveTo(Math.floor(xrange.from), yrange.from); + //ctx.lineTo(Math.floor(xrange.to), yrange.to); + ctx.moveTo(xrange.from, yrange.from); + ctx.lineTo(xrange.to, yrange.to); + ctx.stroke(); + } + else { + // fill area + ctx.fillStyle = m.color || options.grid.markingsColor; + ctx.fillRect(xrange.from, yrange.to, + xrange.to - xrange.from, + yrange.from - yrange.to); + } + } + } + + // draw the inner grid + ctx.lineWidth = 1; + ctx.strokeStyle = options.grid.tickColor; + ctx.beginPath(); + var v, axis = axes.xaxis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axes.xaxis.max) + continue; // skip those lying on the axes + + ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 0); + ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, plotHeight); + } + + axis = axes.yaxis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axis.max) + continue; + + ctx.moveTo(0, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + ctx.lineTo(plotWidth, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + } + + axis = axes.x2axis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axis.max) + continue; + + ctx.moveTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, -5); + ctx.lineTo(Math.floor(axis.p2c(v)) + ctx.lineWidth/2, 5); + } + + axis = axes.y2axis; + for (i = 0; i < axis.ticks.length; ++i) { + v = axis.ticks[i].v; + if (v <= axis.min || v >= axis.max) + continue; + + ctx.moveTo(plotWidth-5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + ctx.lineTo(plotWidth+5, Math.floor(axis.p2c(v)) + ctx.lineWidth/2); + } + + ctx.stroke(); + + if (options.grid.borderWidth) { + // draw border + var bw = options.grid.borderWidth; + ctx.lineWidth = bw; + ctx.strokeStyle = options.grid.borderColor; + ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw); + } + + ctx.restore(); + } + + function insertLabels() { + placeholder.find(".tickLabels").remove(); + + var html = ['<div class="tickLabels" style="font-size:smaller;color:' + options.grid.color + '">']; + + function addLabels(axis, labelGenerator) { + for (var i = 0; i < axis.ticks.length; ++i) { + var tick = axis.ticks[i]; + if (!tick.label || tick.v < axis.min || tick.v > axis.max) + continue; + html.push(labelGenerator(tick, axis)); + } + } + + var margin = options.grid.labelMargin + options.grid.borderWidth; + + addLabels(axes.xaxis, function (tick, axis) { + return '<div style="position:absolute;top:' + (plotOffset.top + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>"; + }); + + + addLabels(axes.yaxis, function (tick, axis) { + return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;right:' + (plotOffset.right + plotWidth + margin) + 'px;width:' + axis.labelWidth + 'px;text-align:right" class="tickLabel">' + tick.label + "</div>"; + }); + + addLabels(axes.x2axis, function (tick, axis) { + return '<div style="position:absolute;bottom:' + (plotOffset.bottom + plotHeight + margin) + 'px;left:' + Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2) + 'px;width:' + axis.labelWidth + 'px;text-align:center" class="tickLabel">' + tick.label + "</div>"; + }); + + addLabels(axes.y2axis, function (tick, axis) { + return '<div style="position:absolute;top:' + Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2) + 'px;left:' + (plotOffset.left + plotWidth + margin) +'px;width:' + axis.labelWidth + 'px;text-align:left" class="tickLabel">' + tick.label + "</div>"; + }); + + html.push('</div>'); + + placeholder.append(html.join("")); + } + + function drawSeries(series) { + if (series.lines.show) + drawSeriesLines(series); + if (series.bars.show) + drawSeriesBars(series); + if (series.points.show) + drawSeriesPoints(series); + } + + function drawSeriesLines(series) { + function plotLine(datapoints, xoffset, yoffset, axisx, axisy) { + var points = datapoints.points, + ps = datapoints.pointsize, + prevx = null, prevy = null; + + ctx.beginPath(); + for (var i = ps; i < points.length; i += ps) { + var x1 = points[i - ps], y1 = points[i - ps + 1], + x2 = points[i], y2 = points[i + 1]; + + if (x1 == null || x2 == null) + continue; + + // clip with ymin + if (y1 <= y2 && y1 < axisy.min) { + if (y2 < axisy.min) + continue; // line segment is outside + // compute new intersection point + x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.min; + } + else if (y2 <= y1 && y2 < axisy.min) { + if (y1 < axisy.min) + continue; + x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.min; + } + + // clip with ymax + if (y1 >= y2 && y1 > axisy.max) { + if (y2 > axisy.max) + continue; + x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.max; + } + else if (y2 >= y1 && y2 > axisy.max) { + if (y1 > axisy.max) + continue; + x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.max; + } + + // clip with xmin + if (x1 <= x2 && x1 < axisx.min) { + if (x2 < axisx.min) + continue; + y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.min; + } + else if (x2 <= x1 && x2 < axisx.min) { + if (x1 < axisx.min) + continue; + y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.min; + } + + // clip with xmax + if (x1 >= x2 && x1 > axisx.max) { + if (x2 > axisx.max) + continue; + y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.max; + } + else if (x2 >= x1 && x2 > axisx.max) { + if (x1 > axisx.max) + continue; + y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.max; + } + + if (x1 != prevx || y1 != prevy) + ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset); + + prevx = x2; + prevy = y2; + ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset); + } + ctx.stroke(); + } + + function plotLineArea(datapoints, axisx, axisy) { + var points = datapoints.points, + ps = datapoints.pointsize, + bottom = Math.min(Math.max(0, axisy.min), axisy.max), + top, lastX = 0, areaOpen = false; + + for (var i = ps; i < points.length; i += ps) { + var x1 = points[i - ps], y1 = points[i - ps + 1], + x2 = points[i], y2 = points[i + 1]; + + if (areaOpen && x1 != null && x2 == null) { + // close area + ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom)); + ctx.fill(); + areaOpen = false; + continue; + } + + if (x1 == null || x2 == null) + continue; + + // clip x values + + // clip with xmin + if (x1 <= x2 && x1 < axisx.min) { + if (x2 < axisx.min) + continue; + y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.min; + } + else if (x2 <= x1 && x2 < axisx.min) { + if (x1 < axisx.min) + continue; + y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.min; + } + + // clip with xmax + if (x1 >= x2 && x1 > axisx.max) { + if (x2 > axisx.max) + continue; + y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x1 = axisx.max; + } + else if (x2 >= x1 && x2 > axisx.max) { + if (x1 > axisx.max) + continue; + y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; + x2 = axisx.max; + } + + if (!areaOpen) { + // open area + ctx.beginPath(); + ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom)); + areaOpen = true; + } + + // now first check the case where both is outside + if (y1 >= axisy.max && y2 >= axisy.max) { + ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max)); + ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max)); + lastX = x2; + continue; + } + else if (y1 <= axisy.min && y2 <= axisy.min) { + ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min)); + ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min)); + lastX = x2; + continue; + } + + // else it's a bit more complicated, there might + // be two rectangles and two triangles we need to fill + // in; to find these keep track of the current x values + var x1old = x1, x2old = x2; + + // and clip the y values, without shortcutting + + // clip with ymin + if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) { + x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.min; + } + else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) { + x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.min; + } + + // clip with ymax + if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) { + x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y1 = axisy.max; + } + else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) { + x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; + y2 = axisy.max; + } + + + // if the x value was changed we got a rectangle + // to fill + if (x1 != x1old) { + if (y1 <= axisy.min) + top = axisy.min; + else + top = axisy.max; + + ctx.lineTo(axisx.p2c(x1old), axisy.p2c(top)); + ctx.lineTo(axisx.p2c(x1), axisy.p2c(top)); + } + + // fill the triangles + ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1)); + ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2)); + + // fill the other rectangle if it's there + if (x2 != x2old) { + if (y2 <= axisy.min) + top = axisy.min; + else + top = axisy.max; + + ctx.lineTo(axisx.p2c(x2), axisy.p2c(top)); + ctx.lineTo(axisx.p2c(x2old), axisy.p2c(top)); + } + + lastX = Math.max(x2, x2old); + } + + if (areaOpen) { + ctx.lineTo(axisx.p2c(lastX), axisy.p2c(bottom)); + ctx.fill(); + } + } + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + ctx.lineJoin = "round"; + + var lw = series.lines.lineWidth, + sw = series.shadowSize; + // FIXME: consider another form of shadow when filling is turned on + if (lw > 0 && sw > 0) { + // draw shadow as a thick and thin line with transparency + ctx.lineWidth = sw; + ctx.strokeStyle = "rgba(0,0,0,0.1)"; + // position shadow at angle from the mid of line + var angle = Math.PI/18; + plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis); + ctx.lineWidth = sw/2; + plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis); + } + + ctx.lineWidth = lw; + ctx.strokeStyle = series.color; + var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight); + if (fillStyle) { + ctx.fillStyle = fillStyle; + plotLineArea(series.datapoints, series.xaxis, series.yaxis); + } + + if (lw > 0) + plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis); + ctx.restore(); + } + + function drawSeriesPoints(series) { + function plotPoints(datapoints, radius, fillStyle, offset, circumference, axisx, axisy) { + var points = datapoints.points, ps = datapoints.pointsize; + + for (var i = 0; i < points.length; i += ps) { + var x = points[i], y = points[i + 1]; + if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) + continue; + + ctx.beginPath(); + ctx.arc(axisx.p2c(x), axisy.p2c(y) + offset, radius, 0, circumference, false); + if (fillStyle) { + ctx.fillStyle = fillStyle; + ctx.fill(); + } + ctx.stroke(); + } + } + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + + var lw = series.lines.lineWidth, + sw = series.shadowSize, + radius = series.points.radius; + if (lw > 0 && sw > 0) { + // draw shadow in two steps + var w = sw / 2; + ctx.lineWidth = w; + ctx.strokeStyle = "rgba(0,0,0,0.1)"; + plotPoints(series.datapoints, radius, null, w + w/2, Math.PI, + series.xaxis, series.yaxis); + + ctx.strokeStyle = "rgba(0,0,0,0.2)"; + plotPoints(series.datapoints, radius, null, w/2, Math.PI, + series.xaxis, series.yaxis); + } + + ctx.lineWidth = lw; + ctx.strokeStyle = series.color; + plotPoints(series.datapoints, radius, + getFillStyle(series.points, series.color), 0, 2 * Math.PI, + series.xaxis, series.yaxis); + ctx.restore(); + } + + function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal) { + var left, right, bottom, top, + drawLeft, drawRight, drawTop, drawBottom, + tmp; + + if (horizontal) { + drawBottom = drawRight = drawTop = true; + drawLeft = false; + left = b; + right = x; + top = y + barLeft; + bottom = y + barRight; + + // account for negative bars + if (right < left) { + tmp = right; + right = left; + left = tmp; + drawLeft = true; + drawRight = false; + } + } + else { + drawLeft = drawRight = drawTop = true; + drawBottom = false; + left = x + barLeft; + right = x + barRight; + bottom = b; + top = y; + + // account for negative bars + if (top < bottom) { + tmp = top; + top = bottom; + bottom = tmp; + drawBottom = true; + drawTop = false; + } + } + + // clip + if (right < axisx.min || left > axisx.max || + top < axisy.min || bottom > axisy.max) + return; + + if (left < axisx.min) { + left = axisx.min; + drawLeft = false; + } + + if (right > axisx.max) { + right = axisx.max; + drawRight = false; + } + + if (bottom < axisy.min) { + bottom = axisy.min; + drawBottom = false; + } + + if (top > axisy.max) { + top = axisy.max; + drawTop = false; + } + + left = axisx.p2c(left); + bottom = axisy.p2c(bottom); + right = axisx.p2c(right); + top = axisy.p2c(top); + + // fill the bar + if (fillStyleCallback) { + c.beginPath(); + c.moveTo(left, bottom); + c.lineTo(left, top); + c.lineTo(right, top); + c.lineTo(right, bottom); + c.fillStyle = fillStyleCallback(bottom, top); + c.fill(); + } + + // draw outline + if (drawLeft || drawRight || drawTop || drawBottom) { + c.beginPath(); + + // FIXME: inline moveTo is buggy with excanvas + c.moveTo(left, bottom + offset); + if (drawLeft) + c.lineTo(left, top + offset); + else + c.moveTo(left, top + offset); + if (drawTop) + c.lineTo(right, top + offset); + else + c.moveTo(right, top + offset); + if (drawRight) + c.lineTo(right, bottom + offset); + else + c.moveTo(right, bottom + offset); + if (drawBottom) + c.lineTo(left, bottom + offset); + else + c.moveTo(left, bottom + offset); + c.stroke(); + } + } + + function drawSeriesBars(series) { + function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) { + var points = datapoints.points, ps = datapoints.pointsize; + + for (var i = 0; i < points.length; i += ps) { + if (points[i] == null) + continue; + drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal); + } + } + + ctx.save(); + ctx.translate(plotOffset.left, plotOffset.top); + + // FIXME: figure out a way to add shadows (for instance along the right edge) + ctx.lineWidth = series.bars.lineWidth; + ctx.strokeStyle = series.color; + var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; + var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null; + plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis); + ctx.restore(); + } + + function getFillStyle(filloptions, seriesColor, bottom, top) { + var fill = filloptions.fill; + if (!fill) + return null; + + if (filloptions.fillColor) + return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor); + + var c = $.color.parse(seriesColor); + c.a = typeof fill == "number" ? fill : 0.4; + c.normalize(); + return c.toString(); + } + + function insertLegend() { + placeholder.find(".legend").remove(); + + if (!options.legend.show) + return; + + var fragments = [], rowStarted = false, + lf = options.legend.labelFormatter, s, label; + for (i = 0; i < series.length; ++i) { + s = series[i]; + label = s.label; + if (!label) + continue; + + if (i % options.legend.noColumns == 0) { + if (rowStarted) + fragments.push('</tr>'); + fragments.push('<tr>'); + rowStarted = true; + } + + if (lf) + label = lf(label, s); + + fragments.push( + '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + s.color + ';overflow:hidden"></div></div></td>' + + '<td class="legendLabel">' + label + '</td>'); + } + if (rowStarted) + fragments.push('</tr>'); + + if (fragments.length == 0) + return; + + var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>'; + if (options.legend.container != null) + $(options.legend.container).html(table); + else { + var pos = "", + p = options.legend.position, + m = options.legend.margin; + if (m[0] == null) + m = [m, m]; + if (p.charAt(0) == "n") + pos += 'top:' + (m[1] + plotOffset.top) + 'px;'; + else if (p.charAt(0) == "s") + pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;'; + if (p.charAt(1) == "e") + pos += 'right:' + (m[0] + plotOffset.right) + 'px;'; + else if (p.charAt(1) == "w") + pos += 'left:' + (m[0] + plotOffset.left) + 'px;'; + var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder); + if (options.legend.backgroundOpacity != 0.0) { + // put in the transparent background + // separately to avoid blended labels and + // label boxes + var c = options.legend.backgroundColor; + if (c == null) { + c = options.grid.backgroundColor; + if (c && typeof c == "string") + c = $.color.parse(c); + else + c = $.color.extract(legend, 'background-color'); + c.a = 1; + c = c.toString(); + } + var div = legend.children(); + $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity); + } + } + } + + + // interactive features + + var highlights = [], + redrawTimeout = null; + + // returns the data item the mouse is over, or null if none is found + function findNearbyItem(mouseX, mouseY, seriesFilter) { + var maxDistance = options.grid.mouseActiveRadius, + smallestDistance = maxDistance * maxDistance + 1, + item = null, foundPoint = false, i, j; + + for (i = 0; i < series.length; ++i) { + if (!seriesFilter(series[i])) + continue; + + var s = series[i], + axisx = s.xaxis, + axisy = s.yaxis, + points = s.datapoints.points, + ps = s.datapoints.pointsize, + mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster + my = axisy.c2p(mouseY), + maxx = maxDistance / axisx.scale, + maxy = maxDistance / axisy.scale; + + if (s.lines.show || s.points.show) { + for (j = 0; j < points.length; j += ps) { + var x = points[j], y = points[j + 1]; + if (x == null) + continue; + + // For points and lines, the cursor must be within a + // certain distance to the data point + if (x - mx > maxx || x - mx < -maxx || + y - my > maxy || y - my < -maxy) + continue; + + // We have to calculate distances in pixels, not in + // data units, because the scales of the axes may be different + var dx = Math.abs(axisx.p2c(x) - mouseX), + dy = Math.abs(axisy.p2c(y) - mouseY), + dist = dx * dx + dy * dy; // we save the sqrt + + // use <= to ensure last point takes precedence + // (last generally means on top of) + if (dist <= smallestDistance) { + smallestDistance = dist; + item = [i, j / ps]; + } + } + } + + if (s.bars.show && !item) { // no other point can be nearby + var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2, + barRight = barLeft + s.bars.barWidth; + + for (j = 0; j < points.length; j += ps) { + var x = points[j], y = points[j + 1], b = points[j + 2]; + if (x == null) + continue; + + // for a bar graph, the cursor must be inside the bar + if (series[i].bars.horizontal ? + (mx <= Math.max(b, x) && mx >= Math.min(b, x) && + my >= y + barLeft && my <= y + barRight) : + (mx >= x + barLeft && mx <= x + barRight && + my >= Math.min(b, y) && my <= Math.max(b, y))) + item = [i, j / ps]; + } + } + } + + if (item) { + i = item[0]; + j = item[1]; + ps = series[i].datapoints.pointsize; + + return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps), + dataIndex: j, + series: series[i], + seriesIndex: i }; + } + + return null; + } + + function onMouseMove(e) { + if (options.grid.hoverable) + triggerClickHoverEvent("plothover", e, + function (s) { return s["hoverable"] != false; }); + } + + function onClick(e) { + triggerClickHoverEvent("plotclick", e, + function (s) { return s["clickable"] != false; }); + } + + // trigger click or hover event (they send the same parameters + // so we share their code) + function triggerClickHoverEvent(eventname, event, seriesFilter) { + var offset = eventHolder.offset(), + pos = { pageX: event.pageX, pageY: event.pageY }, + canvasX = event.pageX - offset.left - plotOffset.left, + canvasY = event.pageY - offset.top - plotOffset.top; + + if (axes.xaxis.used) + pos.x = axes.xaxis.c2p(canvasX); + if (axes.yaxis.used) + pos.y = axes.yaxis.c2p(canvasY); + if (axes.x2axis.used) + pos.x2 = axes.x2axis.c2p(canvasX); + if (axes.y2axis.used) + pos.y2 = axes.y2axis.c2p(canvasY); + + var item = findNearbyItem(canvasX, canvasY, seriesFilter); + + if (item) { + // fill in mouse pos for any listeners out there + item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left); + item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top); + } + + if (options.grid.autoHighlight) { + // clear auto-highlights + for (var i = 0; i < highlights.length; ++i) { + var h = highlights[i]; + if (h.auto == eventname && + !(item && h.series == item.series && h.point == item.datapoint)) + unhighlight(h.series, h.point); + } + + if (item) + highlight(item.series, item.datapoint, eventname); + } + + placeholder.trigger(eventname, [ pos, item ]); + } + + function triggerRedrawOverlay() { + if (!redrawTimeout) + redrawTimeout = setTimeout(drawOverlay, 30); + } + + function drawOverlay() { + redrawTimeout = null; + + // draw highlights + octx.save(); + octx.clearRect(0, 0, canvasWidth, canvasHeight); + octx.translate(plotOffset.left, plotOffset.top); + + var i, hi; + for (i = 0; i < highlights.length; ++i) { + hi = highlights[i]; + + if (hi.series.bars.show) + drawBarHighlight(hi.series, hi.point); + else + drawPointHighlight(hi.series, hi.point); + } + octx.restore(); + + executeHooks(hooks.drawOverlay, [octx]); + } + + function highlight(s, point, auto) { + if (typeof s == "number") + s = series[s]; + + if (typeof point == "number") + point = s.data[point]; + + var i = indexOfHighlight(s, point); + if (i == -1) { + highlights.push({ series: s, point: point, auto: auto }); + + triggerRedrawOverlay(); + } + else if (!auto) + highlights[i].auto = false; + } + + function unhighlight(s, point) { + if (s == null && point == null) { + highlights = []; + triggerRedrawOverlay(); + } + + if (typeof s == "number") + s = series[s]; + + if (typeof point == "number") + point = s.data[point]; + + var i = indexOfHighlight(s, point); + if (i != -1) { + highlights.splice(i, 1); + + triggerRedrawOverlay(); + } + } + + function indexOfHighlight(s, p) { + for (var i = 0; i < highlights.length; ++i) { + var h = highlights[i]; + if (h.series == s && h.point[0] == p[0] + && h.point[1] == p[1]) + return i; + } + return -1; + } + + function drawPointHighlight(series, point) { + var x = point[0], y = point[1], + axisx = series.xaxis, axisy = series.yaxis; + + if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) + return; + + var pointRadius = series.points.radius + series.points.lineWidth / 2; + octx.lineWidth = pointRadius; + octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString(); + var radius = 1.5 * pointRadius; + octx.beginPath(); + octx.arc(axisx.p2c(x), axisy.p2c(y), radius, 0, 2 * Math.PI, false); + octx.stroke(); + } + + function drawBarHighlight(series, point) { + octx.lineWidth = series.bars.lineWidth; + octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString(); + var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString(); + var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; + drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth, + 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal); + } + + function getColorOrGradient(spec, bottom, top, defaultColor) { + if (typeof spec == "string") + return spec; + else { + // assume this is a gradient spec; IE currently only + // supports a simple vertical gradient properly, so that's + // what we support too + var gradient = ctx.createLinearGradient(0, top, 0, bottom); + + for (var i = 0, l = spec.colors.length; i < l; ++i) { + var c = spec.colors[i]; + if (typeof c != "string") { + c = $.color.parse(defaultColor).scale('rgb', c.brightness); + c.a *= c.opacity; + c = c.toString(); + } + gradient.addColorStop(i / (l - 1), c); + } + + return gradient; + } + } + } + + $.plot = function(placeholder, data, options) { + var plot = new Plot($(placeholder), data, options, $.plot.plugins); + /*var t0 = new Date(); + var t1 = new Date(); + var tstr = "time used (msecs): " + (t1.getTime() - t0.getTime()) + if (window.console) + console.log(tstr); + else + alert(tstr);*/ + return plot; + }; + + $.plot.plugins = []; + + // returns a string with the date d formatted according to fmt + $.plot.formatDate = function(d, fmt, monthNames) { + var leftPad = function(n) { + n = "" + n; + return n.length == 1 ? "0" + n : n; + }; + + var r = []; + var escape = false; + var hours = d.getUTCHours(); + var isAM = hours < 12; + if (monthNames == null) + monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + + if (fmt.search(/%p|%P/) != -1) { + if (hours > 12) { + hours = hours - 12; + } else if (hours == 0) { + hours = 12; + } + } + for (var i = 0; i < fmt.length; ++i) { + var c = fmt.charAt(i); + + if (escape) { + switch (c) { + case 'h': c = "" + hours; break; + case 'H': c = leftPad(hours); break; + case 'M': c = leftPad(d.getUTCMinutes()); break; + case 'S': c = leftPad(d.getUTCSeconds()); break; + case 'd': c = "" + d.getUTCDate(); break; + case 'm': c = "" + (d.getUTCMonth() + 1); break; + case 'y': c = "" + d.getUTCFullYear(); break; + case 'b': c = "" + monthNames[d.getUTCMonth()]; break; + case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break; + case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break; + } + r.push(c); + escape = false; + } + else { + if (c == "%") + escape = true; + else + r.push(c); + } + } + return r.join(""); + }; + + // round to nearby lower multiple of base + function floorInBase(n, base) { + return base * Math.floor(n / base); + } + +})(jQuery); diff --git a/askbot/skins/old/media/js/jquery.flot.min.js b/askbot/skins/old/media/js/jquery.flot.min.js new file mode 100644 index 00000000..31f465b8 --- /dev/null +++ b/askbot/skins/old/media/js/jquery.flot.min.js @@ -0,0 +1 @@ +(function(){jQuery.color={};jQuery.color.make=function(G,H,J,I){var A={};A.r=G||0;A.g=H||0;A.b=J||0;A.a=I!=null?I:1;A.add=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]+=D}return A.normalize()};A.scale=function(C,D){for(var E=0;E<C.length;++E){A[C.charAt(E)]*=D}return A.normalize()};A.toString=function(){if(A.a>=1){return"rgb("+[A.r,A.g,A.b].join(",")+")"}else{return"rgba("+[A.r,A.g,A.b,A.a].join(",")+")"}};A.normalize=function(){function C(E,D,F){return D<E?E:(D>F?F:D)}A.r=C(0,parseInt(A.r),255);A.g=C(0,parseInt(A.g),255);A.b=C(0,parseInt(A.b),255);A.a=C(0,A.a,1);return A};A.clone=function(){return jQuery.color.make(A.r,A.b,A.g,A.a)};return A.normalize()};jQuery.color.extract=function(E,F){var A;do{A=E.css(F).toLowerCase();if(A!=""&&A!="transparent"){break}E=E.parent()}while(!jQuery.nodeName(E.get(0),"body"));if(A=="rgba(0, 0, 0, 0)"){A="transparent"}return jQuery.color.parse(A)};jQuery.color.parse=function(A){var F,H=jQuery.color.make;if(F=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10))}if(F=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseInt(F[1],10),parseInt(F[2],10),parseInt(F[3],10),parseFloat(F[4]))}if(F=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55)}if(F=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(A)){return H(parseFloat(F[1])*2.55,parseFloat(F[2])*2.55,parseFloat(F[3])*2.55,parseFloat(F[4]))}if(F=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(A)){return H(parseInt(F[1],16),parseInt(F[2],16),parseInt(F[3],16))}if(F=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(A)){return H(parseInt(F[1]+F[1],16),parseInt(F[2]+F[2],16),parseInt(F[3]+F[3],16))}var G=jQuery.trim(A).toLowerCase();if(G=="transparent"){return H(255,255,255,0)}else{F=B[G];return H(F[0],F[1],F[2])}};var B={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();(function(C){function B(l,W,X,E){var O=[],g={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:0.85},xaxis:{mode:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,tickDecimals:null,tickSize:null,minTickSize:null,monthNames:null,timeformat:null,twelveHourClock:false},yaxis:{autoscaleMargin:0.02},x2axis:{autoscaleMargin:null},y2axis:{autoscaleMargin:0.02},series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false},shadowSize:3},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,tickColor:"rgba(0,0,0,0.15)",labelMargin:5,borderWidth:2,borderColor:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},hooks:{}},P=null,AC=null,AD=null,Y=null,AJ=null,s={xaxis:{},yaxis:{},x2axis:{},y2axis:{}},e={left:0,right:0,top:0,bottom:0},y=0,Q=0,I=0,t=0,L={processOptions:[],processRawData:[],processDatapoints:[],draw:[],bindEvents:[],drawOverlay:[]},G=this;G.setData=f;G.setupGrid=k;G.draw=AH;G.getPlaceholder=function(){return l};G.getCanvas=function(){return P};G.getPlotOffset=function(){return e};G.width=function(){return I};G.height=function(){return t};G.offset=function(){var AK=AD.offset();AK.left+=e.left;AK.top+=e.top;return AK};G.getData=function(){return O};G.getAxes=function(){return s};G.getOptions=function(){return g};G.highlight=AE;G.unhighlight=x;G.triggerRedrawOverlay=q;G.pointOffset=function(AK){return{left:parseInt(T(AK,"xaxis").p2c(+AK.x)+e.left),top:parseInt(T(AK,"yaxis").p2c(+AK.y)+e.top)}};G.hooks=L;b(G);r(X);c();f(W);k();AH();AG();function Z(AM,AK){AK=[G].concat(AK);for(var AL=0;AL<AM.length;++AL){AM[AL].apply(this,AK)}}function b(){for(var AK=0;AK<E.length;++AK){var AL=E[AK];AL.init(G);if(AL.options){C.extend(true,g,AL.options)}}}function r(AK){C.extend(true,g,AK);if(g.grid.borderColor==null){g.grid.borderColor=g.grid.color}if(g.xaxis.noTicks&&g.xaxis.ticks==null){g.xaxis.ticks=g.xaxis.noTicks}if(g.yaxis.noTicks&&g.yaxis.ticks==null){g.yaxis.ticks=g.yaxis.noTicks}if(g.grid.coloredAreas){g.grid.markings=g.grid.coloredAreas}if(g.grid.coloredAreasColor){g.grid.markingsColor=g.grid.coloredAreasColor}if(g.lines){C.extend(true,g.series.lines,g.lines)}if(g.points){C.extend(true,g.series.points,g.points)}if(g.bars){C.extend(true,g.series.bars,g.bars)}if(g.shadowSize){g.series.shadowSize=g.shadowSize}for(var AL in L){if(g.hooks[AL]&&g.hooks[AL].length){L[AL]=L[AL].concat(g.hooks[AL])}}Z(L.processOptions,[g])}function f(AK){O=M(AK);U();m()}function M(AN){var AL=[];for(var AK=0;AK<AN.length;++AK){var AM=C.extend(true,{},g.series);if(AN[AK].data){AM.data=AN[AK].data;delete AN[AK].data;C.extend(true,AM,AN[AK]);AN[AK].data=AM.data}else{AM.data=AN[AK]}AL.push(AM)}return AL}function T(AM,AK){var AL=AM[AK];if(!AL||AL==1){return s[AK]}if(typeof AL=="number"){return s[AK.charAt(0)+AL+AK.slice(1)]}return AL}function U(){var AP;var AV=O.length,AK=[],AN=[];for(AP=0;AP<O.length;++AP){var AS=O[AP].color;if(AS!=null){--AV;if(typeof AS=="number"){AN.push(AS)}else{AK.push(C.color.parse(O[AP].color))}}}for(AP=0;AP<AN.length;++AP){AV=Math.max(AV,AN[AP]+1)}var AL=[],AO=0;AP=0;while(AL.length<AV){var AR;if(g.colors.length==AP){AR=C.color.make(100,100,100)}else{AR=C.color.parse(g.colors[AP])}var AM=AO%2==1?-1:1;AR.scale("rgb",1+AM*Math.ceil(AO/2)*0.2);AL.push(AR);++AP;if(AP>=g.colors.length){AP=0;++AO}}var AQ=0,AW;for(AP=0;AP<O.length;++AP){AW=O[AP];if(AW.color==null){AW.color=AL[AQ].toString();++AQ}else{if(typeof AW.color=="number"){AW.color=AL[AW.color].toString()}}if(AW.lines.show==null){var AU,AT=true;for(AU in AW){if(AW[AU].show){AT=false;break}}if(AT){AW.lines.show=true}}AW.xaxis=T(AW,"xaxis");AW.yaxis=T(AW,"yaxis")}}function m(){var AW=Number.POSITIVE_INFINITY,AQ=Number.NEGATIVE_INFINITY,Ac,Aa,AZ,AV,AL,AR,Ab,AX,AP,AO,AK,Ai,Af,AT;for(AK in s){s[AK].datamin=AW;s[AK].datamax=AQ;s[AK].used=false}function AN(Al,Ak,Aj){if(Ak<Al.datamin){Al.datamin=Ak}if(Aj>Al.datamax){Al.datamax=Aj}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];AR.datapoints={points:[]};Z(L.processRawData,[AR,AR.data,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];var Ah=AR.data,Ae=AR.datapoints.format;if(!Ae){Ae=[];Ae.push({x:true,number:true,required:true});Ae.push({y:true,number:true,required:true});if(AR.bars.show){Ae.push({y:true,number:true,required:false,defaultValue:0})}AR.datapoints.format=Ae}if(AR.datapoints.pointsize!=null){continue}if(AR.datapoints.pointsize==null){AR.datapoints.pointsize=Ae.length}AX=AR.datapoints.pointsize;Ab=AR.datapoints.points;insertSteps=AR.lines.show&&AR.lines.steps;AR.xaxis.used=AR.yaxis.used=true;for(Aa=AZ=0;Aa<Ah.length;++Aa,AZ+=AX){AT=Ah[Aa];var AM=AT==null;if(!AM){for(AV=0;AV<AX;++AV){Ai=AT[AV];Af=Ae[AV];if(Af){if(Af.number&&Ai!=null){Ai=+Ai;if(isNaN(Ai)){Ai=null}}if(Ai==null){if(Af.required){AM=true}if(Af.defaultValue!=null){Ai=Af.defaultValue}}}Ab[AZ+AV]=Ai}}if(AM){for(AV=0;AV<AX;++AV){Ai=Ab[AZ+AV];if(Ai!=null){Af=Ae[AV];if(Af.x){AN(AR.xaxis,Ai,Ai)}if(Af.y){AN(AR.yaxis,Ai,Ai)}}Ab[AZ+AV]=null}}else{if(insertSteps&&AZ>0&&Ab[AZ-AX]!=null&&Ab[AZ-AX]!=Ab[AZ]&&Ab[AZ-AX+1]!=Ab[AZ+1]){for(AV=0;AV<AX;++AV){Ab[AZ+AX+AV]=Ab[AZ+AV]}Ab[AZ+1]=Ab[AZ-AX+1];AZ+=AX}}}}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Z(L.processDatapoints,[AR,AR.datapoints])}for(Ac=0;Ac<O.length;++Ac){AR=O[Ac];Ab=AR.datapoints.points,AX=AR.datapoints.pointsize;var AS=AW,AY=AW,AU=AQ,Ad=AQ;for(Aa=0;Aa<Ab.length;Aa+=AX){if(Ab[Aa]==null){continue}for(AV=0;AV<AX;++AV){Ai=Ab[Aa+AV];Af=Ae[AV];if(!Af){continue}if(Af.x){if(Ai<AS){AS=Ai}if(Ai>AU){AU=Ai}}if(Af.y){if(Ai<AY){AY=Ai}if(Ai>Ad){Ad=Ai}}}}if(AR.bars.show){var Ag=AR.bars.align=="left"?0:-AR.bars.barWidth/2;if(AR.bars.horizontal){AY+=Ag;Ad+=Ag+AR.bars.barWidth}else{AS+=Ag;AU+=Ag+AR.bars.barWidth}}AN(AR.xaxis,AS,AU);AN(AR.yaxis,AY,Ad)}for(AK in s){if(s[AK].datamin==AW){s[AK].datamin=null}if(s[AK].datamax==AQ){s[AK].datamax=null}}}function c(){function AK(AM,AL){var AN=document.createElement("canvas");AN.width=AM;AN.height=AL;if(C.browser.msie){AN=window.G_vmlCanvasManager.initElement(AN)}return AN}y=l.width();Q=l.height();l.html("");if(l.css("position")=="static"){l.css("position","relative")}if(y<=0||Q<=0){throw"Invalid dimensions for plot, width = "+y+", height = "+Q}if(C.browser.msie){window.G_vmlCanvasManager.init_(document)}P=C(AK(y,Q)).appendTo(l).get(0);Y=P.getContext("2d");AC=C(AK(y,Q)).css({position:"absolute",left:0,top:0}).appendTo(l).get(0);AJ=AC.getContext("2d");AJ.stroke()}function AG(){AD=C([AC,P]);if(g.grid.hoverable){AD.mousemove(D)}if(g.grid.clickable){AD.click(d)}Z(L.bindEvents,[AD])}function k(){function AL(AT,AU){function AP(AV){return AV}var AS,AO,AQ=AU.transform||AP,AR=AU.inverseTransform;if(AT==s.xaxis||AT==s.x2axis){AS=AT.scale=I/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.min);if(AQ==AP){AT.p2c=function(AV){return(AV-AO)*AS}}else{AT.p2c=function(AV){return(AQ(AV)-AO)*AS}}if(!AR){AT.c2p=function(AV){return AO+AV/AS}}else{AT.c2p=function(AV){return AR(AO+AV/AS)}}}else{AS=AT.scale=t/(AQ(AT.max)-AQ(AT.min));AO=AQ(AT.max);if(AQ==AP){AT.p2c=function(AV){return(AO-AV)*AS}}else{AT.p2c=function(AV){return(AO-AQ(AV))*AS}}if(!AR){AT.c2p=function(AV){return AO-AV/AS}}else{AT.c2p=function(AV){return AR(AO-AV/AS)}}}}function AN(AR,AT){var AQ,AS=[],AP;AR.labelWidth=AT.labelWidth;AR.labelHeight=AT.labelHeight;if(AR==s.xaxis||AR==s.x2axis){if(AR.labelWidth==null){AR.labelWidth=y/(AR.ticks.length>0?AR.ticks.length:1)}if(AR.labelHeight==null){AS=[];for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel" style="float:left;width:'+AR.labelWidth+'px">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;width:10000px;font-size:smaller">'+AS.join("")+'<div style="clear:left"></div></div>').appendTo(l);AR.labelHeight=AO.height();AO.remove()}}}else{if(AR.labelWidth==null||AR.labelHeight==null){for(AQ=0;AQ<AR.ticks.length;++AQ){AP=AR.ticks[AQ].label;if(AP){AS.push('<div class="tickLabel">'+AP+"</div>")}}if(AS.length>0){var AO=C('<div style="position:absolute;top:-10000px;font-size:smaller">'+AS.join("")+"</div>").appendTo(l);if(AR.labelWidth==null){AR.labelWidth=AO.width()}if(AR.labelHeight==null){AR.labelHeight=AO.find("div").height()}AO.remove()}}}if(AR.labelWidth==null){AR.labelWidth=0}if(AR.labelHeight==null){AR.labelHeight=0}}function AM(){var AP=g.grid.borderWidth;for(i=0;i<O.length;++i){AP=Math.max(AP,2*(O[i].points.radius+O[i].points.lineWidth/2))}e.left=e.right=e.top=e.bottom=AP;var AO=g.grid.labelMargin+g.grid.borderWidth;if(s.xaxis.labelHeight>0){e.bottom=Math.max(AP,s.xaxis.labelHeight+AO)}if(s.yaxis.labelWidth>0){e.left=Math.max(AP,s.yaxis.labelWidth+AO)}if(s.x2axis.labelHeight>0){e.top=Math.max(AP,s.x2axis.labelHeight+AO)}if(s.y2axis.labelWidth>0){e.right=Math.max(AP,s.y2axis.labelWidth+AO)}I=y-e.left-e.right;t=Q-e.bottom-e.top}var AK;for(AK in s){K(s[AK],g[AK])}if(g.grid.show){for(AK in s){F(s[AK],g[AK]);p(s[AK],g[AK]);AN(s[AK],g[AK])}AM()}else{e.left=e.right=e.top=e.bottom=0;I=y;t=Q}for(AK in s){AL(s[AK],g[AK])}if(g.grid.show){h()}AI()}function K(AN,AQ){var AM=+(AQ.min!=null?AQ.min:AN.datamin),AK=+(AQ.max!=null?AQ.max:AN.datamax),AP=AK-AM;if(AP==0){var AL=AK==0?1:0.01;if(AQ.min==null){AM-=AL}if(AQ.max==null||AQ.min!=null){AK+=AL}}else{var AO=AQ.autoscaleMargin;if(AO!=null){if(AQ.min==null){AM-=AP*AO;if(AM<0&&AN.datamin!=null&&AN.datamin>=0){AM=0}}if(AQ.max==null){AK+=AP*AO;if(AK>0&&AN.datamax!=null&&AN.datamax<=0){AK=0}}}}AN.min=AM;AN.max=AK}function F(AP,AS){var AO;if(typeof AS.ticks=="number"&&AS.ticks>0){AO=AS.ticks}else{if(AP==s.xaxis||AP==s.x2axis){AO=0.3*Math.sqrt(y)}else{AO=0.3*Math.sqrt(Q)}}var AX=(AP.max-AP.min)/AO,AZ,AT,AV,AW,AR,AM,AL;if(AS.mode=="time"){var AU={second:1000,minute:60*1000,hour:60*60*1000,day:24*60*60*1000,month:30*24*60*60*1000,year:365.2425*24*60*60*1000};var AY=[[1,"second"],[2,"second"],[5,"second"],[10,"second"],[30,"second"],[1,"minute"],[2,"minute"],[5,"minute"],[10,"minute"],[30,"minute"],[1,"hour"],[2,"hour"],[4,"hour"],[8,"hour"],[12,"hour"],[1,"day"],[2,"day"],[3,"day"],[0.25,"month"],[0.5,"month"],[1,"month"],[2,"month"],[3,"month"],[6,"month"],[1,"year"]];var AN=0;if(AS.minTickSize!=null){if(typeof AS.tickSize=="number"){AN=AS.tickSize}else{AN=AS.minTickSize[0]*AU[AS.minTickSize[1]]}}for(AR=0;AR<AY.length-1;++AR){if(AX<(AY[AR][0]*AU[AY[AR][1]]+AY[AR+1][0]*AU[AY[AR+1][1]])/2&&AY[AR][0]*AU[AY[AR][1]]>=AN){break}}AZ=AY[AR][0];AV=AY[AR][1];if(AV=="year"){AM=Math.pow(10,Math.floor(Math.log(AX/AU.year)/Math.LN10));AL=(AX/AU.year)/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM}if(AS.tickSize){AZ=AS.tickSize[0];AV=AS.tickSize[1]}AT=function(Ac){var Ah=[],Af=Ac.tickSize[0],Ai=Ac.tickSize[1],Ag=new Date(Ac.min);var Ab=Af*AU[Ai];if(Ai=="second"){Ag.setUTCSeconds(A(Ag.getUTCSeconds(),Af))}if(Ai=="minute"){Ag.setUTCMinutes(A(Ag.getUTCMinutes(),Af))}if(Ai=="hour"){Ag.setUTCHours(A(Ag.getUTCHours(),Af))}if(Ai=="month"){Ag.setUTCMonth(A(Ag.getUTCMonth(),Af))}if(Ai=="year"){Ag.setUTCFullYear(A(Ag.getUTCFullYear(),Af))}Ag.setUTCMilliseconds(0);if(Ab>=AU.minute){Ag.setUTCSeconds(0)}if(Ab>=AU.hour){Ag.setUTCMinutes(0)}if(Ab>=AU.day){Ag.setUTCHours(0)}if(Ab>=AU.day*4){Ag.setUTCDate(1)}if(Ab>=AU.year){Ag.setUTCMonth(0)}var Ak=0,Aj=Number.NaN,Ad;do{Ad=Aj;Aj=Ag.getTime();Ah.push({v:Aj,label:Ac.tickFormatter(Aj,Ac)});if(Ai=="month"){if(Af<1){Ag.setUTCDate(1);var Aa=Ag.getTime();Ag.setUTCMonth(Ag.getUTCMonth()+1);var Ae=Ag.getTime();Ag.setTime(Aj+Ak*AU.hour+(Ae-Aa)*Af);Ak=Ag.getUTCHours();Ag.setUTCHours(0)}else{Ag.setUTCMonth(Ag.getUTCMonth()+Af)}}else{if(Ai=="year"){Ag.setUTCFullYear(Ag.getUTCFullYear()+Af)}else{Ag.setTime(Aj+Ab)}}}while(Aj<Ac.max&&Aj!=Ad);return Ah};AW=function(Aa,Ad){var Af=new Date(Aa);if(AS.timeformat!=null){return C.plot.formatDate(Af,AS.timeformat,AS.monthNames)}var Ab=Ad.tickSize[0]*AU[Ad.tickSize[1]];var Ac=Ad.max-Ad.min;var Ae=(AS.twelveHourClock)?" %p":"";if(Ab<AU.minute){fmt="%h:%M:%S"+Ae}else{if(Ab<AU.day){if(Ac<2*AU.day){fmt="%h:%M"+Ae}else{fmt="%b %d %h:%M"+Ae}}else{if(Ab<AU.month){fmt="%b %d"}else{if(Ab<AU.year){if(Ac<AU.year){fmt="%b"}else{fmt="%b %y"}}else{fmt="%y"}}}}return C.plot.formatDate(Af,fmt,AS.monthNames)}}else{var AK=AS.tickDecimals;var AQ=-Math.floor(Math.log(AX)/Math.LN10);if(AK!=null&&AQ>AK){AQ=AK}AM=Math.pow(10,-AQ);AL=AX/AM;if(AL<1.5){AZ=1}else{if(AL<3){AZ=2;if(AL>2.25&&(AK==null||AQ+1<=AK)){AZ=2.5;++AQ}}else{if(AL<7.5){AZ=5}else{AZ=10}}}AZ*=AM;if(AS.minTickSize!=null&&AZ<AS.minTickSize){AZ=AS.minTickSize}if(AS.tickSize!=null){AZ=AS.tickSize}AP.tickDecimals=Math.max(0,(AK!=null)?AK:AQ);AT=function(Ac){var Ae=[];var Af=A(Ac.min,Ac.tickSize),Ab=0,Aa=Number.NaN,Ad;do{Ad=Aa;Aa=Af+Ab*Ac.tickSize;Ae.push({v:Aa,label:Ac.tickFormatter(Aa,Ac)});++Ab}while(Aa<Ac.max&&Aa!=Ad);return Ae};AW=function(Aa,Ab){return Aa.toFixed(Ab.tickDecimals)}}AP.tickSize=AV?[AZ,AV]:AZ;AP.tickGenerator=AT;if(C.isFunction(AS.tickFormatter)){AP.tickFormatter=function(Aa,Ab){return""+AS.tickFormatter(Aa,Ab)}}else{AP.tickFormatter=AW}}function p(AO,AQ){AO.ticks=[];if(!AO.used){return }if(AQ.ticks==null){AO.ticks=AO.tickGenerator(AO)}else{if(typeof AQ.ticks=="number"){if(AQ.ticks>0){AO.ticks=AO.tickGenerator(AO)}}else{if(AQ.ticks){var AP=AQ.ticks;if(C.isFunction(AP)){AP=AP({min:AO.min,max:AO.max})}var AN,AK;for(AN=0;AN<AP.length;++AN){var AL=null;var AM=AP[AN];if(typeof AM=="object"){AK=AM[0];if(AM.length>1){AL=AM[1]}}else{AK=AM}if(AL==null){AL=AO.tickFormatter(AK,AO)}AO.ticks[AN]={v:AK,label:AL}}}}}if(AQ.autoscaleMargin!=null&&AO.ticks.length>0){if(AQ.min==null){AO.min=Math.min(AO.min,AO.ticks[0].v)}if(AQ.max==null&&AO.ticks.length>1){AO.max=Math.max(AO.max,AO.ticks[AO.ticks.length-1].v)}}}function AH(){Y.clearRect(0,0,y,Q);var AL=g.grid;if(AL.show&&!AL.aboveData){S()}for(var AK=0;AK<O.length;++AK){AA(O[AK])}Z(L.draw,[Y]);if(AL.show&&AL.aboveData){S()}}function N(AL,AR){var AO=AR+"axis",AK=AR+"2axis",AN,AQ,AP,AM;if(AL[AO]){AN=s[AO];AQ=AL[AO].from;AP=AL[AO].to}else{if(AL[AK]){AN=s[AK];AQ=AL[AK].from;AP=AL[AK].to}else{AN=s[AO];AQ=AL[AR+"1"];AP=AL[AR+"2"]}}if(AQ!=null&&AP!=null&&AQ>AP){return{from:AP,to:AQ,axis:AN}}return{from:AQ,to:AP,axis:AN}}function S(){var AO;Y.save();Y.translate(e.left,e.top);if(g.grid.backgroundColor){Y.fillStyle=R(g.grid.backgroundColor,t,0,"rgba(255, 255, 255, 0)");Y.fillRect(0,0,I,t)}var AL=g.grid.markings;if(AL){if(C.isFunction(AL)){AL=AL({xmin:s.xaxis.min,xmax:s.xaxis.max,ymin:s.yaxis.min,ymax:s.yaxis.max,xaxis:s.xaxis,yaxis:s.yaxis,x2axis:s.x2axis,y2axis:s.y2axis})}for(AO=0;AO<AL.length;++AO){var AK=AL[AO],AQ=N(AK,"x"),AN=N(AK,"y");if(AQ.from==null){AQ.from=AQ.axis.min}if(AQ.to==null){AQ.to=AQ.axis.max}if(AN.from==null){AN.from=AN.axis.min}if(AN.to==null){AN.to=AN.axis.max}if(AQ.to<AQ.axis.min||AQ.from>AQ.axis.max||AN.to<AN.axis.min||AN.from>AN.axis.max){continue}AQ.from=Math.max(AQ.from,AQ.axis.min);AQ.to=Math.min(AQ.to,AQ.axis.max);AN.from=Math.max(AN.from,AN.axis.min);AN.to=Math.min(AN.to,AN.axis.max);if(AQ.from==AQ.to&&AN.from==AN.to){continue}AQ.from=AQ.axis.p2c(AQ.from);AQ.to=AQ.axis.p2c(AQ.to);AN.from=AN.axis.p2c(AN.from);AN.to=AN.axis.p2c(AN.to);if(AQ.from==AQ.to||AN.from==AN.to){Y.beginPath();Y.strokeStyle=AK.color||g.grid.markingsColor;Y.lineWidth=AK.lineWidth||g.grid.markingsLineWidth;Y.moveTo(AQ.from,AN.from);Y.lineTo(AQ.to,AN.to);Y.stroke()}else{Y.fillStyle=AK.color||g.grid.markingsColor;Y.fillRect(AQ.from,AN.to,AQ.to-AQ.from,AN.from-AN.to)}}}Y.lineWidth=1;Y.strokeStyle=g.grid.tickColor;Y.beginPath();var AM,AP=s.xaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=s.xaxis.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,0);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,t)}AP=s.yaxis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(0,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}AP=s.x2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,-5);Y.lineTo(Math.floor(AP.p2c(AM))+Y.lineWidth/2,5)}AP=s.y2axis;for(AO=0;AO<AP.ticks.length;++AO){AM=AP.ticks[AO].v;if(AM<=AP.min||AM>=AP.max){continue}Y.moveTo(I-5,Math.floor(AP.p2c(AM))+Y.lineWidth/2);Y.lineTo(I+5,Math.floor(AP.p2c(AM))+Y.lineWidth/2)}Y.stroke();if(g.grid.borderWidth){var AR=g.grid.borderWidth;Y.lineWidth=AR;Y.strokeStyle=g.grid.borderColor;Y.strokeRect(-AR/2,-AR/2,I+AR,t+AR)}Y.restore()}function h(){l.find(".tickLabels").remove();var AK=['<div class="tickLabels" style="font-size:smaller;color:'+g.grid.color+'">'];function AM(AP,AQ){for(var AO=0;AO<AP.ticks.length;++AO){var AN=AP.ticks[AO];if(!AN.label||AN.v<AP.min||AN.v>AP.max){continue}AK.push(AQ(AN,AP))}}var AL=g.grid.labelMargin+g.grid.borderWidth;AM(s.xaxis,function(AN,AO){return'<div style="position:absolute;top:'+(e.top+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.yaxis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;right:"+(e.right+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:right" class="tickLabel">'+AN.label+"</div>"});AM(s.x2axis,function(AN,AO){return'<div style="position:absolute;bottom:'+(e.bottom+t+AL)+"px;left:"+Math.round(e.left+AO.p2c(AN.v)-AO.labelWidth/2)+"px;width:"+AO.labelWidth+'px;text-align:center" class="tickLabel">'+AN.label+"</div>"});AM(s.y2axis,function(AN,AO){return'<div style="position:absolute;top:'+Math.round(e.top+AO.p2c(AN.v)-AO.labelHeight/2)+"px;left:"+(e.left+I+AL)+"px;width:"+AO.labelWidth+'px;text-align:left" class="tickLabel">'+AN.label+"</div>"});AK.push("</div>");l.append(AK.join(""))}function AA(AK){if(AK.lines.show){a(AK)}if(AK.bars.show){n(AK)}if(AK.points.show){o(AK)}}function a(AN){function AM(AY,AZ,AR,Ad,Ac){var Ae=AY.points,AS=AY.pointsize,AW=null,AV=null;Y.beginPath();for(var AX=AS;AX<Ae.length;AX+=AS){var AU=Ae[AX-AS],Ab=Ae[AX-AS+1],AT=Ae[AX],Aa=Ae[AX+1];if(AU==null||AT==null){continue}if(Ab<=Aa&&Ab<Ac.min){if(Aa<Ac.min){continue}AU=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(Aa<=Ab&&Aa<Ac.min){if(Ab<Ac.min){continue}AT=(Ac.min-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.min}}if(Ab>=Aa&&Ab>Ac.max){if(Aa>Ac.max){continue}AU=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(Aa>=Ab&&Aa>Ac.max){if(Ab>Ac.max){continue}AT=(Ac.max-Ab)/(Aa-Ab)*(AT-AU)+AU;Aa=Ac.max}}if(AU<=AT&&AU<Ad.min){if(AT<Ad.min){continue}Ab=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.min}else{if(AT<=AU&&AT<Ad.min){if(AU<Ad.min){continue}Aa=(Ad.min-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.min}}if(AU>=AT&&AU>Ad.max){if(AT>Ad.max){continue}Ab=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AU=Ad.max}else{if(AT>=AU&&AT>Ad.max){if(AU>Ad.max){continue}Aa=(Ad.max-AU)/(AT-AU)*(Aa-Ab)+Ab;AT=Ad.max}}if(AU!=AW||Ab!=AV){Y.moveTo(Ad.p2c(AU)+AZ,Ac.p2c(Ab)+AR)}AW=AT;AV=Aa;Y.lineTo(Ad.p2c(AT)+AZ,Ac.p2c(Aa)+AR)}Y.stroke()}function AO(AX,Ae,Ac){var Af=AX.points,AR=AX.pointsize,AS=Math.min(Math.max(0,Ac.min),Ac.max),Aa,AV=0,Ad=false;for(var AW=AR;AW<Af.length;AW+=AR){var AU=Af[AW-AR],Ab=Af[AW-AR+1],AT=Af[AW],AZ=Af[AW+1];if(Ad&&AU!=null&&AT==null){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill();Ad=false;continue}if(AU==null||AT==null){continue}if(AU<=AT&&AU<Ae.min){if(AT<Ae.min){continue}Ab=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.min}else{if(AT<=AU&&AT<Ae.min){if(AU<Ae.min){continue}AZ=(Ae.min-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.min}}if(AU>=AT&&AU>Ae.max){if(AT>Ae.max){continue}Ab=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AU=Ae.max}else{if(AT>=AU&&AT>Ae.max){if(AU>Ae.max){continue}AZ=(Ae.max-AU)/(AT-AU)*(AZ-Ab)+Ab;AT=Ae.max}}if(!Ad){Y.beginPath();Y.moveTo(Ae.p2c(AU),Ac.p2c(AS));Ad=true}if(Ab>=Ac.max&&AZ>=Ac.max){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.max));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.max));AV=AT;continue}else{if(Ab<=Ac.min&&AZ<=Ac.min){Y.lineTo(Ae.p2c(AU),Ac.p2c(Ac.min));Y.lineTo(Ae.p2c(AT),Ac.p2c(Ac.min));AV=AT;continue}}var Ag=AU,AY=AT;if(Ab<=AZ&&Ab<Ac.min&&AZ>=Ac.min){AU=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.min}else{if(AZ<=Ab&&AZ<Ac.min&&Ab>=Ac.min){AT=(Ac.min-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.min}}if(Ab>=AZ&&Ab>Ac.max&&AZ<=Ac.max){AU=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;Ab=Ac.max}else{if(AZ>=Ab&&AZ>Ac.max&&Ab<=Ac.max){AT=(Ac.max-Ab)/(AZ-Ab)*(AT-AU)+AU;AZ=Ac.max}}if(AU!=Ag){if(Ab<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(Ag),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AU),Ac.p2c(Aa))}Y.lineTo(Ae.p2c(AU),Ac.p2c(Ab));Y.lineTo(Ae.p2c(AT),Ac.p2c(AZ));if(AT!=AY){if(AZ<=Ac.min){Aa=Ac.min}else{Aa=Ac.max}Y.lineTo(Ae.p2c(AT),Ac.p2c(Aa));Y.lineTo(Ae.p2c(AY),Ac.p2c(Aa))}AV=Math.max(AT,AY)}if(Ad){Y.lineTo(Ae.p2c(AV),Ac.p2c(AS));Y.fill()}}Y.save();Y.translate(e.left,e.top);Y.lineJoin="round";var AP=AN.lines.lineWidth,AK=AN.shadowSize;if(AP>0&&AK>0){Y.lineWidth=AK;Y.strokeStyle="rgba(0,0,0,0.1)";var AQ=Math.PI/18;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/2),Math.cos(AQ)*(AP/2+AK/2),AN.xaxis,AN.yaxis);Y.lineWidth=AK/2;AM(AN.datapoints,Math.sin(AQ)*(AP/2+AK/4),Math.cos(AQ)*(AP/2+AK/4),AN.xaxis,AN.yaxis)}Y.lineWidth=AP;Y.strokeStyle=AN.color;var AL=V(AN.lines,AN.color,0,t);if(AL){Y.fillStyle=AL;AO(AN.datapoints,AN.xaxis,AN.yaxis)}if(AP>0){AM(AN.datapoints,0,0,AN.xaxis,AN.yaxis)}Y.restore()}function o(AN){function AP(AU,AT,Ab,AR,AV,AZ,AY){var Aa=AU.points,AQ=AU.pointsize;for(var AS=0;AS<Aa.length;AS+=AQ){var AX=Aa[AS],AW=Aa[AS+1];if(AX==null||AX<AZ.min||AX>AZ.max||AW<AY.min||AW>AY.max){continue}Y.beginPath();Y.arc(AZ.p2c(AX),AY.p2c(AW)+AR,AT,0,AV,false);if(Ab){Y.fillStyle=Ab;Y.fill()}Y.stroke()}}Y.save();Y.translate(e.left,e.top);var AO=AN.lines.lineWidth,AL=AN.shadowSize,AK=AN.points.radius;if(AO>0&&AL>0){var AM=AL/2;Y.lineWidth=AM;Y.strokeStyle="rgba(0,0,0,0.1)";AP(AN.datapoints,AK,null,AM+AM/2,Math.PI,AN.xaxis,AN.yaxis);Y.strokeStyle="rgba(0,0,0,0.2)";AP(AN.datapoints,AK,null,AM/2,Math.PI,AN.xaxis,AN.yaxis)}Y.lineWidth=AO;Y.strokeStyle=AN.color;AP(AN.datapoints,AK,V(AN.points,AN.color),0,2*Math.PI,AN.xaxis,AN.yaxis);Y.restore()}function AB(AV,AU,Ad,AQ,AY,AN,AL,AT,AS,Ac,AZ){var AM,Ab,AR,AX,AO,AK,AW,AP,Aa;if(AZ){AP=AK=AW=true;AO=false;AM=Ad;Ab=AV;AX=AU+AQ;AR=AU+AY;if(Ab<AM){Aa=Ab;Ab=AM;AM=Aa;AO=true;AK=false}}else{AO=AK=AW=true;AP=false;AM=AV+AQ;Ab=AV+AY;AR=Ad;AX=AU;if(AX<AR){Aa=AX;AX=AR;AR=Aa;AP=true;AW=false}}if(Ab<AT.min||AM>AT.max||AX<AS.min||AR>AS.max){return }if(AM<AT.min){AM=AT.min;AO=false}if(Ab>AT.max){Ab=AT.max;AK=false}if(AR<AS.min){AR=AS.min;AP=false}if(AX>AS.max){AX=AS.max;AW=false}AM=AT.p2c(AM);AR=AS.p2c(AR);Ab=AT.p2c(Ab);AX=AS.p2c(AX);if(AL){Ac.beginPath();Ac.moveTo(AM,AR);Ac.lineTo(AM,AX);Ac.lineTo(Ab,AX);Ac.lineTo(Ab,AR);Ac.fillStyle=AL(AR,AX);Ac.fill()}if(AO||AK||AW||AP){Ac.beginPath();Ac.moveTo(AM,AR+AN);if(AO){Ac.lineTo(AM,AX+AN)}else{Ac.moveTo(AM,AX+AN)}if(AW){Ac.lineTo(Ab,AX+AN)}else{Ac.moveTo(Ab,AX+AN)}if(AK){Ac.lineTo(Ab,AR+AN)}else{Ac.moveTo(Ab,AR+AN)}if(AP){Ac.lineTo(AM,AR+AN)}else{Ac.moveTo(AM,AR+AN)}Ac.stroke()}}function n(AM){function AL(AS,AR,AU,AP,AT,AW,AV){var AX=AS.points,AO=AS.pointsize;for(var AQ=0;AQ<AX.length;AQ+=AO){if(AX[AQ]==null){continue}AB(AX[AQ],AX[AQ+1],AX[AQ+2],AR,AU,AP,AT,AW,AV,Y,AM.bars.horizontal)}}Y.save();Y.translate(e.left,e.top);Y.lineWidth=AM.bars.lineWidth;Y.strokeStyle=AM.color;var AK=AM.bars.align=="left"?0:-AM.bars.barWidth/2;var AN=AM.bars.fill?function(AO,AP){return V(AM.bars,AM.color,AO,AP)}:null;AL(AM.datapoints,AK,AK+AM.bars.barWidth,0,AN,AM.xaxis,AM.yaxis);Y.restore()}function V(AM,AK,AL,AO){var AN=AM.fill;if(!AN){return null}if(AM.fillColor){return R(AM.fillColor,AL,AO,AK)}var AP=C.color.parse(AK);AP.a=typeof AN=="number"?AN:0.4;AP.normalize();return AP.toString()}function AI(){l.find(".legend").remove();if(!g.legend.show){return }var AP=[],AN=false,AV=g.legend.labelFormatter,AU,AR;for(i=0;i<O.length;++i){AU=O[i];AR=AU.label;if(!AR){continue}if(i%g.legend.noColumns==0){if(AN){AP.push("</tr>")}AP.push("<tr>");AN=true}if(AV){AR=AV(AR,AU)}AP.push('<td class="legendColorBox"><div style="border:1px solid '+g.legend.labelBoxBorderColor+';padding:1px"><div style="width:4px;height:0;border:5px solid '+AU.color+';overflow:hidden"></div></div></td><td class="legendLabel">'+AR+"</td>")}if(AN){AP.push("</tr>")}if(AP.length==0){return }var AT='<table style="font-size:smaller;color:'+g.grid.color+'">'+AP.join("")+"</table>";if(g.legend.container!=null){C(g.legend.container).html(AT)}else{var AQ="",AL=g.legend.position,AM=g.legend.margin;if(AM[0]==null){AM=[AM,AM]}if(AL.charAt(0)=="n"){AQ+="top:"+(AM[1]+e.top)+"px;"}else{if(AL.charAt(0)=="s"){AQ+="bottom:"+(AM[1]+e.bottom)+"px;"}}if(AL.charAt(1)=="e"){AQ+="right:"+(AM[0]+e.right)+"px;"}else{if(AL.charAt(1)=="w"){AQ+="left:"+(AM[0]+e.left)+"px;"}}var AS=C('<div class="legend">'+AT.replace('style="','style="position:absolute;'+AQ+";")+"</div>").appendTo(l);if(g.legend.backgroundOpacity!=0){var AO=g.legend.backgroundColor;if(AO==null){AO=g.grid.backgroundColor;if(AO&&typeof AO=="string"){AO=C.color.parse(AO)}else{AO=C.color.extract(AS,"background-color")}AO.a=1;AO=AO.toString()}var AK=AS.children();C('<div style="position:absolute;width:'+AK.width()+"px;height:"+AK.height()+"px;"+AQ+"background-color:"+AO+';"> </div>').prependTo(AS).css("opacity",g.legend.backgroundOpacity)}}}var w=[],J=null;function AF(AR,AP,AM){var AX=g.grid.mouseActiveRadius,Aj=AX*AX+1,Ah=null,Aa=false,Af,Ad;for(Af=0;Af<O.length;++Af){if(!AM(O[Af])){continue}var AY=O[Af],AQ=AY.xaxis,AO=AY.yaxis,Ae=AY.datapoints.points,Ac=AY.datapoints.pointsize,AZ=AQ.c2p(AR),AW=AO.c2p(AP),AL=AX/AQ.scale,AK=AX/AO.scale;if(AY.lines.show||AY.points.show){for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1];if(AT==null){continue}if(AT-AZ>AL||AT-AZ<-AL||AS-AW>AK||AS-AW<-AK){continue}var AV=Math.abs(AQ.p2c(AT)-AR),AU=Math.abs(AO.p2c(AS)-AP),Ab=AV*AV+AU*AU;if(Ab<=Aj){Aj=Ab;Ah=[Af,Ad/Ac]}}}if(AY.bars.show&&!Ah){var AN=AY.bars.align=="left"?0:-AY.bars.barWidth/2,Ag=AN+AY.bars.barWidth;for(Ad=0;Ad<Ae.length;Ad+=Ac){var AT=Ae[Ad],AS=Ae[Ad+1],Ai=Ae[Ad+2];if(AT==null){continue}if(O[Af].bars.horizontal?(AZ<=Math.max(Ai,AT)&&AZ>=Math.min(Ai,AT)&&AW>=AS+AN&&AW<=AS+Ag):(AZ>=AT+AN&&AZ<=AT+Ag&&AW>=Math.min(Ai,AS)&&AW<=Math.max(Ai,AS))){Ah=[Af,Ad/Ac]}}}}if(Ah){Af=Ah[0];Ad=Ah[1];Ac=O[Af].datapoints.pointsize;return{datapoint:O[Af].datapoints.points.slice(Ad*Ac,(Ad+1)*Ac),dataIndex:Ad,series:O[Af],seriesIndex:Af}}return null}function D(AK){if(g.grid.hoverable){H("plothover",AK,function(AL){return AL.hoverable!=false})}}function d(AK){H("plotclick",AK,function(AL){return AL.clickable!=false})}function H(AL,AK,AM){var AN=AD.offset(),AS={pageX:AK.pageX,pageY:AK.pageY},AQ=AK.pageX-AN.left-e.left,AO=AK.pageY-AN.top-e.top;if(s.xaxis.used){AS.x=s.xaxis.c2p(AQ)}if(s.yaxis.used){AS.y=s.yaxis.c2p(AO)}if(s.x2axis.used){AS.x2=s.x2axis.c2p(AQ)}if(s.y2axis.used){AS.y2=s.y2axis.c2p(AO)}var AT=AF(AQ,AO,AM);if(AT){AT.pageX=parseInt(AT.series.xaxis.p2c(AT.datapoint[0])+AN.left+e.left);AT.pageY=parseInt(AT.series.yaxis.p2c(AT.datapoint[1])+AN.top+e.top)}if(g.grid.autoHighlight){for(var AP=0;AP<w.length;++AP){var AR=w[AP];if(AR.auto==AL&&!(AT&&AR.series==AT.series&&AR.point==AT.datapoint)){x(AR.series,AR.point)}}if(AT){AE(AT.series,AT.datapoint,AL)}}l.trigger(AL,[AS,AT])}function q(){if(!J){J=setTimeout(v,30)}}function v(){J=null;AJ.save();AJ.clearRect(0,0,y,Q);AJ.translate(e.left,e.top);var AL,AK;for(AL=0;AL<w.length;++AL){AK=w[AL];if(AK.series.bars.show){z(AK.series,AK.point)}else{u(AK.series,AK.point)}}AJ.restore();Z(L.drawOverlay,[AJ])}function AE(AM,AK,AN){if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL==-1){w.push({series:AM,point:AK,auto:AN});q()}else{if(!AN){w[AL].auto=false}}}function x(AM,AK){if(AM==null&&AK==null){w=[];q()}if(typeof AM=="number"){AM=O[AM]}if(typeof AK=="number"){AK=AM.data[AK]}var AL=j(AM,AK);if(AL!=-1){w.splice(AL,1);q()}}function j(AM,AN){for(var AK=0;AK<w.length;++AK){var AL=w[AK];if(AL.series==AM&&AL.point[0]==AN[0]&&AL.point[1]==AN[1]){return AK}}return -1}function u(AN,AM){var AL=AM[0],AR=AM[1],AQ=AN.xaxis,AP=AN.yaxis;if(AL<AQ.min||AL>AQ.max||AR<AP.min||AR>AP.max){return }var AO=AN.points.radius+AN.points.lineWidth/2;AJ.lineWidth=AO;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AK=1.5*AO;AJ.beginPath();AJ.arc(AQ.p2c(AL),AP.p2c(AR),AK,0,2*Math.PI,false);AJ.stroke()}function z(AN,AK){AJ.lineWidth=AN.bars.lineWidth;AJ.strokeStyle=C.color.parse(AN.color).scale("a",0.5).toString();var AM=C.color.parse(AN.color).scale("a",0.5).toString();var AL=AN.bars.align=="left"?0:-AN.bars.barWidth/2;AB(AK[0],AK[1],AK[2]||0,AL,AL+AN.bars.barWidth,0,function(){return AM},AN.xaxis,AN.yaxis,AJ,AN.bars.horizontal)}function R(AM,AL,AQ,AO){if(typeof AM=="string"){return AM}else{var AP=Y.createLinearGradient(0,AQ,0,AL);for(var AN=0,AK=AM.colors.length;AN<AK;++AN){var AR=AM.colors[AN];if(typeof AR!="string"){AR=C.color.parse(AO).scale("rgb",AR.brightness);AR.a*=AR.opacity;AR=AR.toString()}AP.addColorStop(AN/(AK-1),AR)}return AP}}}C.plot=function(G,E,D){var F=new B(C(G),E,D,C.plot.plugins);return F};C.plot.plugins=[];C.plot.formatDate=function(H,E,G){var L=function(N){N=""+N;return N.length==1?"0"+N:N};var D=[];var M=false;var K=H.getUTCHours();var I=K<12;if(G==null){G=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}if(E.search(/%p|%P/)!=-1){if(K>12){K=K-12}else{if(K==0){K=12}}}for(var F=0;F<E.length;++F){var J=E.charAt(F);if(M){switch(J){case"h":J=""+K;break;case"H":J=L(K);break;case"M":J=L(H.getUTCMinutes());break;case"S":J=L(H.getUTCSeconds());break;case"d":J=""+H.getUTCDate();break;case"m":J=""+(H.getUTCMonth()+1);break;case"y":J=""+H.getUTCFullYear();break;case"b":J=""+G[H.getUTCMonth()];break;case"p":J=(I)?("am"):("pm");break;case"P":J=(I)?("AM"):("PM");break}D.push(J);M=false}else{if(J=="%"){M=true}else{D.push(J)}}}return D.join("")};function A(E,D){return D*Math.floor(E/D)}})(jQuery);
\ No newline at end of file diff --git a/askbot/skins/old/media/js/jquery.form.js b/askbot/skins/old/media/js/jquery.form.js new file mode 100644 index 00000000..443114fd --- /dev/null +++ b/askbot/skins/old/media/js/jquery.form.js @@ -0,0 +1,654 @@ +/* + * jQuery Form Plugin + * version: 2.33 (22-SEP-2009) + * @requires jQuery v1.2.6 or later + * + * Examples and documentation at: http://malsup.com/jquery/form/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ +;(function($) { + +/* + Usage Note: + ----------- + Do not use both ajaxSubmit and ajaxForm on the same form. These + functions are intended to be exclusive. Use ajaxSubmit if you want + to bind your own submit handler to the form. For example, + + $(document).ready(function() { + $('#myForm').bind('submit', function() { + $(this).ajaxSubmit({ + target: '#output' + }); + return false; // <-- important! + }); + }); + + Use ajaxForm when you want the plugin to manage all the event binding + for you. For example, + + $(document).ready(function() { + $('#myForm').ajaxForm({ + target: '#output' + }); + }); + + When using ajaxForm, the ajaxSubmit function will be invoked for you + at the appropriate time. +*/ + +/** + * ajaxSubmit() provides a mechanism for immediately submitting + * an HTML form using AJAX. + */ +$.fn.ajaxSubmit = function(options) { + // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) + if (!this.length) { + log('ajaxSubmit: skipping submit process - no element selected'); + return this; + } + + if (typeof options == 'function') + options = { success: options }; + + var url = $.trim(this.attr('action')); + if (url) { + // clean url (don't include hash vaue) + url = (url.match(/^([^#]+)/)||[])[1]; + } + url = url || window.location.href || ''; + + options = $.extend({ + url: url, + type: this.attr('method') || 'GET' + }, options || {}); + + // hook for manipulating the form data before it is extracted; + // convenient for use with rich editors like tinyMCE or FCKEditor + var veto = {}; + this.trigger('form-pre-serialize', [this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); + return this; + } + + // provide opportunity to alter form data before it is serialized + if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { + log('ajaxSubmit: submit aborted via beforeSerialize callback'); + return this; + } + + var a = this.formToArray(options.semantic); + if (options.data) { + options.extraData = options.data; + for (var n in options.data) { + if(options.data[n] instanceof Array) { + for (var k in options.data[n]) + a.push( { name: n, value: options.data[n][k] } ); + } + else + a.push( { name: n, value: options.data[n] } ); + } + } + + // give pre-submit callback an opportunity to abort the submit + if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { + log('ajaxSubmit: submit aborted via beforeSubmit callback'); + return this; + } + + // fire vetoable 'validate' event + this.trigger('form-submit-validate', [a, this, options, veto]); + if (veto.veto) { + log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); + return this; + } + + var q = $.param(a); + + if (options.type.toUpperCase() == 'GET') { + options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; + options.data = null; // data is null for 'get' + } + else + options.data = q; // data is the query string for 'post' + + var $form = this, callbacks = []; + if (options.resetForm) callbacks.push(function() { $form.resetForm(); }); + if (options.clearForm) callbacks.push(function() { $form.clearForm(); }); + + // perform a load on the target only if dataType is not provided + if (!options.dataType && options.target) { + var oldSuccess = options.success || function(){}; + callbacks.push(function(data) { + $(options.target).html(data).each(oldSuccess, arguments); + }); + } + else if (options.success) + callbacks.push(options.success); + + options.success = function(data, status) { + for (var i=0, max=callbacks.length; i < max; i++) + callbacks[i].apply(options, [data, status, $form]); + }; + + // are there files to upload? + var files = $('input:file', this).fieldValue(); + var found = false; + for (var j=0; j < files.length; j++) + if (files[j]) + found = true; + + var multipart = false; +// var mp = 'multipart/form-data'; +// multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); + + // options.iframe allows user to force iframe mode + if (options.iframe || found || multipart) { + // hack to fix Safari hang (thanks to Tim Molendijk for this) + // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d + if (options.closeKeepAlive) + $.get(options.closeKeepAlive, fileUpload); + else + fileUpload(); + } + else{ + $.ajax(options); + } + + // fire 'notify' event + this.trigger('form-submit-notify', [this, options]); + return this; + + + // private function for handling file uploads (hat tip to YAHOO!) + function fileUpload() { + var form = $form[0]; + + if ($(':input[name=submit]', form).length) { + alert('Error: Form elements must not be named "submit".'); + return; + } + + var opts = $.extend({}, $.ajaxSettings, options); + var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts); + + var id = 'jqFormIO' + (new Date().getTime()); + var $io = $('<iframe id="' + id + '" name="' + id + '" src="about:blank" />'); + var io = $io[0]; + + $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' }); + + var xhr = { // mock object + aborted: 0, + responseText: null, + responseXML: null, + status: 0, + statusText: 'n/a', + getAllResponseHeaders: function() {}, + getResponseHeader: function() {}, + setRequestHeader: function() {}, + abort: function() { + this.aborted = 1; + $io.attr('src','about:blank'); // abort op in progress + } + }; + + var g = opts.global; + // trigger ajax global events so that activity/block indicators work like normal + if (g && ! $.active++) $.event.trigger("ajaxStart"); + if (g) $.event.trigger("ajaxSend", [xhr, opts]); + + if (s.beforeSend && s.beforeSend(xhr, s) === false) { + s.global && $.active--; + return; + } + if (xhr.aborted) + return; + + var cbInvoked = 0; + var timedOut = 0; + + // add submitting element to data if we know it + var sub = form.clk; + if (sub) { + var n = sub.name; + if (n && !sub.disabled) { + options.extraData = options.extraData || {}; + options.extraData[n] = sub.value; + if (sub.type == "image") { + options.extraData[name+'.x'] = form.clk_x; + options.extraData[name+'.y'] = form.clk_y; + } + } + } + + // take a breath so that pending repaints get some cpu time before the upload starts + setTimeout(function() { + // make sure form attrs are set + var t = $form.attr('target'), a = $form.attr('action'); + + // update form attrs in IE friendly way + form.setAttribute('target',id); + if (form.getAttribute('method') != 'POST') + form.setAttribute('method', 'POST'); + if (form.getAttribute('action') != opts.url) + form.setAttribute('action', opts.url); + + // ie borks in some cases when setting encoding + if (! options.skipEncodingOverride) { + $form.attr({ + encoding: 'multipart/form-data', + enctype: 'multipart/form-data' + }); + } + + // support timout + if (opts.timeout) + setTimeout(function() { timedOut = true; cb(); }, opts.timeout); + + // add "extra" data to form if provided in options + var extraInputs = []; + try { + if (options.extraData) + for (var n in options.extraData) + extraInputs.push( + $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />') + .appendTo(form)[0]); + + // add iframe to doc and submit the form + $io.appendTo('body'); + io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false); + form.submit(); + } + finally { + // reset attrs and remove "extra" input elements + form.setAttribute('action',a); + t ? form.setAttribute('target', t) : $form.removeAttr('target'); + $(extraInputs).remove(); + } + }, 10); + + var domCheckCount = 50; + + function cb() { + if (cbInvoked++) return; + + io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false); + + var ok = true; + try { + if (timedOut) throw 'timeout'; + // extract the server response from the iframe + var data, doc; + + doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document; + + var isXml = opts.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc); + log('isXml='+isXml); + if (!isXml && (doc.body == null || doc.body.innerHTML == '')) { + if (--domCheckCount) { + // in some browsers (Opera) the iframe DOM is not always traversable when + // the onload callback fires, so we loop a bit to accommodate + cbInvoked = 0; + setTimeout(cb, 100); + return; + } + log('Could not access iframe DOM after 50 tries.'); + return; + } + + xhr.responseText = doc.body ? doc.body.innerHTML : null; + xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; + xhr.getResponseHeader = function(header){ + var headers = {'content-type': opts.dataType}; + return headers[header]; + }; + + if (opts.dataType == 'json' || opts.dataType == 'script') { + // see if user embedded response in textarea + var ta = doc.getElementsByTagName('textarea')[0]; + if (ta) + xhr.responseText = ta.value; + else { + // account for browsers injecting pre around json response + var pre = doc.getElementsByTagName('pre')[0]; + if (pre) + xhr.responseText = pre.innerHTML; + } + } + else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) { + xhr.responseXML = toXml(xhr.responseText); + } + data = $.httpData(xhr, opts.dataType); + } + catch(e){ + ok = false; + $.handleError(opts, xhr, 'error', e); + } + + // ordering of these callbacks/triggers is odd, but that's how $.ajax does it + if (ok) { + opts.success(data, 'success'); + if (g) $.event.trigger("ajaxSuccess", [xhr, opts]); + } + if (g) $.event.trigger("ajaxComplete", [xhr, opts]); + if (g && ! --$.active) $.event.trigger("ajaxStop"); + if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error'); + + // clean up + setTimeout(function() { + $io.remove(); + xhr.responseXML = null; + }, 100); + }; + + function toXml(s, doc) { + if (window.ActiveXObject) { + doc = new ActiveXObject('Microsoft.XMLDOM'); + doc.async = 'false'; + doc.loadXML(s); + } + else + doc = (new DOMParser()).parseFromString(s, 'text/xml'); + return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null; + }; + }; +}; + +/** + * ajaxForm() provides a mechanism for fully automating form submission. + * + * The advantages of using this method instead of ajaxSubmit() are: + * + * 1: This method will include coordinates for <input type="image" /> elements (if the element + * is used to submit the form). + * 2. This method will include the submit element's name/value data (for the element that was + * used to submit the form). + * 3. This method binds the submit() method to the form for you. + * + * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely + * passes the options argument along after properly binding events for submit elements and + * the form itself. + */ +$.fn.ajaxForm = function(options) { + return this.ajaxFormUnbind().bind('submit.form-plugin', function() { + $(this).ajaxSubmit(options); + return false; + }).bind('click.form-plugin', function(e) { + var $el = $(e.target); + if (!($el.is(":submit,input:image"))) { + return; + } + var form = this; + form.clk = e.target; + if (e.target.type == 'image') { + if (e.offsetX != undefined) { + form.clk_x = e.offsetX; + form.clk_y = e.offsetY; + } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin + var offset = $el.offset(); + form.clk_x = e.pageX - offset.left; + form.clk_y = e.pageY - offset.top; + } else { + form.clk_x = e.pageX - e.target.offsetLeft; + form.clk_y = e.pageY - e.target.offsetTop; + } + } + // clear form vars + setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 10); + }); +}; + +// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm +$.fn.ajaxFormUnbind = function() { + return this.unbind('submit.form-plugin click.form-plugin'); +}; + +/** + * formToArray() gathers form element data into an array of objects that can + * be passed to any of the following ajax functions: $.get, $.post, or load. + * Each object in the array has both a 'name' and 'value' property. An example of + * an array for a simple login form might be: + * + * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] + * + * It is this array that is passed to pre-submit callback functions provided to the + * ajaxSubmit() and ajaxForm() methods. + */ +$.fn.formToArray = function(semantic) { + var a = []; + if (this.length == 0) return a; + + var form = this[0]; + var els = semantic ? form.getElementsByTagName('*') : form.elements; + if (!els) return a; + for(var i=0, max=els.length; i < max; i++) { + var el = els[i]; + var n = el.name; + if (!n) continue; + + if (semantic && form.clk && el.type == "image") { + // handle image inputs on the fly when semantic == true + if(!el.disabled && form.clk == el) { + a.push({name: n, value: $(el).val()}); + a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); + } + continue; + } + + var v = $.fieldValue(el, true); + if (v && v.constructor == Array) { + for(var j=0, jmax=v.length; j < jmax; j++) + a.push({name: n, value: v[j]}); + } + else if (v !== null && typeof v != 'undefined') + a.push({name: n, value: v}); + } + + if (!semantic && form.clk) { + // input type=='image' are not found in elements array! handle it here + var $input = $(form.clk), input = $input[0], n = input.name; + if (n && !input.disabled && input.type == 'image') { + a.push({name: n, value: $input.val()}); + a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y}); + } + } + return a; +}; + +/** + * Serializes form data into a 'submittable' string. This method will return a string + * in the format: name1=value1&name2=value2 + */ +$.fn.formSerialize = function(semantic) { + //hand off to jQuery.param for proper encoding + return $.param(this.formToArray(semantic)); +}; + +/** + * Serializes all field elements in the jQuery object into a query string. + * This method will return a string in the format: name1=value1&name2=value2 + */ +$.fn.fieldSerialize = function(successful) { + var a = []; + this.each(function() { + var n = this.name; + if (!n) return; + var v = $.fieldValue(this, successful); + if (v && v.constructor == Array) { + for (var i=0,max=v.length; i < max; i++) + a.push({name: n, value: v[i]}); + } + else if (v !== null && typeof v != 'undefined') + a.push({name: this.name, value: v}); + }); + //hand off to jQuery.param for proper encoding + return $.param(a); +}; + +/** + * Returns the value(s) of the element in the matched set. For example, consider the following form: + * + * <form><fieldset> + * <input name="A" type="text" /> + * <input name="A" type="text" /> + * <input name="B" type="checkbox" value="B1" /> + * <input name="B" type="checkbox" value="B2"/> + * <input name="C" type="radio" value="C1" /> + * <input name="C" type="radio" value="C2" /> + * </fieldset></form> + * + * var v = $(':text').fieldValue(); + * // if no values are entered into the text inputs + * v == ['',''] + * // if values entered into the text inputs are 'foo' and 'bar' + * v == ['foo','bar'] + * + * var v = $(':checkbox').fieldValue(); + * // if neither checkbox is checked + * v === undefined + * // if both checkboxes are checked + * v == ['B1', 'B2'] + * + * var v = $(':radio').fieldValue(); + * // if neither radio is checked + * v === undefined + * // if first radio is checked + * v == ['C1'] + * + * The successful argument controls whether or not the field element must be 'successful' + * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). + * The default value of the successful argument is true. If this value is false the value(s) + * for each element is returned. + * + * Note: This method *always* returns an array. If no valid value can be determined the + * array will be empty, otherwise it will contain one or more values. + */ +$.fn.fieldValue = function(successful) { + for (var val=[], i=0, max=this.length; i < max; i++) { + var el = this[i]; + var v = $.fieldValue(el, successful); + if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) + continue; + v.constructor == Array ? $.merge(val, v) : val.push(v); + } + return val; +}; + +/** + * Returns the value of the field element. + */ +$.fieldValue = function(el, successful) { + var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); + if (typeof successful == 'undefined') successful = true; + + if (successful && (!n || el.disabled || t == 'reset' || t == 'button' || + (t == 'checkbox' || t == 'radio') && !el.checked || + (t == 'submit' || t == 'image') && el.form && el.form.clk != el || + tag == 'select' && el.selectedIndex == -1)) + return null; + + if (tag == 'select') { + var index = el.selectedIndex; + if (index < 0) return null; + var a = [], ops = el.options; + var one = (t == 'select-one'); + var max = (one ? index+1 : ops.length); + for(var i=(one ? index : 0); i < max; i++) { + var op = ops[i]; + if (op.selected) { + var v = op.value; + if (!v) // extra pain for IE... + v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value; + if (one) return v; + a.push(v); + } + } + return a; + } + return el.value; +}; + +/** + * Clears the form data. Takes the following actions on the form's input fields: + * - input text fields will have their 'value' property set to the empty string + * - select elements will have their 'selectedIndex' property set to -1 + * - checkbox and radio inputs will have their 'checked' property set to false + * - inputs of type submit, button, reset, and hidden will *not* be effected + * - button elements will *not* be effected + */ +$.fn.clearForm = function() { + return this.each(function() { + $('input,select,textarea', this).clearFields(); + }); +}; + +/** + * Clears the selected form elements. + */ +$.fn.clearFields = $.fn.clearInputs = function() { + return this.each(function() { + var t = this.type, tag = this.tagName.toLowerCase(); + if (t == 'text' || t == 'password' || tag == 'textarea') + this.value = ''; + else if (t == 'checkbox' || t == 'radio') + this.checked = false; + else if (tag == 'select') + this.selectedIndex = -1; + }); +}; + +/** + * Resets the form data. Causes all form elements to be reset to their original value. + */ +$.fn.resetForm = function() { + return this.each(function() { + // guard against an input with the name of 'reset' + // note that IE reports the reset function as an 'object' + if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) + this.reset(); + }); +}; + +/** + * Enables or disables any matching elements. + */ +$.fn.enable = function(b) { + if (b == undefined) b = true; + return this.each(function() { + this.disabled = !b; + }); +}; + +/** + * Checks/unchecks any matching checkboxes or radio buttons and + * selects/deselects and matching option elements. + */ +$.fn.selected = function(select) { + if (select == undefined) select = true; + return this.each(function() { + var t = this.type; + if (t == 'checkbox' || t == 'radio') + this.checked = select; + else if (this.tagName.toLowerCase() == 'option') { + var $sel = $(this).parent('select'); + if (select && $sel[0] && $sel[0].type == 'select-one') { + // deselect all other options + $sel.find('option').selected(false); + } + this.selected = select; + } + }); +}; + +// helper fn for console logging +// set $.fn.ajaxSubmit.debug to true to enable debug logging +function log() { + if ($.fn.ajaxSubmit.debug && window.console && window.console.log) + window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,'')); +}; + +})(jQuery); diff --git a/askbot/skins/old/media/js/jquery.i18n.js b/askbot/skins/old/media/js/jquery.i18n.js new file mode 100644 index 00000000..0a155a31 --- /dev/null +++ b/askbot/skins/old/media/js/jquery.i18n.js @@ -0,0 +1,133 @@ +/* + * jQuery i18n plugin + * @requires jQuery v1.1 or later + * + * Examples at: http://recurser.com/articles/2008/02/21/jquery-i18n-translation-plugin/ + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Based on 'javascript i18n that almost doesn't suck' by markos + * http://markos.gaivo.net/blog/?p=100 + * + * Revision: $Id$ + * Version: 1.0.0 Feb-10-2008 + */ + (function($) { +/** + * i18n provides a mechanism for translating strings using a jscript dictionary. + * + */ + + +/* + * i18n property list + */ +$.i18n = { + +/** + * setDictionary() + * Initialise the dictionary and translate nodes + * + * @param property_list i18n_dict : The dictionary to use for translation + */ + setDictionary: function(i18n_dict) { + i18n_dict = i18n_dict; + }, + +/** + * _() + * The actual translation function. Looks the given string up in the + * dictionary and returns the translation if one exists. If a translation + * is not found, returns the original word + * + * @param string str : The string to translate + * @param property_list params : params for using printf() on the string + * @return string : Translated word + * + */ + _: function (str, params) { + var transl = str; + if (i18n_dict&& i18n_dict[str]) { + transl = i18n_dict[str]; + } + return this.printf(transl, params); + }, + +/** + * toEntity() + * Change non-ASCII characters to entity representation + * + * @param string str : The string to transform + * @return string result : Original string with non-ASCII content converted to entities + * + */ + toEntity: function (str) { + var result = ''; + for (var i=0;i<str.length; i++) { + if (str.charCodeAt(i) > 128) + result += "&#"+str.charCodeAt(i)+";"; + else + result += str.charAt(i); + } + return result; + }, + +/** + * stripStr() + * + * @param string str : The string to strip + * @return string result : Stripped string + * + */ + stripStr: function(str) { + return str.replace(/^\s*/, "").replace(/\s*$/, ""); + }, + +/** + * stripStrML() + * + * @param string str : The multi-line string to strip + * @return string result : Stripped string + * + */ + stripStrML: function(str) { + // Split because m flag doesn't exist before JS1.5 and we need to + // strip newlines anyway + var parts = str.split('\n'); + for (var i=0; i<parts.length; i++) + parts[i] = stripStr(parts[i]); + + // Don't join with empty strings, because it "concats" words + // And strip again + return stripStr(parts.join(" ")); + }, + +/* + * printf() + * C-printf like function, which substitutes %s with parameters + * given in list. %%s is used to escape %s. + * + * Doesn't work in IE5.0 (splice) + * + * @param string S : string to perform printf on. + * @param string L : Array of arguments for printf() + */ + printf: function(S, L) { + if (!L) return S; + + var nS = ""; + var tS = S.split("%s"); + + for(var i=0; i<L.length; i++) { + if (tS[i].lastIndexOf('%') == tS[i].length-1 && i != L.length-1) + tS[i] += "s"+tS.splice(i+1,1)[0]; + nS += tS[i] + L[i]; + } + return nS + tS[tS.length-1]; + } + +}; + + +})(jQuery); diff --git a/askbot/skins/old/media/js/jquery.openid.js b/askbot/skins/old/media/js/jquery.openid.js new file mode 100644 index 00000000..af7d8cb9 --- /dev/null +++ b/askbot/skins/old/media/js/jquery.openid.js @@ -0,0 +1,176 @@ +/* +openid login boxes +*/ +var providers_large = { + google: { + name: 'Google', + url: 'https://www.google.com/accounts/o8/id' + }, + yahoo: { + name: 'Yahoo', + url: 'http://yahoo.com/' + }, + aol: { + name: 'AOL', + label: 'Enter your AOL screenname.', + url: 'http://openid.aol.com/{username}' + }, + openid: { + name: 'OpenID', + label: 'Enter your OpenID.', + url: 'http://' + } +}; +var providers_small = { + myopenid: { + name: 'MyOpenID', + label: 'Enter your MyOpenID username.', + url: 'http://{username}.myopenid.com/' + }, + livejournal: { + name: 'LiveJournal', + label: 'Enter your Livejournal username.', + url: 'http://{username}.livejournal.com/' + }, + flickr: { + name: 'Flickr', + label: 'Enter your Flickr username.', + url: 'http://flickr.com/{username}/' + }, + technorati: { + name: 'Technorati', + label: 'Enter your Technorati username.', + url: 'http://technorati.com/people/technorati/{username}/' + }, + wordpress: { + name: 'Wordpress', + label: 'Enter your Wordpress.com username.', + url: 'http://{username}.wordpress.com/' + }, + blogger: { + name: 'Blogger', + label: 'Your Blogger account', + url: 'http://{username}.blogspot.com/' + }, + verisign: { + name: 'Verisign', + label: 'Your Verisign username', + url: 'http://{username}.pip.verisignlabs.com/' + }, + vidoop: { + name: 'Vidoop', + label: 'Your Vidoop username', + url: 'http://{username}.myvidoop.com/' + }, + verisign: { + name: 'Verisign', + label: 'Your Verisign username', + url: 'http://{username}.pip.verisignlabs.com/' + }, + claimid: { + name: 'ClaimID', + label: 'Your ClaimID username', + url: 'http://claimid.com/{username}' + } +}; +var providers = $.extend({}, providers_large, providers_small); + +var openid = { + + cookie_expires: 6*30, // 6 months. + cookie_name: 'openid_provider', + cookie_path: '/', + + img_path: '/media/images/openid/', + + input_id: null, + provider_url: null, + + init: function(input_id) { + + var openid_btns = $('#openid_btns'); + this.input_id = input_id; + + $('#openid_choice').show(); + //$('#openid_input_area').empty(); + + // add box for each provider + for (id in providers_large) { + openid_btns.append(this.getBoxHTML(providers_large[id], 'large', '.gif')); + } + if (providers_small) { + openid_btns.append('<br/>'); + for (id in providers_small) { + openid_btns.append(this.getBoxHTML(providers_small[id], 'small', '.ico')); + } + } + + var box_id = this.readCookie(); + if (box_id) { + this.signin(box_id, true); + } + }, + getBoxHTML: function(provider, box_size, image_ext) { + + var box_id = provider["name"].toLowerCase(); + return '<a title="'+provider["name"]+'" href="javascript: openid.signin(\''+ box_id +'\');"' + + ' style="background: #FFF url(' + this.img_path + box_id + image_ext+') no-repeat center center" ' + 'class="' + box_id + ' openid_' + box_size + '_btn"></a>'; + + }, + /* Provider image click */ + signin: function(box_id, onload) { + var provider = providers[box_id]; + if (! provider) { + return; + } + this.highlight(box_id); + this.setCookie(box_id); + + $('#'+this.input_id).val(provider['url']); + var input = $('#'+this.input_id); + if(document.selection){ + var r = document.all.openid_url.createTextRange(); + var res = r.findText("{username}"); + if(res) + r.select(); + + } + else { + var text = input.val(); + var searchText = "{username}"; + var posStart = text.indexOf(searchText); + if(posStart > -1){ + input.focus(); + document.getElementById(this.input_id).setSelectionRange(posStart, posStart + searchText.length); + } + } + }, + + highlight: function (box_id) { + // remove previous highlight. + var highlight = $('#openid_highlight'); + if (highlight) { + highlight.replaceWith($('#openid_highlight a')[0]); + } + // add new highlight. + $('.'+box_id).wrap('<div id="openid_highlight"></div>'); + }, + + setCookie: function (value) { + var date = new Date(); + date.setTime(date.getTime()+(this.cookie_expires*24*60*60*1000)); + var expires = "; expires="+date.toGMTString(); + document.cookie = this.cookie_name+"="+value+expires+"; path=" + this.cookie_path; + }, + + readCookie: function () { + var nameEQ = this.cookie_name + "="; + var ca = document.cookie.split(';'); + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1,c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); + } + return null; + } +}; diff --git a/askbot/skins/old/media/js/jquery.validate.js b/askbot/skins/old/media/js/jquery.validate.js new file mode 100644 index 00000000..e402ea8c --- /dev/null +++ b/askbot/skins/old/media/js/jquery.validate.js @@ -0,0 +1,1146 @@ +/* + * jQuery validation plug-in 1.7 + * + * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ + * http://docs.jquery.com/Plugins/Validation + * + * Copyright (c) 2006 - 2008 Jörn Zaefferer + * + * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +(function($) { + +$.extend($.fn, { + // http://docs.jquery.com/Plugins/Validation/validate + validate: function( options ) { + + // if nothing is selected, return nothing; can't chain anyway + if (!this.length) { + options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" ); + return; + } + + // check if a validator for this form was already created + var validator = $.data(this[0], 'validator'); + if ( validator ) { + return validator; + } + + validator = new $.validator( options, this[0] ); + $.data(this[0], 'validator', validator); + + if ( validator.settings.onsubmit ) { + + // allow suppresing validation by adding a cancel class to the submit button + this.find("input, button").filter(".cancel").click(function() { + validator.cancelSubmit = true; + }); + + // when a submitHandler is used, capture the submitting button + if (validator.settings.submitHandler) { + this.find("input, button").filter(":submit").click(function() { + validator.submitButton = this; + }); + } + + // validate the form on submit + this.submit( function( event ) { + if ( validator.settings.debug ) + // prevent form submit to be able to see console output + event.preventDefault(); + + function handle() { + if ( validator.settings.submitHandler ) { + if (validator.submitButton) { + // insert a hidden input as a replacement for the missing submit button + var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); + } + validator.settings.submitHandler.call( validator, validator.currentForm ); + if (validator.submitButton) { + // and clean up afterwards; thanks to no-block-scope, hidden can be referenced + hidden.remove(); + } + return false; + } + return true; + } + + // prevent submit for invalid forms or custom submit handlers + if ( validator.cancelSubmit ) { + validator.cancelSubmit = false; + return handle(); + } + if ( validator.form() ) { + if ( validator.pendingRequest ) { + validator.formSubmitted = true; + return false; + } + return handle(); + } else { + validator.focusInvalid(); + return false; + } + }); + } + + return validator; + }, + // http://docs.jquery.com/Plugins/Validation/valid + valid: function() { + if ( $(this[0]).is('form')) { + return this.validate().form(); + } else { + var valid = true; + var validator = $(this[0].form).validate(); + this.each(function() { + valid &= validator.element(this); + }); + return valid; + } + }, + // attributes: space seperated list of attributes to retrieve and remove + removeAttrs: function(attributes) { + var result = {}, + $element = this; + $.each(attributes.split(/\s/), function(index, value) { + result[value] = $element.attr(value); + $element.removeAttr(value); + }); + return result; + }, + // http://docs.jquery.com/Plugins/Validation/rules + rules: function(command, argument) { + var element = this[0]; + + if (command) { + var settings = $.data(element.form, 'validator').settings; + var staticRules = settings.rules; + var existingRules = $.validator.staticRules(element); + switch(command) { + case "add": + $.extend(existingRules, $.validator.normalizeRule(argument)); + staticRules[element.name] = existingRules; + if (argument.messages) + settings.messages[element.name] = $.extend( settings.messages[element.name], argument.messages ); + break; + case "remove": + if (!argument) { + delete staticRules[element.name]; + return existingRules; + } + var filtered = {}; + $.each(argument.split(/\s/), function(index, method) { + filtered[method] = existingRules[method]; + delete existingRules[method]; + }); + return filtered; + } + } + + var data = $.validator.normalizeRules( + $.extend( + {}, + $.validator.metadataRules(element), + $.validator.classRules(element), + $.validator.attributeRules(element), + $.validator.staticRules(element) + ), element); + + // make sure required is at front + if (data.required) { + var param = data.required; + delete data.required; + data = $.extend({required: param}, data); + } + + return data; + } +}); + +// Custom selectors +$.extend($.expr[":"], { + // http://docs.jquery.com/Plugins/Validation/blank + blank: function(a) {return !$.trim("" + a.value);}, + // http://docs.jquery.com/Plugins/Validation/filled + filled: function(a) {return !!$.trim("" + a.value);}, + // http://docs.jquery.com/Plugins/Validation/unchecked + unchecked: function(a) {return !a.checked;} +}); + +// constructor for validator +$.validator = function( options, form ) { + this.settings = $.extend( true, {}, $.validator.defaults, options ); + this.currentForm = form; + this.init(); +}; + +$.validator.format = function(source, params) { + if ( arguments.length == 1 ) + return function() { + var args = $.makeArray(arguments); + args.unshift(source); + return $.validator.format.apply( this, args ); + }; + if ( arguments.length > 2 && params.constructor != Array ) { + params = $.makeArray(arguments).slice(1); + } + if ( params.constructor != Array ) { + params = [ params ]; + } + $.each(params, function(i, n) { + source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n); + }); + return source; +}; + +$.extend($.validator, { + + defaults: { + messages: {}, + groups: {}, + rules: {}, + errorClass: "error", + validClass: "valid", + errorElement: "label", + focusInvalid: true, + errorContainer: $( [] ), + errorLabelContainer: $( [] ), + onsubmit: true, + ignore: [], + ignoreTitle: false, + onfocusin: function(element) { + this.lastActive = element; + + // hide error label and remove error class on focus if enabled + if ( this.settings.focusCleanup && !this.blockFocusCleanup ) { + this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); + this.errorsFor(element).hide(); + } + }, + onfocusout: function(element) { + if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) { + this.element(element); + } + }, + onkeyup: function(element) { + if ( element.name in this.submitted || element == this.lastElement ) { + this.element(element); + } + }, + onclick: function(element) { + // click on selects, radiobuttons and checkboxes + if ( element.name in this.submitted ) + this.element(element); + // or option elements, check parent select in that case + else if (element.parentNode.name in this.submitted) + this.element(element.parentNode); + }, + highlight: function( element, errorClass, validClass ) { + $(element).addClass(errorClass).removeClass(validClass); + }, + unhighlight: function( element, errorClass, validClass ) { + $(element).removeClass(errorClass).addClass(validClass); + } + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults + setDefaults: function(settings) { + $.extend( $.validator.defaults, settings ); + }, + + messages: { + required: "This field is required.", + remote: "Please fix this field.", + email: "Please enter a valid email address.", + url: "Please enter a valid URL.", + date: "Please enter a valid date.", + dateISO: "Please enter a valid date (ISO).", + number: "Please enter a valid number.", + digits: "Please enter only digits.", + creditcard: "Please enter a valid credit card number.", + equalTo: "Please enter the same value again.", + accept: "Please enter a value with a valid extension.", + maxlength: $.validator.format("Please enter no more than {0} characters."), + minlength: $.validator.format("Please enter at least {0} characters."), + rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), + range: $.validator.format("Please enter a value between {0} and {1}."), + max: $.validator.format("Please enter a value less than or equal to {0}."), + min: $.validator.format("Please enter a value greater than or equal to {0}.") + }, + + autoCreateRanges: false, + + prototype: { + + init: function() { + this.labelContainer = $(this.settings.errorLabelContainer); + this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); + this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer ); + this.submitted = {}; + this.valueCache = {}; + this.pendingRequest = 0; + this.pending = {}; + this.invalid = {}; + this.reset(); + + var groups = (this.groups = {}); + $.each(this.settings.groups, function(key, value) { + $.each(value.split(/\s/), function(index, name) { + groups[name] = key; + }); + }); + var rules = this.settings.rules; + $.each(rules, function(key, value) { + rules[key] = $.validator.normalizeRule(value); + }); + + function delegate(event) { + var validator = $.data(this[0].form, "validator"), + eventType = "on" + event.type.replace(/^validate/, ""); + validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] ); + } + $(this.currentForm) + .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate) + .validateDelegate(":radio, :checkbox, select, option", "click", delegate); + + if (this.settings.invalidHandler) + $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/form + form: function() { + this.checkForm(); + $.extend(this.submitted, this.errorMap); + this.invalid = $.extend({}, this.errorMap); + if (!this.valid()) + $(this.currentForm).triggerHandler("invalid-form", [this]); + this.showErrors(); + return this.valid(); + }, + + checkForm: function() { + this.prepareForm(); + for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) { + this.check( elements[i] ); + } + return this.valid(); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/element + element: function( element ) { + element = this.clean( element ); + this.lastElement = element; + this.prepareElement( element ); + this.currentElements = $(element); + var result = this.check( element ); + if ( result ) { + delete this.invalid[element.name]; + } else { + this.invalid[element.name] = true; + } + if ( !this.numberOfInvalids() ) { + // Hide error containers on last error + this.toHide = this.toHide.add( this.containers ); + } + this.showErrors(); + return result; + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/showErrors + showErrors: function(errors) { + if(errors) { + // add items to error list and map + $.extend( this.errorMap, errors ); + this.errorList = []; + for ( var name in errors ) { + this.errorList.push({ + message: errors[name], + element: this.findByName(name)[0] + }); + } + // remove items from success list + this.successList = $.grep( this.successList, function(element) { + return !(element.name in errors); + }); + } + this.settings.showErrors + ? this.settings.showErrors.call( this, this.errorMap, this.errorList ) + : this.defaultShowErrors(); + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/resetForm + resetForm: function() { + if ( $.fn.resetForm ) + $( this.currentForm ).resetForm(); + this.submitted = {}; + this.prepareForm(); + this.hideErrors(); + this.elements().removeClass( this.settings.errorClass ); + }, + + numberOfInvalids: function() { + return this.objectLength(this.invalid); + }, + + objectLength: function( obj ) { + var count = 0; + for ( var i in obj ) + count++; + return count; + }, + + hideErrors: function() { + this.addWrapper( this.toHide ).hide(); + }, + + valid: function() { + return this.size() == 0; + }, + + size: function() { + return this.errorList.length; + }, + + focusInvalid: function() { + if( this.settings.focusInvalid ) { + try { + $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) + .filter(":visible") + .focus() + // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find + .trigger("focusin"); + } catch(e) { + // ignore IE throwing errors when focusing hidden elements + } + } + }, + + findLastActive: function() { + var lastActive = this.lastActive; + return lastActive && $.grep(this.errorList, function(n) { + return n.element.name == lastActive.name; + }).length == 1 && lastActive; + }, + + elements: function() { + var validator = this, + rulesCache = {}; + + // select all valid inputs inside the form (no submit or reset buttons) + // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved + return $([]).add(this.currentForm.elements) + .filter(":input") + .not(":submit, :reset, :image, [disabled]") + .not( this.settings.ignore ) + .filter(function() { + !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this); + + // select only the first element for each name, and only those with rules specified + if ( this.name in rulesCache || !validator.objectLength($(this).rules()) ) + return false; + + rulesCache[this.name] = true; + return true; + }); + }, + + clean: function( selector ) { + return $( selector )[0]; + }, + + errors: function() { + return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext ); + }, + + reset: function() { + this.successList = []; + this.errorList = []; + this.errorMap = {}; + this.toShow = $([]); + this.toHide = $([]); + this.currentElements = $([]); + }, + + prepareForm: function() { + this.reset(); + this.toHide = this.errors().add( this.containers ); + }, + + prepareElement: function( element ) { + this.reset(); + this.toHide = this.errorsFor(element); + }, + + check: function( element ) { + element = this.clean( element ); + + // if radio/checkbox, validate first element in group instead + if (this.checkable(element)) { + element = this.findByName( element.name )[0]; + } + + var rules = $(element).rules(); + var dependencyMismatch = false; + for( method in rules ) { + var rule = { method: method, parameters: rules[method] }; + try { + var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters ); + + // if a method indicates that the field is optional and therefore valid, + // don't mark it as valid when there are no other rules + if ( result == "dependency-mismatch" ) { + dependencyMismatch = true; + continue; + } + dependencyMismatch = false; + + if ( result == "pending" ) { + this.toHide = this.toHide.not( this.errorsFor(element) ); + return; + } + + if( !result ) { + this.formatAndAdd( element, rule ); + return false; + } + } catch(e) { + this.settings.debug && window.console && console.log("exception occured when checking element " + element.id + + ", check the '" + rule.method + "' method", e); + throw e; + } + } + if (dependencyMismatch) + return; + if ( this.objectLength(rules) ) + this.successList.push(element); + return true; + }, + + // return the custom message for the given element and validation method + // specified in the element's "messages" metadata + customMetaMessage: function(element, method) { + if (!$.metadata) + return; + + var meta = this.settings.meta + ? $(element).metadata()[this.settings.meta] + : $(element).metadata(); + + return meta && meta.messages && meta.messages[method]; + }, + + // return the custom message for the given element name and validation method + customMessage: function( name, method ) { + var m = this.settings.messages[name]; + return m && (m.constructor == String + ? m + : m[method]); + }, + + // return the first defined argument, allowing empty strings + findDefined: function() { + for(var i = 0; i < arguments.length; i++) { + if (arguments[i] !== undefined) + return arguments[i]; + } + return undefined; + }, + + defaultMessage: function( element, method) { + return this.findDefined( + this.customMessage( element.name, method ), + this.customMetaMessage( element, method ), + // title is never undefined, so handle empty string as undefined + !this.settings.ignoreTitle && element.title || undefined, + $.validator.messages[method], + "<strong>Warning: No message defined for " + element.name + "</strong>" + ); + }, + + formatAndAdd: function( element, rule ) { + var message = this.defaultMessage( element, rule.method ), + theregex = /\$?\{(\d+)\}/g; + if ( typeof message == "function" ) { + message = message.call(this, rule.parameters, element); + } else if (theregex.test(message)) { + message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters); + } + this.errorList.push({ + message: message, + element: element + }); + + this.errorMap[element.name] = message; + this.submitted[element.name] = message; + }, + + addWrapper: function(toToggle) { + if ( this.settings.wrapper ) + toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); + return toToggle; + }, + + defaultShowErrors: function() { + for ( var i = 0; this.errorList[i]; i++ ) { + var error = this.errorList[i]; + this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); + this.showLabel( error.element, error.message ); + } + if( this.errorList.length ) { + this.toShow = this.toShow.add( this.containers ); + } + if (this.settings.success) { + for ( var i = 0; this.successList[i]; i++ ) { + this.showLabel( this.successList[i] ); + } + } + if (this.settings.unhighlight) { + for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) { + this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass ); + } + } + this.toHide = this.toHide.not( this.toShow ); + this.hideErrors(); + this.addWrapper( this.toShow ).show(); + }, + + validElements: function() { + return this.currentElements.not(this.invalidElements()); + }, + + invalidElements: function() { + return $(this.errorList).map(function() { + return this.element; + }); + }, + + showLabel: function(element, message) { + var label = this.errorsFor( element ); + if ( label.length ) { + // refresh error/success class + label.removeClass().addClass( this.settings.errorClass ); + + // check if we have a generated label, replace the message then + label.attr("generated") && label.html(message); + } else { + // create label + label = $("<" + this.settings.errorElement + "/>") + .attr({"for": this.idOrName(element), generated: true}) + .addClass(this.settings.errorClass) + .html(message || ""); + if ( this.settings.wrapper ) { + // make sure the element is visible, even in IE + // actually showing the wrapped element is handled elsewhere + label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); + } + if ( !this.labelContainer.append(label).length ) + this.settings.errorPlacement + ? this.settings.errorPlacement(label, $(element) ) + : label.insertAfter(element); + } + if ( !message && this.settings.success ) { + label.text(""); + typeof this.settings.success == "string" + ? label.addClass( this.settings.success ) + : this.settings.success( label ); + } + this.toShow = this.toShow.add(label); + }, + + errorsFor: function(element) { + var name = this.idOrName(element); + return this.errors().filter(function() { + return $(this).attr('for') == name; + }); + }, + + idOrName: function(element) { + return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); + }, + + checkable: function( element ) { + return /radio|checkbox/i.test(element.type); + }, + + findByName: function( name ) { + // select by name and filter by form for performance over form.find("[name=...]") + var form = this.currentForm; + return $(document.getElementsByName(name)).map(function(index, element) { + return element.form == form && element.name == name && element || null; + }); + }, + + getLength: function(value, element) { + switch( element.nodeName.toLowerCase() ) { + case 'select': + return $("option:selected", element).length; + case 'input': + if( this.checkable( element) ) + return this.findByName(element.name).filter(':checked').length; + } + return value.length; + }, + + depend: function(param, element) { + return this.dependTypes[typeof param] + ? this.dependTypes[typeof param](param, element) + : true; + }, + + dependTypes: { + "boolean": function(param, element) { + return param; + }, + "string": function(param, element) { + return !!$(param, element.form).length; + }, + "function": function(param, element) { + return param(element); + } + }, + + optional: function(element) { + return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch"; + }, + + startRequest: function(element) { + if (!this.pending[element.name]) { + this.pendingRequest++; + this.pending[element.name] = true; + } + }, + + stopRequest: function(element, valid) { + this.pendingRequest--; + // sometimes synchronization fails, make sure pendingRequest is never < 0 + if (this.pendingRequest < 0) + this.pendingRequest = 0; + delete this.pending[element.name]; + if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) { + $(this.currentForm).submit(); + this.formSubmitted = false; + } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) { + $(this.currentForm).triggerHandler("invalid-form", [this]); + this.formSubmitted = false; + } + }, + + previousValue: function(element) { + return $.data(element, "previousValue") || $.data(element, "previousValue", { + old: null, + valid: true, + message: this.defaultMessage( element, "remote" ) + }); + } + + }, + + classRuleSettings: { + required: {required: true}, + email: {email: true}, + url: {url: true}, + date: {date: true}, + dateISO: {dateISO: true}, + dateDE: {dateDE: true}, + number: {number: true}, + numberDE: {numberDE: true}, + digits: {digits: true}, + creditcard: {creditcard: true} + }, + + addClassRules: function(className, rules) { + className.constructor == String ? + this.classRuleSettings[className] = rules : + $.extend(this.classRuleSettings, className); + }, + + classRules: function(element) { + var rules = {}; + var classes = $(element).attr('class'); + classes && $.each(classes.split(' '), function() { + if (this in $.validator.classRuleSettings) { + $.extend(rules, $.validator.classRuleSettings[this]); + } + }); + return rules; + }, + + attributeRules: function(element) { + var rules = {}; + var $element = $(element); + + for (method in $.validator.methods) { + var value = $element.attr(method); + if (value) { + rules[method] = value; + } + } + + // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs + if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { + delete rules.maxlength; + } + + return rules; + }, + + metadataRules: function(element) { + if (!$.metadata) return {}; + + var meta = $.data(element.form, 'validator').settings.meta; + return meta ? + $(element).metadata()[meta] : + $(element).metadata(); + }, + + staticRules: function(element) { + var rules = {}; + var validator = $.data(element.form, 'validator'); + if (validator.settings.rules) { + rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; + } + return rules; + }, + + normalizeRules: function(rules, element) { + // handle dependency check + $.each(rules, function(prop, val) { + // ignore rule when param is explicitly false, eg. required:false + if (val === false) { + delete rules[prop]; + return; + } + if (val.param || val.depends) { + var keepRule = true; + switch (typeof val.depends) { + case "string": + keepRule = !!$(val.depends, element.form).length; + break; + case "function": + keepRule = val.depends.call(element, element); + break; + } + if (keepRule) { + rules[prop] = val.param !== undefined ? val.param : true; + } else { + delete rules[prop]; + } + } + }); + + // evaluate parameters + $.each(rules, function(rule, parameter) { + rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; + }); + + // clean number parameters + $.each(['minlength', 'maxlength', 'min', 'max'], function() { + if (rules[this]) { + rules[this] = Number(rules[this]); + } + }); + $.each(['rangelength', 'range'], function() { + if (rules[this]) { + rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; + } + }); + + if ($.validator.autoCreateRanges) { + // auto-create ranges + if (rules.min && rules.max) { + rules.range = [rules.min, rules.max]; + delete rules.min; + delete rules.max; + } + if (rules.minlength && rules.maxlength) { + rules.rangelength = [rules.minlength, rules.maxlength]; + delete rules.minlength; + delete rules.maxlength; + } + } + + // To support custom messages in metadata ignore rule methods titled "messages" + if (rules.messages) { + delete rules.messages; + } + + return rules; + }, + + // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} + normalizeRule: function(data) { + if( typeof data == "string" ) { + var transformed = {}; + $.each(data.split(/\s/), function() { + transformed[this] = true; + }); + data = transformed; + } + return data; + }, + + // http://docs.jquery.com/Plugins/Validation/Validator/addMethod + addMethod: function(name, method, message) { + $.validator.methods[name] = method; + $.validator.messages[name] = message != undefined ? message : $.validator.messages[name]; + if (method.length < 3) { + $.validator.addClassRules(name, $.validator.normalizeRule(name)); + } + }, + + methods: { + + // http://docs.jquery.com/Plugins/Validation/Methods/required + required: function(value, element, param) { + // check if dependency is met + if ( !this.depend(param, element) ) + return "dependency-mismatch"; + switch( element.nodeName.toLowerCase() ) { + case 'select': + // could be an array for select-multiple or a string, both are fine this way + var val = $(element).val(); + return val && val.length > 0; + case 'input': + if ( this.checkable(element) ) + return this.getLength(value, element) > 0; + default: + return $.trim(value).length > 0; + } + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/remote + remote: function(value, element, param) { + if ( this.optional(element) ) + return "dependency-mismatch"; + + var previous = this.previousValue(element); + if (!this.settings.messages[element.name] ) + this.settings.messages[element.name] = {}; + previous.originalMessage = this.settings.messages[element.name].remote; + this.settings.messages[element.name].remote = previous.message; + + param = typeof param == "string" && {url:param} || param; + + if ( previous.old !== value ) { + previous.old = value; + var validator = this; + this.startRequest(element); + var data = {}; + data[element.name] = value; + $.ajax($.extend(true, { + url: param, + mode: "abort", + port: "validate" + element.name, + dataType: "json", + data: data, + success: function(response) { + validator.settings.messages[element.name].remote = previous.originalMessage; + var valid = response === true; + if ( valid ) { + var submitted = validator.formSubmitted; + validator.prepareElement(element); + validator.formSubmitted = submitted; + validator.successList.push(element); + validator.showErrors(); + } else { + var errors = {}; + var message = (previous.message = response || validator.defaultMessage( element, "remote" )); + errors[element.name] = $.isFunction(message) ? message(value) : message; + validator.showErrors(errors); + } + previous.valid = valid; + validator.stopRequest(element, valid); + } + }, param)); + return "pending"; + } else if( this.pending[element.name] ) { + return "pending"; + } + return previous.valid; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/minlength + minlength: function(value, element, param) { + return this.optional(element) || this.getLength($.trim(value), element) >= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/maxlength + maxlength: function(value, element, param) { + return this.optional(element) || this.getLength($.trim(value), element) <= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/rangelength + rangelength: function(value, element, param) { + var length = this.getLength($.trim(value), element); + return this.optional(element) || ( length >= param[0] && length <= param[1] ); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/min + min: function( value, element, param ) { + return this.optional(element) || value >= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/max + max: function( value, element, param ) { + return this.optional(element) || value <= param; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/range + range: function( value, element, param ) { + return this.optional(element) || ( value >= param[0] && value <= param[1] ); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/email + email: function(value, element) { + // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ + return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/url + url: function(value, element) { + // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ + return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/date + date: function(value, element) { + return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/dateISO + dateISO: function(value, element) { + return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/number + number: function(value, element) { + return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/digits + digits: function(value, element) { + return this.optional(element) || /^\d+$/.test(value); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/creditcard + // based on http://en.wikipedia.org/wiki/Luhn + creditcard: function(value, element) { + if ( this.optional(element) ) + return "dependency-mismatch"; + // accept only digits and dashes + if (/[^0-9-]+/.test(value)) + return false; + var nCheck = 0, + nDigit = 0, + bEven = false; + + value = value.replace(/\D/g, ""); + + for (var n = value.length - 1; n >= 0; n--) { + var cDigit = value.charAt(n); + var nDigit = parseInt(cDigit, 10); + if (bEven) { + if ((nDigit *= 2) > 9) + nDigit -= 9; + } + nCheck += nDigit; + bEven = !bEven; + } + + return (nCheck % 10) == 0; + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/accept + accept: function(value, element, param) { + param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif"; + return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); + }, + + // http://docs.jquery.com/Plugins/Validation/Methods/equalTo + equalTo: function(value, element, param) { + // bind to the blur event of the target in order to revalidate whenever the target field is updated + // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead + var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() { + $(element).valid(); + }); + return value == target.val(); + } + + } + +}); + +// deprecated, use $.validator.format instead +$.format = $.validator.format; + +})(jQuery); + +// ajax mode: abort +// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); +// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() +;(function($) { + var ajax = $.ajax; + var pendingRequests = {}; + $.ajax = function(settings) { + // create settings for compatibility with ajaxSetup + settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings)); + var port = settings.port; + if (settings.mode == "abort") { + if ( pendingRequests[port] ) { + pendingRequests[port].abort(); + } + return (pendingRequests[port] = ajax.apply(this, arguments)); + } + return ajax.apply(this, arguments); + }; +})(jQuery); + +// provides cross-browser focusin and focusout events +// IE has native support, in other browsers, use event caputuring (neither bubbles) + +// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation +// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target +;(function($) { + // only implement if not provided by jQuery core (since 1.4) + // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs + if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) { + $.each({ + focus: 'focusin', + blur: 'focusout' + }, function( original, fix ){ + $.event.special[fix] = { + setup:function() { + this.addEventListener( original, handler, true ); + }, + teardown:function() { + this.removeEventListener( original, handler, true ); + }, + handler: function(e) { + arguments[0] = $.event.fix(e); + arguments[0].type = fix; + return $.event.handle.apply(this, arguments); + } + }; + function handler(e) { + e = $.event.fix(e); + e.type = fix; + return $.event.handle.call(this, e); + } + }); + }; + $.extend($.fn, { + validateDelegate: function(delegate, type, handler) { + return this.bind(type, function(event) { + var target = $(event.target); + if (target.is(delegate)) { + return handler.apply(target, arguments); + } + }); + } + }); +})(jQuery); diff --git a/askbot/skins/old/media/js/jquery.validate.min.js b/askbot/skins/old/media/js/jquery.validate.min.js new file mode 100644 index 00000000..6264866f --- /dev/null +++ b/askbot/skins/old/media/js/jquery.validate.min.js @@ -0,0 +1,16 @@ +/* + * jQuery validation plug-in 1.7 + * + * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ + * http://docs.jquery.com/Plugins/Validation + * + * Copyright (c) 2006 - 2008 Jörn Zaefferer + * + * $Id: jquery.validate.js 6403 2009-06-17 14:27:16Z joern.zaefferer $ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ +(function($){$.extend($.fn,{validate:function(options){if(!this.length){options&&options.debug&&window.console&&console.warn("nothing selected, can't validate, returning nothing");return;}var validator=$.data(this[0],'validator');if(validator){return validator;}validator=new $.validator(options,this[0]);$.data(this[0],'validator',validator);if(validator.settings.onsubmit){this.find("input, button").filter(".cancel").click(function(){validator.cancelSubmit=true;});if(validator.settings.submitHandler){this.find("input, button").filter(":submit").click(function(){validator.submitButton=this;});}this.submit(function(event){if(validator.settings.debug)event.preventDefault();function handle(){if(validator.settings.submitHandler){if(validator.submitButton){var hidden=$("<input type='hidden'/>").attr("name",validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);}validator.settings.submitHandler.call(validator,validator.currentForm);if(validator.submitButton){hidden.remove();}return false;}return true;}if(validator.cancelSubmit){validator.cancelSubmit=false;return handle();}if(validator.form()){if(validator.pendingRequest){validator.formSubmitted=true;return false;}return handle();}else{validator.focusInvalid();return false;}});}return validator;},valid:function(){if($(this[0]).is('form')){return this.validate().form();}else{var valid=true;var validator=$(this[0].form).validate();this.each(function(){valid&=validator.element(this);});return valid;}},removeAttrs:function(attributes){var result={},$element=this;$.each(attributes.split(/\s/),function(index,value){result[value]=$element.attr(value);$element.removeAttr(value);});return result;},rules:function(command,argument){var element=this[0];if(command){var settings=$.data(element.form,'validator').settings;var staticRules=settings.rules;var existingRules=$.validator.staticRules(element);switch(command){case"add":$.extend(existingRules,$.validator.normalizeRule(argument));staticRules[element.name]=existingRules;if(argument.messages)settings.messages[element.name]=$.extend(settings.messages[element.name],argument.messages);break;case"remove":if(!argument){delete staticRules[element.name];return existingRules;}var filtered={};$.each(argument.split(/\s/),function(index,method){filtered[method]=existingRules[method];delete existingRules[method];});return filtered;}}var data=$.validator.normalizeRules($.extend({},$.validator.metadataRules(element),$.validator.classRules(element),$.validator.attributeRules(element),$.validator.staticRules(element)),element);if(data.required){var param=data.required;delete data.required;data=$.extend({required:param},data);}return data;}});$.extend($.expr[":"],{blank:function(a){return!$.trim(""+a.value);},filled:function(a){return!!$.trim(""+a.value);},unchecked:function(a){return!a.checked;}});$.validator=function(options,form){this.settings=$.extend(true,{},$.validator.defaults,options);this.currentForm=form;this.init();};$.validator.format=function(source,params){if(arguments.length==1)return function(){var args=$.makeArray(arguments);args.unshift(source);return $.validator.format.apply(this,args);};if(arguments.length>2&¶ms.constructor!=Array){params=$.makeArray(arguments).slice(1);}if(params.constructor!=Array){params=[params];}$.each(params,function(i,n){source=source.replace(new RegExp("\\{"+i+"\\}","g"),n);});return source;};$.extend($.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:true,errorContainer:$([]),errorLabelContainer:$([]),onsubmit:true,ignore:[],ignoreTitle:false,onfocusin:function(element){this.lastActive=element;if(this.settings.focusCleanup&&!this.blockFocusCleanup){this.settings.unhighlight&&this.settings.unhighlight.call(this,element,this.settings.errorClass,this.settings.validClass);this.errorsFor(element).hide();}},onfocusout:function(element){if(!this.checkable(element)&&(element.name in this.submitted||!this.optional(element))){this.element(element);}},onkeyup:function(element){if(element.name in this.submitted||element==this.lastElement){this.element(element);}},onclick:function(element){if(element.name in this.submitted)this.element(element);else if(element.parentNode.name in this.submitted)this.element(element.parentNode);},highlight:function(element,errorClass,validClass){$(element).addClass(errorClass).removeClass(validClass);},unhighlight:function(element,errorClass,validClass){$(element).removeClass(errorClass).addClass(validClass);}},setDefaults:function(settings){$.extend($.validator.defaults,settings);},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",accept:"Please enter a value with a valid extension.",maxlength:$.validator.format("Please enter no more than {0} characters."),minlength:$.validator.format("Please enter at least {0} characters."),rangelength:$.validator.format("Please enter a value between {0} and {1} characters long."),range:$.validator.format("Please enter a value between {0} and {1}."),max:$.validator.format("Please enter a value less than or equal to {0}."),min:$.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:false,prototype:{init:function(){this.labelContainer=$(this.settings.errorLabelContainer);this.errorContext=this.labelContainer.length&&this.labelContainer||$(this.currentForm);this.containers=$(this.settings.errorContainer).add(this.settings.errorLabelContainer);this.submitted={};this.valueCache={};this.pendingRequest=0;this.pending={};this.invalid={};this.reset();var groups=(this.groups={});$.each(this.settings.groups,function(key,value){$.each(value.split(/\s/),function(index,name){groups[name]=key;});});var rules=this.settings.rules;$.each(rules,function(key,value){rules[key]=$.validator.normalizeRule(value);});function delegate(event){var validator=$.data(this[0].form,"validator"),eventType="on"+event.type.replace(/^validate/,"");validator.settings[eventType]&&validator.settings[eventType].call(validator,this[0]);}$(this.currentForm).validateDelegate(":text, :password, :file, select, textarea","focusin focusout keyup",delegate).validateDelegate(":radio, :checkbox, select, option","click",delegate);if(this.settings.invalidHandler)$(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler);},form:function(){this.checkForm();$.extend(this.submitted,this.errorMap);this.invalid=$.extend({},this.errorMap);if(!this.valid())$(this.currentForm).triggerHandler("invalid-form",[this]);this.showErrors();return this.valid();},checkForm:function(){this.prepareForm();for(var i=0,elements=(this.currentElements=this.elements());elements[i];i++){this.check(elements[i]);}return this.valid();},element:function(element){element=this.clean(element);this.lastElement=element;this.prepareElement(element);this.currentElements=$(element);var result=this.check(element);if(result){delete this.invalid[element.name];}else{this.invalid[element.name]=true;}if(!this.numberOfInvalids()){this.toHide=this.toHide.add(this.containers);}this.showErrors();return result;},showErrors:function(errors){if(errors){$.extend(this.errorMap,errors);this.errorList=[];for(var name in errors){this.errorList.push({message:errors[name],element:this.findByName(name)[0]});}this.successList=$.grep(this.successList,function(element){return!(element.name in errors);});}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors();},resetForm:function(){if($.fn.resetForm)$(this.currentForm).resetForm();this.submitted={};this.prepareForm();this.hideErrors();this.elements().removeClass(this.settings.errorClass);},numberOfInvalids:function(){return this.objectLength(this.invalid);},objectLength:function(obj){var count=0;for(var i in obj)count++;return count;},hideErrors:function(){this.addWrapper(this.toHide).hide();},valid:function(){return this.size()==0;},size:function(){return this.errorList.length;},focusInvalid:function(){if(this.settings.focusInvalid){try{$(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin");}catch(e){}}},findLastActive:function(){var lastActive=this.lastActive;return lastActive&&$.grep(this.errorList,function(n){return n.element.name==lastActive.name;}).length==1&&lastActive;},elements:function(){var validator=this,rulesCache={};return $([]).add(this.currentForm.elements).filter(":input").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){!this.name&&validator.settings.debug&&window.console&&console.error("%o has no name assigned",this);if(this.name in rulesCache||!validator.objectLength($(this).rules()))return false;rulesCache[this.name]=true;return true;});},clean:function(selector){return $(selector)[0];},errors:function(){return $(this.settings.errorElement+"."+this.settings.errorClass,this.errorContext);},reset:function(){this.successList=[];this.errorList=[];this.errorMap={};this.toShow=$([]);this.toHide=$([]);this.currentElements=$([]);},prepareForm:function(){this.reset();this.toHide=this.errors().add(this.containers);},prepareElement:function(element){this.reset();this.toHide=this.errorsFor(element);},check:function(element){element=this.clean(element);if(this.checkable(element)){element=this.findByName(element.name)[0];}var rules=$(element).rules();var dependencyMismatch=false;for(method in rules){var rule={method:method,parameters:rules[method]};try{var result=$.validator.methods[method].call(this,element.value.replace(/\r/g,""),element,rule.parameters);if(result=="dependency-mismatch"){dependencyMismatch=true;continue;}dependencyMismatch=false;if(result=="pending"){this.toHide=this.toHide.not(this.errorsFor(element));return;}if(!result){this.formatAndAdd(element,rule);return false;}}catch(e){this.settings.debug&&window.console&&console.log("exception occured when checking element "+element.id ++", check the '"+rule.method+"' method",e);throw e;}}if(dependencyMismatch)return;if(this.objectLength(rules))this.successList.push(element);return true;},customMetaMessage:function(element,method){if(!$.metadata)return;var meta=this.settings.meta?$(element).metadata()[this.settings.meta]:$(element).metadata();return meta&&meta.messages&&meta.messages[method];},customMessage:function(name,method){var m=this.settings.messages[name];return m&&(m.constructor==String?m:m[method]);},findDefined:function(){for(var i=0;i<arguments.length;i++){if(arguments[i]!==undefined)return arguments[i];}return undefined;},defaultMessage:function(element,method){return this.findDefined(this.customMessage(element.name,method),this.customMetaMessage(element,method),!this.settings.ignoreTitle&&element.title||undefined,$.validator.messages[method],"<strong>Warning: No message defined for "+element.name+"</strong>");},formatAndAdd:function(element,rule){var message=this.defaultMessage(element,rule.method),theregex=/\$?\{(\d+)\}/g;if(typeof message=="function"){message=message.call(this,rule.parameters,element);}else if(theregex.test(message)){message=jQuery.format(message.replace(theregex,'{$1}'),rule.parameters);}this.errorList.push({message:message,element:element});this.errorMap[element.name]=message;this.submitted[element.name]=message;},addWrapper:function(toToggle){if(this.settings.wrapper)toToggle=toToggle.add(toToggle.parent(this.settings.wrapper));return toToggle;},defaultShowErrors:function(){for(var i=0;this.errorList[i];i++){var error=this.errorList[i];this.settings.highlight&&this.settings.highlight.call(this,error.element,this.settings.errorClass,this.settings.validClass);this.showLabel(error.element,error.message);}if(this.errorList.length){this.toShow=this.toShow.add(this.containers);}if(this.settings.success){for(var i=0;this.successList[i];i++){this.showLabel(this.successList[i]);}}if(this.settings.unhighlight){for(var i=0,elements=this.validElements();elements[i];i++){this.settings.unhighlight.call(this,elements[i],this.settings.errorClass,this.settings.validClass);}}this.toHide=this.toHide.not(this.toShow);this.hideErrors();this.addWrapper(this.toShow).show();},validElements:function(){return this.currentElements.not(this.invalidElements());},invalidElements:function(){return $(this.errorList).map(function(){return this.element;});},showLabel:function(element,message){var label=this.errorsFor(element);if(label.length){label.removeClass().addClass(this.settings.errorClass);label.attr("generated")&&label.html(message);}else{label=$("<"+this.settings.errorElement+"/>").attr({"for":this.idOrName(element),generated:true}).addClass(this.settings.errorClass).html(message||"");if(this.settings.wrapper){label=label.hide().show().wrap("<"+this.settings.wrapper+"/>").parent();}if(!this.labelContainer.append(label).length)this.settings.errorPlacement?this.settings.errorPlacement(label,$(element)):label.insertAfter(element);}if(!message&&this.settings.success){label.text("");typeof this.settings.success=="string"?label.addClass(this.settings.success):this.settings.success(label);}this.toShow=this.toShow.add(label);},errorsFor:function(element){var name=this.idOrName(element);return this.errors().filter(function(){return $(this).attr('for')==name;});},idOrName:function(element){return this.groups[element.name]||(this.checkable(element)?element.name:element.id||element.name);},checkable:function(element){return/radio|checkbox/i.test(element.type);},findByName:function(name){var form=this.currentForm;return $(document.getElementsByName(name)).map(function(index,element){return element.form==form&&element.name==name&&element||null;});},getLength:function(value,element){switch(element.nodeName.toLowerCase()){case'select':return $("option:selected",element).length;case'input':if(this.checkable(element))return this.findByName(element.name).filter(':checked').length;}return value.length;},depend:function(param,element){return this.dependTypes[typeof param]?this.dependTypes[typeof param](param,element):true;},dependTypes:{"boolean":function(param,element){return param;},"string":function(param,element){return!!$(param,element.form).length;},"function":function(param,element){return param(element);}},optional:function(element){return!$.validator.methods.required.call(this,$.trim(element.value),element)&&"dependency-mismatch";},startRequest:function(element){if(!this.pending[element.name]){this.pendingRequest++;this.pending[element.name]=true;}},stopRequest:function(element,valid){this.pendingRequest--;if(this.pendingRequest<0)this.pendingRequest=0;delete this.pending[element.name];if(valid&&this.pendingRequest==0&&this.formSubmitted&&this.form()){$(this.currentForm).submit();this.formSubmitted=false;}else if(!valid&&this.pendingRequest==0&&this.formSubmitted){$(this.currentForm).triggerHandler("invalid-form",[this]);this.formSubmitted=false;}},previousValue:function(element){return $.data(element,"previousValue")||$.data(element,"previousValue",{old:null,valid:true,message:this.defaultMessage(element,"remote")});}},classRuleSettings:{required:{required:true},email:{email:true},url:{url:true},date:{date:true},dateISO:{dateISO:true},dateDE:{dateDE:true},number:{number:true},numberDE:{numberDE:true},digits:{digits:true},creditcard:{creditcard:true}},addClassRules:function(className,rules){className.constructor==String?this.classRuleSettings[className]=rules:$.extend(this.classRuleSettings,className);},classRules:function(element){var rules={};var classes=$(element).attr('class');classes&&$.each(classes.split(' '),function(){if(this in $.validator.classRuleSettings){$.extend(rules,$.validator.classRuleSettings[this]);}});return rules;},attributeRules:function(element){var rules={};var $element=$(element);for(method in $.validator.methods){var value=$element.attr(method);if(value){rules[method]=value;}}if(rules.maxlength&&/-1|2147483647|524288/.test(rules.maxlength)){delete rules.maxlength;}return rules;},metadataRules:function(element){if(!$.metadata)return{};var meta=$.data(element.form,'validator').settings.meta;return meta?$(element).metadata()[meta]:$(element).metadata();},staticRules:function(element){var rules={};var validator=$.data(element.form,'validator');if(validator.settings.rules){rules=$.validator.normalizeRule(validator.settings.rules[element.name])||{};}return rules;},normalizeRules:function(rules,element){$.each(rules,function(prop,val){if(val===false){delete rules[prop];return;}if(val.param||val.depends){var keepRule=true;switch(typeof val.depends){case"string":keepRule=!!$(val.depends,element.form).length;break;case"function":keepRule=val.depends.call(element,element);break;}if(keepRule){rules[prop]=val.param!==undefined?val.param:true;}else{delete rules[prop];}}});$.each(rules,function(rule,parameter){rules[rule]=$.isFunction(parameter)?parameter(element):parameter;});$.each(['minlength','maxlength','min','max'],function(){if(rules[this]){rules[this]=Number(rules[this]);}});$.each(['rangelength','range'],function(){if(rules[this]){rules[this]=[Number(rules[this][0]),Number(rules[this][1])];}});if($.validator.autoCreateRanges){if(rules.min&&rules.max){rules.range=[rules.min,rules.max];delete rules.min;delete rules.max;}if(rules.minlength&&rules.maxlength){rules.rangelength=[rules.minlength,rules.maxlength];delete rules.minlength;delete rules.maxlength;}}if(rules.messages){delete rules.messages;}return rules;},normalizeRule:function(data){if(typeof data=="string"){var transformed={};$.each(data.split(/\s/),function(){transformed[this]=true;});data=transformed;}return data;},addMethod:function(name,method,message){$.validator.methods[name]=method;$.validator.messages[name]=message!=undefined?message:$.validator.messages[name];if(method.length<3){$.validator.addClassRules(name,$.validator.normalizeRule(name));}},methods:{required:function(value,element,param){if(!this.depend(param,element))return"dependency-mismatch";switch(element.nodeName.toLowerCase()){case'select':var val=$(element).val();return val&&val.length>0;case'input':if(this.checkable(element))return this.getLength(value,element)>0;default:return $.trim(value).length>0;}},remote:function(value,element,param){if(this.optional(element))return"dependency-mismatch";var previous=this.previousValue(element);if(!this.settings.messages[element.name])this.settings.messages[element.name]={};previous.originalMessage=this.settings.messages[element.name].remote;this.settings.messages[element.name].remote=previous.message;param=typeof param=="string"&&{url:param}||param;if(previous.old!==value){previous.old=value;var validator=this;this.startRequest(element);var data={};data[element.name]=value;$.ajax($.extend(true,{url:param,mode:"abort",port:"validate"+element.name,dataType:"json",data:data,success:function(response){validator.settings.messages[element.name].remote=previous.originalMessage;var valid=response===true;if(valid){var submitted=validator.formSubmitted;validator.prepareElement(element);validator.formSubmitted=submitted;validator.successList.push(element);validator.showErrors();}else{var errors={};var message=(previous.message=response||validator.defaultMessage(element,"remote"));errors[element.name]=$.isFunction(message)?message(value):message;validator.showErrors(errors);}previous.valid=valid;validator.stopRequest(element,valid);}},param));return"pending";}else if(this.pending[element.name]){return"pending";}return previous.valid;},minlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)>=param;},maxlength:function(value,element,param){return this.optional(element)||this.getLength($.trim(value),element)<=param;},rangelength:function(value,element,param){var length=this.getLength($.trim(value),element);return this.optional(element)||(length>=param[0]&&length<=param[1]);},min:function(value,element,param){return this.optional(element)||value>=param;},max:function(value,element,param){return this.optional(element)||value<=param;},range:function(value,element,param){return this.optional(element)||(value>=param[0]&&value<=param[1]);},email:function(value,element){return this.optional(element)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);},url:function(value,element){return this.optional(element)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value);},date:function(value,element){return this.optional(element)||!/Invalid|NaN/.test(new Date(value));},dateISO:function(value,element){return this.optional(element)||/^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);},number:function(value,element){return this.optional(element)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);},digits:function(value,element){return this.optional(element)||/^\d+$/.test(value);},creditcard:function(value,element){if(this.optional(element))return"dependency-mismatch";if(/[^0-9-]+/.test(value))return false;var nCheck=0,nDigit=0,bEven=false;value=value.replace(/\D/g,"");for(var n=value.length-1;n>=0;n--){var cDigit=value.charAt(n);var nDigit=parseInt(cDigit,10);if(bEven){if((nDigit*=2)>9)nDigit-=9;}nCheck+=nDigit;bEven=!bEven;}return(nCheck%10)==0;},accept:function(value,element,param){param=typeof param=="string"?param.replace(/,/g,'|'):"png|jpe?g|gif";return this.optional(element)||value.match(new RegExp(".("+param+")$","i"));},equalTo:function(value,element,param){var target=$(param).unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){$(element).valid();});return value==target.val();}}});$.format=$.validator.format;})(jQuery);;(function($){var ajax=$.ajax;var pendingRequests={};$.ajax=function(settings){settings=$.extend(settings,$.extend({},$.ajaxSettings,settings));var port=settings.port;if(settings.mode=="abort"){if(pendingRequests[port]){pendingRequests[port].abort();}return(pendingRequests[port]=ajax.apply(this,arguments));}return ajax.apply(this,arguments);};})(jQuery);;(function($){if(!jQuery.event.special.focusin&&!jQuery.event.special.focusout&&document.addEventListener){$.each({focus:'focusin',blur:'focusout'},function(original,fix){$.event.special[fix]={setup:function(){this.addEventListener(original,handler,true);},teardown:function(){this.removeEventListener(original,handler,true);},handler:function(e){arguments[0]=$.event.fix(e);arguments[0].type=fix;return $.event.handle.apply(this,arguments);}};function handler(e){e=$.event.fix(e);e.type=fix;return $.event.handle.call(this,e);}});};$.extend($.fn,{validateDelegate:function(delegate,type,handler){return this.bind(type,function(event){var target=$(event.target);if(target.is(delegate)){return handler.apply(target,arguments);}});}});})(jQuery);
\ No newline at end of file diff --git a/askbot/skins/old/media/js/jquery.validate.pack.js b/askbot/skins/old/media/js/jquery.validate.pack.js new file mode 100644 index 00000000..49134500 --- /dev/null +++ b/askbot/skins/old/media/js/jquery.validate.pack.js @@ -0,0 +1,15 @@ +/* + * jQuery validation plug-in 1.5 + * + * http://bassistance.de/jquery-plugins/jquery-plugin-validation/ + * http://docs.jquery.com/Plugins/Validation + * + * Copyright (c) 2006 - 2008 Jörn Zaefferer + * + * $Id: jquery.validate.js 5952 2008-11-25 19:12:30Z joern.zaefferer $ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ +eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(7($){$.G($.2J,{1y:7(c){l(!6.E){c&&c.2g&&2T.1q&&1q.4Z("3r 2y, 4B\'t 1y, 6d 3r");8}p b=$.16(6[0],\'u\');l(b){8 b}b=1V $.u(c,6[0]);$.16(6[0],\'u\',b);l(b.q.3s){6.4I("1Y, 4E").1t(".4w").4p(7(){b.35=v});6.30(7(a){l(b.q.2g)a.5X();7 24(){l(b.q.3S){b.q.3S.12(b,b.V);8 H}8 v}l(b.35){b.35=H;8 24()}l(b.K()){l(b.1g){b.1v=v;8 H}8 24()}1c{b.2i();8 H}})}8 b},M:7(){l($(6[0]).2H(\'K\')){8 6.1y().K()}1c{p b=H;p a=$(6[0].K).1y();6.O(7(){b|=a.L(6)});8 b}},4L:7(a){p b={},$L=6;$.O(a.1H(/\\s/),7(){b[6]=$L.1G(6);$L.4G(6)});8 b},1b:7(h,k){p f=6[0];l(h){p i=$.16(f.K,\'u\').q;p d=i.1b;p c=$.u.2s(f);2q(h){1e"2o":$.G(c,$.u.1S(k));d[f.r]=c;l(k.J)i.J[f.r]=$.G(i.J[f.r],k.J);31;1e"63":l(!k){R d[f.r];8 c}p e={};$.O(k.1H(/\\s/),7(a,b){e[b]=c[b];R c[b]});8 e}}p g=$.u.3x($.G({},$.u.40(f),$.u.3W(f),$.u.3T(f),$.u.2s(f)),f);l(g.13){p j=g.13;R g.13;g=$.G({13:j},g)}8 g},Y:7(t){8 6.5A(6.2o(t).5w())}});$.G($.5t[":"],{5p:7(a){8!$.2b(a.T)},5m:7(a){8!!$.2b(a.T)},5i:7(a){8!a.3U}});$.1a=7(c,b){l(P.E==1)8 7(){p a=$.48(P);a.52(c);8 $.1a.1I(6,a)};l(P.E>2&&b.2m!=3A){b=$.48(P).4O(1)}l(b.2m!=3A){b=[b]}$.O(b,7(i,n){c=c.3u(1V 3t("\\\\{"+i+"\\\\}","g"),n)});8 c};$.u=7(b,a){6.q=$.G({},$.u.2D,b);6.V=a;6.3q()};$.G($.u,{2D:{J:{},21:{},1b:{},18:"3l",2B:"4H",2i:v,3k:$([]),2A:$([]),3s:v,3j:[],3h:H,4F:7(a){6.3g=a;l(6.q.4D&&!6.4C){6.q.1U&&6.q.1U.12(6,a,6.q.18);6.1E(a).2v()}},4z:7(a){l(!6.1u(a)&&(a.r Z 6.1j||!6.F(a))){6.L(a)}},4t:7(a){l(a.r Z 6.1j||a==6.4q){6.L(a)}},6n:7(a){l(a.r Z 6.1j)6.L(a)},37:7(a,b){$(a).2p(b)},1U:7(a,b){$(a).36(b)}},6g:7(a){$.G($.u.2D,a)},J:{13:"6e 4k 2H 13.",1R:"I 38 6 4k.",1F:"I N a M 1F 65.",1k:"I N a M 62.",1l:"I N a M 1l.",2a:"I N a M 1l (61).",20:"45 44 42 2E 5T¼5S 5R 2E.",1n:"I N a M 1n.",28:"45 44 42 5N 5M 2E.",1O:"I N 5G 1O",2d:"I N a M 5E 5C 1n.",3P:"I N 3O 5v T 5u.",3L:"I N a T 5q a M 5o.",15:$.1a("I N 3K 5n 2O {0} 2R."),1r:$.1a("I N 5k 5h {0} 2R."),2h:$.1a("I N a T 3E {0} 3R {1} 2R 5c."),27:$.1a("I N a T 3E {0} 3R {1}."),1m:$.1a("I N a T 5a 2O 47 43 3D {0}."),1w:$.1a("I N a T 51 2O 47 43 3D {0}.")},4f:H,4Y:{3q:7(){6.26=$(6.q.2A);6.3C=6.26.E&&6.26||$(6.V);6.2k=$(6.q.3k).2o(6.q.2A);6.1j={};6.4S={};6.1g=0;6.1d={};6.1f={};6.1J();p f=(6.21={});$.O(6.q.21,7(d,c){$.O(c.1H(/\\s/),7(a,b){f[b]=d})});p e=6.q.1b;$.O(e,7(b,a){e[b]=$.u.1S(a)});7 1p(a){p b=$.16(6[0].K,"u");b.q["3z"+a.1o]&&b.q["3z"+a.1o].12(b,6[0])}$(6.V).1p("3y 3w 4N",":2F, :4M, :4K, 23, 4J",1p).1p("4p",":3p, :3o",1p);l(6.q.3n)$(6.V).3m("1f-K.1y",6.q.3n)},K:7(){6.3v();$.G(6.1j,6.1z);6.1f=$.G({},6.1z);l(!6.M())$(6.V).2C("1f-K",[6]);6.1h();8 6.M()},3v:7(){6.2G();Q(p i=0,11=(6.1Z=6.11());11[i];i++){6.2n(11[i])}8 6.M()},L:7(a){a=6.2z(a);6.4q=a;6.2N(a);6.1Z=$(a);p b=6.2n(a);l(b){R 6.1f[a.r]}1c{6.1f[a.r]=v}l(!6.3i()){6.14.Y(6.2k)}6.1h();8 b},1h:7(b){l(b){$.G(6.1z,b);6.S=[];Q(p c Z b){6.S.Y({19:b[c],L:6.1X(c)[0]})}6.1i=$.3f(6.1i,7(a){8!(a.r Z b)})}6.q.1h?6.q.1h.12(6,6.1z,6.S):6.3e()},2x:7(){l($.2J.2x)$(6.V).2x();6.1j={};6.2G();6.2W();6.11().36(6.q.18)},3i:7(){8 6.2c(6.1f)},2c:7(a){p b=0;Q(p i Z a)b++;8 b},2W:7(){6.2w(6.14).2v()},M:7(){8 6.3d()==0},3d:7(){8 6.S.E},2i:7(){l(6.q.2i){3c{$(6.3b()||6.S.E&&6.S[0].L||[]).1t(":4A").3a()}39(e){}}},3b:7(){p a=6.3g;8 a&&$.3f(6.S,7(n){8 n.L.r==a.r}).E==1&&a},11:7(){p a=6,2u={};8 $([]).2o(6.V.11).1t(":1Y").1D(":30, :1J, :4y, [4x]").1D(6.q.3j).1t(7(){!6.r&&a.q.2g&&2T.1q&&1q.3l("%o 4v 3K r 4u",6);l(6.r Z 2u||!a.2c($(6).1b()))8 H;2u[6.r]=v;8 v})},2z:7(a){8 $(a)[0]},2t:7(){8 $(6.q.2B+"."+6.q.18,6.3C)},1J:7(){6.1i=[];6.S=[];6.1z={};6.1C=$([]);6.14=$([]);6.1v=H;6.1Z=$([])},2G:7(){6.1J();6.14=6.2t().Y(6.2k)},2N:7(a){6.1J();6.14=6.1E(a)},2n:7(d){d=6.2z(d);l(6.1u(d)){d=6.1X(d.r)[0]}p a=$(d).1b();p c=H;Q(W Z a){p b={W:W,2r:a[W]};3c{p f=$.u.1P[W].12(6,d.T,d,b.2r);l(f=="1T-1Q"){c=v;6m}c=H;l(f=="1d"){6.14=6.14.1D(6.1E(d));8}l(!f){6.4o(d,b);8 H}}39(e){6.q.2g&&2T.1q&&1q.6l("6k 6j 6i 6h L "+d.4n+", 2n 3O \'"+b.W+"\' W");6f e;}}l(c)8;l(6.2c(a))6.1i.Y(d);8 v},4l:7(a,b){l(!$.1x)8;p c=6.q.33?$(a).1x()[6.q.33]:$(a).1x();8 c&&c.J&&c.J[b]},4j:7(a,b){p m=6.q.J[a];8 m&&(m.2m==4i?m:m[b])},4h:7(){Q(p i=0;i<P.E;i++){l(P[i]!==2l)8 P[i]}8 2l},2j:7(a,b){8 6.4h(6.4j(a.r,b),6.4l(a,b),!6.q.3h&&a.6c||2l,$.u.J[b],"<4g>6b: 6a 19 68 Q "+a.r+"</4g>")},4o:7(b,a){p c=6.2j(b,a.W);l(17 c=="7")c=c.12(6,a.2r,b);6.S.Y({19:c,L:b});6.1z[b.r]=c;6.1j[b.r]=c},2w:7(a){l(6.q.1W)a.Y(a.64(6.q.1W));8 a},3e:7(){Q(p i=0;6.S[i];i++){p a=6.S[i];6.q.37&&6.q.37.12(6,a.L,6.q.18);6.2Z(a.L,a.19)}l(6.S.E){6.1C.Y(6.2k)}l(6.q.1s){Q(p i=0;6.1i[i];i++){6.2Z(6.1i[i])}}l(6.q.1U){Q(p i=0,11=6.4e();11[i];i++){6.q.1U.12(6,11[i],6.q.18)}}6.14=6.14.1D(6.1C);6.2W();6.2w(6.1C).4d()},4e:7(){8 6.1Z.1D(6.4c())},4c:7(){8 $(6.S).4b(7(){8 6.L})},2Z:7(a,c){p b=6.1E(a);l(b.E){b.36().2p(6.q.18);b.1G("4a")&&b.49(c)}1c{b=$("<"+6.q.2B+"/>").1G({"Q":6.2Y(a),4a:v}).2p(6.q.18).49(c||"");l(6.q.1W){b=b.2v().4d().60("<"+6.q.1W+">").5Z()}l(!6.26.5Y(b).E)6.q.46?6.q.46(b,$(a)):b.5W(a)}l(!c&&6.q.1s){b.2F("");17 6.q.1s=="1B"?b.2p(6.q.1s):6.q.1s(b)}6.1C.Y(b)},1E:7(a){8 6.2t().1t("[@Q=\'"+6.2Y(a)+"\']")},2Y:7(a){8 6.21[a.r]||(6.1u(a)?a.r:a.4n||a.r)},1u:7(a){8/3p|3o/i.U(a.1o)},1X:7(d){p c=6.V;8 $(5V.5U(d)).4b(7(a,b){8 b.K==c&&b.r==d&&b||41})},1K:7(a,b){2q(b.3Z.3Y()){1e\'23\':8 $("3X:2y",b).E;1e\'1Y\':l(6.1u(b))8 6.1X(b.r).1t(\':3U\').E}8 a.E},3B:7(b,a){8 6.2X[17 b]?6.2X[17 b](b,a):v},2X:{"5Q":7(b,a){8 b},"1B":7(b,a){8!!$(b,a.K).E},"7":7(b,a){8 b(a)}},F:7(a){8!$.u.1P.13.12(6,$.2b(a.T),a)&&"1T-1Q"},3V:7(a){l(!6.1d[a.r]){6.1g++;6.1d[a.r]=v}},4s:7(a,b){6.1g--;l(6.1g<0)6.1g=0;R 6.1d[a.r];l(b&&6.1g==0&&6.1v&&6.K()){$(6.V).30()}1c l(!b&&6.1g==0&&6.1v){$(6.V).2C("1f-K",[6])}},2f:7(a){8 $.16(a,"2f")||$.16(a,"2f",5O={2K:41,M:v,19:6.2j(a,"1R")})}},1M:{13:{13:v},1F:{1F:v},1k:{1k:v},1l:{1l:v},2a:{2a:v},20:{20:v},1n:{1n:v},28:{28:v},1O:{1O:v},2d:{2d:v}},3Q:7(a,b){a.2m==4i?6.1M[a]=b:$.G(6.1M,a)},3W:7(b){p a={};p c=$(b).1G(\'5K\');c&&$.O(c.1H(\' \'),7(){l(6 Z $.u.1M){$.G(a,$.u.1M[6])}});8 a},3T:7(c){p a={};p d=$(c);Q(W Z $.u.1P){p b=d.1G(W);l(b){a[W]=b}}l(a.15&&/-1|5J|5H/.U(a.15)){R a.15}8 a},40:7(a){l(!$.1x)8{};p b=$.16(a.K,\'u\').q.33;8 b?$(a).1x()[b]:$(a).1x()},2s:7(b){p a={};p c=$.16(b.K,\'u\');l(c.q.1b){a=$.u.1S(c.q.1b[b.r])||{}}8 a},3x:7(d,e){$.O(d,7(c,b){l(b===H){R d[c];8}l(b.2V||b.2e){p a=v;2q(17 b.2e){1e"1B":a=!!$(b.2e,e.K).E;31;1e"7":a=b.2e.12(e,e);31}l(a){d[c]=b.2V!==2l?b.2V:v}1c{R d[c]}}});$.O(d,7(a,b){d[a]=$.5F(b)?b(e):b});$.O([\'1r\',\'15\',\'1w\',\'1m\'],7(){l(d[6]){d[6]=2U(d[6])}});$.O([\'2h\',\'27\'],7(){l(d[6]){d[6]=[2U(d[6][0]),2U(d[6][1])]}});l($.u.4f){l(d.1w&&d.1m){d.27=[d.1w,d.1m];R d.1w;R d.1m}l(d.1r&&d.15){d.2h=[d.1r,d.15];R d.1r;R d.15}}l(d.J){R d.J}8 d},1S:7(a){l(17 a=="1B"){p b={};$.O(a.1H(/\\s/),7(){b[6]=v});a=b}8 a},5D:7(c,a,b){$.u.1P[c]=a;$.u.J[c]=b;l(a.E<3){$.u.3Q(c,$.u.1S(c))}},1P:{13:7(b,c,a){l(!6.3B(a,c))8"1T-1Q";2q(c.3Z.3Y()){1e\'23\':p d=$("3X:2y",c);8 d.E>0&&(c.1o=="23-5B"||($.2S.2Q&&!(d[0].5z[\'T\'].5y)?d[0].2F:d[0].T).E>0);1e\'1Y\':l(6.1u(c))8 6.1K(b,c)>0;5x:8 $.2b(b).E>0}},1R:7(e,h,d){l(6.F(h))8"1T-1Q";p g=6.2f(h);l(!6.q.J[h.r])6.q.J[h.r]={};6.q.J[h.r].1R=17 g.19=="7"?g.19(e):g.19;d=17 d=="1B"&&{1k:d}||d;l(g.2K!==e){g.2K=e;p i=6;6.3V(h);p f={};f[h.r]=e;$.2P($.G(v,{1k:d,3N:"2L",3M:"1y"+h.r,5s:"5r",16:f,1s:7(a){l(a){p b=i.1v;i.2N(h);i.1v=b;i.1i.Y(h);i.1h()}1c{p c={};c[h.r]=a||i.2j(h,"1R");i.1h(c)}g.M=a;i.4s(h,a)}},d));8"1d"}1c l(6.1d[h.r]){8"1d"}8 g.M},1r:7(b,c,a){8 6.F(c)||6.1K(b,c)>=a},15:7(b,c,a){8 6.F(c)||6.1K(b,c)<=a},2h:7(b,d,a){p c=6.1K(b,d);8 6.F(d)||(c>=a[0]&&c<=a[1])},1w:7(b,c,a){8 6.F(c)||b>=a},1m:7(b,c,a){8 6.F(c)||b<=a},27:7(b,c,a){8 6.F(c)||(b>=a[0]&&b<=a[1])},1F:7(a,b){8 6.F(b)||/^((([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\A-\\C\\w-\\B\\x-\\y])+(\\.([a-z]|\\d|[!#\\$%&\'\\*\\+\\-\\/=\\?\\^X`{\\|}~]|[\\A-\\C\\w-\\B\\x-\\y])+)*)|((\\3J)((((\\29|\\1N)*(\\2M\\3I))?(\\29|\\1N)+)?(([\\3H-\\5l\\3G\\3F\\5j-\\5I\\4r]|\\5g|[\\5L-\\5f]|[\\5e-\\5d]|[\\A-\\C\\w-\\B\\x-\\y])|(\\\\([\\3H-\\1N\\3G\\3F\\2M-\\4r]|[\\A-\\C\\w-\\B\\x-\\y]))))*(((\\29|\\1N)*(\\2M\\3I))?(\\29|\\1N)+)?(\\3J)))@((([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])))\\.)+(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|[\\A-\\C\\w-\\B\\x-\\y])))\\.?$/i.U(a)},1k:7(a,b){8 6.F(b)||/^(5P?|5b):\\/\\/(((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|\\d|[\\A-\\C\\w-\\B\\x-\\y])))\\.)+(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])|(([a-z]|[\\A-\\C\\w-\\B\\x-\\y])([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])*([a-z]|[\\A-\\C\\w-\\B\\x-\\y])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|[\\59-\\58]|\\/|\\?)*)?(\\#((([a-z]|\\d|-|\\.|X|~|[\\A-\\C\\w-\\B\\x-\\y])|(%[\\1L-f]{2})|[!\\$&\'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.U(a)},1l:7(a,b){8 6.F(b)||!/57|56/.U(1V 55(a))},2a:7(a,b){8 6.F(b)||/^\\d{4}[\\/-]\\d{1,2}[\\/-]\\d{1,2}$/.U(a)},20:7(a,b){8 6.F(b)||/^\\d\\d?\\.\\d\\d?\\.\\d\\d\\d?\\d?$/.U(a)},1n:7(a,b){8 6.F(b)||/^-?(?:\\d+|\\d{1,3}(?:,\\d{3})+)(?:\\.\\d+)?$/.U(a)},28:7(a,b){8 6.F(b)||/^-?(?:\\d+|\\d{1,3}(?:\\.\\d{3})+)(?:,\\d+)?$/.U(a)},1O:7(a,b){8 6.F(b)||/^\\d+$/.U(a)},2d:7(b,e){l(6.F(e))8"1T-1Q";l(/[^0-9-]+/.U(b))8 H;p a=0,d=0,22=H;b=b.3u(/\\D/g,"");Q(n=b.E-1;n>=0;n--){p c=b.54(n);p d=53(c,10);l(22){l((d*=2)>9)d-=9}a+=d;22=!22}8(a%10)==0},3L:7(b,c,a){a=17 a=="1B"?a:"66|67?g|50";8 6.F(c)||b.69(1V 3t(".("+a+")$","i"))},3P:7(b,c,a){8 b==$(a).4X()}}})})(2I);(7($){p c=$.2P;p d={};$.2P=7(a){a=$.G(a,$.G({},$.4W,a));p b=a.3M;l(a.3N=="2L"){l(d[b]){d[b].2L()}8(d[b]=c.1I(6,P))}8 c.1I(6,P)}})(2I);(7($){$.O({3a:\'3y\',4V:\'3w\'},7(b,a){$.1A.32[a]={4U:7(){l($.2S.2Q)8 H;6.4T(b,$.1A.32[a].34,v)},4R:7(){l($.2S.2Q)8 H;6.4Q(b,$.1A.32[a].34,v)},34:7(e){P[0]=$.1A.38(e);P[0].1o=a;8 $.1A.24.1I(6,P)}}});$.G($.2J,{1p:7(d,e,c){8 6.3m(d,7(a){p b=$(a.4m);l(b.2H(e)){8 c.1I(b,P)}})},4P:7(a,b){8 6.2C(a,[$.1A.38({1o:a,4m:b})])}})})(2I);',62,396,'||||||this|function|return|||||||||||||if||||var|settings|name|||validator|true|uF900|uFDF0|uFFEF||u00A0|uFDCF|uD7FF||length|optional|extend|false|Please|messages|form|element|valid|enter|each|arguments|for|delete|errorList|value|test|currentForm|method|_|push|in||elements|call|required|toHide|maxlength|data|typeof|errorClass|message|format|rules|else|pending|case|invalid|pendingRequest|showErrors|successList|submitted|url|date|max|number|type|delegate|console|minlength|success|filter|checkable|formSubmitted|min|metadata|validate|errorMap|event|string|toShow|not|errorsFor|email|attr|split|apply|reset|getLength|da|classRuleSettings|x09|digits|methods|mismatch|remote|normalizeRule|dependency|unhighlight|new|wrapper|findByName|input|currentElements|dateDE|groups|bEven|select|handle||labelContainer|range|numberDE|x20|dateISO|trim|objectLength|creditcard|depends|previousValue|debug|rangelength|focusInvalid|defaultMessage|containers|undefined|constructor|check|add|addClass|switch|parameters|staticRules|errors|rulesCache|hide|addWrapper|resetForm|selected|clean|errorLabelContainer|errorElement|triggerHandler|defaults|ein|text|prepareForm|is|jQuery|fn|old|abort|x0d|prepareElement|than|ajax|msie|characters|browser|window|Number|param|hideErrors|dependTypes|idOrName|showLabel|submit|break|special|meta|handler|cancelSubmit|removeClass|highlight|fix|catch|focus|findLastActive|try|size|defaultShowErrors|grep|lastActive|ignoreTitle|numberOfInvalids|ignore|errorContainer|error|bind|invalidHandler|checkbox|radio|init|nothing|onsubmit|RegExp|replace|checkForm|focusout|normalizeRules|focusin|on|Array|depend|errorContext|to|between|x0c|x0b|x01|x0a|x22|no|accept|port|mode|the|equalTo|addClassRules|and|submitHandler|attributeRules|checked|startRequest|classRules|option|toLowerCase|nodeName|metadataRules|null|Sie|equal|geben|Bitte|errorPlacement|or|makeArray|html|generated|map|invalidElements|show|validElements|autoCreateRanges|strong|findDefined|String|customMessage|field|customMetaMessage|target|id|formatAndAdd|click|lastElement|x7f|stopRequest|onkeyup|assigned|has|cancel|disabled|image|onfocusout|visible|can|blockFocusCleanup|focusCleanup|button|onfocusin|removeAttr|label|find|textarea|file|removeAttrs|password|keyup|slice|triggerEvent|removeEventListener|teardown|valueCache|addEventListener|setup|blur|ajaxSettings|val|prototype|warn|gif|greater|unshift|parseInt|charAt|Date|NaN|Invalid|uF8FF|uE000|less|ftp|long|x7e|x5d|x5b|x21|least|unchecked|x0e|at|x08|filled|more|extension|blank|with|json|dataType|expr|again|same|get|default|specified|attributes|setArray|multiple|card|addMethod|credit|isFunction|only|524288|x1f|2147483647|class|x23|Nummer|eine|previous|https|boolean|Datum|ltiges|gÃ|getElementsByName|document|insertAfter|preventDefault|append|parent|wrap|ISO|URL|remove|parents|address|png|jpe|defined|match|No|Warning|title|returning|This|throw|setDefaults|checking|when|occured|exception|log|continue|onclick'.split('|'),0,{}))
\ No newline at end of file diff --git a/askbot/skins/old/media/js/live_search.js b/askbot/skins/old/media/js/live_search.js new file mode 100644 index 00000000..f9f03453 --- /dev/null +++ b/askbot/skins/old/media/js/live_search.js @@ -0,0 +1,546 @@ +var prevSortMethod = sortMethod; +var liveSearch = function(){ + var query = undefined; + var prev_text = undefined; + var running = false; + var q_list_sel = 'question-list';//id of question listing div + var search_url = undefined; + var restart_query = function(){}; + var process_query = function(){}; + var render_result = function(){}; + + var refresh_x_button = function(){ + if ($.trim(query.val()).length > 0){ + if (query.attr('class') === 'searchInput'){ + query.attr('class', 'searchInputCancelable'); + x_button = $('<input class="cancelSearchBtn" type="button" name="reset_query"/>'); + //x_button.click(reset_query); + x_button.val('x'); + x_button.click( + function(){ + query.val(''); + if (sortMethod === 'relevance-desc'){ + sortMethod = prevSortMethod; + } + refresh_x_button(); + reset_query(sortMethod); + } + ); + query.after(x_button); + } + } else { + $('input[name=reset_query]').remove(); + query.attr('class', 'searchInput'); + } + }; + + var reset_sort_method = function(){ + if (sortMethod === 'relevance-desc'){ + sortMethod = prevSortMethod; + if (sortMethod === 'relevance-desc'){ + sortMethod = 'activity-desc'; + } + } else { + sortMethod = 'activity-desc'; + prevSortMethod = 'activity-desc'; + } + }; + + var eval_query = function(){ + cur_text = $.trim(query.val()); + if (cur_text !== prev_text && running === false){ + if (cur_text.length >= minSearchWordLength){ + process_query(); + running = true; + } else if (cur_text.length === 0){ + restart_query(); + } + } + }; + + var ask_page_search_listen = function(){ + running = false; + var ask_page_eval_handle; + query.keyup(function(e){ + if (running === false){ + clearTimeout(ask_page_eval_handle); + ask_page_eval_handle = setTimeout(eval_query, 400); + } + }); + }; + + var main_page_search_listen = function(){ + running = false; + refresh_x_button(); + var main_page_eval_handle; + query.keyup(function(e){ + refresh_x_button(); + if (running === false){ + clearTimeout(main_page_eval_handle); + main_page_eval_handle = setTimeout(eval_query, 400); + } + }); + }; + + var render_counter = function(count, word, counter_class, counter_subclass){ + var output = '<div class="' + counter_class + ' ' + counter_subclass + '">' + + '<span class="item-count">' + + count; + if (counter_class === 'accepted'){ + output += '✓'; + } + output += '</span>' + + '<div>' + word + '</div>' + + '</div>'; + return output; + }; + + var render_title = function(result){ + return '<h2>' + + '<a title="' + result['summary'] + '" ' + + 'href="' + + askbot['urls']['question_url_template'] + .replace('{{QuestionID}}', result['id']) + + '">' + + result['title'] + + '</a>' + + '</h2>'; + }; + + var render_user_link = function(result){ + if (result['u_id'] !== false){ + if (result['u_is_anonymous'] === true){ + return '<span class="anonymous">' + + askbot['messages']['name_of_anonymous_user'] + + '</span>'; + } else { + var u_slug = result['u_name'].toLowerCase().replace(/ +/g, '-'); + return '<a ' + + 'href="' + + askbot['urls']['user_url_template'] + .replace('{{user_id}}', result['u_id']) + .replace('{{slug}}', u_slug) + + '">' + + result['u_name'] + + '</a> '; + } + } + else { + return ''; + } + }; + + var render_badge = function(result, key){ + return '<span ' + + 'title="' + result[key + '_title'] + '"' + + '>' + + '<span ' + + 'class="' + result[key + '_css_class'] + '"' + + '>' + result[key + '_badge_symbol'] + '</span>' + + '<span class="badgecount">' + result[key] + '</span>'; + }; + + var render_user_badge_and_karma = function(result){ + var rep_title = result['u_rep'] + ' ' + result['u_rep_word']; + var html = '<span ' + + 'class="reputation-score" ' + + 'title="' + rep_title + '"' + + '>' + result['u_rep'] + '</span>'; + if (result['u_gold'] > 0){ + html += render_badge(result, 'u_gold'); + } + if (result['u_silver'] > 0){ + html += render_badge(result, 'u_silver'); + } + if (result['u_bronze'] > 0){ + html += render_badge(result, 'u_bronze'); + } + return html; + }; + + var render_user_flag = function(result){ + var country_code = result['u_country_code']; + if (country_code) { + return '<img class="flag" src="'+ + mediaUrl( + 'media/images/flags/' + + country_code.toLowerCase() + + '.gif' + ) + + '"/>'; + } else { + return ''; + } + }; + + var render_user_info = function(result){ + var user_html = + '<div class="userinfo">' + + '<span class="relativetime" ' + + 'title="' + result['timestamp'] + '"' + + '>' + + result['timesince'] + + '</span> ' + + render_user_link(result); + if (result['u_is_anonymous'] === false){ + user_html += render_user_flag(result); + //render_user_badge_and_karma(result) + + } + user_html += '</div>'; + return user_html; + }; + + var render_tag = function(tag_name, linkable, deletable){ + var tag = new Tag(); + tag.setName(tag_name); + tag.setDeletable(deletable); + tag.setLinkable(linkable); + return tag.getElement().outerHTML(); + }; + + var render_tags = function(tags, linkable, deletable){ + var tags_html = '<ul class="tags">'; + $.each(tags, function(idx, item){ + tags_html += render_tag(item, linkable, deletable); + }); + tags_html += '</ul>'; + return tags_html; + }; + + var render_question = function(question){ + var entry_html = + '<div class="short-summary">' + + '<div class="counts">' + + render_counter( + question['views'], + question['views_word'], + 'views', + question['views_class'] + ) + + render_counter( + question['answers'], + question['answers_word'], + 'answers', + question['answers_class'] + ) + + render_counter( + question['votes'], + question['votes_word'], + 'votes', + question['votes_class'] + ) + + '<div style="clear:both"></div>' + + render_user_info(question) + + '</div>' + + render_title(question) + + render_tags(question['tags'], true, false) + + '</div>'; + return entry_html; + }; + + var render_question_list = function(questions){ + var output = ''; + for (var i=0; i<questions.length; i++){ + output += render_question(questions[i]); + } + return output; + }; + + var render_faces = function(faces){ + if (faces.length === 0){ + return; + } + $('#contrib-users>a').remove(); + var html = ''; + for (var i=0; i<faces.length; i++){ + html += faces[i]; + } + $('#contrib-users').append(html); + }; + + var render_related_tags = function(tags){ + if (tags.length === 0){ + return; + } + var html = ''; + for (var i=0; i<tags.length; i++){ + html += render_tag(tags[i]['name'], true, false); + html += '<span class="tag-number">× ' + + tags[i]['used_count'] + + '</span>' + + '<br />'; + } + $('#related-tags').html(html); + }; + + var render_paginator = function(paginator){ + var pager = $('#pager'); + if (paginator === ''){ + pager.hide(); + return; + } + else { + pager.show(); + pager.html(paginator); + } + }; + + var set_question_count = function(count_html){ + $('#question-count').html(count_html); + }; + + var get_old_tags = function(container){ + var tag_elements = container.find('.tag'); + var old_tags = []; + tag_elements.each(function(idx, element){ + old_tags.push($(element).html()); + }); + return old_tags; + }; + + var render_search_tags = function(tags){ + var search_tags = $('#search-tags'); + search_tags.children().remove(); + var tags_html = ''; + $.each(tags, function(idx, tag_name){ + var tag = new Tag(); + tag.setName(tag_name); + tag.setDeletable(true); + tag.setLinkable(false); + tag.setDeleteHandler( + function(){ + remove_search_tag(tag_name); + } + ); + search_tags.append(tag.getElement()); + }); + }; + + var create_relevance_tab = function(){ + relevance_tab = $('<a></a>'); + relevance_tab.attr('href', '?sort=relevance-desc'); + relevance_tab.attr('id', 'by_relevance'); + relevance_tab.html('<span>' + sortButtonData['relevance']['label'] + '</span>'); + return relevance_tab; + } + + var set_active_sort_tab = function(sort_method){ + var tabs = $('#sort_tabs>a'); + tabs.attr('class', 'off'); + tabs.each(function(index, element){ + var tab = $(element); + var tab_name = tab.attr('id').replace(/^by_/,''); + if (tab_name in sortButtonData){ + tab.attr( + 'href', + '?sort=' + tab_name + '-desc' + ); + tab.attr( + 'title', + sortButtonData[tab_name]['desc_tooltip'] + ); + tab.html(sortButtonData[tab_name]['label']); + } + }); + var bits = sort_method.split('-', 2); + var name = bits[0]; + var sense = bits[1];//sense of sort + var antisense = (sense == 'asc' ? 'desc':'asc'); + var arrow = (sense == 'asc' ? ' ▲':' ▼'); + var active_tab = $('#by_' + name); + active_tab.attr('class', 'on'); + active_tab.attr('title', sortButtonData[name][antisense + '_tooltip']); + active_tab.html(sortButtonData[name]['label'] + arrow); + }; + + var render_relevance_sort_tab = function(){ + if (showSortByRelevance === false){ + return; + } + var relevance_tab = $('#by_relevance'); + if (prev_text && prev_text.length > 0){ + if (relevance_tab.length == 0){ + relevance_tab = create_relevance_tab(); + $('#sort_tabs>span').after(relevance_tab); + } + } + else { + if (relevance_tab.length > 0){ + relevance_tab.remove(); + } + } + }; + + var remove_search_tag = function(tag_name){ + $.ajax({ + url: askbot['urls']['questions'], + data: {remove_tag: tag_name}, + dataType: 'json', + success: render_result, + complete: try_again + }); + }; + + var activate_search_tags = function(){ + var search_tags = $('#search-tags .tag-left'); + $.each(search_tags, function(idx, element){ + var tag = new Tag(); + tag.decorate($(element)); + //todo: setDeleteHandler and setHandler + //must work after decorate & must have getName + tag.setDeleteHandler( + function(){ + remove_search_tag(tag.getName()); + } + ); + }); + }; + + var render_ask_page_result = function(data, text_status, xhr){ + var container = $('#' + q_list_sel); + container.fadeOut(200, function() { + container.children().remove(); + if (data.length > 5){ + container.css('overflow-y', 'scroll'); + container.css('height', '120px'); + } else { + container.css('height', data.length * 24 + 'px'); + container.css('overflow-y', 'hidden'); + } + $.each(data, function(idx, question){ + var url = question['url']; + var title = question['title']; + var answer_count = question['answer_count']; + var list_item = $('<h2></h2>'); + var count_element = $('<span class="item-count"></span>'); + count_element.html(answer_count); + list_item.append(count_element); + var link = $('<a></a>'); + link.attr('href', url); + list_item.append(link); + title_element = $('<span class="title"></span>'); + title_element.html(title); + link.append(title) + container.append(list_item); + }); + container.fadeIn(); + }); + }; + + var render_main_page_result = function(data, text_status, xhr){ + var old_list = $('#' + q_list_sel); + var new_list = $('<div></div>').hide(); + if (data['questions'].length > 0){ + old_list.stop(true); + + new_list.html(render_question_list(data['questions'])); + //old_list.hide(); + old_list.after(new_list); + //old_list.remove(); + //rename new div to old + render_paginator(data['paginator']); + set_question_count(data['question_counter']); + render_search_tags(data['query_data']['tags']); + render_faces(data['faces']); + render_related_tags(data['related_tags']); + render_relevance_sort_tab(); + set_active_sort_tab(sortMethod); + query.focus(); + + //show new div with a fadeIn effect + old_list.fadeOut(200, function() { + old_list.remove(); + new_list.attr('id', q_list_sel); + new_list.fadeIn(400); + }); + } + } + + var try_again = function(){ + running = false; + eval_query(); + } + + var send_query = function(query_text, sort_method){ + var post_data = {query: query_text}; + $.ajax({ + url: search_url, + data: {query: query_text, sort: sort_method}, + dataType: 'json', + success: render_result, + complete: try_again + }); + prev_text = query_text; + } + + var reset_query = function(sort_method){ + $.ajax({ + url: search_url, + data: {reset_query: true, sort: sort_method}, + dataType: 'json', + success: render_result, + complete: try_again + }); + prev_text = ''; + } + + var refresh_main_page = function(){ + $.ajax({ + url: askbot['urls']['questions'], + data: {preserve_state: true}, + dataType: 'json', + success: render_main_page_result + }); + }; + + return { + refresh: function(){ + query = $('input#keywords'); + refresh_main_page(); + }, + init: function(mode){ + if (mode === 'main_page'){ + //live search for the main page + query = $('input#keywords'); + search_url = askbot['urls']['questions']; + render_result = render_main_page_result; + + process_query = function(){ + if (prev_text.length === 0 && showSortByRelevance){ + if (sortMethod === 'activity-desc'){ + prevSortMethod = sortMethod; + sortMethod = 'relevance-desc'; + } + } + send_query(cur_text, sortMethod); + }; + restart_query = function() { + reset_sort_method(); + refresh_x_button(); + reset_query(sortMethod); + running = true; + }; + + activate_search_tags(); + main_page_search_listen(); + } else { + query = $('input#id_title.questionTitleInput'); + search_url = askbot['urls']['api_get_questions']; + render_result = render_ask_page_result; + process_query = function(){ + send_query(cur_text); + }; + restart_query = function(){ + $('#' + q_list_sel).css('height',0).children().remove(); + running = false; + prev_text = ''; + //ask_page_search_listen(); + }; + ask_page_search_listen(); + } + prev_text = $.trim(query.val()); + running = false; + } + }; + +}; diff --git a/askbot/skins/old/media/js/output-words.html b/askbot/skins/old/media/js/output-words.html new file mode 100644 index 00000000..8ea5f314 --- /dev/null +++ b/askbot/skins/old/media/js/output-words.html @@ -0,0 +1,49 @@ +<!--
+
+ @desc Word checker
+ Tests the JavaScript-side i18n translation arrays for completeness
+ and generates an empty template containing all the keys
+ for new translations.
+
+ Needs output-words.js and other JavaScript files shipped with Askbot.
+
+ @author Pekka Gaiser <post@pekkagaiser.com>
+ @package Part of the ASKBOT project <www.askbot.org>
+ @license Published with NO WARRANTY WHATSOEVER
+ under the same license as the Askbot project.
+ @version First release, May 7th 2010
+
+
+--><html>
+<head>
+
+<title>Translation check</title>
+
+<style type="text/css">
+
+ body { margin: 16px; color: navy}
+
+ table.languages td.language { width: 40px; padding-top: 4px; padding-bottom: 4px; text-align: center }
+ table.languages td.okay { background-color: lightgreen }
+ table.languages td.missing { background-color: orange }
+
+ div.column { width: 49%; float: left; padding-bottom: 64px }
+
+</style>
+
+<script type="text/javascript">i18nLang = "De";</script>
+<script type="text/javascript" src="jquery-1.2.6.js"></script>
+<script type="text/javascript" src="i18n.js"></script>
+<script type="text/javascript" src="output-words.js"></script>
+
+
+</head>
+<body>
+
+ <script type="text/javascript">
+ output();
+ </script>
+
+
+</body>
+</html>
\ No newline at end of file diff --git a/askbot/skins/old/media/js/output-words.js b/askbot/skins/old/media/js/output-words.js new file mode 100644 index 00000000..41e25651 --- /dev/null +++ b/askbot/skins/old/media/js/output-words.js @@ -0,0 +1,97 @@ +/* + + @desc Word checker + Tests the JavaScript-side i18n translation arrays for completeness + and generates an empty template containing all the keys + for new translations. + + Is included by output-words.html. + + @author Pekka Gaiser <post@pekkagaiser.com> + @package Part of the ASKBOT project <www.askbot.org> + @license Published with NO WARRANTY WHATSOEVER + under the same license as the Askbot project. + @version First release, May 7th 2010 + +*/ + + +function output() + { + + document.write("<div class='column'><h1>Translation check</h1><table class='languages'>"); + + var allKeys = new Array(); + + + for (var key in i18n) + { + if(!i18n.hasOwnProperty(key)) continue; + + for (var word in i18n[key]) + { + if(!i18n[key].hasOwnProperty(word)) continue; + + if (jQuery.inArray(word, allKeys) == -1) + allKeys.push(word); + + } + } + + + // Output all keys + for (var key in allKeys.sort()) + { + + document.write("<tr><td>"); + document.write(allKeys[key]); + document.write("</td><td>"); + + // Check word in all languages + for (var language in i18n) + { + if(!i18n.hasOwnProperty(language)) continue; + + if ((!i18n[language][allKeys[key]]) || (i18n[language][allKeys[key]] == "")) + document.write("<td class='language missing'>"+language+"</td>"); + else + document.write("<td class='language okay' title='"+escape(i18n[language][allKeys[key]])+"'>"+language+"</td>"); + + escape(i18n[language][key]) + + } + + document.write("</tr>"); + + } + + document.write("</table></div><div class='column'>"); + + // Translation template + + document.write("<h1>Template for new translation</h1>"); + document.write("<textarea style='width: 100%; height: 600px'>"); + document.write("// Note that the words ending with '/' (e.g. 'questions/') are directory names\n"); + document.write("// And need to be identical with the directory names\n"); + document.write("// in the basic server-side translation\n\n"); + + + document.write("var i18nXY = {\n"); + + // Output all words + for (var key in allKeys.sort()) + { + + document.write(" '"+allKeys[key]+"': '', \n"); + + } + + document.write(" 'delete_this': ''\n}"); // To prevent trailing comma + document.write("</textarea>"); + + document.write("</div>"); + + + } + + diff --git a/askbot/skins/old/media/js/post.js b/askbot/skins/old/media/js/post.js new file mode 100644 index 00000000..52772cc0 --- /dev/null +++ b/askbot/skins/old/media/js/post.js @@ -0,0 +1,1665 @@ +/* +Scripts for cnprog.com +Project Name: Lanai +All Rights Resevred 2008. CNPROG.COM +*/ +var lanai = +{ + /** + * Finds any <pre><code></code></pre> tags which aren't registered for + * pretty printing, adds the appropriate class name and invokes prettify. + */ + highlightSyntax: function(){ + var styled = false; + $("pre code").parent().each(function(){ + if (!$(this).hasClass('prettyprint')){ + $(this).addClass('prettyprint'); + styled = true; + } + }); + + if (styled){ + prettyPrint(); + } + } +}; + +function appendLoader(element) { + element.append('<img class="ajax-loader" ' + + 'src="' + mediaUrl("media/images/indicator.gif") + '" title="' + + $.i18n._('loading...') + + '" alt="' + + $.i18n._('loading...') + + '" />'); +} + +function removeLoader() { + $("img.ajax-loader").remove(); +} + +function setSubmitButtonDisabled(form, isDisabled) { + form.find("input[type='submit']").attr("disabled", isDisabled ? "true" : ""); +} + +function enableSubmitButton(form) { + setSubmitButtonDisabled(form, false); +} + +function disableSubmitButton(form) { + setSubmitButtonDisabled(form, true); +} + +function setupFormValidation(form, validationRules, validationMessages, onSubmitCallback) { + enableSubmitButton(form); + form.validate({ + debug: true, + rules: (validationRules ? validationRules : {}), + messages: (validationMessages ? validationMessages : {}), + errorElement: "span", + errorClass: "form-error", + errorPlacement: function(error, element) { + var span = element.next().find("span.form-error"); + if (span.length === 0) { + span = element.parent().find("span.form-error"); + if (span.length === 0){ + //for resizable textarea + var element_id = element.attr('id'); + span = $("label[for='" + element_id + "']"); + } + } + span.replaceWith(error); + }, + submitHandler: function(form_dom) { + disableSubmitButton($(form_dom)); + + if (onSubmitCallback){ + onSubmitCallback(); + } + else{ + form_dom.submit(); + } + } + }); +} + +var validateTagLength = function(value){ + var tags = getUniqueWords(value); + var are_tags_ok = true; + $.each(tags, function(index, value){ + if (value.length > askbot['settings']['maxTagLength']){ + are_tags_ok = false; + } + }); + return are_tags_ok; +}; +var validateTagCount = function(value){ + var tags = getUniqueWords(value); + return (tags.length <= askbot['settings']['maxTagsPerPost']); +}; + +$.validator.addMethod('limit_tag_count', validateTagCount); +$.validator.addMethod('limit_tag_length', validateTagLength); + +var CPValidator = function(){ + return { + getQuestionFormRules : function(){ + return { + tags: { + required: true, + maxlength: 105, + limit_tag_count: true, + limit_tag_length: true + }, + text: { + required: true, + minlength: 10 + } + /*title: { + required: true, + minlength: 10 + }*/ + }; + }, + getQuestionFormMessages: function(){ + return { + tags: { + required: " " + $.i18n._('tags cannot be empty'), + maxlength: askbot['messages']['tagLimits'], + limit_tag_count: askbot['messages']['maxTagsPerPost'], + limit_tag_length: askbot['messages']['maxTagLength'] + }, + text: { + required: " " + $.i18n._('content cannot be empty'), + minlength: $.i18n._('content minchars').replace('{0}', 10) + }, + title: { + required: " " + $.i18n._('please enter title'), + minlength: $.i18n._('title minchars').replace('{0}', 10) + } + }; + } + }; +}(); + +/** + * @constructor + * @extends {SimpleControl} + * @param {Comment} comment to upvote + */ +var CommentVoteButton = function(comment){ + SimpleControl.call(this); + /** + * @param {Comment} + */ + this._comment = comment; + /** + * @type {boolean} + */ + this._voted = false; + /** + * @type {number} + */ + this._score = 0; +}; +inherits(CommentVoteButton, SimpleControl); +/** + * @param {number} score + */ +CommentVoteButton.prototype.setScore = function(score){ + this._score = score; + if (this._element){ + this._element.html(score); + } +}; +/** + * @param {boolean} voted + */ +CommentVoteButton.prototype.setVoted = function(voted){ + this._voted = voted; + if (this._element){ + this._element.addClass('upvoted'); + } +}; + +CommentVoteButton.prototype.getVoteHandler = function(){ + var me = this; + var comment = this._comment; + return function(){ + var voted = me._voted; + var post_id = me._comment.getId(); + var data = { + cancel_vote: voted ? true:false, + post_id: post_id + }; + $.ajax({ + type: 'POST', + data: data, + dataType: 'json', + url: askbot['urls']['upvote_comment'], + cache: false, + success: function(data){ + if (data['success'] == true){ + me.setScore(data['score']); + me.setVoted(true); + } else { + showMessage(comment.getElement(), data['message'], 'after'); + } + } + }); + }; +}; + +CommentVoteButton.prototype.decorate = function(element){ + this._element = element; + this.setHandler(this.getVoteHandler()); + + var element = this._element; + var comment = this._comment; + /* can't call comment.getElement() here due + * an issue in the getElement() of comment + * so use an "illegal" access to comment._element here + */ + comment._element.mouseenter(function(){ + //outside height may not be known + //var height = comment.getElement().height(); + //element.height(height); + element.addClass('hover'); + }); + comment._element.mouseleave(function(){ + element.removeClass('hover'); + }); + +}; + +CommentVoteButton.prototype.createDom = function(){ + this._element = this.makeElement('div'); + if (this._score > 0){ + this._element.html(this._score); + } + this._element.addClass('upvote'); + if (this._voted){ + this._element.addClass('upvoted'); + } + this.decorate(this._element); +}; + +/** + * legacy Vote class + * handles all sorts of vote-like operations + */ +var Vote = function(){ + // All actions are related to a question + var questionId; + //question slug to build redirect urls + var questionSlug; + // The object we operate on actually. It can be a question or an answer. + var postId; + var questionAuthorId; + var currentUserId; + var answerContainerIdPrefix = 'answer-container-'; + var voteContainerId = 'vote-buttons'; + var imgIdPrefixAccept = 'answer-img-accept-'; + var classPrefixFollow= 'button follow'; + var classPrefixFollowed= 'button followed'; + var imgIdPrefixQuestionVoteup = 'question-img-upvote-'; + var imgIdPrefixQuestionVotedown = 'question-img-downvote-'; + var imgIdPrefixAnswerVoteup = 'answer-img-upvote-'; + var imgIdPrefixAnswerVotedown = 'answer-img-downvote-'; + var divIdFavorite = 'favorite-number'; + var commentLinkIdPrefix = 'comment-'; + var voteNumberClass = "vote-number"; + var offensiveIdPrefixQuestionFlag = 'question-offensive-flag-'; + var offensiveIdPrefixAnswerFlag = 'answer-offensive-flag-'; + var offensiveClassFlag = 'offensive-flag'; + var questionControlsId = 'question-controls'; + var removeQuestionLinkIdPrefix = 'question-delete-link-'; + var removeAnswerLinkIdPrefix = 'answer-delete-link-'; + var questionSubscribeUpdates = 'question-subscribe-updates'; + var questionSubscribeSidebar= 'question-subscribe-sidebar'; + + var acceptAnonymousMessage = $.i18n._('insufficient privilege'); + var acceptOwnAnswerMessage = $.i18n._('cannot pick own answer as best'); + + var pleaseLogin = " <a href='" + askbot['urls']['user_signin'] + + "?next=" + askbot['urls']['question_url_template'] + + "'>" + + $.i18n._('please login') + "</a>"; + + var favoriteAnonymousMessage = $.i18n._('anonymous users cannot follow questions') + pleaseLogin; + var subscribeAnonymousMessage = $.i18n._('anonymous users cannot subscribe to questions') + pleaseLogin; + var voteAnonymousMessage = $.i18n._('anonymous users cannot vote') + pleaseLogin; + //there were a couple of more messages... + var offensiveConfirmation = $.i18n._('please confirm offensive'); + var offensiveAnonymousMessage = $.i18n._('anonymous users cannot flag offensive posts') + pleaseLogin; + var removeConfirmation = $.i18n._('confirm delete'); + var removeAnonymousMessage = $.i18n._('anonymous users cannot delete/undelete') + pleaseLogin; + var recoveredMessage = $.i18n._('post recovered'); + var deletedMessage = $.i18n._('post deleted'); + + var VoteType = { + acceptAnswer : 0, + questionUpVote : 1, + questionDownVote : 2, + favorite : 4, + answerUpVote: 5, + answerDownVote:6, + offensiveQuestion : 7, + offensiveAnswer:8, + removeQuestion: 9, + removeAnswer:10, + questionSubscribeUpdates:11, + questionUnsubscribeUpdates:12 + }; + + var getFavoriteButton = function(){ + var favoriteButton = 'div.'+ voteContainerId +' a[class='+ classPrefixFollow +']'; + favoriteButton += ', div.'+ voteContainerId +' a[class='+ classPrefixFollowed +']'; + return $(favoriteButton); + }; + var getFavoriteNumber = function(){ + var favoriteNumber = '#'+ divIdFavorite ; + return $(favoriteNumber); + }; + var getQuestionVoteUpButton = function(){ + var questionVoteUpButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixQuestionVoteup +']'; + return $(questionVoteUpButton); + }; + var getQuestionVoteDownButton = function(){ + var questionVoteDownButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixQuestionVotedown +']'; + return $(questionVoteDownButton); + }; + var getAnswerVoteUpButtons = function(){ + var answerVoteUpButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAnswerVoteup +']'; + return $(answerVoteUpButton); + }; + var getAnswerVoteDownButtons = function(){ + var answerVoteDownButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAnswerVotedown +']'; + return $(answerVoteDownButton); + }; + var getAnswerVoteUpButton = function(id){ + var answerVoteUpButton = 'div.'+ voteContainerId +' img[id='+ imgIdPrefixAnswerVoteup + id + ']'; + return $(answerVoteUpButton); + }; + var getAnswerVoteDownButton = function(id){ + var answerVoteDownButton = 'div.'+ voteContainerId +' img[id='+ imgIdPrefixAnswerVotedown + id + ']'; + return $(answerVoteDownButton); + }; + + var getOffensiveQuestionFlag = function(){ + var offensiveQuestionFlag = '#question-table span[class='+ offensiveClassFlag +']'; + return $(offensiveQuestionFlag); + }; + + var getOffensiveAnswerFlags = function(){ + var offensiveQuestionFlag = 'div.answer span[class='+ offensiveClassFlag +']'; + return $(offensiveQuestionFlag); + }; + + var getremoveQuestionLink = function(){ + var removeQuestionLink = 'div#question-controls a[id^='+ removeQuestionLinkIdPrefix +']'; + return $(removeQuestionLink); + }; + + var getquestionSubscribeUpdatesCheckbox = function(){ + return $('#' + questionSubscribeUpdates); + }; + + var getquestionSubscribeSidebarCheckbox= function(){ + return $('#' + questionSubscribeSidebar); + }; + + var getremoveAnswersLinks = function(){ + var removeAnswerLinks = 'div.answer-controls a[id^='+ removeAnswerLinkIdPrefix +']'; + return $(removeAnswerLinks); + }; + + var setVoteImage = function(voteType, undo, object){ + var flag = undo ? "" : "-on"; + var arrow = (voteType == VoteType.questionUpVote || voteType == VoteType.answerUpVote) ? "up" : "down"; + object.attr("src", mediaUrl("media/images/vote-arrow-"+ arrow + flag +".png")); + + // if undo voting, then undo the pair of arrows. + if(undo){ + if(voteType == VoteType.questionUpVote || voteType == VoteType.questionDownVote){ + $(getQuestionVoteUpButton()).attr("src", mediaUrl("media/images/vote-arrow-up.png")); + $(getQuestionVoteDownButton()).attr("src", mediaUrl("media/images/vote-arrow-down.png")); + } + else{ + $(getAnswerVoteUpButton(postId)).attr("src", mediaUrl("media/images/vote-arrow-up.png")); + $(getAnswerVoteDownButton(postId)).attr("src", mediaUrl("media/images/vote-arrow-down.png")); + } + } + }; + + var setVoteNumber = function(object, number){ + var voteNumber = object.parent('div.'+ voteContainerId).find('div.'+ voteNumberClass); + $(voteNumber).text(number); + }; + + var bindEvents = function(){ + // accept answers + if(questionAuthorId == currentUserId){ + var acceptedButtons = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAccept +']'; + $(acceptedButtons).unbind('click').click(function(event){ + Vote.accept($(event.target)); + }); + } + // set favorite question + var favoriteButton = getFavoriteButton(); + favoriteButton.unbind('click').click(function(event){ + //Vote.favorite($(event.target)); + Vote.favorite(favoriteButton); + }); + + // question vote up + var questionVoteUpButton = getQuestionVoteUpButton(); + questionVoteUpButton.unbind('click').click(function(event){ + Vote.vote($(event.target), VoteType.questionUpVote); + }); + + var questionVoteDownButton = getQuestionVoteDownButton(); + questionVoteDownButton.unbind('click').click(function(event){ + Vote.vote($(event.target), VoteType.questionDownVote); + }); + + var answerVoteUpButton = getAnswerVoteUpButtons(); + answerVoteUpButton.unbind('click').click(function(event){ + Vote.vote($(event.target), VoteType.answerUpVote); + }); + + var answerVoteDownButton = getAnswerVoteDownButtons(); + answerVoteDownButton.unbind('click').click(function(event){ + Vote.vote($(event.target), VoteType.answerDownVote); + }); + + getOffensiveQuestionFlag().unbind('click').click(function(event){ + Vote.offensive(this, VoteType.offensiveQuestion); + }); + + getOffensiveAnswerFlags().unbind('click').click(function(event){ + Vote.offensive(this, VoteType.offensiveAnswer); + }); + + getremoveQuestionLink().unbind('click').click(function(event){ + Vote.remove(this, VoteType.removeQuestion); + }); + + getquestionSubscribeUpdatesCheckbox().unbind('click').click(function(event){ + //despeluchar esto + if (this.checked){ + getquestionSubscribeSidebarCheckbox().attr({'checked': true}); + Vote.vote($(event.target), VoteType.questionSubscribeUpdates); + } + else { + getquestionSubscribeSidebarCheckbox().attr({'checked': false}); + Vote.vote($(event.target), VoteType.questionUnsubscribeUpdates); + } + }); + + getquestionSubscribeSidebarCheckbox().unbind('click').click(function(event){ + if (this.checked){ + getquestionSubscribeUpdatesCheckbox().attr({'checked': true}); + Vote.vote($(event.target), VoteType.questionSubscribeUpdates); + } + else { + getquestionSubscribeUpdatesCheckbox().attr({'checked': false}); + Vote.vote($(event.target), VoteType.questionUnsubscribeUpdates); + } + }); + + getremoveAnswersLinks().unbind('click').click(function(event){ + Vote.remove(this, VoteType.removeAnswer); + }); + }; + + var submit = function(object, voteType, callback) { + //this function submits votes + $.ajax({ + type: "POST", + cache: false, + dataType: "json", + url: askbot['urls']['vote_url_template'].replace('{{QuestionID}}', questionId), + data: { "type": voteType, "postId": postId }, + error: handleFail, + success: function(data){callback(object, voteType, data);} + }); + }; + + var handleFail = function(xhr, msg){ + alert("Callback invoke error: " + msg); + }; + + // callback function for Accept Answer action + var callback_accept = function(object, voteType, data){ + if(data.allowed == "0" && data.success == "0"){ + showMessage(object, acceptAnonymousMessage); + } + else if(data.allowed == "-1"){ + showMessage(object, acceptOwnAnswerMessage); + } + else if(data.status == "1"){ + object.attr("src", mediaUrl("media/images/vote-accepted.png")); + $("#"+answerContainerIdPrefix+postId).removeClass("accepted-answer"); + $("#"+commentLinkIdPrefix+postId).removeClass("comment-link-accepted"); + } + else if(data.success == "1"){ + var acceptedButtons = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAccept +']'; + $(acceptedButtons).attr("src", mediaUrl("media/images/vote-accepted.png")); + var answers = ("div[id^="+answerContainerIdPrefix +"]"); + $(answers).removeClass("accepted-answer"); + var commentLinks = ("div[id^="+answerContainerIdPrefix +"] div[id^="+ commentLinkIdPrefix +"]"); + $(commentLinks).removeClass("comment-link-accepted"); + + object.attr("src", mediaUrl("media/images/vote-accepted-on.png")); + $("#"+answerContainerIdPrefix+postId).addClass("accepted-answer"); + $("#"+commentLinkIdPrefix+postId).addClass("comment-link-accepted"); + } + else{ + showMessage(object, data.message); + } + }; + + var callback_favorite = function(object, voteType, data){ + if(data.allowed == "0" && data.success == "0"){ + showMessage( + object, + favoriteAnonymousMessage.replace( + '{{QuestionID}}', + questionId).replace( + '{{questionSlug}}', + '' + ) + ); + } + else if(data.status == "1"){ + var follow_html = gettext('Follow'); + object.attr("class", 'button follow'); + object.html(follow_html); + var fav = getFavoriteNumber(); + fav.removeClass("my-favorite-number"); + if(data.count === 0){ + data.count = ''; + fav.text(''); + }else{ + var fmts = ngettext('%s follower', '%s followers', data.count); + fav.text(interpolate(fmts, [data.count])); + } + } + else if(data.success == "1"){ + var followed_html = gettext('<div>Following</div><div class="unfollow">Unfollow</div>'); + object.html(followed_html); + object.attr("class", 'button followed'); + var fav = getFavoriteNumber(); + var fmts = ngettext('%s follower', '%s followers', data.count); + fav.text(interpolate(fmts, [data.count])); + fav.addClass("my-favorite-number"); + } + else{ + showMessage(object, data.message); + } + }; + + var callback_vote = function(object, voteType, data){ + if (data.success == '0'){ + showMessage(object, data.message); + return; + } + else { + if (data.status == '1'){ + setVoteImage(voteType, true, object); + } + else { + setVoteImage(voteType, false, object); + } + setVoteNumber(object, data.count); + if (data.message && data.message.length > 0){ + showMessage(object, data.message); + } + return; + } + //may need to take a look at this again + if (data.status == "1"){ + setVoteImage(voteType, true, object); + setVoteNumber(object, data.count); + } + else if (data.success == "1"){ + setVoteImage(voteType, false, object); + setVoteNumber(object, data.count); + if (data.message.length > 0){ + showMessage(object, data.message); + } + } + }; + + var callback_offensive = function(object, voteType, data){ + //todo: transfer proper translations of these from i18n.js + //to django.po files + //_('anonymous users cannot flag offensive posts') + pleaseLogin; + if (data.success == "1"){ + $(object).children('span[class=darkred]').text("("+ data.count +")"); + } + else { + object = $(object); + showMessage(object, data.message) + } + }; + + var callback_remove = function(object, voteType, data){ + if (data.success == "1"){ + if (removeActionType == 'delete'){ + postNode.addClass('deleted'); + postRemoveLink.innerHTML = $.i18n._('undelete'); + showMessage(object, deletedMessage); + } + else if (removeActionType == 'undelete') { + postNode.removeClass('deleted'); + postRemoveLink.innerHTML = $.i18n._('delete'); + showMessage(object, recoveredMessage); + } + } + else { + showMessage(object, data.message) + } + }; + + return { + init : function(qId, qSlug, questionAuthor, userId){ + questionId = qId; + questionSlug = qSlug; + questionAuthorId = questionAuthor; + currentUserId = userId; + bindEvents(); + }, + + //accept answer + accept: function(object){ + postId = object.attr("id").substring(imgIdPrefixAccept.length); + submit(object, VoteType.acceptAnswer, callback_accept); + }, + //mark question as favorite + favorite: function(object){ + if (!currentUserId || currentUserId.toUpperCase() == "NONE"){ + showMessage( + object, + favoriteAnonymousMessage.replace( + "{{QuestionID}}", + questionId + ).replace( + '{{questionSlug}}', + questionSlug + ) + ); + return false; + } + submit(object, VoteType.favorite, callback_favorite); + }, + + vote: function(object, voteType){ + if (!currentUserId || currentUserId.toUpperCase() == "NONE"){ + if (voteType == VoteType.questionSubscribeUpdates || voteType == VoteType.questionUnsubscribeUpdates){ + getquestionSubscribeSidebarCheckbox().removeAttr('checked'); + getquestionSubscribeUpdatesCheckbox().removeAttr('checked'); + showMessage(object, subscribeAnonymousMessage); + }else { + showMessage( + $(object), + voteAnonymousMessage.replace( + "{{QuestionID}}", + questionId + ).replace( + '{{questionSlug}}', + questionSlug + ) + ); + } + return false; + } + // up and downvote processor + if (voteType == VoteType.answerUpVote){ + postId = object.attr("id").substring(imgIdPrefixAnswerVoteup.length); + } + else if (voteType == VoteType.answerDownVote){ + postId = object.attr("id").substring(imgIdPrefixAnswerVotedown.length); + } + + submit(object, voteType, callback_vote); + }, + //flag offensive + offensive: function(object, voteType){ + if (!currentUserId || currentUserId.toUpperCase() == "NONE"){ + showMessage( + $(object), + offensiveAnonymousMessage.replace( + "{{QuestionID}}", + questionId + ).replace( + '{{questionSlug}}', + questionSlug + ) + ); + return false; + } + if (confirm(offensiveConfirmation)){ + postId = object.id.substr(object.id.lastIndexOf('-') + 1); + submit(object, voteType, callback_offensive); + } + }, + //delete question or answer (comments are deleted separately) + remove: function(object, voteType){ + if (!currentUserId || currentUserId.toUpperCase() == "NONE"){ + showMessage( + $(object), + removeAnonymousMessage.replace( + '{{QuestionID}}', + questionId + ).replace( + '{{questionSlug}}', + questionSlug + ) + ); + return false; + } + bits = object.id.split('-'); + postId = bits.pop();/* this seems to be used within submit! */ + postType = bits.shift(); + + var do_proceed = false; + if (postType == 'answer'){ + postNode = $('#answer-container-' + postId); + } + else if (postType == 'question'){ + postNode = $('#question-table'); + } + postRemoveLink = object; + if (postNode.hasClass('deleted')){ + removeActionType = 'undelete'; + do_proceed = true; + } + else { + removeActionType = 'delete'; + do_proceed = confirm(removeConfirmation); + } + if (do_proceed) { + submit($(object), voteType, callback_remove); + } + } + }; +} (); + +var questionRetagger = function(){ + + var oldTagsHTML = ''; + var tagInput = null; + var tagsDiv = null; + var retagLink = null; + + var restoreEventHandlers = function(){ + $(document).unbind('click'); + }; + + var cancelRetag = function(){ + tagsDiv.html(oldTagsHTML); + tagsDiv.removeClass('post-retag'); + tagsDiv.addClass('post-tags'); + restoreEventHandlers(); + initRetagger(); + }; + + var render_tag = function(tag_name){ + //copy-paste from live search!!! + var tag = new Tag(); + tag.setName(tag_name); + return tag.getElement().outerHTML(); + }; + + var drawNewTags = function(new_tags){ + new_tags = new_tags.split(/\s+/); + var tags_html = '' + $.each(new_tags, function(index, name){ + tags_html += render_tag(name); + }); + tagsDiv.html(tags_html); + }; + + var doRetag = function(){ + $.ajax({ + type: "POST", + url: retagUrl, + dataType: "json", + data: { tags: getUniqueWords(tagInput.val()).join(' ') }, + success: function(json) { + if (json['success'] === true){ + new_tags = getUniqueWords(json['new_tags']); + oldTagsHtml = ''; + cancelRetag(); + drawNewTags(new_tags.join(' ')); + } + else { + cancelRetag(); + showMessage(tagsDiv, json['message']); + } + }, + error: function(xhr, textStatus, errorThrown) { + showMessage(tagsDiv, 'sorry, somethin is not right here'); + cancelRetag(); + } + }); + return false; + } + + var setupInputEventHandlers = function(input){ + input.keydown(function(e){ + if ((e.which && e.which == 27) || (e.keyCode && e.keyCode == 27)){ + cancelRetag(); + } + }); + $(document).unbind('click').click(cancelRetag, false); + input.click(function(){return false}); + }; + + var createRetagForm = function(old_tags_string){ + var div = $('<form method="post"></form>'); + tagInput = $('<input id="retag_tags" type="text" autocomplete="off" name="tags" size="30"/>'); + //var tagLabel = $('<label for="retag_tags" class="error"></label>'); + tagInput.val(old_tags_string); + //populate input + var tagAc = new AutoCompleter({ + url: askbot['urls']['get_tag_list'], + preloadData: true, + minChars: 1, + useCache: true, + matchInside: true, + maxCacheLength: 100, + delay: 10 + }); + tagAc.decorate(tagInput); + div.append(tagInput); + //div.append(tagLabel); + setupInputEventHandlers(tagInput); + + //button = $('<input type="submit" />'); + //button.val($.i18n._('save tags')); + //div.append(button); + //setupButtonEventHandlers(button); + div.validate({//copy-paste from utils.js + rules: { + tags: { + required: true, + maxlength: askbot['settings']['maxTagsPerPost'] * askbot['settings']['maxTagLength'], + limit_tag_count: true, + limit_tag_length: true + } + }, + messages: { + tags: { + required: $.i18n._('tags cannot be empty'), + maxlength: askbot['messages']['tagLimits'], + limit_tag_count: askbot['messages']['maxTagsPerPost'], + limit_tag_length: askbot['messages']['maxTagLength'] + } + }, + submitHandler: doRetag, + errorClass: "retag-error" + }); + + return div; + }; + + var getTagsAsString = function(tags_div){ + var links = tags_div.find('a'); + var tags_str = ''; + links.each(function(index, element){ + if (index === 0){ + tags_str = $(element).html(); + } + else { + tags_str += ' ' + $(element).html(); + } + }); + return tags_str; + }; + + var noopHandler = function(){ + tagInput.focus(); + return false; + }; + + var deactivateRetagLink = function(){ + retagLink.unbind('click').click(noopHandler); + retagLink.unbind('keypress').keypress(noopHandler); + }; + + var startRetag = function(){ + tagsDiv = $('#question-tags'); + oldTagsHTML = tagsDiv.html();//save to restore on cancel + var old_tags_string = getTagsAsString(tagsDiv); + var retag_form = createRetagForm(old_tags_string); + tagsDiv.html(''); + tagsDiv.append(retag_form); + tagsDiv.removeClass('post-tags'); + tagsDiv.addClass('post-retag'); + tagInput.focus(); + deactivateRetagLink(); + return false; + }; + + var setupClickAndEnterHandler = function(element, callback){ + element.unbind('click').click(callback); + element.unbind('keypress').keypress(function(e){ + if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)){ + callback(); + } + }); + } + + var initRetagger = function(){ + setupClickAndEnterHandler(retagLink, startRetag); + }; + + return { + init: function(){ + retagLink = $('#retag'); + initRetagger(); + } + }; +}(); + +//constructor for the form +var EditCommentForm = function(){ + WrappedElement.call(this); + this._comment = null; + this._comment_widget = null; + this._element = null; + this._text = ''; + this._id = 'edit-comment-form'; +}; +inherits(EditCommentForm, WrappedElement); + +EditCommentForm.prototype.getElement = function(){ + EditCommentForm.superClass_.getElement.call(this); + this._textarea.val(this._text); + return this._element; +}; + +EditCommentForm.prototype.attachTo = function(comment, mode){ + this._comment = comment; + this._type = mode; + this._comment_widget = comment.getContainerWidget(); + this._text = comment.getText(); + comment.getElement().after(this.getElement()); + comment.getElement().hide(); + this._comment_widget.hideButton(); + if (this._type == 'add'){ + this._submit_btn.html($.i18n._('add comment')); + } + else { + this._submit_btn.html($.i18n._('save comment')); + } + this.getElement().show(); + this.focus(); + putCursorAtEnd(this._textarea); +}; + +EditCommentForm.prototype.getCounterUpdater = function(){ + //returns event handler + var counter = this._text_counter; + var handler = function(){ + var textarea = $(this); + var length = textarea.val() ? textarea.val().length : 0; + var length1 = maxCommentLength - 100; + if (length1 < 0){ + length1 = Math.round(0.7*maxCommentLength); + } + var length2 = maxCommentLength - 30; + if (length2 < 0){ + length2 = Math.round(0.9*maxCommentLength); + } + + var color = 'maroon'; + if (length === 0){ + var feedback = $.i18n._('title minchars').replace('{0}', 10); + } + else if (length < 10){ + var feedback = $.i18n._('enter more characters').replace('{0}', 10 - length); + } + else { + color = length > length2 ? "#f00" : length > length1 ? "#f60" : "#999"; + var feedback = $.i18n._('{0} characters left') + .replace('{0}', maxCommentLength - length); + } + counter.html(feedback).css('color', color); + }; + return handler; +}; + +EditCommentForm.prototype.canCancel = function(){ + if (this._element === null){ + return true; + } + var ctext = $.trim(this._textarea.val()); + if ($.trim(ctext) == $.trim(this._text)){ + return true; + } + else if (this.confirmAbandon()){ + return true; + } + this.focus(); + return false; +}; + +EditCommentForm.prototype.getCancelHandler = function(){ + var form = this; + return function(){ + if (form.canCancel()){ + form.detach(); + } + return false; + }; +}; + +EditCommentForm.prototype.detach = function(){ + if (this._comment === null){ + return; + } + this._comment.getContainerWidget().showButton(); + if (this._comment.isBlank()){ + this._comment.dispose(); + } + else { + this._comment.getElement().show(); + } + this.reset(); + this._element = this._element.detach(); +}; + +EditCommentForm.prototype.createDom = function(){ + this._element = $('<form></form>'); + this._element.attr('class', 'post-comments'); + + var div = $('<div></div>'); + this._textarea = $('<textarea></textarea>'); + this._textarea.attr('id', this._id); + + /* + this._help_text = $('<span></span>').attr('class', 'help-text'); + this._help_text.html(gettext('Markdown is allowed in the comments')); + div.append(this._help_text); + + this._help_text = $('<div></div>').attr('class', 'clearfix'); + div.append(this._help_text); + */ + + this._element.append(div); + div.append(this._textarea); + this._text_counter = $('<span></span>').attr('class', 'counter'); + div.append(this._text_counter); + this._submit_btn = $('<button class="submit small"></button>'); + div.append(this._submit_btn); + this._cancel_btn = $('<button class="submit small"></button>'); + this._cancel_btn.html($.i18n._('cancel')); + div.append(this._cancel_btn); + + setupButtonEventHandlers(this._submit_btn, this.getSaveHandler()); + setupButtonEventHandlers(this._cancel_btn, this.getCancelHandler()); + + var update_counter = this.getCounterUpdater(); + var escape_handler = makeKeyHandler(27, this.getCancelHandler()); + this._textarea.attr('name', 'comment') + .attr('cols', 60) + .attr('rows', 5) + .attr('maxlength', maxCommentLength) + .blur(update_counter) + .focus(update_counter) + .keyup(update_counter) + .keyup(escape_handler); + if (askbot['settings']['saveCommentOnEnter']){ + var save_handler = makeKeyHandler(13, this.getSaveHandler()); + this._textarea.keydown(save_handler); + } + this._textarea.val(this._text); +}; + +EditCommentForm.prototype.enableButtons = function(){ + this._submit_btn.attr('disabled', ''); + this._cancel_btn.attr('disabled', ''); +}; + +EditCommentForm.prototype.disableButtons = function(){ + this._submit_btn.attr('disabled', 'disabled'); + this._cancel_btn.attr('disabled', 'disabled'); +}; + +EditCommentForm.prototype.reset = function(){ + this._comment = null; + this._text = ''; + this._textarea.val(''); + this.enableButtons(); +}; + +EditCommentForm.prototype.confirmAbandon = function(){ + this.focus(true); + this._textarea.addClass('highlight'); + var answer = confirm($.i18n._('confirm abandon comment')); + this._textarea.removeClass('highlight'); + return answer; +}; + +EditCommentForm.prototype.focus = function(hard){ + this._textarea.focus(); + if (hard === true){ + $(this._textarea).scrollTop(); + } +}; + +EditCommentForm.prototype.getSaveHandler = function(){ + + var me = this; + return function(){ + var text = me._textarea.val(); + if (text.length < 10){ + me.focus(); + return false; + } + + var post_data = { + comment: text + }; + + if (me._type == 'edit'){ + post_data['comment_id'] = me._comment.getId(); + post_url = askbot['urls']['editComment']; + } + else { + post_data['post_type'] = me._comment.getParentType(); + post_data['post_id'] = me._comment.getParentId(); + post_url = askbot['urls']['postComments']; + } + + me.disableButtons(); + + $.ajax({ + type: "POST", + url: post_url, + dataType: "json", + data: post_data, + success: function(json) { + if (me._type == 'add'){ + me._comment.dispose(); + me._comment.getContainerWidget().reRenderComments(json); + } + else { + me._comment.setContent(json); + me._comment.getElement().show(); + } + me.detach(); + }, + error: function(xhr, textStatus, errorThrown) { + me._comment.getElement().show(); + showMessage(me._comment.getElement(), xhr.responseText, 'after'); + me.detach(); + me.enableButtons(); + } + }); + return false; + }; +}; + +//a single instance to reuse +var editCommentForm = new EditCommentForm(); + +var Comment = function(widget, data){ + WrappedElement.call(this); + this._container_widget = widget; + this._data = data || {}; + this._blank = true;//set to false by setContent + this._element = null; + this._delete_prompt = $.i18n._('delete this comment'); + if (data && data['is_deletable']){ + this._deletable = data['is_deletable']; + } + else { + this._deletable = false; + } + if (data && data['is_editable']){ + this._editable = data['is_deletable']; + } + else { + this._editable = false; + } +}; +inherits(Comment, WrappedElement); + +Comment.prototype.decorate = function(element){ + this._element = $(element); + var parent_type = this._element.parent().parent().attr('id').split('-')[2]; + var comment_id = this._element.attr('id').replace('comment-',''); + this._data = {id: comment_id}; + var delete_img = this._element.find('span.delete-icon'); + if (delete_img.length > 0){ + this._deletable = true; + this._delete_icon = new DeleteIcon(this.deletePrompt); + this._delete_icon.setHandler(this.getDeleteHandler()); + this._delete_icon.decorate(delete_img); + } + var edit_link = this._element.find('a.edit'); + if (edit_link.length > 0){ + this._editable = true; + this._edit_link = new EditLink(); + this._edit_link.setHandler(this.getEditHandler()); + this._edit_link.decorate(edit_link); + } + + var vote = new CommentVoteButton(this); + vote.decorate(this._element.find('.comment-votes .upvote')); + + this._blank = false; +}; + +Comment.prototype.isBlank = function(){ + return this._blank; +}; + +Comment.prototype.getId = function(){ + return this._data['id']; +}; + +Comment.prototype.hasContent = function(){ + return ('id' in this._data); + //shortcut for 'user_url' 'html' 'user_display_name' 'comment_age' +}; + +Comment.prototype.hasText = function(){ + return ('text' in this._data); +} + +Comment.prototype.getContainerWidget = function(){ + return this._container_widget; +}; + +Comment.prototype.getParentType = function(){ + return this._container_widget.getPostType(); +}; + +Comment.prototype.getParentId = function(){ + return this._container_widget.getPostId(); +}; + +Comment.prototype.setContent = function(data){ + this._data = data || this._data; + this._element.html(''); + this._element.attr('class', 'comment'); + this._element.attr('id', 'comment-' + this._data['id']); + + var votes = this.makeElement('div'); + votes.addClass('comment-votes'); + + var vote = new CommentVoteButton(this); + if (this._data['upvoted_by_user']){ + vote.setVoted(true); + } + vote.setScore(this._data['score']); + votes.append(vote.getElement()); + + this._element.append(votes); + + this._comment_delete = $('<div class="comment-delete"></div>'); + if (this._deletable){ + this._delete_icon = new DeleteIcon(this._delete_prompt); + this._delete_icon.setHandler(this.getDeleteHandler()); + this._comment_delete.append(this._delete_icon.getElement()); + } + this._element.append(this._comment_delete); + + this._comment_body = $('<div class="comment-body"></div>'); + this._comment_body.html(this._data['html']); + //this._comment_body.append(' – '); + + this._user_link = $('<a></a>').attr('class', 'author'); + this._user_link.attr('href', this._data['user_url']); + this._user_link.html(this._data['user_display_name']); + this._comment_body.append(this._user_link); + + this._comment_body.append(' ('); + this._comment_age = $('<span class="age"></span>'); + this._comment_age.html(this._data['comment_age']); + this._comment_body.append(this._comment_age); + this._comment_body.append(')'); + + if (this._editable){ + this._edit_link = new EditLink(); + this._edit_link.setHandler(this.getEditHandler()) + this._comment_body.append(this._edit_link.getElement()); + } + this._element.append(this._comment_body); + + this._blank = false; +}; + +Comment.prototype.dispose = function(){ + if (this._comment_body){ + this._comment_body.remove(); + } + if (this._comment_delete){ + this._comment_delete.remove(); + } + if (this._user_link){ + this._user_link.remove(); + } + if (this._comment_age){ + this._comment_age.remove(); + } + if (this._delete_icon){ + this._delete_icon.dispose(); + } + if (this._edit_link){ + this._edit_link.dispose(); + } + this._data = null; + Comment.superClass_.dispose.call(this); +}; + +Comment.prototype.getElement = function(){ + Comment.superClass_.getElement.call(this); + if (this.isBlank() && this.hasContent()){ + this.setContent(); + if (enableMathJax === true){ + MathJax.Hub.Queue(['Typeset', MathJax.Hub]); + } + } + return this._element; +}; + +Comment.prototype.loadText = function(on_load_handler){ + var me = this; + $.ajax({ + type: "GET", + url: askbot['urls']['getComment'], + data: {id: this._data['id']}, + success: function(json){ + me._data['text'] = json['text']; + on_load_handler() + }, + error: function(xhr, textStatus, exception) { + showMessage(me.getElement(), xhr.responseText, 'after'); + } + }); +}; + +Comment.prototype.getText = function(){ + if (!this.isBlank()){ + if ('text' in this._data){ + return this._data['text']; + } + } + return ''; +} + +Comment.prototype.getEditHandler = function(){ + var comment = this; + return function(){ + if (editCommentForm.canCancel()){ + editCommentForm.detach(); + if (comment.hasText()){ + editCommentForm.attachTo(comment, 'edit'); + } + else { + comment.loadText( + function(){ + editCommentForm.attachTo(comment, 'edit'); + } + ); + } + } + }; +}; + +Comment.prototype.getDeleteHandler = function(){ + var comment = this; + var del_icon = this._delete_icon; + return function(){ + if (confirm($.i18n._('confirm delete comment'))){ + comment.getElement().hide(); + $.ajax({ + type: 'POST', + url: askbot['urls']['deleteComment'], + data: { comment_id: comment.getId() }, + success: function(json, textStatus, xhr) { + comment.dispose(); + }, + error: function(xhr, textStatus, exception) { + comment.getElement().show() + showMessage(del_icon.getElement(), xhr.responseText); + }, + dataType: "json" + }); + } + }; +}; + +var PostCommentsWidget = function(){ + WrappedElement.call(this); + this._denied = false; +}; +inherits(PostCommentsWidget, WrappedElement); + +PostCommentsWidget.prototype.decorate = function(element){ + var element = $(element); + this._element = element; + + var widget_id = element.attr('id'); + var id_bits = widget_id.split('-'); + this._post_id = id_bits[3]; + this._post_type = id_bits[2]; + this._is_truncated = askbot['data'][widget_id]['truncated']; + this._user_can_post = askbot['data'][widget_id]['can_post']; + + //see if user can comment here + var controls = element.find('.controls'); + this._activate_button = controls.find('.button'); + + if (this._user_can_post == false){ + setupButtonEventHandlers( + this._activate_button, + this.getReadOnlyLoadHandler() + ); + } + else { + setupButtonEventHandlers( + this._activate_button, + this.getActivateHandler() + ); + } + + this._cbox = element.find('.content'); + var comments = new Array(); + var me = this; + this._cbox.children().each(function(index, element){ + var comment = new Comment(me); + comments.push(comment) + comment.decorate(element); + }); + this._comments = comments; +}; + +PostCommentsWidget.prototype.getPostType = function(){ + return this._post_type; +}; + +PostCommentsWidget.prototype.getPostId = function(){ + return this._post_id; +}; + +PostCommentsWidget.prototype.hideButton = function(){ + this._activate_button.hide(); +}; + +PostCommentsWidget.prototype.showButton = function(){ + if (this._is_truncated === false){ + this._activate_button.html(askbot['messages']['addComment']); + } + this._activate_button.show(); +} + +PostCommentsWidget.prototype.startNewComment = function(){ + var comment = new Comment(this); + this._cbox.append(comment.getElement()); + editCommentForm.attachTo(comment, 'add'); +}; + +PostCommentsWidget.prototype.needToReload = function(){ + return this._is_truncated; +}; + +PostCommentsWidget.prototype.getActivateHandler = function(){ + var me = this; + return function() { + if (editCommentForm.canCancel()){ + editCommentForm.detach(); + if (me.needToReload()){ + me.reloadAllComments(function(json){ + me.reRenderComments(json); + me.startNewComment(); + }); + } + else { + me.startNewComment(); + } + } + }; +}; + +PostCommentsWidget.prototype.getReadOnlyLoadHandler = function(){ + var me = this; + return function(){ + me.reloadAllComments(function(json){ + me.reRenderComments(json); + me._activate_button.remove(); + }); + }; +}; + + +PostCommentsWidget.prototype.reloadAllComments = function(callback){ + var post_data = {post_id: this._post_id, post_type: this._post_type}; + var me = this; + $.ajax({ + type: "GET", + url: askbot['urls']['postComments'], + data: post_data, + success: function(json){ + callback(json); + me._is_truncated = false; + }, + dataType: "json" + }); +}; + +PostCommentsWidget.prototype.reRenderComments = function(json){ + $.each(this._comments, function(i, item){ + item.dispose(); + }); + this._comments = new Array(); + var me = this; + $.each(json, function(i, item){ + var comment = new Comment(me, item); + me._cbox.append(comment.getElement()); + me._comments.push(comment); + }); +}; + + +var socialSharing = function(){ + + var SERVICE_DATA = { + //url - template for the sharing service url, params are for the popup + identica: { + url: "http://identi.ca/notice/new?status_textarea={TEXT}%20{URL}", + params: "width=820, height=526,toolbar=1,status=1,resizable=1,scrollbars=1" + }, + twitter: { + url: "http://twitter.com/share?url={URL}&ref=twitbtn&text={TEXT}", + params: "width=820,height=526,toolbar=1,status=1,resizable=1,scrollbars=1" + }, + facebook: { + url: "http://www.facebook.com/sharer.php?u={URL}&ref=fbshare&t={TEXT}", + params: "width=630,height=436,toolbar=1,status=1,resizable=1,scrollbars=1" + }, + linkedin: { + url: "http://www.linkedin.com/shareArticle?mini=true&url={URL}&source={TEXT}", + params: "width=630,height=436,toolbar=1,status=1,resizable=1,scrollbars=1" + } + }; + var URL = ""; + var TEXT = ""; + + var share_page = function(service_name){ + if (SERVICE_DATA[service_name]){ + var url = SERVICE_DATA[service_name]['url']; + $.ajax({ + async: false, + url: "http://json-tinyurl.appspot.com/?&callback=?", + dataType: "json", + data: {'url':URL}, + success: function(data){ + url = url.replace('{URL}', data.tinyurl); + }, + error: function(data){ + url = url.replace('{URL}', URL); + }, + complete: function(data){ + url = url.replace('{TEXT}', TEXT); + var params = SERVICE_DATA[service_name]['params']; + if(!window.open(url, "sharing", params)){ + window.location.href=share_url; + } + } + }); + } + } + + return { + init: function(){ + URL = window.location.href; + TEXT = escape($('h1 > a').html()); + var fb = $('a.facebook-share') + var tw = $('a.twitter-share'); + var ln = $('a.linkedin-share'); + var ica = $('a.identica-share'); + copyAltToTitle(fb); + copyAltToTitle(tw); + copyAltToTitle(ln); + copyAltToTitle(ica); + setupButtonEventHandlers(fb, function(){share_page("facebook")}); + setupButtonEventHandlers(tw, function(){share_page("twitter")}); + setupButtonEventHandlers(ln, function(){share_page("linkedin")}); + setupButtonEventHandlers(ica, function(){share_page("identica")}); + } + } +}(); + +/** + * @constructor + * @extends {SimpleControl} + */ +var QASwapper = function(){ + SimpleControl.call(this); + this._ans_id = null; +}; +inherits(QASwapper, SimpleControl); + +QASwapper.prototype.decorate = function(element){ + this._element = element; + this._ans_id = parseInt(element.attr('id').split('-').pop()); + var me = this; + this.setHandler(function(){ + me.startSwapping(); + }); +}; + +QASwapper.prototype.startSwapping = function(){ + while (true){ + var title = prompt(gettext('Please enter question title (>10 characters)')); + if (title.length >= 10){ + var data = {new_title: title, answer_id: this._ans_id}; + $.ajax({ + type: "POST", + cache: false, + dataType: "json", + url: askbot['urls']['swap_question_with_answer'], + data: data, + success: function(data){ + var url_template = askbot['urls']['question_url_template']; + new_question_url = url_template.replace( + '{{QuestionID}}', + data['id'] + ).replace( + '{{questionSlug}}', + data['slug'] + ); + window.location.href = new_question_url; + } + }); + break; + } + } +}; + +$(document).ready(function() { + $('[id^="comments-for-"]').each(function(index, element){ + var comments = new PostCommentsWidget(); + comments.decorate(element); + }); + $('[id^="swap-question-with-answer-"]').each(function(idx, element){ + var swapper = new QASwapper(); + swapper.decorate($(element)); + }); + questionRetagger.init(); + socialSharing.init(); +}); + + +/* +Prettify +http://www.apache.org/licenses/LICENSE-2.0 +*/ +var PR_SHOULD_USE_CONTINUATION = true; var PR_TAB_WIDTH = 8; var PR_normalizedHtml; var PR; var prettyPrintOne; var prettyPrint; function _pr_isIE6() { var isIE6 = navigator && navigator.userAgent && /\bMSIE 6\./.test(navigator.userAgent); _pr_isIE6 = function() { return isIE6; }; return isIE6; } (function() { function wordSet(words) { words = words.split(/ /g); var set = {}; for (var i = words.length; --i >= 0; ) { var w = words[i]; if (w) { set[w] = null; } } return set; } var FLOW_CONTROL_KEYWORDS = "break continue do else for if return while "; var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " + "double enum extern float goto int long register short signed sizeof " + "static struct switch typedef union unsigned void volatile "; var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " + "new operator private protected public this throw true try "; var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " + "concept concept_map const_cast constexpr decltype " + "dynamic_cast explicit export friend inline late_check " + "mutable namespace nullptr reinterpret_cast static_assert static_cast " + "template typeid typename typeof using virtual wchar_t where "; var JAVA_KEYWORDS = COMMON_KEYWORDS + "boolean byte extends final finally implements import instanceof null " + "native package strictfp super synchronized throws transient "; var CSHARP_KEYWORDS = JAVA_KEYWORDS + "as base by checked decimal delegate descending event " + "fixed foreach from group implicit in interface internal into is lock " + "object out override orderby params readonly ref sbyte sealed " + "stackalloc string select uint ulong unchecked unsafe ushort var "; var JSCRIPT_KEYWORDS = COMMON_KEYWORDS + "debugger eval export function get null set undefined var with " + "Infinity NaN "; var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " + "goto if import last local my next no our print package redo require " + "sub undef unless until use wantarray while BEGIN END "; var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " + "elif except exec finally from global import in is lambda " + "nonlocal not or pass print raise try with yield " + "False True None "; var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" + " defined elsif end ensure false in module next nil not or redo rescue " + "retry self super then true undef unless until when yield BEGIN END "; var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " + "function in local set then until "; var ALL_KEYWORDS = (CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS + PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS); var PR_STRING = 'str'; var PR_KEYWORD = 'kwd'; var PR_COMMENT = 'com'; var PR_TYPE = 'typ'; var PR_LITERAL = 'lit'; var PR_PUNCTUATION = 'pun'; var PR_PLAIN = 'pln'; var PR_TAG = 'tag'; var PR_DECLARATION = 'dec'; var PR_SOURCE = 'src'; var PR_ATTRIB_NAME = 'atn'; var PR_ATTRIB_VALUE = 'atv'; var PR_NOCODE = 'nocode'; function isWordChar(ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); } function spliceArrayInto(inserted, container, containerPosition, countReplaced) { inserted.unshift(containerPosition, countReplaced || 0); try { container.splice.apply(container, inserted); } finally { inserted.splice(0, 2); } } var REGEXP_PRECEDER_PATTERN = function() { var preceders = ["!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=", "&=", "(", "*", "*=", "+=", ",", "-=", "->", "/", "/=", ":", "::", ";", "<", "<<", "<<=", "<=", "=", "==", "===", ">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", "^", "^=", "^^", "^^=", "{", "|", "|=", "||", "||=", "~", "break", "case", "continue", "delete", "do", "else", "finally", "instanceof", "return", "throw", "try", "typeof"]; var pattern = '(?:' + '(?:(?:^|[^0-9.])\\.{1,3})|' + '(?:(?:^|[^\\+])\\+)|' + '(?:(?:^|[^\\-])-)'; for (var i = 0; i < preceders.length; ++i) { var preceder = preceders[i]; if (isWordChar(preceder.charAt(0))) { pattern += '|\\b' + preceder; } else { pattern += '|' + preceder.replace(/([^=<>:&])/g, '\\$1'); } } pattern += '|^)\\s*$'; return new RegExp(pattern); } (); var pr_amp = /&/g; var pr_lt = /</g; var pr_gt = />/g; var pr_quot = /\"/g; function attribToHtml(str) { return str.replace(pr_amp, '&').replace(pr_lt, '<').replace(pr_gt, '>').replace(pr_quot, '"'); } function textToHtml(str) { return str.replace(pr_amp, '&').replace(pr_lt, '<').replace(pr_gt, '>'); } var pr_ltEnt = /</g; var pr_gtEnt = />/g; var pr_aposEnt = /'/g; var pr_quotEnt = /"/g; var pr_ampEnt = /&/g; var pr_nbspEnt = / /g; function htmlToText(html) { var pos = html.indexOf('&'); if (pos < 0) { return html; } for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0; ) { var end = html.indexOf(';', pos); if (end >= 0) { var num = html.substring(pos + 3, end); var radix = 10; if (num && num.charAt(0) === 'x') { num = num.substring(1); radix = 16; } var codePoint = parseInt(num, radix); if (!isNaN(codePoint)) { html = (html.substring(0, pos) + String.fromCharCode(codePoint) + html.substring(end + 1)); } } } return html.replace(pr_ltEnt, '<').replace(pr_gtEnt, '>').replace(pr_aposEnt, "'").replace(pr_quotEnt, '"').replace(pr_ampEnt, '&').replace(pr_nbspEnt, ' '); } function isRawContent(node) { return 'XMP' === node.tagName; } function normalizedHtml(node, out) { switch (node.nodeType) { case 1: var name = node.tagName.toLowerCase(); out.push('<', name); for (var i = 0; i < node.attributes.length; ++i) { var attr = node.attributes[i]; if (!attr.specified) { continue; } out.push(' '); normalizedHtml(attr, out); } out.push('>'); for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } if (node.firstChild || !/^(?:br|link|img)$/.test(name)) { out.push('<\/', name, '>'); } break; case 2: out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"'); break; case 3: case 4: out.push(textToHtml(node.nodeValue)); break; } } var PR_innerHtmlWorks = null; function getInnerHtml(node) { if (null === PR_innerHtmlWorks) { var testNode = document.createElement('PRE'); testNode.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />')); PR_innerHtmlWorks = !/</.test(testNode.innerHTML); } if (PR_innerHtmlWorks) { var content = node.innerHTML; if (isRawContent(node)) { content = textToHtml(content); } return content; } var out = []; for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } return out.join(''); } function makeTabExpander(tabWidth) { var SPACES = ' '; var charInLine = 0; return function(plainText) { var out = null; var pos = 0; for (var i = 0, n = plainText.length; i < n; ++i) { var ch = plainText.charAt(i); switch (ch) { case '\t': if (!out) { out = []; } out.push(plainText.substring(pos, i)); var nSpaces = tabWidth - (charInLine % tabWidth); charInLine += nSpaces; for (; nSpaces >= 0; nSpaces -= SPACES.length) { out.push(SPACES.substring(0, nSpaces)); } pos = i + 1; break; case '\n': charInLine = 0; break; default: ++charInLine; } } if (!out) { return plainText; } out.push(plainText.substring(pos)); return out.join(''); }; } var pr_chunkPattern = /(?:[^<]+|<!--[\s\S]*?-->|<!\[CDATA\[([\s\S]*?)\]\]>|<\/?[a-zA-Z][^>]*>|<)/g; var pr_commentPrefix = /^<!--/; var pr_cdataPrefix = /^<\[CDATA\[/; var pr_brPrefix = /^<br\b/i; var pr_tagNameRe = /^<(\/?)([a-zA-Z]+)/; function extractTags(s) { var matches = s.match(pr_chunkPattern); var sourceBuf = []; var sourceBufLen = 0; var extractedTags = []; if (matches) { for (var i = 0, n = matches.length; i < n; ++i) { var match = matches[i]; if (match.length > 1 && match.charAt(0) === '<') { if (pr_commentPrefix.test(match)) { continue; } if (pr_cdataPrefix.test(match)) { sourceBuf.push(match.substring(9, match.length - 3)); sourceBufLen += match.length - 12; } else if (pr_brPrefix.test(match)) { sourceBuf.push('\n'); ++sourceBufLen; } else { if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) { var name = match.match(pr_tagNameRe)[2]; var depth = 1; end_tag_loop: for (var j = i + 1; j < n; ++j) { var name2 = matches[j].match(pr_tagNameRe); if (name2 && name2[2] === name) { if (name2[1] === '/') { if (--depth === 0) { break end_tag_loop; } } else { ++depth; } } } if (j < n) { extractedTags.push(sourceBufLen, matches.slice(i, j + 1).join('')); i = j; } else { extractedTags.push(sourceBufLen, match); } } else { extractedTags.push(sourceBufLen, match); } } } else { var literalText = htmlToText(match); sourceBuf.push(literalText); sourceBufLen += literalText.length; } } } return { source: sourceBuf.join(''), tags: extractedTags }; } function isNoCodeTag(tag) { return !!tag.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g, ' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/); } function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) { var shortcuts = {}; (function() { var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns); for (var i = allPatterns.length; --i >= 0; ) { var patternParts = allPatterns[i]; var shortcutChars = patternParts[3]; if (shortcutChars) { for (var c = shortcutChars.length; --c >= 0; ) { shortcuts[shortcutChars.charAt(c)] = patternParts; } } } })(); var nPatterns = fallthroughStylePatterns.length; var notWs = /\S/; return function(sourceCode, opt_basePos) { opt_basePos = opt_basePos || 0; var decorations = [opt_basePos, PR_PLAIN]; var lastToken = ''; var pos = 0; var tail = sourceCode; while (tail.length) { var style; var token = null; var match; var patternParts = shortcuts[tail.charAt(0)]; if (patternParts) { match = tail.match(patternParts[1]); token = match[0]; style = patternParts[0]; } else { for (var i = 0; i < nPatterns; ++i) { patternParts = fallthroughStylePatterns[i]; var contextPattern = patternParts[2]; if (contextPattern && !contextPattern.test(lastToken)) { continue; } match = tail.match(patternParts[1]); if (match) { token = match[0]; style = patternParts[0]; break; } } if (!token) { style = PR_PLAIN; token = tail.substring(0, 1); } } decorations.push(opt_basePos + pos, style); pos += token.length; tail = tail.substring(token.length); if (style !== PR_COMMENT && notWs.test(token)) { lastToken = token; } } return decorations; }; } var PR_MARKUP_LEXER = createSimpleLexer([], [[PR_PLAIN, /^[^<]+/, null], [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/, null], [PR_COMMENT, /^<!--[\s\S]*?(?:-->|$)/, null], [PR_SOURCE, /^<\?[\s\S]*?(?:\?>|$)/, null], [PR_SOURCE, /^<%[\s\S]*?(?:%>|$)/, null], [PR_SOURCE, /^<(script|style|xmp)\b[^>]*>[\s\S]*?<\/\1\b[^>]*>/i, null], [PR_TAG, /^<\/?\w[^<>]*>/, null]]); var PR_SOURCE_CHUNK_PARTS = /^(<[^>]*>)([\s\S]*)(<\/[^>]*>)$/; function tokenizeMarkup(source) { var decorations = PR_MARKUP_LEXER(source); for (var i = 0; i < decorations.length; i += 2) { if (decorations[i + 1] === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var sourceChunk = source.substring(start, end); var match = sourceChunk.match(PR_SOURCE_CHUNK_PARTS); if (match) { decorations.splice(i, 2, start, PR_TAG, start + match[1].length, PR_SOURCE, start + match[1].length + (match[2] || '').length, PR_TAG); } } } return decorations; } var PR_TAG_LEXER = createSimpleLexer([[PR_ATTRIB_VALUE, /^\'[^\']*(?:\'|$)/, null, "'"], [PR_ATTRIB_VALUE, /^\"[^\"]*(?:\"|$)/, null, '"'], [PR_PUNCTUATION, /^[<>\/=]+/, null, '<>/=']], [[PR_TAG, /^[\w:\-]+/, /^</], [PR_ATTRIB_VALUE, /^[\w\-]+/, /^=/], [PR_ATTRIB_NAME, /^[\w:\-]+/, null], [PR_PLAIN, /^\s+/, null, ' \t\r\n']]); function splitTagAttributes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_TAG) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var chunk = source.substring(start, end); var subDecorations = PR_TAG_LEXER(chunk, start); spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function sourceDecorator(options) { var shortcutStylePatterns = [], fallthroughStylePatterns = []; if (options.tripleQuotedStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, null, '\'"']); } else if (options.multiLineStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, null, '\'"`']); } else { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, null, '"\'']); } fallthroughStylePatterns.push([PR_PLAIN, /^(?:[^\'\"\`\/\#]+)/, null, ' \r\n']); if (options.hashComments) { shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']); } if (options.cStyleComments) { fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]); fallthroughStylePatterns.push([PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); } if (options.regexLiterals) { var REGEX_LITERAL = ('^/(?=[^/*])' + '(?:[^/\\x5B\\x5C]' + '|\\x5C[\\s\\S]' + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+' + '(?:/|$)'); fallthroughStylePatterns.push([PR_STRING, new RegExp(REGEX_LITERAL), REGEXP_PRECEDER_PATTERN]); } var keywords = wordSet(options.keywords); options = null; var splitStringAndCommentTokens = createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns); var styleLiteralIdentifierPuncRecognizer = createSimpleLexer([], [[PR_PLAIN, /^\s+/, null, ' \r\n'], [PR_PLAIN, /^[a-z_$@][a-z_$@0-9]*/i, null], [PR_LITERAL, /^0x[a-f0-9]+[a-z]/i, null], [PR_LITERAL, /^(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?[a-z]*/i, null, '123456789'], [PR_PUNCTUATION, /^[^\s\w\.$@]+/, null]]); function splitNonStringNonCommentTokens(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_PLAIN) { var start, end, chunk, subDecs; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; chunk = source.substring(start, end); subDecs = styleLiteralIdentifierPuncRecognizer(chunk, start); for (var j = 0, m = subDecs.length; j < m; j += 2) { var subStyle = subDecs[j + 1]; if (subStyle === PR_PLAIN) { var subStart = subDecs[j]; var subEnd = j + 2 < m ? subDecs[j + 2] : chunk.length; var token = source.substring(subStart, subEnd); if (token === '.') { subDecs[j + 1] = PR_PUNCTUATION; } else if (token in keywords) { subDecs[j + 1] = PR_KEYWORD; } else if (/^@?[A-Z][A-Z$]*[a-z][A-Za-z$]*$/.test(token)) { subDecs[j + 1] = token.charAt(0) === '@' ? PR_LITERAL : PR_TYPE; } } } spliceArrayInto(subDecs, decorations, i, 2); i += subDecs.length - 2; } } return decorations; } return function(sourceCode) { var decorations = splitStringAndCommentTokens(sourceCode); decorations = splitNonStringNonCommentTokens(sourceCode, decorations); return decorations; }; } var decorateSource = sourceDecorator({ keywords: ALL_KEYWORDS, hashComments: true, cStyleComments: true, multiLineStrings: true, regexLiterals: true }); function splitSourceNodes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var subDecorations = decorateSource(source.substring(start, end)); for (var j = 0, m = subDecorations.length; j < m; j += 2) { subDecorations[j] += start; } spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function splitSourceAttributes(source, decorations) { var nextValueIsSource = false; for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; var start, end; if (style === PR_ATTRIB_NAME) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; nextValueIsSource = /^on|^style$/i.test(source.substring(start, end)); } else if (style === PR_ATTRIB_VALUE) { if (nextValueIsSource) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var attribValue = source.substring(start, end); var attribLen = attribValue.length; var quoted = (attribLen >= 2 && /^[\"\']/.test(attribValue) && attribValue.charAt(0) === attribValue.charAt(attribLen - 1)); var attribSource; var attribSourceStart; var attribSourceEnd; if (quoted) { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue; } else { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue.substring(1, attribValue.length - 1); } var attribSourceDecorations = decorateSource(attribSource); for (var j = 0, m = attribSourceDecorations.length; j < m; j += 2) { attribSourceDecorations[j] += attribSourceStart; } if (quoted) { attribSourceDecorations.push(attribSourceEnd, PR_ATTRIB_VALUE); spliceArrayInto(attribSourceDecorations, decorations, i + 2, 0); } else { spliceArrayInto(attribSourceDecorations, decorations, i, 2); } } nextValueIsSource = false; } } return decorations; } function decorateMarkup(sourceCode) { var decorations = tokenizeMarkup(sourceCode); decorations = splitTagAttributes(sourceCode, decorations); decorations = splitSourceNodes(sourceCode, decorations); decorations = splitSourceAttributes(sourceCode, decorations); return decorations; } function recombineTagsAndDecorations(sourceText, extractedTags, decorations) { var html = []; var outputIdx = 0; var openDecoration = null; var currentDecoration = null; var tagPos = 0; var decPos = 0; var tabExpander = makeTabExpander(PR_TAB_WIDTH); var adjacentSpaceRe = /([\r\n ]) /g; var startOrSpaceRe = /(^| ) /gm; var newlineRe = /\r\n?|\n/g; var trailingSpaceRe = /[ \r\n]$/; var lastWasSpace = true; function emitTextUpTo(sourceIdx) { if (sourceIdx > outputIdx) { if (openDecoration && openDecoration !== currentDecoration) { html.push('</span>'); openDecoration = null; } if (!openDecoration && currentDecoration) { openDecoration = currentDecoration; html.push('<span class="', openDecoration, '">'); } var htmlChunk = textToHtml(tabExpander(sourceText.substring(outputIdx, sourceIdx))).replace(lastWasSpace ? startOrSpaceRe : adjacentSpaceRe, '$1 '); lastWasSpace = trailingSpaceRe.test(htmlChunk); html.push(htmlChunk.replace(newlineRe, '<br />')); outputIdx = sourceIdx; } } while (true) { var outputTag; if (tagPos < extractedTags.length) { if (decPos < decorations.length) { outputTag = extractedTags[tagPos] <= decorations[decPos]; } else { outputTag = true; } } else { outputTag = false; } if (outputTag) { emitTextUpTo(extractedTags[tagPos]); if (openDecoration) { html.push('</span>'); openDecoration = null; } html.push(extractedTags[tagPos + 1]); tagPos += 2; } else if (decPos < decorations.length) { emitTextUpTo(decorations[decPos]); currentDecoration = decorations[decPos + 1]; decPos += 2; } else { break; } } emitTextUpTo(sourceText.length); if (openDecoration) { html.push('</span>'); } return html.join(''); } var langHandlerRegistry = {}; function registerLangHandler(handler, fileExtensions) { for (var i = fileExtensions.length; --i >= 0; ) { var ext = fileExtensions[i]; if (!langHandlerRegistry.hasOwnProperty(ext)) { langHandlerRegistry[ext] = handler; } else if ('console' in window) { console.log('cannot override language handler %s', ext); } } } registerLangHandler(decorateSource, ['default-code']); registerLangHandler(decorateMarkup, ['default-markup', 'html', 'htm', 'xhtml', 'xml', 'xsl']); registerLangHandler(sourceDecorator({ keywords: CPP_KEYWORDS, hashComments: true, cStyleComments: true }), ['c', 'cc', 'cpp', 'cs', 'cxx', 'cyc']); registerLangHandler(sourceDecorator({ keywords: JAVA_KEYWORDS, cStyleComments: true }), ['java']); registerLangHandler(sourceDecorator({ keywords: SH_KEYWORDS, hashComments: true, multiLineStrings: true }), ['bsh', 'csh', 'sh']); registerLangHandler(sourceDecorator({ keywords: PYTHON_KEYWORDS, hashComments: true, multiLineStrings: true, tripleQuotedStrings: true }), ['cv', 'py']); registerLangHandler(sourceDecorator({ keywords: PERL_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['perl', 'pl', 'pm']); registerLangHandler(sourceDecorator({ keywords: RUBY_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['rb']); registerLangHandler(sourceDecorator({ keywords: JSCRIPT_KEYWORDS, cStyleComments: true, regexLiterals: true }), ['js']); function prettyPrintOne(sourceCodeHtml, opt_langExtension) { try { var sourceAndExtractedTags = extractTags(sourceCodeHtml); var source = sourceAndExtractedTags.source; var extractedTags = sourceAndExtractedTags.tags; if (!langHandlerRegistry.hasOwnProperty(opt_langExtension)) { opt_langExtension = /^\s*</.test(source) ? 'default-markup' : 'default-code'; } var decorations = langHandlerRegistry[opt_langExtension].call({}, source); return recombineTagsAndDecorations(source, extractedTags, decorations); } catch (e) { if ('console' in window) { console.log(e); console.trace(); } return sourceCodeHtml; } } function prettyPrint(opt_whenDone) { var isIE6 = _pr_isIE6(); var codeSegments = [document.getElementsByTagName('pre'), document.getElementsByTagName('code'), document.getElementsByTagName('xmp')]; var elements = []; for (var i = 0; i < codeSegments.length; ++i) { for (var j = 0; j < codeSegments[i].length; ++j) { elements.push(codeSegments[i][j]); } } codeSegments = null; var k = 0; function doWork() { var endTime = (PR_SHOULD_USE_CONTINUATION ? new Date().getTime() + 250 : Infinity); for (; k < elements.length && new Date().getTime() < endTime; k++) { var cs = elements[k]; if (cs.className && cs.className.indexOf('prettyprint') >= 0) { var langExtension = cs.className.match(/\blang-(\w+)\b/); if (langExtension) { langExtension = langExtension[1]; } var nested = false; for (var p = cs.parentNode; p; p = p.parentNode) { if ((p.tagName === 'pre' || p.tagName === 'code' || p.tagName === 'xmp') && p.className && p.className.indexOf('prettyprint') >= 0) { nested = true; break; } } if (!nested) { var content = getInnerHtml(cs); content = content.replace(/(?:\r\n?|\n)$/, ''); var newContent = prettyPrintOne(content, langExtension); if (!isRawContent(cs)) { cs.innerHTML = newContent; } else { var pre = document.createElement('PRE'); for (var i = 0; i < cs.attributes.length; ++i) { var a = cs.attributes[i]; if (a.specified) { var aname = a.name.toLowerCase(); if (aname === 'class') { pre.className = a.value; } else { pre.setAttribute(a.name, a.value); } } } pre.innerHTML = newContent; cs.parentNode.replaceChild(pre, cs); cs = pre; } if (isIE6 && cs.tagName === 'PRE') { var lineBreaks = cs.getElementsByTagName('br'); for (var j = lineBreaks.length; --j >= 0; ) { var lineBreak = lineBreaks[j]; lineBreak.parentNode.replaceChild(document.createTextNode('\r\n'), lineBreak); } } } } } if (k < elements.length) { setTimeout(doWork, 250); } else if (opt_whenDone) { opt_whenDone(); } } doWork(); } window['PR_normalizedHtml'] = normalizedHtml; window['prettyPrintOne'] = prettyPrintOne; window['prettyPrint'] = prettyPrint; window['PR'] = { 'createSimpleLexer': createSimpleLexer, 'registerLangHandler': registerLangHandler, 'sourceDecorator': sourceDecorator, 'PR_ATTRIB_NAME': PR_ATTRIB_NAME, 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE, 'PR_COMMENT': PR_COMMENT, 'PR_DECLARATION': PR_DECLARATION, 'PR_KEYWORD': PR_KEYWORD, 'PR_LITERAL': PR_LITERAL, 'PR_NOCODE': PR_NOCODE, 'PR_PLAIN': PR_PLAIN, 'PR_PUNCTUATION': PR_PUNCTUATION, 'PR_SOURCE': PR_SOURCE, 'PR_STRING': PR_STRING, 'PR_TAG': PR_TAG, 'PR_TYPE': PR_TYPE }; })(); diff --git a/askbot/skins/old/media/js/se_hilite.js b/askbot/skins/old/media/js/se_hilite.js new file mode 100644 index 00000000..42e99c8e --- /dev/null +++ b/askbot/skins/old/media/js/se_hilite.js @@ -0,0 +1 @@ +Hilite={elementid:"content",exact:true,max_nodes:1000,onload:true,style_name:"hilite",style_name_suffix:true,debug_referrer:""};Hilite.search_engines=[["google\\.","q"],["search\\.yahoo\\.","p"],["search\\.msn\\.","q"],["search\\.live\\.","query"],["search\\.aol\\.","userQuery"],["ask\\.com","q"],["altavista\\.","q"],["feedster\\.","q"],["search\\.lycos\\.","q"],["alltheweb\\.","q"],["technorati\\.com/search/([^\\?/]+)",1],["dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)",1,true]];Hilite.decodeReferrer=function(d){var g=null;var e=new RegExp("");for(var c=0;c<Hilite.search_engines.length;c++){var f=Hilite.search_engines[c];e.compile("^http://(www\\.)?"+f[0],"i");var b=d.match(e);if(b){var a;if(isNaN(f[1])){a=Hilite.decodeReferrerQS(d,f[1])}else{a=b[f[1]+1]}if(a){a=decodeURIComponent(a);if(f.length>2&&f[2]){a=decodeURIComponent(a)}a=a.replace(/\'|"/g,"");a=a.split(/[\s,\+\.]+/);return a}break}}return null};Hilite.decodeReferrerQS=function(f,d){var b=f.indexOf("?");var c;if(b>=0){var a=new String(f.substring(b+1));b=0;c=0;while((b>=0)&&((c=a.indexOf("=",b))>=0)){var e,g;e=a.substring(b,c);b=a.indexOf("&",c)+1;if(e==d){if(b<=0){return a.substring(c+1)}else{return a.substring(c+1,b-1)}}else{if(b<=0){return null}}}}return null};Hilite.hiliteElement=function(f,e){if(!e||f.childNodes.length==0){return}var c=new Array();for(var b=0;b<e.length;b++){e[b]=e[b].toLowerCase();if(Hilite.exact){c.push("\\b"+e[b]+"\\b")}else{c.push(e[b])}}c=new RegExp(c.join("|"),"i");var a={};for(var b=0;b<e.length;b++){if(Hilite.style_name_suffix){a[e[b]]=Hilite.style_name+(b+1)}else{a[e[b]]=Hilite.style_name}}var d=function(m){var j=c.exec(m.data);if(j){var n=j[0];var i="";var h=m.splitText(j.index);var g=h.splitText(n.length);var l=m.ownerDocument.createElement("SPAN");m.parentNode.replaceChild(l,h);l.className=a[n.toLowerCase()];l.appendChild(h);return l}else{return m}};Hilite.walkElements(f.childNodes[0],1,d)};Hilite.hilite=function(){var a=Hilite.debug_referrer?Hilite.debug_referrer:document.referrer;var b=null;a=Hilite.decodeReferrer(a);if(a&&((Hilite.elementid&&(b=document.getElementById(Hilite.elementid)))||(b=document.body))){Hilite.hiliteElement(b,a)}};Hilite.walkElements=function(d,f,e){var a=/^(script|style|textarea)/i;var c=0;while(d&&f>0){c++;if(c>=Hilite.max_nodes){var b=function(){Hilite.walkElements(d,f,e)};setTimeout(b,50);return}if(d.nodeType==1){if(!a.test(d.tagName)&&d.childNodes.length>0){d=d.childNodes[0];f++;continue}}else{if(d.nodeType==3){d=e(d)}}if(d.nextSibling){d=d.nextSibling}else{while(f>0){d=d.parentNode;f--;if(d.nextSibling){d=d.nextSibling;break}}}}};if(Hilite.onload){if(window.attachEvent){window.attachEvent("onload",Hilite.hilite)}else{if(window.addEventListener){window.addEventListener("load",Hilite.hilite,false)}else{var __onload=window.onload;window.onload=function(){Hilite.hilite();__onload()}}}};
\ No newline at end of file diff --git a/askbot/skins/old/media/js/se_hilite_src.js b/askbot/skins/old/media/js/se_hilite_src.js new file mode 100644 index 00000000..b604f156 --- /dev/null +++ b/askbot/skins/old/media/js/se_hilite_src.js @@ -0,0 +1,273 @@ +/** + * Search Engine Keyword Highlight (http://fucoder.com/code/se-hilite/) + * + * This module can be imported by any HTML page, and it would analyse the + * referrer for search engine keywords, and then highlight those keywords on + * the page, by wrapping them around <span class="hilite">...</span> tags. + * Document can then define styles else where to provide visual feedbacks. + * + * Usage: + * + * In HTML. Add the following line towards the end of the document. + * + * <script type="text/javascript" src="se_hilite.js"></script> + * + * In CSS, define the following style: + * + * .hilite { background-color: #ff0; } + * + * If Hilite.style_name_suffix is true, then define the follow styles: + * + * .hilite1 { background-color: #ff0; } + * .hilite2 { background-color: #f0f; } + * .hilite3 { background-color: #0ff; } + * .hilite4 ... + * + * @author Scott Yang <http://scott.yang.id.au/> + * @version 1.5 + */ + +// Configuration: +Hilite = { + /** + * Element ID to be highlighted. If set, then only content inside this DOM + * element will be highlighted, otherwise everything inside document.body + * will be searched. + */ + elementid: 'content', + + /** + * Whether we are matching an exact word. For example, searching for + * "highlight" will only match "highlight" but not "highlighting" if exact + * is set to true. + */ + exact: true, + + /** + * Maximum number of DOM nodes to test, before handing the control back to + * the GUI thread. This prevents locking up the UI when parsing and + * replacing inside a large document. + */ + max_nodes: 1000, + + /** + * Whether to automatically hilite a section of the HTML document, by + * binding the "Hilite.hilite()" to window.onload() event. If this + * attribute is set to false, you can still manually trigger the hilite by + * calling Hilite.hilite() in Javascript after document has been fully + * loaded. + */ + onload: true, + + /** + * Name of the style to be used. Default to 'hilite'. + */ + style_name: 'hilite', + + /** + * Whether to use different style names for different search keywords by + * appending a number starting from 1, i.e. hilite1, hilite2, etc. + */ + style_name_suffix: true, + + /** + * Set it to override the document.referrer string. Used for debugging + * only. + */ + debug_referrer: '' +}; + +Hilite.search_engines = [ + ['google\\.', 'q'], // Google + ['search\\.yahoo\\.', 'p'], // Yahoo + ['search\\.msn\\.', 'q'], // MSN + ['search\\.live\\.', 'query'], // MSN Live + ['search\\.aol\\.', 'userQuery'], // AOL + ['ask\\.com', 'q'], // Ask.com + ['altavista\\.', 'q'], // AltaVista + ['feedster\\.', 'q'], // Feedster + ['search\\.lycos\\.', 'q'], // Lycos + ['alltheweb\\.', 'q'], // AllTheWeb + ['technorati\\.com/search/([^\\?/]+)', 1], // Technorati + ['dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)', 1, true] // DogPile +]; + +/** + * Decode the referrer string and return a list of search keywords. + */ +Hilite.decodeReferrer = function(referrer) { + var query = null; + var regex = new RegExp(''); + + for (var i = 0; i < Hilite.search_engines.length; i ++) { + var se = Hilite.search_engines[i]; + regex.compile('^http://(www\\.)?' + se[0], 'i'); + var match = referrer.match(regex); + if (match) { + var result; + if (isNaN(se[1])) { + result = Hilite.decodeReferrerQS(referrer, se[1]); + } else { + result = match[se[1] + 1]; + } + if (result) { + result = decodeURIComponent(result); + // XXX: DogPile's URI requires decoding twice. + if (se.length > 2 && se[2]) + result = decodeURIComponent(result); + result = result.replace(/\'|"/g, ''); + result = result.split(/[\s,\+\.]+/); + return result; + } + break; + } + } + return null; +}; + +Hilite.decodeReferrerQS = function(referrer, match) { + var idx = referrer.indexOf('?'); + var idx2; + if (idx >= 0) { + var qs = new String(referrer.substring(idx + 1)); + idx = 0; + idx2 = 0; + while ((idx >= 0) && ((idx2 = qs.indexOf('=', idx)) >= 0)) { + var key, val; + key = qs.substring(idx, idx2); + idx = qs.indexOf('&', idx2) + 1; + if (key == match) { + if (idx <= 0) { + return qs.substring(idx2+1); + } else { + return qs.substring(idx2+1, idx - 1); + } + } + else if (idx <=0) { + return null; + } + } + } + return null; +}; + +/** + * Highlight a DOM element with a list of keywords. + */ +Hilite.hiliteElement = function(elm, query) { + if (!query || elm.childNodes.length == 0) + return; + + var qre = new Array(); + for (var i = 0; i < query.length; i ++) { + query[i] = query[i].toLowerCase(); + if (Hilite.exact) + qre.push('\\b'+query[i]+'\\b'); + else + qre.push(query[i]); + } + + qre = new RegExp(qre.join("|"), "i"); + + var stylemapper = {}; + for (var i = 0; i < query.length; i ++) { + if (Hilite.style_name_suffix) + stylemapper[query[i]] = Hilite.style_name+(i+1); + else + stylemapper[query[i]] = Hilite.style_name; + } + + var textproc = function(node) { + var match = qre.exec(node.data); + if (match) { + var val = match[0]; + var k = ''; + var node2 = node.splitText(match.index); + var node3 = node2.splitText(val.length); + var span = node.ownerDocument.createElement('SPAN'); + node.parentNode.replaceChild(span, node2); + span.className = stylemapper[val.toLowerCase()]; + span.appendChild(node2); + return span; + } else { + return node; + } + }; + Hilite.walkElements(elm.childNodes[0], 1, textproc); +}; + +/** + * Highlight a HTML document using keywords extracted from document.referrer. + * This is the main function to be called to perform search engine highlight + * on a document. + * + * Currently it would check for DOM element 'content', element 'container' and + * then document.body in that order, so it only highlights appropriate section + * on WordPress and Movable Type pages. + */ +Hilite.hilite = function() { + // If 'debug_referrer' then we will use that as our referrer string + // instead. + var q = Hilite.debug_referrer ? Hilite.debug_referrer : document.referrer; + var e = null; + q = Hilite.decodeReferrer(q); + if (q && ((Hilite.elementid && + (e = document.getElementById(Hilite.elementid))) || + (e = document.body))) + { + Hilite.hiliteElement(e, q); + } +}; + +Hilite.walkElements = function(node, depth, textproc) { + var skipre = /^(script|style|textarea)/i; + var count = 0; + while (node && depth > 0) { + count ++; + if (count >= Hilite.max_nodes) { + var handler = function() { + Hilite.walkElements(node, depth, textproc); + }; + setTimeout(handler, 50); + return; + } + + if (node.nodeType == 1) { // ELEMENT_NODE + if (!skipre.test(node.tagName) && node.childNodes.length > 0) { + node = node.childNodes[0]; + depth ++; + continue; + } + } else if (node.nodeType == 3) { // TEXT_NODE + node = textproc(node); + } + + if (node.nextSibling) { + node = node.nextSibling; + } else { + while (depth > 0) { + node = node.parentNode; + depth --; + if (node.nextSibling) { + node = node.nextSibling; + break; + } + } + } + } +}; + +// Trigger the highlight using the onload handler. +if (Hilite.onload) { + if (window.attachEvent) { + window.attachEvent('onload', Hilite.hilite); + } else if (window.addEventListener) { + window.addEventListener('load', Hilite.hilite, false); + } else { + var __onload = window.onload; + window.onload = function() { + Hilite.hilite(); + __onload(); + }; + } +} diff --git a/askbot/skins/old/media/js/tag_selector.js b/askbot/skins/old/media/js/tag_selector.js new file mode 100644 index 00000000..659c157b --- /dev/null +++ b/askbot/skins/old/media/js/tag_selector.js @@ -0,0 +1,375 @@ + +var TagDetailBox = function(box_type){ + WrappedElement.call(this); + this.box_type = box_type; + this._is_blank = true; + this._tags = new Array(); + this.wildcard = undefined; +}; +inherits(TagDetailBox, WrappedElement); + +TagDetailBox.prototype.createDom = function(){ + this._element = this.makeElement('div'); + this._element.addClass('wildcard-tags'); + this._headline = this.makeElement('p'); + this._headline.html(gettext('Tag "<span></span>" matches:')); + this._element.append(this._headline); + this._tag_list_element = this.makeElement('ul'); + this._tag_list_element.addClass('tags'); + this._element.append(this._tag_list_element); + this._footer = this.makeElement('p'); + this._footer.css('clear', 'left'); + this._element.append(this._footer); + this._element.hide(); +}; + +TagDetailBox.prototype.belongsTo = function(wildcard){ + return (this.wildcard === wildcard); +}; + +TagDetailBox.prototype.isBlank = function(){ + return this._is_blank; +}; + +TagDetailBox.prototype.clear = function(){ + if (this.isBlank()){ + return; + } + this._is_blank = true; + this.getElement().hide(); + this.wildcard = null; + $.each(this._tags, function(idx, item){ + item.dispose(); + }); + this._tags = new Array(); +}; + +TagDetailBox.prototype.loadTags = function(wildcard, callback){ + var me = this; + $.ajax({ + type: 'GET', + dataType: 'json', + cache: false, + url: askbot['urls']['get_tags_by_wildcard'], + data: { wildcard: wildcard }, + success: callback, + failure: function(){ me._loading = false; } + }); +}; + +TagDetailBox.prototype.renderFor = function(wildcard){ + var me = this; + if (this._loading === true){ + return; + } + this._loading = true; + this.loadTags( + wildcard, + function(data, text_status, xhr){ + me._tag_names = data['tag_names']; + if (data['tag_count'] > 0){ + var wildcard_display = wildcard.replace(/\*$/, '✽'); + me._headline.find('span').html(wildcard_display); + $.each(me._tag_names, function(idx, name){ + var tag = new Tag(); + tag.setName(name); + //tag.setLinkable(false); + me._tags.push(tag); + me._tag_list_element.append(tag.getElement()); + }); + me._is_blank = false; + me.wildcard = wildcard; + var tag_count = data['tag_count']; + if (tag_count > 20){ + var fmts = gettext('and %s more, not shown...'); + var footer_text = interpolate(fmts, [tag_count - 20]); + me._footer.html(footer_text); + me._footer.show(); + } else { + me._footer.hide(); + } + me._element.show(); + } else { + me.clear(); + } + me._loading = false; + } + ); +} + +function pickedTags(){ + + var interestingTags = {}; + var ignoredTags = {}; + var interestingTagDetailBox = new TagDetailBox('interesting'); + var ignoredTagDetailBox = new TagDetailBox('ignored'); + + var sendAjax = function(tagnames, reason, action, callback){ + var url = ''; + if (action == 'add'){ + if (reason == 'good'){ + url = askbot['urls']['mark_interesting_tag']; + } + else { + url = askbot['urls']['mark_ignored_tag']; + } + } + else { + url = askbot['urls']['unmark_tag']; + } + + var call_settings = { + type:'POST', + url:url, + data: JSON.stringify({tagnames: tagnames}), + dataType: 'json' + }; + if (callback !== false){ + call_settings.success = callback; + } + $.ajax(call_settings); + }; + + var unpickTag = function(from_target, tagname, reason, send_ajax){ + //send ajax request to delete tag + var deleteTagLocally = function(){ + from_target[tagname].remove(); + delete from_target[tagname]; + }; + if (send_ajax){ + sendAjax( + [tagname], + reason, + 'remove', + function(){ + deleteTagLocally(); + liveSearch().refresh(); + } + ); + } + else { + deleteTagLocally(); + } + }; + + var getTagList = function(reason){ + var base_selector = '.marked-tags'; + if (reason === 'good'){ + var extra_selector = '.interesting'; + } else { + var extra_selector = '.ignored'; + } + return $(base_selector + extra_selector); + }; + + var getWildcardTagDetailBox = function(reason){ + if (reason === 'good'){ + return interestingTagDetailBox; + } else { + return ignoredTagDetailBox; + } + }; + + var handleWildcardTagClick = function(tag_name, reason){ + var detail_box = getWildcardTagDetailBox(reason); + var tag_box = getTagList(reason); + if (detail_box.isBlank()){ + detail_box.renderFor(tag_name); + } else if (detail_box.belongsTo(tag_name)){ + detail_box.clear();//toggle off + } else { + detail_box.clear();//redraw with new data + detail_box.renderFor(tag_name); + } + if (!detail_box.inDocument()){ + tag_box.after(detail_box.getElement()); + detail_box.enterDocument(); + } + }; + + var renderNewTags = function( + clean_tag_names, + reason, + to_target, + to_tag_container + ){ + $.each(clean_tag_names, function(idx, tag_name){ + var tag = new Tag(); + tag.setName(tag_name); + tag.setDeletable(true); + + if (/\*$/.test(tag_name)){ + tag.setLinkable(false); + var detail_box = getWildcardTagDetailBox(reason); + tag.setHandler(function(){ + handleWildcardTagClick(tag_name, reason); + if (detail_box.belongsTo(tag_name)){ + detail_box.clear(); + } + }); + var delete_handler = function(){ + unpickTag(to_target, tag_name, reason, true); + if (detail_box.belongsTo(tag_name)){ + detail_box.clear(); + } + } + } else { + var delete_handler = function(){ + unpickTag(to_target, tag_name, reason, true); + } + } + + tag.setDeleteHandler(delete_handler); + var tag_element = tag.getElement(); + to_tag_container.append(tag_element); + to_target[tag_name] = tag_element; + }); + }; + + var handlePickedTag = function(reason){ + var to_target = interestingTags; + var from_target = ignoredTags; + var to_tag_container; + if (reason == 'bad'){ + var input_sel = '#ignoredTagInput'; + to_target = ignoredTags; + from_target = interestingTags; + to_tag_container = $('div .tags.ignored'); + } + else if (reason == 'good'){ + var input_sel = '#interestingTagInput'; + to_tag_container = $('div .tags.interesting'); + } + else { + return; + } + + var tagnames = getUniqueWords($(input_sel).attr('value')); + + $.each(tagnames, function(idx, tagname){ + if (tagname in from_target){ + unpickTag(from_target,tagname,reason,false); + } + }); + + var clean_tagnames = []; + $.each(tagnames, function(idx, tagname){ + if (!(tagname in to_target)){ + clean_tagnames.push(tagname); + } + }); + + if (clean_tagnames.length > 0){ + //send ajax request to pick this tag + + sendAjax( + clean_tagnames, + reason, + 'add', + function(){ + renderNewTags( + clean_tagnames, + reason, + to_target, + to_tag_container + ); + $(input_sel).val(''); + liveSearch().refresh(); + } + ); + } + }; + + var collectPickedTags = function(section){ + if (section === 'interesting'){ + var reason = 'good'; + var tag_store = interestingTags; + } + else if (section === 'ignored'){ + var reason = 'bad'; + var tag_store = ignoredTags; + } + else { + return; + } + $('.' + section + '.tags.marked-tags .tag-left').each( + function(i,item){ + var tag = new Tag(); + tag.decorate($(item)); + tag.setDeleteHandler(function(){ + unpickTag( + tag_store, + tag.getName(), + reason, + true + ) + }); + if (tag.isWildcard()){ + tag.setHandler(function(){ + handleWildcardTagClick(tag.getName(), reason) + }); + } + tag_store[tag.getName()] = $(item); + } + ); + }; + + var setupTagFilterControl = function(control_type){ + $('#' + control_type + 'TagFilterControl input') + .unbind('click') + .click(function(){ + $.ajax({ + type: 'POST', + dataType: 'json', + cache: false, + url: askbot['urls']['set_tag_filter_strategy'], + data: { + filter_type: control_type, + filter_value: $(this).val() + }, + success: function(){ + liveSearch().refresh(); + } + }); + }); + }; + + var getResultCallback = function(reason){ + return function(){ + handlePickedTag(reason); + }; + }; + + return { + init: function(){ + collectPickedTags('interesting'); + collectPickedTags('ignored'); + setupTagFilterControl('display'); + var ac = new AutoCompleter({ + url: askbot['urls']['get_tag_list'], + preloadData: true, + minChars: 1, + useCache: true, + matchInside: true, + maxCacheLength: 100, + delay: 10 + }); + + + var interestingTagAc = $.extend(true, {}, ac); + interestingTagAc.decorate($('#interestingTagInput')); + interestingTagAc.setOption('onItemSelect', getResultCallback('good')); + + var ignoredTagAc = $.extend(true, {}, ac); + ignoredTagAc.decorate($('#ignoredTagInput')); + ignoredTagAc.setOption('onItemSelect', getResultCallback('bad')); + + $("#interestingTagAdd").click(getResultCallback('good')); + $("#ignoredTagAdd").click(getResultCallback('bad')); + } + }; +} + +$(document).ready( function(){ + pickedTags().init(); +}); diff --git a/askbot/skins/old/media/js/user.js b/askbot/skins/old/media/js/user.js new file mode 100644 index 00000000..438a3273 --- /dev/null +++ b/askbot/skins/old/media/js/user.js @@ -0,0 +1,185 @@ +$(document).ready(function(){ + + var getSelected = function(){ + + var id_list = new Array(); + var elements = $('#responses input:checked').parent(); + + elements.each(function(index, element){ + var id = $(element).attr('id').replace(/^re_/,''); + id_list.push(id); + }); + + if (id_list.length === 0){ + alert($.i18n._('Please select at least one item')); + } + + return {id_list: id_list, elements: elements}; + }; + + var submit = function(id_list, elements, action_type){ + if (action_type == 'delete' || action_type == 'mark_new' || action_type == 'mark_seen'){ + $.ajax({ + type: 'POST', + cache: false, + dataType: 'json', + data: JSON.stringify({memo_list: id_list, action_type: action_type}), + url: askbot['urls']['manageInbox'], + success: function(response_data){ + if (response_data['success'] === true){ + if (action_type == 'delete'){ + elements.remove(); + } + else if (action_type == 'mark_new'){ + elements.addClass('highlight'); + elements.addClass('new'); + elements.removeClass('seen'); + } + else if (action_type == 'mark_seen'){ + elements.removeClass('highlight'); + elements.addClass('seen'); + elements.removeClass('new'); + } + } + else { + showMessage($('#responses'), response_data['message']); + } + } + }); + } + }; + + var startAction = function(action_type){ + var data = getSelected(); + if (data['id_list'].length === 0){ + return; + } + if (action_type == 'delete'){ + if (data['id_list'].length === 1){ + var msg = $.i18n._('Delete this notification?') + } + else { + var msg = $.i18n._('Delete these notifications?') + } + if (confirm(msg) === false){ + return; + } + } + submit(data['id_list'], data['elements'], action_type); + }; + setupButtonEventHandlers($('#re_mark_seen'), function(){startAction('mark_seen')}); + setupButtonEventHandlers($('#re_mark_new'), function(){startAction('mark_new')}); + setupButtonEventHandlers($('#re_dismiss'), function(){startAction('delete')}); + setupButtonEventHandlers( + $('#sel_all'), + function(){ + setCheckBoxesIn('#responses .new', true); + setCheckBoxesIn('#responses .seen', true); + } + ); + setupButtonEventHandlers( + $('#sel_seen'), + function(){ + setCheckBoxesIn('#responses .seen', true); + } + ); + setupButtonEventHandlers( + $('#sel_new'), + function(){ + setCheckBoxesIn('#responses .new', true); + } + ); + setupButtonEventHandlers( + $('#sel_none'), + function(){ + setCheckBoxesIn('#responses .new', false); + setCheckBoxesIn('#responses .seen', false); + } + ); +}); + +/** + * @constructor + * allows to follow/unfollow users + */ +var FollowUser = function(){ + WrappedElement.call(this); + this._user_id = null; + this._user_name = null; +}; +inherits(FollowUser, WrappedElement); + +/** + * @param {string} user_name + */ +FollowUser.prototype.setUserName = function(user_name){ + this._user_name = user_name; +}; + +FollowUser.prototype.decorate = function(element){ + this._element = element; + this._user_id = parseInt(element.attr('id').split('-').pop()); + this._available_action = element.children().hasClass('follow') ? 'follow':'unfollow'; + var me = this; + setupButtonEventHandlers(this._element, function(){ me.go() }); +}; + +FollowUser.prototype.go = function(){ + if (askbot['data']['userIsAuthenticated'] === false){ + var message = gettext('Please <a href="%(signin_url)s">signin</a> to follow %(username)s'); + var message_data = { + signin_url: askbot['urls']['user_signin'] + '?next=' + window.location.href, + username: this._user_name + } + message = interpolate(message, message_data, true); + showMessage(this._element, message); + return; + } + var user_id = this._user_id; + if (this._available_action === 'follow'){ + var url = askbot['urls']['follow_user']; + } else { + var url = askbot['urls']['unfollow_user']; + } + var me = this; + $.ajax({ + type: 'POST', + cache: false, + dataType: 'json', + url: url.replace('{{userId}}', user_id), + success: function(){ me.toggleState() } + }); +}; + +FollowUser.prototype.toggleState = function(){ + if (this._available_action === 'follow'){ + this._available_action = 'unfollow'; + var unfollow_div = document.createElement('div'); + unfollow_div.setAttribute('class', 'unfollow'); + var red_div = document.createElement('div'); + red_div.setAttribute('class', 'unfollow-red'); + red_div.innerHTML = interpolate(gettext('unfollow %s'), [this._user_name]); + var green_div = document.createElement('div'); + green_div.setAttribute('class', 'unfollow-green'); + green_div.innerHTML = interpolate(gettext('following %s'), [this._user_name]); + unfollow_div.appendChild(red_div); + unfollow_div.appendChild(green_div); + this._element.html(unfollow_div); + } else { + var follow_div = document.createElement('div'); + follow_div.innerHTML = interpolate(gettext('follow %s'), [this._user_name]); + follow_div.setAttribute('class', 'follow'); + this._available_action = 'follow'; + this._element.html(follow_div); + } +}; + +(function(){ + var fbtn = $('.follow-toggle'); + if (fbtn.length === 1){ + var follow_user = new FollowUser(); + follow_user.decorate(fbtn); + follow_user.setUserName(askbot['data']['viewUserName']); + } +})(); + diff --git a/askbot/skins/old/media/js/utils.js b/askbot/skins/old/media/js/utils.js new file mode 100644 index 00000000..ec55e535 --- /dev/null +++ b/askbot/skins/old/media/js/utils.js @@ -0,0 +1,391 @@ +//var $, scriptUrl, askbotSkin +var mediaUrl = function(resource){ + return scriptUrl + 'm/' + askbotSkin + '/' + resource; +}; + +var cleanUrl = function(url){ + var re = new RegExp('//', 'g'); + return url.replace(re, '/'); +}; + +var copyAltToTitle = function(sel){ + sel.attr('title', sel.attr('alt')); +}; + +var getUniqueWords = function(value){ + var words = $.trim(value).split(/\s+/); + var uniques = new Object(); + var out = new Array(); + $.each(words, function(idx, item){ + if (!(item in uniques)){ + uniques[item] = 1; + out.push(item); + }; + }); + return out; +}; + +var showMessage = function(element, msg, where) { + var div = $('<div class="vote-notification"><h3>' + msg + '</h3>(' + + $.i18n._('click to close') + ')</div>'); + + div.click(function(event) { + $(".vote-notification").fadeOut("fast", function() { $(this).remove(); }); + }); + + var where = where || 'parent'; + + if (where == 'parent'){ + element.parent().append(div); + } + else { + element.after(div); + } + + div.fadeIn("fast"); +}; + +//outer html hack - https://github.com/brandonaaron/jquery-outerhtml/ +(function($){ + var div; + $.fn.outerHTML = function() { + var elem = this[0], + tmp; + return !elem ? null + : typeof ( tmp = elem.outerHTML ) === 'string' ? tmp + : ( div = div || $('<div/>') ).html( this.eq(0).clone() ).html(); + }; +})(jQuery); + +var makeKeyHandler = function(key, callback){ + return function(e){ + if ((e.which && e.which == key) || (e.keyCode && e.keyCode == key)){ + if(!e.shiftKey){ + callback(); + return false; + } + } + }; +}; + + +var setupButtonEventHandlers = function(button, callback){ + button.keydown(makeKeyHandler(13, callback)); + button.click(callback); +}; + + +var putCursorAtEnd = function(element){ + var el = element.get()[0]; + if (el.setSelectionRange){ + var len = element.val().length * 2; + el.setSelectionRange(len, len); + } + else{ + element.val(element.val()); + } + element.scrollTop = 999999; +}; + +var setCheckBoxesIn = function(selector, value){ + return $(selector + '> input[type=checkbox]').attr('checked', value); +}; + +var notify = function() { + var visible = false; + return { + show: function(html) { + if (html) { + $("body").css("margin-top", "2.2em"); + $(".notify span").html(html); + } + $(".notify").fadeIn("slow"); + visible = true; + }, + close: function(doPostback) { + if (doPostback) { + $.post( + askbot['urls']['mark_read_message'], + { formdata: "required" } + ); + } + $(".notify").fadeOut("fast"); + $("body").css("margin-top", "0"); + visible = false; + }, + isVisible: function() { return visible; } + }; +} (); + +/* some google closure-like code for the ui elements */ +var inherits = function(childCtor, parentCtor) { + /** @constructor taken from google closure */ + function tempCtor() {}; + tempCtor.prototype = parentCtor.prototype; + childCtor.superClass_ = parentCtor.prototype; + childCtor.prototype = new tempCtor(); + childCtor.prototype.constructor = childCtor; +}; + +/* wrapper around jQuery object */ +var WrappedElement = function(){ + this._element = null; + this._in_document = false; +}; +WrappedElement.prototype.setElement = function(element){ + this._element = element; +}; +WrappedElement.prototype.createDom = function(){ + this._element = $('<div></div>'); +}; +WrappedElement.prototype.getElement = function(){ + if (this._element === null){ + this.createDom(); + } + return this._element; +}; +WrappedElement.prototype.inDocument = function(){ + return this._in_document; +}; +WrappedElement.prototype.enterDocument = function(){ + return this._in_document = true; +}; +WrappedElement.prototype.hasElement = function(){ + return (this._element !== null); +}; +WrappedElement.prototype.makeElement = function(html_tag){ + //makes jQuery element with tags + return $('<' + html_tag + '></' + html_tag + '>'); +}; +WrappedElement.prototype.dispose = function(){ + this._element.remove(); + this._in_document = false; +}; + +var SimpleControl = function(){ + WrappedElement.call(this); + this._handler = null; + this._title = null; +}; +inherits(SimpleControl, WrappedElement); + +SimpleControl.prototype.setHandler = function(handler){ + this._handler = handler; + if (this.hasElement()){ + this.setHandlerInternal(); + } +}; + +SimpleControl.prototype.setHandlerInternal = function(){ + //default internal setHandler behavior + setupButtonEventHandlers(this._element, this._handler); +}; + +SimpleControl.prototype.setTitle = function(title){ + this._title = title; +}; + +var EditLink = function(){ + SimpleControl.call(this) +}; +inherits(EditLink, SimpleControl); + +EditLink.prototype.createDom = function(){ + var element = $('<a></a>'); + element.addClass('edit'); + this.decorate(element); +}; + +EditLink.prototype.decorate = function(element){ + this._element = element; + this._element.attr('title', $.i18n._('click to edit this comment')); + this._element.html($.i18n._('edit')); + this.setHandlerInternal(); +}; + +var DeleteIcon = function(title){ + SimpleControl.call(this); + this._title = title; +}; +inherits(DeleteIcon, SimpleControl); + +DeleteIcon.prototype.decorate = function(element){ + this._element = element; + this._element.attr('class', 'delete-icon'); + this._element.attr('title', this._title); + if (this._handler !== null){ + this.setHandlerInternal(); + } +}; + +DeleteIcon.prototype.setHandlerInternal = function(){ + setupButtonEventHandlers(this._element, this._handler); +}; + +DeleteIcon.prototype.createDom = function(){ + this._element = this.makeElement('span'); + this.decorate(this._element); +}; + +var Tag = function(){ + SimpleControl.call(this); + this._deletable = false; + this._delete_handler = null; + this._delete_icon_title = null; + this._tag_title = null; + this._name = null; + this._url_params = null; + this._inner_html_tag = 'a'; + this._html_tag = 'li'; +} +inherits(Tag, SimpleControl); + +Tag.prototype.setName = function(name){ + this._name = name; +}; + +Tag.prototype.getName = function(){ + return this._name; +}; + +Tag.prototype.setHtmlTag = function(html_tag){ + this._html_tag = html_tag; +}; + +Tag.prototype.setDeletable = function(is_deletable){ + this._deletable = is_deletable; +}; + +Tag.prototype.setLinkable = function(is_linkable){ + if (is_linkable === true){ + this._inner_html_tag = 'a'; + } else { + this._inner_html_tag = 'span'; + } +}; + +Tag.prototype.isLinkable = function(){ + return (this._inner_html_tag === 'a'); +}; + +Tag.prototype.isDeletable = function(){ + return this._deletable; +}; + +Tag.prototype.isWildcard = function(){ + return (this.getName().substr(-1) === '*'); +}; + +Tag.prototype.setUrlParams = function(url_params){ + this._url_params = url_params; +}; + +Tag.prototype.setHandlerInternal = function(){ + setupButtonEventHandlers(this._element.find('.tag'), this._handler); +}; + +/* delete handler will be specific to the task */ +Tag.prototype.setDeleteHandler = function(delete_handler){ + this._delete_handler = delete_handler; + if (this.hasElement() && this.isDeletable()){ + this._delete_icon.setHandler(delete_handler); + } +}; + +Tag.prototype.getDeleteHandler = function(){ + return this._delete_handler; +}; + +Tag.prototype.setDeleteIconTitle = function(title){ + this._delete_icon_title = title; +}; + +Tag.prototype.decorate = function(element){ + this._element = element; + var del = element.find('.delete-icon'); + if (del.length === 1){ + this.setDeletable(true); + this._delete_icon = new DeleteIcon(); + if (this._delete_icon_title != null){ + this._delete_icon.setTitle(this._delete_icon_title); + } + //do not set the delete handler here + this._delete_icon.decorate(del); + } + this._inner_element = this._element.find('.tag'); + this._name = this.decodeTagName($.trim(this._inner_element.html())); + if (this._title !== null){ + this._inner_element.attr('title', this._title); + } + if (this._handler !== null){ + this.setHandlerInternal(); + } +}; + +Tag.prototype.getDisplayTagName = function(){ + //replaces the trailing * symbol with the unicode asterisk + return this._name.replace(/\*$/, '✽'); +}; + +Tag.prototype.decodeTagName = function(encoded_name){ + return encoded_name.replace('\u273d', '*'); +}; + +Tag.prototype.createDom = function(){ + this._element = this.makeElement(this._html_tag); + //render the outer element + if (this._deletable){ + this._element.addClass('deletable-tag'); + } + this._element.addClass('tag-left'); + + //render the inner element + this._inner_element = this.makeElement(this._inner_html_tag); + if (this.isLinkable()){ + var url = askbot['urls']['questions']; + url += '?tags=' + escape(this.getName()); + if (this._url_params !== null){ + url += escape('&' + this._url_params); + } + this._inner_element.attr('href', url); + } + this._inner_element.addClass('tag tag-right'); + this._inner_element.attr('rel', 'tag'); + if (this._title === null){ + this.setTitle( + $.i18n._( + "see questions tagged '{tag}'" + ).replace( + '{tag}', + this.getName() + ) + ); + } + this._inner_element.attr('title', this._title); + this._inner_element.html(this.getDisplayTagName()); + + this._element.append(this._inner_element); + + if (!this.isLinkable() && this._handler !== null){ + this.setHandlerInternal(); + } + + if (this._deletable){ + this._delete_icon = new DeleteIcon(); + this._delete_icon.setHandler(this.getDeleteHandler()); + if (this._delete_icon_title !== null){ + this._delete_icon.setTitle(this._delete_icon_title); + } + this._element.append(this._delete_icon.getElement()); + } +}; + +//Search Engine Keyword Highlight with Javascript +//http://scott.yang.id.au/code/se-hilite/ +Hilite={elementid:"content",exact:true,max_nodes:1000,onload:true,style_name:"hilite",style_name_suffix:true,debug_referrer:""};Hilite.search_engines=[["local","q"],["cnprog\\.","q"],["google\\.","q"],["search\\.yahoo\\.","p"],["search\\.msn\\.","q"],["search\\.live\\.","query"],["search\\.aol\\.","userQuery"],["ask\\.com","q"],["altavista\\.","q"],["feedster\\.","q"],["search\\.lycos\\.","q"],["alltheweb\\.","q"],["technorati\\.com/search/([^\\?/]+)",1],["dogpile\\.com/info\\.dogpl/search/web/([^\\?/]+)",1,true]];Hilite.decodeReferrer=function(d){var g=null;var e=new RegExp("");for(var c=0;c<Hilite.search_engines.length;c++){var f=Hilite.search_engines[c];e.compile("^http://(www\\.)?"+f[0],"i");var b=d.match(e);if(b){var a;if(isNaN(f[1])){a=Hilite.decodeReferrerQS(d,f[1])}else{a=b[f[1]+1]}if(a){a=decodeURIComponent(a);if(f.length>2&&f[2]){a=decodeURIComponent(a)}a=a.replace(/\'|"/g,"");a=a.split(/[\s,\+\.]+/);return a}break}}return null};Hilite.decodeReferrerQS=function(f,d){var b=f.indexOf("?");var c;if(b>=0){var a=new String(f.substring(b+1));b=0;c=0;while((b>=0)&&((c=a.indexOf("=",b))>=0)){var e,g;e=a.substring(b,c);b=a.indexOf("&",c)+1;if(e==d){if(b<=0){return a.substring(c+1)}else{return a.substring(c+1,b-1)}}else{if(b<=0){return null}}}}return null};Hilite.hiliteElement=function(f,e){if(!e||f.childNodes.length==0){return}var c=new Array();for(var b=0;b<e.length;b++){e[b]=e[b].toLowerCase();if(Hilite.exact){c.push("\\b"+e[b]+"\\b")}else{c.push(e[b])}}c=new RegExp(c.join("|"),"i");var a={};for(var b=0;b<e.length;b++){if(Hilite.style_name_suffix){a[e[b]]=Hilite.style_name+(b+1)}else{a[e[b]]=Hilite.style_name}}var d=function(m){var j=c.exec(m.data);if(j){var n=j[0];var i="";var h=m.splitText(j.index);var g=h.splitText(n.length);var l=m.ownerDocument.createElement("SPAN");m.parentNode.replaceChild(l,h);l.className=a[n.toLowerCase()];l.appendChild(h);return l}else{return m}};Hilite.walkElements(f.childNodes[0],1,d)};Hilite.hilite=function(){var a=Hilite.debug_referrer?Hilite.debug_referrer:document.referrer;var b=null;a=Hilite.decodeReferrer(a);if(a&&((Hilite.elementid&&(b=document.getElementById(Hilite.elementid)))||(b=document.body))){Hilite.hiliteElement(b,a)}};Hilite.walkElements=function(d,f,e){var a=/^(script|style|textarea)/i;var c=0;while(d&&f>0){c++;if(c>=Hilite.max_nodes){var b=function(){Hilite.walkElements(d,f,e)};setTimeout(b,50);return}if(d.nodeType==1){if(!a.test(d.tagName)&&d.childNodes.length>0){d=d.childNodes[0];f++;continue}}else{if(d.nodeType==3){d=e(d)}}if(d.nextSibling){d=d.nextSibling}else{while(f>0){d=d.parentNode;f--;if(d.nextSibling){d=d.nextSibling;break}}}}};if(Hilite.onload){if(window.attachEvent){window.attachEvent("onload",Hilite.hilite)}else{if(window.addEventListener){window.addEventListener("load",Hilite.hilite,false)}else{var __onload=window.onload;window.onload=function(){Hilite.hilite();__onload()}}}}; +/* json2.js by D. Crockford */ +if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}()); +//jquery fieldselection +(function(){var a={getSelection:function(){var b=this.jquery?this[0]:this;return(("selectionStart" in b&&function(){var c=b.selectionEnd-b.selectionStart;return{start:b.selectionStart,end:b.selectionEnd,length:c,text:b.value.substr(b.selectionStart,c)}})||(document.selection&&function(){b.focus();var d=document.selection.createRange();if(d==null){return{start:0,end:b.value.length,length:0}}var c=b.createTextRange();var e=c.duplicate();c.moveToBookmark(d.getBookmark());e.setEndPoint("EndToStart",c);return{start:e.text.length,end:e.text.length+d.text.length,length:d.text.length,text:d.text}})||function(){return{start:0,end:b.value.length,length:0}})()},replaceSelection:function(){var b=this.jquery?this[0]:this;var c=arguments[0]||"";return(("selectionStart" in b&&function(){b.value=b.value.substr(0,b.selectionStart)+c+b.value.substr(b.selectionEnd,b.value.length);return this})||(document.selection&&function(){b.focus();document.selection.createRange().text=c;return this})||function(){b.value+=c;return this})()}};jQuery.each(a,function(b){jQuery.fn[b]=this})})(); +//our custom autocompleter +var AutoCompleter=function(a){var b={autocompleteMultiple:true,multipleSeparator:" ",inputClass:"acInput",loadingClass:"acLoading",resultsClass:"acResults",selectClass:"acSelect",queryParamName:"q",limitParamName:"limit",extraParams:{},lineSeparator:"\n",cellSeparator:"|",minChars:2,maxItemsToShow:10,delay:400,useCache:true,maxCacheLength:10,matchSubset:true,matchCase:false,matchInside:true,mustMatch:false,preloadData:false,selectFirst:false,stopCharRegex:/\s+/,selectOnly:false,formatItem:null,onItemSelect:false,autoFill:false,filterResults:true,sortResults:true,sortFunction:false,onNoMatch:false};this.options=$.extend({},b,a);this.cacheData_={};this.cacheLength_=0;this.selectClass_="jquery-autocomplete-selected-item";this.keyTimeout_=null;this.lastKeyPressed_=null;this.lastProcessedValue_=null;this.lastSelectedValue_=null;this.active_=false;this.finishOnBlur_=true;this.options.minChars=parseInt(this.options.minChars,10);if(isNaN(this.options.minChars)||this.options.minChars<1){this.options.minChars=2}this.options.maxItemsToShow=parseInt(this.options.maxItemsToShow,10);if(isNaN(this.options.maxItemsToShow)||this.options.maxItemsToShow<1){this.options.maxItemsToShow=10}this.options.maxCacheLength=parseInt(this.options.maxCacheLength,10);if(isNaN(this.options.maxCacheLength)||this.options.maxCacheLength<1){this.options.maxCacheLength=10}if(this.options.preloadData===true){this.fetchRemoteData("",function(){})}};inherits(AutoCompleter,WrappedElement);AutoCompleter.prototype.decorate=function(a){this._element=a;this._element.attr("autocomplete","off");this._results=$("<div></div>").hide();if(this.options.resultsClass){this._results.addClass(this.options.resultsClass)}this._results.css({position:"absolute"});$("body").append(this._results);this.setEventHandlers()};AutoCompleter.prototype.setEventHandlers=function(){var a=this;a._element.keydown(function(b){a.lastKeyPressed_=b.keyCode;switch(a.lastKeyPressed_){case 38:b.preventDefault();if(a.active_){a.focusPrev()}else{a.activate()}return false;break;case 40:b.preventDefault();if(a.active_){a.focusNext()}else{a.activate()}return false;break;case 9:case 13:if(a.active_){b.preventDefault();a.selectCurrent();return false}break;case 27:if(a.active_){b.preventDefault();a.finish();return false}break;default:a.activate()}});a._element.blur(function(){if(a.finishOnBlur_){setTimeout(function(){a.finish()},200)}})};AutoCompleter.prototype.position=function(){var a=this._element.offset();this._results.css({top:a.top+this._element.outerHeight(),left:a.left})};AutoCompleter.prototype.cacheRead=function(d){var f,c,b,a,e;if(this.options.useCache){d=String(d);f=d.length;if(this.options.matchSubset){c=1}else{c=f}while(c<=f){if(this.options.matchInside){a=f-c}else{a=0}e=0;while(e<=a){b=d.substr(0,c);if(this.cacheData_[b]!==undefined){return this.cacheData_[b]}e++}c++}}return false};AutoCompleter.prototype.cacheWrite=function(a,b){if(this.options.useCache){if(this.cacheLength_>=this.options.maxCacheLength){this.cacheFlush()}a=String(a);if(this.cacheData_[a]!==undefined){this.cacheLength_++}return this.cacheData_[a]=b}return false};AutoCompleter.prototype.cacheFlush=function(){this.cacheData_={};this.cacheLength_=0};AutoCompleter.prototype.callHook=function(c,b){var a=this.options[c];if(a&&$.isFunction(a)){return a(b,this)}return false};AutoCompleter.prototype.activate=function(){var b=this;var a=function(){b.activateNow()};var c=parseInt(this.options.delay,10);if(isNaN(c)||c<=0){c=250}if(this.keyTimeout_){clearTimeout(this.keyTimeout_)}this.keyTimeout_=setTimeout(a,c)};AutoCompleter.prototype.activateNow=function(){var a=this.getValue();if(a!==this.lastProcessedValue_&&a!==this.lastSelectedValue_){if(a.length>=this.options.minChars){this.active_=true;this.lastProcessedValue_=a;this.fetchData(a)}}};AutoCompleter.prototype.fetchData=function(b){if(this.options.data){this.filterAndShowResults(this.options.data,b)}else{var a=this;this.fetchRemoteData(b,function(c){a.filterAndShowResults(c,b)})}};AutoCompleter.prototype.fetchRemoteData=function(c,e){var d=this.cacheRead(c);if(d){e(d)}else{var a=this;if(this._element){this._element.addClass(this.options.loadingClass)}var b=function(g){var f=false;if(g!==false){f=a.parseRemoteData(g);a.options.data=f;a.cacheWrite(c,f)}if(a._element){a._element.removeClass(a.options.loadingClass)}e(f)};$.ajax({url:this.makeUrl(c),success:b,error:function(){b(false)}})}};AutoCompleter.prototype.setOption=function(a,b){this.options[a]=b};AutoCompleter.prototype.setExtraParam=function(b,c){var a=$.trim(String(b));if(a){if(!this.options.extraParams){this.options.extraParams={}}if(this.options.extraParams[a]!==c){this.options.extraParams[a]=c;this.cacheFlush()}}};AutoCompleter.prototype.makeUrl=function(e){var a=this;var b=this.options.url;var d=$.extend({},this.options.extraParams);if(this.options.queryParamName===false){b+=encodeURIComponent(e)}else{d[this.options.queryParamName]=e}if(this.options.limitParamName&&this.options.maxItemsToShow){d[this.options.limitParamName]=this.options.maxItemsToShow}var c=[];$.each(d,function(f,g){c.push(a.makeUrlParam(f,g))});if(c.length){b+=b.indexOf("?")==-1?"?":"&";b+=c.join("&")}return b};AutoCompleter.prototype.makeUrlParam=function(a,b){return String(a)+"="+encodeURIComponent(b)};AutoCompleter.prototype.splitText=function(a){return String(a).replace(/(\r\n|\r|\n)/g,"\n").split(this.options.lineSeparator)};AutoCompleter.prototype.parseRemoteData=function(c){var h,b,f,d,g;var e=[];var b=this.splitText(c);for(f=0;f<b.length;f++){var a=b[f].split(this.options.cellSeparator);g=[];for(d=0;d<a.length;d++){g.push(unescape(a[d]))}h=g.shift();e.push({value:unescape(h),data:g})}return e};AutoCompleter.prototype.filterAndShowResults=function(a,b){this.showResults(this.filterResults(a,b),b)};AutoCompleter.prototype.filterResults=function(d,b){var f=[];var l,c,e,m,j,a;var k,h,g;for(e=0;e<d.length;e++){m=d[e];j=typeof m;if(j==="string"){l=m;c={}}else{if($.isArray(m)){l=m[0];c=m.slice(1)}else{if(j==="object"){l=m.value;c=m.data}}}l=String(l);if(l>""){if(typeof c!=="object"){c={}}if(this.options.filterResults){h=String(b);g=String(l);if(!this.options.matchCase){h=h.toLowerCase();g=g.toLowerCase()}a=g.indexOf(h);if(this.options.matchInside){a=a>-1}else{a=a===0}}else{a=true}if(a){f.push({value:l,data:c})}}}if(this.options.sortResults){f=this.sortResults(f,b)}if(this.options.maxItemsToShow>0&&this.options.maxItemsToShow<f.length){f.length=this.options.maxItemsToShow}return f};AutoCompleter.prototype.sortResults=function(c,d){var b=this;var a=this.options.sortFunction;if(!$.isFunction(a)){a=function(g,e,h){return b.sortValueAlpha(g,e,h)}}c.sort(function(f,e){return a(f,e,d)});return c};AutoCompleter.prototype.sortValueAlpha=function(d,c,e){d=String(d.value);c=String(c.value);if(!this.options.matchCase){d=d.toLowerCase();c=c.toLowerCase()}if(d>c){return 1}if(d<c){return -1}return 0};AutoCompleter.prototype.showResults=function(e,b){var k=this;var g=$("<ul></ul>");var f,l,j,a,h=false,d=false;var c=e.length;for(f=0;f<c;f++){l=e[f];j=$("<li>"+this.showResult(l.value,l.data)+"</li>");j.data("value",l.value);j.data("data",l.data);j.click(function(){var i=$(this);k.selectItem(i)}).mousedown(function(){k.finishOnBlur_=false}).mouseup(function(){k.finishOnBlur_=true});g.append(j);if(h===false){h=String(l.value);d=j;j.addClass(this.options.firstItemClass)}if(f==c-1){j.addClass(this.options.lastItemClass)}}this.position();this._results.html(g).show();a=this._results.outerWidth()-this._results.width();this._results.width(this._element.outerWidth()-a);$("li",this._results).hover(function(){k.focusItem(this)},function(){});if(this.autoFill(h,b)){this.focusItem(d)}};AutoCompleter.prototype.showResult=function(b,a){if($.isFunction(this.options.showResult)){return this.options.showResult(b,a)}else{return b}};AutoCompleter.prototype.autoFill=function(e,c){var b,a,d,f;if(this.options.autoFill&&this.lastKeyPressed_!=8){b=String(e).toLowerCase();a=String(c).toLowerCase();d=e.length;f=c.length;if(b.substr(0,f)===a){this._element.val(e);this.selectRange(f,d);return true}}return false};AutoCompleter.prototype.focusNext=function(){this.focusMove(+1)};AutoCompleter.prototype.focusPrev=function(){this.focusMove(-1)};AutoCompleter.prototype.focusMove=function(a){var b,c=$("li",this._results);a=parseInt(a,10);for(var b=0;b<c.length;b++){if($(c[b]).hasClass(this.selectClass_)){this.focusItem(b+a);return}}this.focusItem(0)};AutoCompleter.prototype.focusItem=function(b){var a,c=$("li",this._results);if(c.length){c.removeClass(this.selectClass_).removeClass(this.options.selectClass);if(typeof b==="number"){b=parseInt(b,10);if(b<0){b=0}else{if(b>=c.length){b=c.length-1}}a=$(c[b])}else{a=$(b)}if(a){a.addClass(this.selectClass_).addClass(this.options.selectClass)}}};AutoCompleter.prototype.selectCurrent=function(){var a=$("li."+this.selectClass_,this._results);if(a.length==1){this.selectItem(a)}else{this.finish()}};AutoCompleter.prototype.selectItem=function(d){var c=d.data("value");var b=d.data("data");var a=this.displayValue(c,b);this.lastProcessedValue_=a;this.lastSelectedValue_=a;this.setValue(a);this.setCaret(a.length);this.callHook("onItemSelect",{value:c,data:b});this.finish()};AutoCompleter.prototype.isContentChar=function(a){if(a.match(this.options.stopCharRegex)){return false}else{if(a===this.options.multipleSeparator){return false}else{return true}}};AutoCompleter.prototype.getValue=function(){var c=this._element.getSelection();var d=this._element.val();var f=c.start;var e=f;for(cpos=f;cpos>=0;cpos=cpos-1){if(cpos===d.length){continue}var b=d.charAt(cpos);if(!this.isContentChar(b)){break}e=cpos}var a=f;for(cpos=f;cpos<d.length;cpos=cpos+1){if(cpos===0){continue}var b=d.charAt(cpos);if(!this.isContentChar(b)){break}a=cpos}this._selection_start=e;this._selection_end=a;return d.substring(e,a)};AutoCompleter.prototype.setValue=function(b){var a=this._element.val().substring(0,this._selection_start);var c=this._element.val().substring(this._selection_end+1);this._element.val(a+b+c)};AutoCompleter.prototype.displayValue=function(b,a){if($.isFunction(this.options.displayValue)){return this.options.displayValue(b,a)}else{return b}};AutoCompleter.prototype.finish=function(){if(this.keyTimeout_){clearTimeout(this.keyTimeout_)}if(this._element.val()!==this.lastSelectedValue_){if(this.options.mustMatch){this._element.val("")}this.callHook("onNoMatch")}this._results.hide();this.lastKeyPressed_=null;this.lastProcessedValue_=null;if(this.active_){this.callHook("onFinish")}this.active_=false};AutoCompleter.prototype.selectRange=function(d,a){var c=this._element.get(0);if(c.setSelectionRange){c.focus();c.setSelectionRange(d,a)}else{if(this.createTextRange){var b=this.createTextRange();b.collapse(true);b.moveEnd("character",a);b.moveStart("character",d);b.select()}}};AutoCompleter.prototype.setCaret=function(a){this.selectRange(a,a)}; diff --git a/askbot/skins/old/media/js/wmd/images/wmd-buttons.png b/askbot/skins/old/media/js/wmd/images/wmd-buttons.png Binary files differnew file mode 100755 index 00000000..3013a4ad --- /dev/null +++ b/askbot/skins/old/media/js/wmd/images/wmd-buttons.png diff --git a/askbot/skins/old/media/js/wmd/showdown-min.js b/askbot/skins/old/media/js/wmd/showdown-min.js new file mode 100644 index 00000000..073613b1 --- /dev/null +++ b/askbot/skins/old/media/js/wmd/showdown-min.js @@ -0,0 +1 @@ +var Attacklab=Attacklab||{};Attacklab.showdown=Attacklab.showdown||{};Attacklab.showdown.converter=function(){var a;var j;var A;var i=0;this.makeHtml=function(H){a=new Array();j=new Array();A=new Array();H=H.replace(/~/g,"~T");H=H.replace(/\$/g,"~D");H=H.replace(/\r\n/g,"\n");H=H.replace(/\r/g,"\n");H="\n\n"+H+"\n\n";H=z(H);H=H.replace(/^[ \t]+$/mg,"");H=m(H);H=d(H);H=G(H);H=q(H);H=H.replace(/~D/g,"$$");H=H.replace(/~T/g,"~");return H};var d=function(H){var H=H.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm,function(K,M,L,J,I){M=M.toLowerCase();a[M]=h(L);if(J){return J+I}else{if(I){j[M]=I.replace(/"/g,""")}}return""});return H};var m=function(J){J=J.replace(/\n/g,"\n\n");var I="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del";var H="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math";J=J.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,x);J=J.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,x);J=J.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,x);J=J.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,x);J=J.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,x);J=J.replace(/\n\n/g,"\n");return J};var x=function(H,I){var J=I;J=J.replace(/\n\n/g,"\n");J=J.replace(/^\n/,"");J=J.replace(/\n+$/g,"");J="\n\n~K"+(A.push(J)-1)+"K\n\n";return J};var G=function(I){I=f(I);var H=o("<hr />");I=I.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,H);I=I.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm,H);I=I.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm,H);I=E(I);I=b(I);I=u(I);I=m(I);I=g(I);return I};var r=function(H){H=C(H);H=l(H);H=e(H);H=F(H);H=y(H);H=n(H);H=h(H);H=c(H);H=H.replace(/ +\n/g," <br />\n");return H};var l=function(I){var H=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;I=I.replace(H,function(K){var J=K.replace(/(.)<\/?code>(?=.)/g,"$1`");J=w(J,"\\`*_");return J});return I};var y=function(H){H=H.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,D);H=H.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,D);H=H.replace(/(\[([^\[\]]+)\])()()()()()/g,D);return H};var D=function(N,T,S,R,Q,P,M,L){if(L==undefined){L=""}var K=T;var I=S;var J=R.toLowerCase();var H=Q;var O=L;if(H==""){if(J==""){J=I.toLowerCase().replace(/ ?\n/g," ")}H="#"+J;if(a[J]!=undefined){H=a[J];if(j[J]!=undefined){O=j[J]}}else{if(K.search(/\(\s*\)$/m)>-1){H=""}else{return K}}}H=w(H,"*_");var U='<a href="'+H+'"';if(O!=""){O=O.replace(/"/g,""");O=w(O,"*_");U+=' title="'+O+'"'}U+=">"+I+"</a>";return U};var F=function(H){H=H.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,t);H=H.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,t);return H};var t=function(N,T,S,R,Q,P,M,L){var K=T;var J=S;var I=R.toLowerCase();var H=Q;var O=L;if(!O){O=""}if(H==""){if(I==""){I=J.toLowerCase().replace(/ ?\n/g," ")}H="#"+I;if(a[I]!=undefined){H=a[I];if(j[I]!=undefined){O=j[I]}}else{return K}}J=J.replace(/"/g,""");H=w(H,"*_");var U='<img src="'+H+'" alt="'+J+'"';O=O.replace(/"/g,""");O=w(O,"*_");U+=' title="'+O+'"';U+=" />";return U};var f=function(H){H=H.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(I,J){return o("<h1>"+r(J)+"</h1>")});H=H.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,function(J,I){return o("<h2>"+r(I)+"</h2>")});H=H.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,function(I,L,K){var J=L.length;return o("<h"+J+">"+r(K)+"</h"+J+">")});return H};var p;var E=function(I){I+="~0";var H=/^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;if(i){I=I.replace(H,function(K,N,M){var O=N;var L=(M.search(/[*+-]/g)>-1)?"ul":"ol";O=O.replace(/\n{2,}/g,"\n\n\n");var J=p(O);J=J.replace(/\s+$/,"");J="<"+L+">"+J+"</"+L+">\n";return J})}else{H=/(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g;I=I.replace(H,function(L,P,N,K){var O=P;var Q=N;var M=(K.search(/[*+-]/g)>-1)?"ul":"ol";var Q=Q.replace(/\n{2,}/g,"\n\n\n");var J=p(Q);J=O+"<"+M+">\n"+J+"</"+M+">\n";return J})}I=I.replace(/~0/,"");return I};p=function(H){i++;H=H.replace(/\n{2,}$/,"\n");H+="~0";H=H.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,function(K,M,L,J,I){var O=I;var N=M;var P=L;if(N||(O.search(/\n{2,}/)>-1)){O=G(s(O))}else{O=E(s(O));O=O.replace(/\n$/,"");O=r(O)}return"<li>"+O+"</li>\n"});H=H.replace(/~0/g,"");i--;return H};var b=function(H){H+="~0";H=H.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,function(I,K,J){var L=K;var M=J;L=v(s(L));L=z(L);L=L.replace(/^\n+/g,"");L=L.replace(/\n+$/g,"");L="<pre><code>"+L+"\n</code></pre>";return o(L)+M});H=H.replace(/~0/,"");return H};var o=function(H){H=H.replace(/(^\n+|\n+$)/g,"");return"\n\n~K"+(A.push(H)-1)+"K\n\n"};var C=function(H){H=H.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(K,M,L,J,I){var N=J;N=N.replace(/^([ \t]*)/g,"");N=N.replace(/[ \t]*$/g,"");N=v(N);return M+"<code>"+N+"</code>"});return H};var v=function(H){H=H.replace(/&/g,"&");H=H.replace(/</g,"<");H=H.replace(/>/g,">");H=w(H,"*_{}[]\\",false);return H};var c=function(H){H=H.replace(/(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\1/g,"<strong>$2</strong>");H=H.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g,"<em>$2</em>");return H};var u=function(H){H=H.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,function(I,J){var K=J;K=K.replace(/^[ \t]*>[ \t]?/gm,"~0");K=K.replace(/~0/g,"");K=K.replace(/^[ \t]+$/gm,"");K=G(K);K=K.replace(/(^|\n)/g,"$1 ");K=K.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm,function(L,M){var N=M;N=N.replace(/^ /mg,"~0");N=N.replace(/~0/g,"");return N});return o("<blockquote>\n"+K+"\n</blockquote>")});return H};var g=function(N){N=N.replace(/^\n+/g,"");N=N.replace(/\n+$/g,"");var M=N.split(/\n{2,}/g);var J=new Array();var H=M.length;for(var I=0;I<H;I++){var L=M[I];if(L.search(/~K(\d+)K/g)>=0){J.push(L)}else{if(L.search(/\S/)>=0){L=r(L);L=L.replace(/^([ \t]*)/g,"<p>");L+="</p>";J.push(L)}}}H=J.length;for(var I=0;I<H;I++){while(J[I].search(/~K(\d+)K/)>=0){var K=A[RegExp.$1];K=K.replace(/\$/g,"$$$$");J[I]=J[I].replace(/~K\d+K/,K)}}return J.join("\n\n")};var h=function(H){H=H.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&");H=H.replace(/<(?![a-z\/?\$!])/gi,"<");return H};var e=function(H){H=H.replace(/\\(\\)/g,k);H=H.replace(/\\([`*_{}\[\]()>#+-.!])/g,k);return H};var n=function(H){H=H.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,'<a href="$1">$1</a>');H=H.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi,function(I,J){return B(q(J))});return H};var B=function(J){function I(L){var K="0123456789ABCDEF";var M=L.charCodeAt(0);return(K.charAt(M>>4)+K.charAt(M&15))}var H=[function(K){return"&#"+K.charCodeAt(0)+";"},function(K){return"&#x"+I(K)+";"},function(K){return K}];J="mailto:"+J;J=J.replace(/./g,function(K){if(K=="@"){K=H[Math.floor(Math.random()*2)](K)}else{if(K!=":"){var L=Math.random();K=(L>0.9?H[2](K):L>0.45?H[1](K):H[0](K))}}return K});J='<a href="'+J+'">'+J+"</a>";J=J.replace(/">.+:/g,'">');return J};var q=function(H){H=H.replace(/~E(\d+)E/g,function(I,K){var J=parseInt(K);return String.fromCharCode(J)});return H};var s=function(H){H=H.replace(/^(\t|[ ]{1,4})/gm,"~0");H=H.replace(/~0/g,"");return H};var z=function(H){H=H.replace(/\t(?=\t)/g," ");H=H.replace(/\t/g,"~A~B");H=H.replace(/~B(.+?)~A/g,function(I,L,K){var N=L;var J=4-N.length%4;for(var M=0;M<J;M++){N+=" "}return N});H=H.replace(/~A/g," ");H=H.replace(/~B/g,"");return H};var w=function(L,I,J){var H="(["+I.replace(/([\[\]\\])/g,"\\$1")+"])";if(J){H="\\\\"+H}var K=new RegExp(H,"g");L=L.replace(K,k);return L};var k=function(H,J){var I=J.charCodeAt(0);return"~E"+I+"E"}};var Showdown=Attacklab.showdown;if(Attacklab.fileLoaded){Attacklab.fileLoaded("showdown.js")};
\ No newline at end of file diff --git a/askbot/skins/old/media/js/wmd/showdown.js b/askbot/skins/old/media/js/wmd/showdown.js new file mode 100644 index 00000000..257b8bd1 --- /dev/null +++ b/askbot/skins/old/media/js/wmd/showdown.js @@ -0,0 +1,1332 @@ +// +// showdown.js -- A javascript port of Markdown. +// +// Copyright (c) 2007 John Fraser. +// +// Original Markdown Copyright (c) 2004-2005 John Gruber +// <http://daringfireball.net/projects/markdown/> +// +// Redistributable under a BSD-style open source license. +// See license.txt for more information. +// +// The full source distribution is at: +// +// A A L +// T C A +// T K B +// +// <http://www.attacklab.net/> +// + +// +// Wherever possible, Showdown is a straight, line-by-line port +// of the Perl version of Markdown. +// +// This is not a normal parser design; it's basically just a +// series of string substitutions. It's hard to read and +// maintain this way, but keeping Showdown close to the original +// design makes it easier to port new features. +// +// More importantly, Showdown behaves like markdown.pl in most +// edge cases. So web applications can do client-side preview +// in Javascript, and then build identical HTML on the server. +// +// This port needs the new RegExp functionality of ECMA 262, +// 3rd Edition (i.e. Javascript 1.5). Most modern web browsers +// should do fine. Even with the new regular expression features, +// We do a lot of work to emulate Perl's regex functionality. +// The tricky changes in this file mostly have the "attacklab:" +// label. Major or self-explanatory changes don't. +// +// Smart diff tools like Araxis Merge will be able to match up +// this file with markdown.pl in a useful way. A little tweaking +// helps: in a copy of markdown.pl, replace "#" with "//" and +// replace "$text" with "text". Be sure to ignore whitespace +// and line endings. +// + + +// +// Showdown usage: +// +// var text = "Markdown *rocks*."; +// +// var converter = new Attacklab.showdown.converter(); +// var html = converter.makeHtml(text); +// +// alert(html); +// +// Note: move the sample code to the bottom of this +// file before uncommenting it. +// + + +// +// Attacklab namespace +// +var Attacklab = Attacklab || {} + +// +// Showdown namespace +// +Attacklab.showdown = Attacklab.showdown || {} + +// +// converter +// +// Wraps all "globals" so that the only thing +// exposed is makeHtml(). +// +Attacklab.showdown.converter = function() { + +// +// Globals: +// + +// Global hashes, used by various utility routines +var g_urls; +var g_titles; +var g_html_blocks; + +// Used to track when we're inside an ordered or unordered list +// (see _ProcessListItems() for details): +var g_list_level = 0; + +var makeHtmlBase = function(text) { +// +// Main function. The order in which other subs are called here is +// essential. Link and image substitutions need to happen before +// _EscapeSpecialCharsWithinTagAttributes(), so that any *'s or _'s in the <a> +// and <img> tags get encoded. +// + + // Clear the global hashes. If we don't clear these, you get conflicts + // from other articles when generating a page which contains more than + // one article (e.g. an index page that shows the N most recent + // articles): + g_urls = new Array(); + g_titles = new Array(); + g_html_blocks = new Array(); + + // attacklab: Replace ~ with ~T + // This lets us use tilde as an escape char to avoid md5 hashes + // The choice of character is arbitray; anything that isn't + // magic in Markdown will work. + text = text.replace(/~/g,"~T"); + + // attacklab: Replace $ with ~D + // RegExp interprets $ as a special character + // when it's in a replacement string + text = text.replace(/\$/g,"~D"); + + // Standardize line endings + text = text.replace(/\r\n/g,"\n"); // DOS to Unix + text = text.replace(/\r/g,"\n"); // Mac to Unix + + // Make sure text begins and ends with a couple of newlines: + text = "\n\n" + text + "\n\n"; + + // Convert all tabs to spaces. + text = _Detab(text); + + // Strip any lines consisting only of spaces and tabs. + // This makes subsequent regexen easier to write, because we can + // match consecutive blank lines with /\n+/ instead of something + // contorted like /[ \t]*\n+/ . + text = text.replace(/^[ \t]+$/mg,""); + + // Turn block-level HTML blocks into hash entries + text = _HashHTMLBlocks(text); + + // Strip link definitions, store in hashes. + text = _StripLinkDefinitions(text); + + text = _RunBlockGamut(text); + + text = _UnescapeSpecialChars(text); + + // attacklab: Restore dollar signs + text = text.replace(/~D/g,"$$"); + + // attacklab: Restore tildes + text = text.replace(/~T/g,"~"); + + return text; +} + +this.makeHtml = function(text){ + if (enableMathJax === false){ + return makeHtmlBase(text); + } + else { + MathJax.Hub.queue.Push( + function(){ + $('#previewer').html(makeHtmlBase(text)); + } + ); + MathJax.Hub.Queue(['Typeset', MathJax.Hub, 'previewer']); + return $('#previewer').html(); + } +} + + +var _StripLinkDefinitions = function(text) { +// +// Strips link definitions from text, stores the URLs and titles in +// hash references. +// + + // Link defs are in the form: ^[id]: url "optional title" + + /* + var text = text.replace(/ + ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1 + [ \t]* + \n? // maybe *one* newline + [ \t]* + <?(\S+?)>? // url = $2 + [ \t]* + \n? // maybe one newline + [ \t]* + (?: + (\n*) // any lines skipped = $3 attacklab: lookbehind removed + ["(] + (.+?) // title = $4 + [")] + [ \t]* + )? // title is optional + (?:\n+|$) + /gm, + function(){...}); + */ + var text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|\Z)/gm, + function (wholeMatch,m1,m2,m3,m4) { + m1 = m1.toLowerCase(); + g_urls[m1] = _EncodeAmpsAndAngles(m2); // Link IDs are case-insensitive + if (m3) { + // Oops, found blank lines, so it's not a title. + // Put back the parenthetical statement we stole. + return m3+m4; + } else if (m4) { + g_titles[m1] = m4.replace(/"/g,"""); + } + + // Completely remove the definition from the text + return ""; + } + ); + + return text; +} + +var _HashHTMLBlocks = function(text) { + // attacklab: Double up blank lines to reduce lookaround + text = text.replace(/\n/g,"\n\n"); + + // Hashify HTML blocks: + // We only want to do this for block-level HTML tags, such as headers, + // lists, and tables. That's because we still want to wrap <p>s around + // "paragraphs" that are wrapped in non-block-level tags, such as anchors, + // phrase emphasis, and spans. The list of tags we're looking for is + // hard-coded: + var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del" + var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math" + + // First, look for nested blocks, e.g.: + // <div> + // <div> + // tags for inner block must be indented. + // </div> + // </div> + // + // The outermost tags must start at the left margin for this to match, and + // the inner nested divs must be indented. + // We need to do this before the next, more liberal match, because the next + // match will start at the first `<div>` and stop at the first `</div>`. + + // attacklab: This regex can be expensive when it fails. + /* + var text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_a) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*?\n // any number of lines, minimally matching + </\2> // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,hashElement); + + // + // Now match more liberally, simply from `\n<tag>` to `</tag>\n` + // + + /* + var text = text.replace(/ + ( // save in $1 + ^ // start of line (with /m) + <($block_tags_b) // start tag = $2 + \b // word break + // attacklab: hack around khtml/pcre bug... + [^\r]*? // any number of lines, minimally matching + .*</\2> // the matching end tag + [ \t]* // trailing spaces/tabs + (?=\n+) // followed by a newline + ) // attacklab: there are sentinel newlines at end of document + /gm,function(){...}}; + */ + text = text.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math)\b[^\r]*?.*<\/\2>[ \t]*(?=\n+)\n)/gm,hashElement); + + // Special case just for <hr />. It was easier to make a special case than + // to make the other regex more complicated. + + /* + text = text.replace(/ + ( // save in $1 + \n\n // Starting after a blank line + [ ]{0,3} + (<(hr) // start tag = $2 + \b // word break + ([^<>])*? // + \/?>) // the matching end tag + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,hashElement); + + // Special case for standalone HTML comments: + + /* + text = text.replace(/ + ( // save in $1 + \n\n // Starting after a blank line + [ ]{0,3} // attacklab: g_tab_width - 1 + <! + (--[^\r]*?--\s*)+ + > + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(\n\n[ ]{0,3}<!(--[^\r]*?--\s*)+>[ \t]*(?=\n{2,}))/g,hashElement); + + // PHP and ASP-style processor instructions (<?...?> and <%...%>) + + /* + text = text.replace(/ + (?: + \n\n // Starting after a blank line + ) + ( // save in $1 + [ ]{0,3} // attacklab: g_tab_width - 1 + (?: + <([?%]) // $2 + [^\r]*? + \2> + ) + [ \t]* + (?=\n{2,}) // followed by a blank line + ) + /g,hashElement); + */ + text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,hashElement); + + // attacklab: Undo double lines (see comment at top of this function) + text = text.replace(/\n\n/g,"\n"); + return text; +} + +var hashElement = function(wholeMatch,m1) { + var blockText = m1; + + // Undo double lines + blockText = blockText.replace(/\n\n/g,"\n"); + blockText = blockText.replace(/^\n/,""); + + // strip trailing blank lines + blockText = blockText.replace(/\n+$/g,""); + + // Replace the element text with a marker ("~KxK" where x is its key) + blockText = "\n\n~K" + (g_html_blocks.push(blockText)-1) + "K\n\n"; + + return blockText; +}; + +var _RunBlockGamut = function(text) { +// +// These are all the transformations that form block-level +// tags like paragraphs, headers, and list items. +// + text = _DoHeaders(text); + + // Do Horizontal Rules: + var key = hashBlock("<hr />"); + text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,key); + text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm,key); + text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm,key); + + text = _DoLists(text); + text = _DoCodeBlocks(text); + text = _DoBlockQuotes(text); + + // We already ran _HashHTMLBlocks() before, in Markdown(), but that + // was to escape raw HTML in the original Markdown source. This time, + // we're escaping the markup we've just created, so that we don't wrap + // <p> tags around block-level tags. + text = _HashHTMLBlocks(text); + text = _FormParagraphs(text); + + return text; +} + + +var _RunSpanGamut = function(text) { +// +// These are all the transformations that occur *within* block-level +// tags like paragraphs, headers, and list items. +// + + text = _DoCodeSpans(text); + text = _EscapeSpecialCharsWithinTagAttributes(text); + text = _EncodeBackslashEscapes(text); + + // Process anchor and image tags. Images must come first, + // because ![foo][f] looks like an anchor. + text = _DoImages(text); + text = _DoAnchors(text); + + // Make links out of things like `<http://example.com/>` + // Must come after _DoAnchors(), because you can use < and > + // delimiters in inline links like [this](<url>). + text = _DoAutoLinks(text); + text = _EncodeAmpsAndAngles(text); + text = _DoItalicsAndBold(text); + + // Do hard breaks: + text = text.replace(/ +\n/g," <br />\n"); + return text; +} + +var _EscapeSpecialCharsWithinTagAttributes = function(text) { +// +// Within tags -- meaning between < and > -- encode [\ ` * _] so they +// don't conflict with their use in Markdown for code, italics and strong. +// + + // Build a regex to find HTML tags and comments. See Friedl's + // "Mastering Regular Expressions", 2nd Ed., pp. 200-201. + var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi; + + text = text.replace(regex, function(wholeMatch) { + var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g,"$1`"); + tag = escapeCharacters(tag,"\\`*_"); + return tag; + }); + + return text; +} + +var _DoAnchors = function(text) { +// +// Turn Markdown link shortcuts into XHTML <a> tags. +// + // + // First, handle reference-style links: [link text] [id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[] // or anything else + )* + ) + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + )()()()() // pad remaining backreferences + /g,_DoAnchors_callback); + */ + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeAnchorTag); + + // + // Next, inline-style links: [link text](url "optional title") + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ( + (?: + \[[^\]]*\] // allow brackets nested one level + | + [^\[\]] // or anything else + ) + ) + \] + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + <?(.*?)>? // href = $4 + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // Title = $7 + \6 // matching quote + [ \t]* // ignore any spaces/tabs between closing quote and ) + )? // title is optional + \) + ) + /g,writeAnchorTag); + */ + text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()<?(.*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeAnchorTag); + + // + // Last, handle reference-style shortcuts: [link text] + // These must come last in case you've also got [link test][1] + // or [link test](/foo) + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + \[ + ([^\[\]]+) // link text = $2; can't contain '[' or ']' + \] + )()()()()() // pad rest of backreferences + /g, writeAnchorTag); + */ + text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag); + + return text; +} + +var writeAnchorTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) { + if (m7 == undefined) m7 = ""; + var whole_match = m1; + var link_text = m2; + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (url == "") { + if (link_id == "") { + // lower-case and turn embedded newlines into spaces + link_id = link_text.toLowerCase().replace(/ ?\n/g," "); + } + url = "#"+link_id; + + if (g_urls[link_id] != undefined) { + url = g_urls[link_id]; + if (g_titles[link_id] != undefined) { + title = g_titles[link_id]; + } + } + else { + if (whole_match.search(/\(\s*\)$/m)>-1) { + // Special case for explicit empty url + url = ""; + } else { + return whole_match; + } + } + } + + url = escapeCharacters(url,"*_"); + var result = "<a href=\"" + url + "\""; + + if (title != "") { + title = title.replace(/"/g,"""); + title = escapeCharacters(title,"*_"); + result += " title=\"" + title + "\""; + } + + result += ">" + link_text + "</a>"; + + return result; +} + + +var _DoImages = function(text) { +// +// Turn Markdown image shortcuts into <img> tags. +// + + // + // First, handle reference-style labeled images: ![alt text][id] + // + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + + [ ]? // one optional space + (?:\n[ ]*)? // one optional newline followed by spaces + + \[ + (.*?) // id = $3 + \] + )()()()() // pad rest of backreferences + /g,writeImageTag); + */ + text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,writeImageTag); + + // + // Next, handle inline images: ![alt text](url "optional title") + // Don't forget: encode * and _ + + /* + text = text.replace(/ + ( // wrap whole match in $1 + !\[ + (.*?) // alt text = $2 + \] + \s? // One optional whitespace character + \( // literal paren + [ \t]* + () // no id, so leave $3 empty + <?(\S+?)>? // src url = $4 + [ \t]* + ( // $5 + (['"]) // quote char = $6 + (.*?) // title = $7 + \6 // matching quote + [ \t]* + )? // title is optional + \) + ) + /g,writeImageTag); + */ + text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()<?(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,writeImageTag); + + return text; +} + +var writeImageTag = function(wholeMatch,m1,m2,m3,m4,m5,m6,m7) { + var whole_match = m1; + var alt_text = m2; + var link_id = m3.toLowerCase(); + var url = m4; + var title = m7; + + if (!title) title = ""; + + if (url == "") { + if (link_id == "") { + // lower-case and turn embedded newlines into spaces + link_id = alt_text.toLowerCase().replace(/ ?\n/g," "); + } + url = "#"+link_id; + + if (g_urls[link_id] != undefined) { + url = g_urls[link_id]; + if (g_titles[link_id] != undefined) { + title = g_titles[link_id]; + } + } + else { + return whole_match; + } + } + + alt_text = alt_text.replace(/"/g,"""); + url = escapeCharacters(url,"*_"); + var result = "<img src=\"" + url + "\" alt=\"" + alt_text + "\""; + + // attacklab: Markdown.pl adds empty title attributes to images. + // Replicate this bug. + + //if (title != "") { + title = title.replace(/"/g,"""); + title = escapeCharacters(title,"*_"); + result += " title=\"" + title + "\""; + //} + + result += " />"; + + return result; +} + + +var _DoHeaders = function(text) { + + // Setext-style headers: + // Header 1 + // ======== + // + // Header 2 + // -------- + // + text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm, + function(wholeMatch,m1){return hashBlock("<h1>" + _RunSpanGamut(m1) + "</h1>");}); + + text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm, + function(matchFound,m1){return hashBlock("<h2>" + _RunSpanGamut(m1) + "</h2>");}); + + // atx-style headers: + // # Header 1 + // ## Header 2 + // ## Header 2 with closing hashes ## + // ... + // ###### Header 6 + // + + /* + text = text.replace(/ + ^(\#{1,6}) // $1 = string of #'s + [ \t]* + (.+?) // $2 = Header text + [ \t]* + \#* // optional closing #'s (not counted) + \n+ + /gm, function() {...}); + */ + + text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm, + function(wholeMatch,m1,m2) { + var h_level = m1.length; + return hashBlock("<h" + h_level + ">" + _RunSpanGamut(m2) + "</h" + h_level + ">"); + }); + + return text; +} + +// This declaration keeps Dojo compressor from outputting garbage: +var _ProcessListItems; + +var _DoLists = function(text) { +// +// Form HTML ordered (numbered) and unordered (bulleted) lists. +// + + // attacklab: add sentinel to hack around khtml/safari bug: + // http://bugs.webkit.org/show_bug.cgi?id=11231 + text += "~0"; + + // Re-usable pattern to match any entirel ul or ol list: + + /* + var whole_list = / + ( // $1 = whole list + ( // $2 + [ ]{0,3} // attacklab: g_tab_width - 1 + ([*+-]|\d+[.]) // $3 = first list item marker + [ \t]+ + ) + [^\r]+? + ( // $4 + ~0 // sentinel for workaround; should be $ + | + \n{2,} + (?=\S) + (?! // Negative lookahead for another list item marker + [ \t]* + (?:[*+-]|\d+[.])[ \t]+ + ) + ) + )/g + */ + var whole_list = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm; + + if (g_list_level) { + text = text.replace(whole_list,function(wholeMatch,m1,m2) { + var list = m1; + var list_type = (m2.search(/[*+-]/g)>-1) ? "ul" : "ol"; + + // Turn double returns into triple returns, so that we can make a + // paragraph for the last item in a list, if necessary: + list = list.replace(/\n{2,}/g,"\n\n\n");; + var result = _ProcessListItems(list); + + // Trim any trailing whitespace, to put the closing `</$list_type>` + // up on the preceding line, to get it past the current stupid + // HTML block parser. This is a hack to work around the terrible + // hack that is the HTML block parser. + result = result.replace(/\s+$/,""); + result = "<"+list_type+">" + result + "</"+list_type+">\n"; + return result; + }); + } else { + whole_list = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/g; + text = text.replace(whole_list,function(wholeMatch,m1,m2,m3) { + var runup = m1; + var list = m2; + + var list_type = (m3.search(/[*+-]/g)>-1) ? "ul" : "ol"; + // Turn double returns into triple returns, so that we can make a + // paragraph for the last item in a list, if necessary: + var list = list.replace(/\n{2,}/g,"\n\n\n");; + var result = _ProcessListItems(list); + result = runup + "<"+list_type+">\n" + result + "</"+list_type+">\n"; + return result; + }); + } + + // attacklab: strip sentinel + text = text.replace(/~0/,""); + + return text; +} + +_ProcessListItems = function(list_str) { +// +// Process the contents of a single ordered or unordered list, splitting it +// into individual list items. +// + // The $g_list_level global keeps track of when we're inside a list. + // Each time we enter a list, we increment it; when we leave a list, + // we decrement. If it's zero, we're not in a list anymore. + // + // We do this because when we're not inside a list, we want to treat + // something like this: + // + // I recommend upgrading to version + // 8. Oops, now this line is treated + // as a sub-list. + // + // As a single paragraph, despite the fact that the second line starts + // with a digit-period-space sequence. + // + // Whereas when we're inside a list (or sub-list), that line will be + // treated as the start of a sub-list. What a kludge, huh? This is + // an aspect of Markdown's syntax that's hard to parse perfectly + // without resorting to mind-reading. Perhaps the solution is to + // change the syntax rules such that sub-lists must start with a + // starting cardinal number; e.g. "1." or "a.". + + g_list_level++; + + // trim trailing blank lines: + list_str = list_str.replace(/\n{2,}$/,"\n"); + + // attacklab: add sentinel to emulate \z + list_str += "~0"; + + /* + list_str = list_str.replace(/ + (\n)? // leading line = $1 + (^[ \t]*) // leading whitespace = $2 + ([*+-]|\d+[.]) [ \t]+ // list marker = $3 + ([^\r]+? // list item text = $4 + (\n{1,2})) + (?= \n* (~0 | \2 ([*+-]|\d+[.]) [ \t]+)) + /gm, function(){...}); + */ + list_str = list_str.replace(/(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+([^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm, + function(wholeMatch,m1,m2,m3,m4){ + var item = m4; + var leading_line = m1; + var leading_space = m2; + + if (leading_line || (item.search(/\n{2,}/)>-1)) { + item = _RunBlockGamut(_Outdent(item)); + } + else { + // Recursion for sub-lists: + item = _DoLists(_Outdent(item)); + item = item.replace(/\n$/,""); // chomp(item) + item = _RunSpanGamut(item); + } + + return "<li>" + item + "</li>\n"; + } + ); + + // attacklab: strip sentinel + list_str = list_str.replace(/~0/g,""); + + g_list_level--; + return list_str; +} + + +var _DoCodeBlocks = function(text) { +// +// Process Markdown `<pre><code>` blocks. +// + + /* + text = text.replace(text, + /(?:\n\n|^) + ( // $1 = the code block -- one or more lines, starting with a space/tab + (?: + (?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width + .*\n+ + )+ + ) + (\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width + /g,function(){...}); + */ + + // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug + text += "~0"; + + text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g, + function(wholeMatch,m1,m2) { + var codeblock = m1; + var nextChar = m2; + + codeblock = _EncodeCode( _Outdent(codeblock)); + codeblock = _Detab(codeblock); + codeblock = codeblock.replace(/^\n+/g,""); // trim leading newlines + codeblock = codeblock.replace(/\n+$/g,""); // trim trailing whitespace + + codeblock = "<pre><code>" + codeblock + "\n</code></pre>"; + + return hashBlock(codeblock) + nextChar; + } + ); + + // attacklab: strip sentinel + text = text.replace(/~0/,""); + + return text; +} + +var hashBlock = function(text) { + text = text.replace(/(^\n+|\n+$)/g,""); + return "\n\n~K" + (g_html_blocks.push(text)-1) + "K\n\n"; +} + + +var _DoCodeSpans = function(text) { +// +// * Backtick quotes are used for <code></code> spans. +// +// * You can use multiple backticks as the delimiters if you want to +// include literal backticks in the code span. So, this input: +// +// Just type ``foo `bar` baz`` at the prompt. +// +// Will translate to: +// +// <p>Just type <code>foo `bar` baz</code> at the prompt.</p> +// +// There's no arbitrary limit to the number of backticks you +// can use as delimters. If you need three consecutive backticks +// in your code, use four for delimiters, etc. +// +// * You can use spaces to get literal backticks at the edges: +// +// ... type `` `bar` `` ... +// +// Turns to: +// +// ... type <code>`bar`</code> ... +// + + /* + text = text.replace(/ + (^|[^\\]) // Character before opening ` can't be a backslash + (`+) // $2 = Opening run of ` + ( // $3 = The code block + [^\r]*? + [^`] // attacklab: work around lack of lookbehind + ) + \2 // Matching closer + (?!`) + /gm, function(){...}); + */ + + text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, + function(wholeMatch,m1,m2,m3,m4) { + var c = m3; + c = c.replace(/^([ \t]*)/g,""); // leading whitespace + c = c.replace(/[ \t]*$/g,""); // trailing whitespace + c = _EncodeCode(c); + return m1+"<code>"+c+"</code>"; + }); + + return text; +} + + +var _EncodeCode = function(text) { +// +// Encode/escape certain characters inside Markdown code runs. +// The point is that in code, these characters are literals, +// and lose their special Markdown meanings. +// + // Encode all ampersands; HTML entities are not + // entities within a Markdown code span. + text = text.replace(/&/g,"&"); + + // Do the angle bracket song and dance: + text = text.replace(/</g,"<"); + text = text.replace(/>/g,">"); + + // Now, escape characters that are magic in Markdown: + text = escapeCharacters(text,"\*_{}[]\\",false); + +// jj the line above breaks this: +//--- + +//* Item + +// 1. Subitem + +// special char: * +//--- + + return text; +} + + +var _DoItalicsAndBold = function(text) { + + // <strong> must go first: + if (codeFriendlyMarkdown === true){ + text = text.replace(/(\*\*)(?=\S)([^\r]*?\S[\*]*)\1/g, + "<strong>$2</strong>"); + + text = text.replace(/(\*)(?=\S)([^\r]*?\S)\1/g, + "<em>$2</em>"); + } + else { + text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\1/g, + "<strong>$2</strong>"); + + text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, + "<em>$2</em>"); + } + + return text; +} + + +var _DoBlockQuotes = function(text) { + + /* + text = text.replace(/ + ( // Wrap whole match in $1 + ( + ^[ \t]*>[ \t]? // '>' at the start of a line + .+\n // rest of the first line + (.+\n)* // subsequent consecutive lines + \n* // blanks + )+ + ) + /gm, function(){...}); + */ + + text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm, + function(wholeMatch,m1) { + var bq = m1; + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + bq = bq.replace(/^[ \t]*>[ \t]?/gm,"~0"); // trim one level of quoting + + // attacklab: clean up hack + bq = bq.replace(/~0/g,""); + + bq = bq.replace(/^[ \t]+$/gm,""); // trim whitespace-only lines + bq = _RunBlockGamut(bq); // recurse + + bq = bq.replace(/(^|\n)/g,"$1 "); + // These leading spaces screw with <pre> content, so we need to fix that: + bq = bq.replace( + /(\s*<pre>[^\r]+?<\/pre>)/gm, + function(wholeMatch,m1) { + var pre = m1; + // attacklab: hack around Konqueror 3.5.4 bug: + pre = pre.replace(/^ /mg,"~0"); + pre = pre.replace(/~0/g,""); + return pre; + }); + + return hashBlock("<blockquote>\n" + bq + "\n</blockquote>"); + }); + return text; +} + + +var _FormParagraphs = function(text) { +// +// Params: +// $text - string to process with html <p> tags +// + + // Strip leading and trailing lines: + text = text.replace(/^\n+/g,""); + text = text.replace(/\n+$/g,""); + + var grafs = text.split(/\n{2,}/g); + var grafsOut = new Array(); + + // + // Wrap <p> tags. + // + var end = grafs.length; + for (var i=0; i<end; i++) { + var str = grafs[i]; + + // if this is an HTML marker, copy it + if (str.search(/~K(\d+)K/g) >= 0) { + grafsOut.push(str); + } + else if (str.search(/\S/) >= 0) { + str = _RunSpanGamut(str); + str = str.replace(/^([ \t]*)/g,"<p>"); + str += "</p>" + grafsOut.push(str); + } + + } + + // + // Unhashify HTML blocks + // + end = grafsOut.length; + for (var i=0; i<end; i++) { + // if this is a marker for an html block... + while (grafsOut[i].search(/~K(\d+)K/) >= 0) { + var blockText = g_html_blocks[RegExp.$1]; + blockText = blockText.replace(/\$/g,"$$$$"); // Escape any dollar signs + grafsOut[i] = grafsOut[i].replace(/~K\d+K/,blockText); + } + } + + return grafsOut.join("\n\n"); +} + + +var _EncodeAmpsAndAngles = function(text) { +// Smart processing for ampersands and angle brackets that need to be encoded. + + // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: + // http://bumppo.net/projects/amputator/ + text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g,"&"); + + // Encode naked <'s + text = text.replace(/<(?![a-z\/?\$!])/gi,"<"); + + return text; +} + + +var _EncodeBackslashEscapes = function(text) { +// +// Parameter: String. +// Returns: The string, with after processing the following backslash +// escape sequences. +// + + // attacklab: The polite way to do this is with the new + // escapeCharacters() function: + // + // text = escapeCharacters(text,"\\",true); + // text = escapeCharacters(text,"`*_{}[]()>#+-.!",true); + // + // ...but we're sidestepping its use of the (slow) RegExp constructor + // as an optimization for Firefox. This function gets called a LOT. + + text = text.replace(/\\(\\)/g,escapeCharacters_callback); + text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g,escapeCharacters_callback); + return text; +} + + +var _DoAutoLinks = function(text) { + + text = text.replace(/<((https?|ftp|dict):[^'">\s]+)>/gi,"<a href=\"$1\">$1</a>"); + + // Email addresses: <address@domain.foo> + + /* + text = text.replace(/ + < + (?:mailto:)? + ( + [-.\w]+ + \@ + [-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+ + ) + > + /gi, _DoAutoLinks_callback()); + */ + text = text.replace(/<(?:mailto:)?([-.\w]+\@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi, + function(wholeMatch,m1) { + return _EncodeEmailAddress( _UnescapeSpecialChars(m1) ); + } + ); + + return text; +} + + +var _EncodeEmailAddress = function(addr) { +// +// Input: an email address, e.g. "foo@example.com" +// +// Output: the email address as a mailto link, with each character +// of the address encoded as either a decimal or hex entity, in +// the hopes of foiling most address harvesting spam bots. E.g.: +// +// <a href="mailto:foo@e +// xample.com">foo +// @example.com</a> +// +// Based on a filter by Matthew Wickline, posted to the BBEdit-Talk +// mailing list: <http://tinyurl.com/yu7ue> +// + + // attacklab: why can't javascript speak hex? + function char2hex(ch) { + var hexDigits = '0123456789ABCDEF'; + var dec = ch.charCodeAt(0); + return(hexDigits.charAt(dec>>4) + hexDigits.charAt(dec&15)); + } + + var encode = [ + function(ch){return "&#"+ch.charCodeAt(0)+";";}, + function(ch){return "&#x"+char2hex(ch)+";";}, + function(ch){return ch;} + ]; + + addr = "mailto:" + addr; + + addr = addr.replace(/./g, function(ch) { + if (ch == "@") { + // this *must* be encoded. I insist. + ch = encode[Math.floor(Math.random()*2)](ch); + } else if (ch !=":") { + // leave ':' alone (to spot mailto: later) + var r = Math.random(); + // roughly 10% raw, 45% hex, 45% dec + ch = ( + r > .9 ? encode[2](ch) : + r > .45 ? encode[1](ch) : + encode[0](ch) + ); + } + return ch; + }); + + addr = "<a href=\"" + addr + "\">" + addr + "</a>"; + addr = addr.replace(/">.+:/g,"\">"); // strip the mailto: from the visible part + + return addr; +} + + +var _UnescapeSpecialChars = function(text) { +// +// Swap back in all the special characters we've hidden. +// + text = text.replace(/~E(\d+)E/g, + function(wholeMatch,m1) { + var charCodeToReplace = parseInt(m1); + return String.fromCharCode(charCodeToReplace); + } + ); + return text; +} + + +var _Outdent = function(text) { +// +// Remove one level of line-leading tabs or spaces +// + + // attacklab: hack around Konqueror 3.5.4 bug: + // "----------bug".replace(/^-/g,"") == "bug" + + text = text.replace(/^(\t|[ ]{1,4})/gm,"~0"); // attacklab: g_tab_width + + // attacklab: clean up hack + text = text.replace(/~0/g,"") + + return text; +} + +var _Detab = function(text) { +// attacklab: Detab's completely rewritten for speed. +// In perl we could fix it by anchoring the regexp with \G. +// In javascript we're less fortunate. + + // expand first n-1 tabs + text = text.replace(/\t(?=\t)/g," "); // attacklab: g_tab_width + + // replace the nth with two sentinels + text = text.replace(/\t/g,"~A~B"); + + // use the sentinel to anchor our regex so it doesn't explode + text = text.replace(/~B(.+?)~A/g, + function(wholeMatch,m1,m2) { + var leadingText = m1; + var numSpaces = 4 - leadingText.length % 4; // attacklab: g_tab_width + + // there *must* be a better way to do this: + for (var i=0; i<numSpaces; i++) leadingText+=" "; + + return leadingText; + } + ); + + // clean up sentinels + text = text.replace(/~A/g," "); // attacklab: g_tab_width + text = text.replace(/~B/g,""); + + return text; +} + + +// +// attacklab: Utility functions +// + + +var escapeCharacters = function(text, charsToEscape, afterBackslash) { + // First we have to escape the escape characters so that + // we can build a character class out of them + var regexString = "([" + charsToEscape.replace(/([\[\]\\])/g,"\\$1") + "])"; + + if (afterBackslash) { + regexString = "\\\\" + regexString; + } + + var regex = new RegExp(regexString,"g"); + text = text.replace(regex,escapeCharacters_callback); + + return text; +} + + +var escapeCharacters_callback = function(wholeMatch,m1) { + var charCodeToEscape = m1.charCodeAt(0); + return "~E"+charCodeToEscape+"E"; +} + +} // end of Attacklab.showdown.converter + + +// Version 0.9 used the Showdown namespace instead of Attacklab.showdown +// The old namespace is deprecated, but we'll support it for now: +var Showdown = Attacklab.showdown; + +// If anyone's interested, tell the world that this file's been loaded +if (Attacklab.fileLoaded) { + Attacklab.fileLoaded("showdown.js"); +} diff --git a/askbot/skins/old/media/js/wmd/wmd-min.js b/askbot/skins/old/media/js/wmd/wmd-min.js new file mode 100644 index 00000000..aa643f1a --- /dev/null +++ b/askbot/skins/old/media/js/wmd/wmd-min.js @@ -0,0 +1 @@ +var Attacklab=Attacklab||{};Attacklab.wmdBase=function(){var y=top.Attacklab;var E=top.document;var s=top.RegExp;var l=top.navigator;y.Util={};y.Position={};y.Command={};y.Global={};var a=y.Util;var C=y.Position;var h=y.Command;var v=y.Global;v.isIE=/msie/.test(l.userAgent.toLowerCase());v.isIE_5or6=/msie 6/.test(l.userAgent.toLowerCase())||/msie 5/.test(l.userAgent.toLowerCase());v.isIE_7plus=v.isIE&&!v.isIE_5or6;v.isOpera=/opera/.test(l.userAgent.toLowerCase());v.isKonqueror=/konqueror/.test(l.userAgent.toLowerCase());var c="粗体 <strong> Ctrl-B";var f="斜体 <em> Ctrl-I";var z="超链接 <a> Ctrl-L";var u="引用 <blockquote> Ctrl-.";var e="代ç <pre><code> Ctrl-K";var d="图片 <img> Ctrl-G";var q="æ•°å—ç¼–å·åˆ—表 <ol> Ctrl-O";var t="项目符å·åˆ—表 <ul> Ctrl-U";var i="æ ‡é¢˜ <h1>/<h2> Ctrl-H";var p="水平线 <hr> Ctrl-R";var m="撤销 Ctrl-Z";var j="é‡åš Ctrl-Y";var B="<p style='margin-top: 0px'><b>输入图片地å€</b></p><p>示例:<br />http://www.cnprog.com/images/temp.jpg \"我的截图\"</p>";var D="<p style='margin-top: 0px'><b>输入Web地å€</b></p><p>示例:<br />http://www.cnprog.com/ \"我的网站\"</p>";var n='<div>æˆ–è€…ä¸Šä¼ æœ¬åœ°å›¾ç‰‡ï¼š</div><input type="file" name="file-upload" id="file-upload" size="26" onchange="return ajaxFileUpload($(\'#image-url\'));"/><br><img id="loading" src="/media/images/indicator.gif" style="display:none;"/>';var b="http://";var g="http://";var o="images/";var A=500;var x=100;var k="http://wmd-editor.com/";var r="WMD website";var w="_blank";y.PanelCollection=function(){this.buttonBar=E.getElementById("wmd-button-bar");this.preview=E.getElementById("previewer");this.output=E.getElementById("wmd-output");this.input=E.getElementById("editor")};y.panels=undefined;y.ieCachedRange=null;y.ieRetardedClick=false;a.isVisible=function(F){if(window.getComputedStyle){return window.getComputedStyle(F,null).getPropertyValue("display")!=="none"}else{if(F.currentStyle){return F.currentStyle.display!=="none"}}};a.addEvent=function(G,F,H){if(G.attachEvent){G.attachEvent("on"+F,H)}else{G.addEventListener(F,H,false)}};a.removeEvent=function(G,F,H){if(G.detachEvent){G.detachEvent("on"+F,H)}else{G.removeEventListener(F,H,false)}};a.fixEolChars=function(F){F=F.replace(/\r\n/g,"\n");F=F.replace(/\r/g,"\n");return F};a.extendRegExp=function(H,J,G){if(J===null||J===undefined){J=""}if(G===null||G===undefined){G=""}var I=H.toString();var F;I=I.replace(/\/([gim]*)$/,"");F=s.$1;I=I.replace(/(^\/|\/$)/g,"");I=J+I+G;return new s(I,F)};a.createImage=function(F){var H=o+F;var G=E.createElement("img");G.className="wmd-button";G.src=H;return G};a.prompt=function(M,P,H){var I;var F;var K;var J=0;if(arguments.length==4){J=arguments[3]}if(P===undefined){P=""}var L=function(Q){var R=(Q.charCode||Q.keyCode);if(R===27){N(true)}};var N=function(Q){a.removeEvent(E.body,"keydown",L);var R=K.value;if(Q){R=null}else{R=R.replace("http://http://","http://");R=R.replace("http://https://","https://");R=R.replace("http://ftp://","ftp://");if(R.indexOf("http://")===-1&&R.indexOf("ftp://")===-1){R="http://"+R}}I.parentNode.removeChild(I);F.parentNode.removeChild(F);H(R);return false};var G=function(){F=E.createElement("div");F.className="wmd-prompt-background";style=F.style;style.position="absolute";style.top="0";style.zIndex="1000";if(v.isKonqueror){style.backgroundColor="transparent"}else{if(v.isIE){style.filter="alpha(opacity=50)"}else{style.opacity="0.5"}}var Q=C.getPageSize();style.height=Q[1]+"px";if(v.isIE){style.left=E.documentElement.scrollLeft;style.width=E.documentElement.clientWidth}else{style.left="0";style.width="100%"}E.body.appendChild(F)};var O=function(){I=E.createElement("div");I.className="wmd-prompt-dialog";I.style.padding="10px;";I.style.position="fixed";I.style.width="400px";I.style.zIndex="1001";var Q=E.createElement("div");Q.innerHTML=M;Q.style.padding="5px";I.appendChild(Q);var S=E.createElement("form");S.onsubmit=function(){return N(false)};style=S.style;style.padding="0";style.margin="0";style.cssFloat="left";style.width="100%";style.textAlign="center";style.position="relative";I.appendChild(S);K=E.createElement("input");if(J==1){K.id="image-url"}K.type="text";K.value=P;style=K.style;style.display="block";style.width="80%";style.marginLeft=style.marginRight="auto";S.appendChild(K);if(J==1){var R=E.createElement("div");R.innerHTML=n;R.style.padding="5px";S.appendChild(R)}var U=E.createElement("input");U.type="button";U.onclick=function(){return N(false)};U.value="OK";style=U.style;style.margin="10px";style.display="inline";style.width="7em";var T=E.createElement("input");T.type="button";T.onclick=function(){return N(true)};T.value="Cancel";style=T.style;style.margin="10px";style.display="inline";style.width="7em";if(/mac/.test(l.platform.toLowerCase())){S.appendChild(T);S.appendChild(U)}else{S.appendChild(U);S.appendChild(T)}a.addEvent(E.body,"keydown",L);I.style.top="50%";I.style.left="50%";I.style.display="block";if(v.isIE_5or6){I.style.position="absolute";I.style.top=E.documentElement.scrollTop+200+"px";I.style.left="50%"}E.body.appendChild(I);I.style.marginTop=-(C.getHeight(I)/2)+"px";I.style.marginLeft=-(C.getWidth(I)/2)+"px"};G();top.setTimeout(function(){O();var R=P.length;if(K.selectionStart!==undefined){K.selectionStart=0;K.selectionEnd=R}else{if(K.createTextRange){var Q=K.createTextRange();Q.collapse(false);Q.moveStart("character",-R);Q.moveEnd("character",R);Q.select()}}K.focus()},0)};C.getTop=function(H,G){var F=H.offsetTop;if(!G){while(H=H.offsetParent){F+=H.offsetTop}}return F};C.getHeight=function(F){return F.offsetHeight||F.scrollHeight};C.getWidth=function(F){return F.offsetWidth||F.scrollWidth};C.getPageSize=function(){var G,H;var F,K;if(self.innerHeight&&self.scrollMaxY){G=E.body.scrollWidth;H=self.innerHeight+self.scrollMaxY}else{if(E.body.scrollHeight>E.body.offsetHeight){G=E.body.scrollWidth;H=E.body.scrollHeight}else{G=E.body.offsetWidth;H=E.body.offsetHeight}}if(self.innerHeight){F=self.innerWidth;K=self.innerHeight}else{if(E.documentElement&&E.documentElement.clientHeight){F=E.documentElement.clientWidth;K=E.documentElement.clientHeight}else{if(E.body){F=E.body.clientWidth;K=E.body.clientHeight}}}var J=Math.max(G,F);var I=Math.max(H,K);return[J,I,F,K]};y.inputPoller=function(O,H){var F=this;var K=y.panels.input;var G;var I;var L;var J;this.tick=function(){if(!a.isVisible(K)){return}if(K.selectionStart||K.selectionStart===0){var Q=K.selectionStart;var P=K.selectionEnd;if(Q!=G||P!=I){G=Q;I=P;if(L!=K.value){L=K.value;return true}}}return false};var N=function(){if(!a.isVisible(K)){return}if(F.tick()){O()}};var M=function(){J=top.setInterval(N,H)};this.destroy=function(){top.clearInterval(J)};M()};y.undoManager=function(Q){var U=this;var O=[];var M=0;var L="none";var G;var R;var H;var K;var F=function(W,V){if(L!=W){L=W;if(!V){I()}}if(!v.isIE||L!="moving"){H=top.setTimeout(N,1)}else{K=null}};var N=function(){K=new y.TextareaState();R.tick();H=undefined};this.setCommandMode=function(){L="command";I();H=top.setTimeout(N,0)};this.canUndo=function(){return M>1};this.canRedo=function(){if(O[M+1]){return true}return false};this.undo=function(){if(U.canUndo()){if(G){G.restore();G=null}else{O[M]=new y.TextareaState();O[--M].restore();if(Q){Q()}}}L="none";y.panels.input.focus();N()};this.redo=function(){if(U.canRedo()){O[++M].restore();if(Q){Q()}}L="none";y.panels.input.focus();N()};var I=function(){var V=K||new y.TextareaState();if(!V){return false}if(L=="moving"){if(!G){G=V}return}if(G){if(O[M-1].text!=G.text){O[M++]=G}G=null}O[M++]=V;O[M+1]=null;if(Q){Q()}};var P=function(V){var X=false;if(V.ctrlKey||V.metaKey){var W=V.charCode||V.keyCode;var Y=String.fromCharCode(W);switch(Y){case"y":U.redo();X=true;break;case"z":if(!V.shiftKey){U.undo()}else{U.redo()}X=true;break}}if(X){if(V.preventDefault){V.preventDefault()}if(top.event){top.event.returnValue=false}return}};var T=function(V){if(!V.ctrlKey&&!V.metaKey){var W=V.keyCode;if((W>=33&&W<=40)||(W>=63232&&W<=63235)){F("moving")}else{if(W==8||W==46||W==127){F("deleting")}else{if(W==13){F("newlines")}else{if(W==27){F("escape")}else{if((W<16||W>20)&&W!=91){F("typing")}}}}}}};var J=function(){a.addEvent(y.panels.input,"keypress",function(W){if((W.ctrlKey||W.metaKey)&&(W.keyCode==89||W.keyCode==90)){W.preventDefault()}});var V=function(){if(v.isIE||(K&&K.text!=y.panels.input.value)){if(H==undefined){L="paste";I();N()}}};R=new y.inputPoller(V,x);a.addEvent(y.panels.input,"keydown",P);a.addEvent(y.panels.input,"keydown",T);a.addEvent(y.panels.input,"mousedown",function(){F("moving")});y.panels.input.onpaste=V;y.panels.input.ondrop=V};var S=function(){J();N();I()};this.destroy=function(){if(R){R.destroy()}};S()};y.editor=function(O){if(!O){O=function(){}}var L=y.panels.input;var I=0;var P=this;var K;var R;var G;var M;var N;var U=function(W){L.focus();if(W.textOp){if(N){N.setCommandMode()}var Y=new y.TextareaState();if(!Y){return}var Z=Y.getChunks();var V=function(){L.focus();if(Z){Y.setChunks(Z)}Y.restore();O()};var X=W.textOp(Z,V);if(!X){V()}}if(W.execute){W.execute(P)}};var S=function(){if(N){F(document.getElementById("wmd-undo-button"),N.canUndo());F(document.getElementById("wmd-redo-button"),N.canRedo())}};var F=function(V,X){var Y="0px";var Z="-20px";var W="-40px";if(X){V.style.backgroundPosition=V.XShift+" "+Y;V.onmouseover=function(){this.style.backgroundPosition=this.XShift+" "+W};V.onmouseout=function(){this.style.backgroundPosition=this.XShift+" "+Y};if(v.isIE){V.onmousedown=function(){y.ieRetardedClick=true;y.ieCachedRange=document.selection.createRange()}}if(!V.isHelp){V.onclick=function(){if(this.onmouseout){this.onmouseout()}U(this);return false}}}else{V.style.backgroundPosition=V.XShift+" "+Z;V.onmouseover=V.onmouseout=V.onclick=function(){}}};var J=function(){var Z=document.getElementById("wmd-button-bar");var W="0px";var Y="-20px";var ae="-40px";var ak=document.createElement("ul");ak.id="wmd-button-row";ak=Z.appendChild(ak);var ad=document.createElement("li");ad.className="wmd-button";ad.id="wmd-bold-button";ad.title=c;ad.XShift="0px";ad.textOp=h.doBold;F(ad,true);ak.appendChild(ad);var ac=document.createElement("li");ac.className="wmd-button";ac.id="wmd-italic-button";ac.title=f;ac.XShift="-20px";ac.textOp=h.doItalic;F(ac,true);ak.appendChild(ac);var ah=document.createElement("li");ah.className="wmd-spacer";ah.id="wmd-spacer1";ak.appendChild(ah);var ai=document.createElement("li");ai.className="wmd-button";ai.id="wmd-link-button";ai.title=z;ai.XShift="-40px";ai.textOp=function(ap,aq){return h.doLinkOrImage(ap,aq,false)};F(ai,true);ak.appendChild(ai);var al=document.createElement("li");al.className="wmd-button";al.id="wmd-quote-button";al.title=u;al.XShift="-60px";al.textOp=h.doBlockquote;F(al,true);ak.appendChild(al);var am=document.createElement("li");am.className="wmd-button";am.id="wmd-code-button";am.title=e;am.XShift="-80px";am.textOp=h.doCode;F(am,true);ak.appendChild(am);var aa=document.createElement("li");aa.className="wmd-button";aa.id="wmd-image-button";aa.title=d;aa.XShift="-100px";aa.textOp=function(ap,aq){return h.doLinkOrImage(ap,aq,true)};F(aa,true);ak.appendChild(aa);var ag=document.createElement("li");ag.className="wmd-spacer";ag.id="wmd-spacer2";ak.appendChild(ag);var ab=document.createElement("li");ab.className="wmd-button";ab.id="wmd-olist-button";ab.title=q;ab.XShift="-120px";ab.textOp=function(ap,aq){h.doList(ap,aq,true)};F(ab,true);ak.appendChild(ab);var ao=document.createElement("li");ao.className="wmd-button";ao.id="wmd-ulist-button";ao.title=t;ao.XShift="-140px";ao.textOp=function(ap,aq){h.doList(ap,aq,false)};F(ao,true);ak.appendChild(ao);var aj=document.createElement("li");aj.className="wmd-button";aj.id="wmd-heading-button";aj.title=i;aj.XShift="-160px";aj.textOp=h.doHeading;F(aj,true);ak.appendChild(aj);var X=document.createElement("li");X.className="wmd-button";X.id="wmd-hr-button";X.title=p;X.XShift="-180px";X.textOp=h.doHorizontalRule;F(X,true);ak.appendChild(X);var af=document.createElement("li");af.className="wmd-spacer";af.id="wmd-spacer3";ak.appendChild(af);var V=document.createElement("li");V.className="wmd-button";V.id="wmd-undo-button";V.title=m;V.XShift="-200px";V.execute=function(ap){ap.undo()};F(V,true);ak.appendChild(V);var an=document.createElement("li");an.className="wmd-button";an.id="wmd-redo-button";an.title=j;if(/win/.test(l.platform.toLowerCase())){an.title=j}else{an.title="é‡åš - Ctrl+Shift+Z"}an.XShift="-220px";an.execute=function(ap){ap.redo()};F(an,true);ak.appendChild(an);S()};var H=function(){if(/\?noundo/.test(E.location.href)){y.nativeUndo=true}if(!y.nativeUndo){N=new y.undoManager(function(){O();S()})}J();var W="keydown";if(v.isOpera){W="keypress"}a.addEvent(L,W,function(Y){if(Y.ctrlKey||Y.metaKey){var Z=Y.charCode||Y.keyCode;var X=String.fromCharCode(Z).toLowerCase();if(Z===46){X=""}if(Z===190){X="."}switch(X){case"b":U(document.getElementById("wmd-bold-button"));break;case"i":U(document.getElementById("wmd-italic-button"));break;case"l":U(document.getElementById("wmd-link-button"));break;case".":U(document.getElementById("wmd-quote-button"));break;case"k":U(document.getElementById("wmd-code-button"));break;case"g":U(document.getElementById("wmd-image-button"));break;case"o":U(document.getElementById("wmd-olist-button"));break;case"u":U(document.getElementById("wmd-ulist-button"));break;case"h":U(document.getElementById("wmd-heading-button"));break;case"r":U(document.getElementById("wmd-hr-button"));break;case"y":U(document.getElementById("wmd-redo-button"));break;case"z":if(Y.shiftKey){U(document.getElementById("wmd-redo-button"))}else{U(document.getElementById("wmd-undo-button"))}break;default:return}if(Y.preventDefault){Y.preventDefault()}if(top.event){top.event.returnValue=false}}});a.addEvent(L,"keyup",function(X){if(X.shiftKey&&!X.ctrlKey&&!X.metaKey){var Y=X.charCode||X.keyCode;if(Y===13){fakeButton={};fakeButton.textOp=h.doAutoindent;U(fakeButton)}}});if(L.form){var V=L.form.onsubmit;L.form.onsubmit=function(){Q();if(V){return V.apply(this,arguments)}}}};var Q=function(){if(y.showdown){var V=new y.showdown.converter()}var W=L.value;var X=function(){L.value=W};if(!/markdown/.test(y.wmd_env.output.toLowerCase())){if(V){L.value=V.makeHtml(W);top.setTimeout(X,0)}}return true};this.undo=function(){if(N){N.undo()}};this.redo=function(){if(N){N.redo()}};var T=function(){H()};this.destroy=function(){if(N){N.destroy()}if(G.parentNode){G.parentNode.removeChild(G)}if(L){L.style.marginTop=""}top.clearInterval(M)};T()};y.TextareaState=function(){var F=this;var G=y.panels.input;this.init=function(){if(!a.isVisible(G)){return}this.setInputAreaSelectionStartEnd();this.scrollTop=G.scrollTop;if(!this.text&&G.selectionStart||G.selectionStart===0){this.text=G.value}};this.setInputAreaSelection=function(){if(!a.isVisible(G)){return}if(G.selectionStart!==undefined&&!v.isOpera){G.focus();G.selectionStart=F.start;G.selectionEnd=F.end;G.scrollTop=F.scrollTop}else{if(E.selection){if(E.activeElement&&E.activeElement!==G){return}G.focus();var H=G.createTextRange();H.moveStart("character",-G.value.length);H.moveEnd("character",-G.value.length);H.moveEnd("character",F.end);H.moveStart("character",F.start);H.select()}}};this.setInputAreaSelectionStartEnd=function(){if(G.selectionStart||G.selectionStart===0){F.start=G.selectionStart;F.end=G.selectionEnd}else{if(E.selection){F.text=a.fixEolChars(G.value);var K;if(y.ieRetardedClick&&y.ieCachedRange){K=y.ieCachedRange;y.ieRetardedClick=false}else{K=E.selection.createRange()}var L=a.fixEolChars(K.text);var J="\x07";var I=J+L+J;K.text=I;var M=a.fixEolChars(G.value);K.moveStart("character",-I.length);K.text=L;F.start=M.indexOf(J);F.end=M.lastIndexOf(J)-J.length;var H=F.text.length-a.fixEolChars(G.value).length;if(H){K.moveStart("character",-L.length);while(H--){L+="\n";F.end+=1}K.text=L}this.setInputAreaSelection()}}};this.restore=function(){if(F.text!=undefined&&F.text!=G.value){G.value=F.text}this.setInputAreaSelection();G.scrollTop=F.scrollTop};this.getChunks=function(){var H=new y.Chunks();H.before=a.fixEolChars(F.text.substring(0,F.start));H.startTag="";H.selection=a.fixEolChars(F.text.substring(F.start,F.end));H.endTag="";H.after=a.fixEolChars(F.text.substring(F.end));H.scrollTop=F.scrollTop;return H};this.setChunks=function(H){H.before=H.before+H.startTag;H.after=H.endTag+H.after;if(v.isOpera){H.before=H.before.replace(/\n/g,"\r\n");H.selection=H.selection.replace(/\n/g,"\r\n");H.after=H.after.replace(/\n/g,"\r\n")}this.start=H.before.length;this.end=H.before.length+H.selection.length;this.text=H.before+H.selection+H.after;this.scrollTop=H.scrollTop};this.init()};y.Chunks=function(){};y.Chunks.prototype.findTags=function(G,I){var F=this;var H;if(G){H=a.extendRegExp(G,"","$");this.before=this.before.replace(H,function(J){F.startTag=F.startTag+J;return""});H=a.extendRegExp(G,"^","");this.selection=this.selection.replace(H,function(J){F.startTag=F.startTag+J;return""})}if(I){H=a.extendRegExp(I,"","$");this.selection=this.selection.replace(H,function(J){F.endTag=J+F.endTag;return""});H=a.extendRegExp(I,"^","");this.after=this.after.replace(H,function(J){F.endTag=J+F.endTag;return""})}};y.Chunks.prototype.trimWhitespace=function(F){this.selection=this.selection.replace(/^(\s*)/,"");if(!F){this.before+=s.$1}this.selection=this.selection.replace(/(\s*)$/,"");if(!F){this.after=s.$1+this.after}};y.Chunks.prototype.skipLines=function(H,G,F){if(H===undefined){H=1}if(G===undefined){G=1}H++;G++;var I;var J;this.selection=this.selection.replace(/(^\n*)/,"");this.startTag=this.startTag+s.$1;this.selection=this.selection.replace(/(\n*$)/,"");this.endTag=this.endTag+s.$1;this.startTag=this.startTag.replace(/(^\n*)/,"");this.before=this.before+s.$1;this.endTag=this.endTag.replace(/(\n*$)/,"");this.after=this.after+s.$1;if(this.before){I=J="";while(H--){I+="\\n?";J+="\n"}if(F){I="\\n*"}this.before=this.before.replace(new s(I+"$",""),J)}if(this.after){I=J="";while(G--){I+="\\n?";J+="\n"}if(F){I="\\n*"}this.after=this.after.replace(new s(I,""),J)}};h.prefixes="(?:\\s{4,}|\\s*>|\\s*-\\s+|\\s*\\d+\\.|=|\\+|-|_|\\*|#|\\s*\\[[^\n]]+\\]:)";h.unwrap=function(G){var F=new s("([^\\n])\\n(?!(\\n|"+h.prefixes+"))","g");G.selection=G.selection.replace(F,"$1 $2")};h.wrap=function(G,F){h.unwrap(G);var H=new s("(.{1,"+F+"})( +|$\\n?)","gm");G.selection=G.selection.replace(H,function(I,J){if(new s("^"+h.prefixes,"").test(I)){return I}return J+"\n"});G.selection=G.selection.replace(/\s+$/,"")};h.doBold=function(F,G){return h.doBorI(F,G,2,"strong text")};h.doItalic=function(F,G){return h.doBorI(F,G,1,"emphasized text")};h.doBorI=function(L,J,K,F){L.trimWhitespace();L.selection=L.selection.replace(/\n{2,}/g,"\n");L.before.search(/(\**$)/);var I=s.$1;L.after.search(/(^\**)/);var G=s.$1;var M=Math.min(I.length,G.length);if((M>=K)&&(M!=2||K!=1)){L.before=L.before.replace(s("[*]{"+K+"}$",""),"");L.after=L.after.replace(s("^[*]{"+K+"}",""),"")}else{if(!L.selection&&G){L.after=L.after.replace(/^([*_]*)/,"");L.before=L.before.replace(/(\s?)$/,"");var H=s.$1;L.before=L.before+G+H}else{if(!L.selection&&!G){L.selection=F}var N=K<=1?"*":"**";L.before=L.before+N;L.after=N+L.after}}return};h.stripLinkDefs=function(G,F){G=G.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm,function(K,L,H,I,J){F[L]=K.replace(/\s*$/,"");if(I){F[L]=K.replace(/["(](.+?)[")]$/,"");return I+J}return""});return G};h.addLinkDef=function(M,I){var F=0;var H={};M.before=h.stripLinkDefs(M.before,H);M.selection=h.stripLinkDefs(M.selection,H);M.after=h.stripLinkDefs(M.after,H);var G="";var L=/(\[(?:\[[^\]]*\]|[^\[\]])*\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g;var K=function(O){F++;O=O.replace(/^[ ]{0,3}\[(\d+)\]:/," ["+F+"]:");G+="\n"+O};var J=function(P,Q,R,O){if(H[R]){K(H[R]);return Q+F+O}return P};M.before=M.before.replace(L,J);if(I){K(I)}else{M.selection=M.selection.replace(L,J)}var N=F;M.after=M.after.replace(L,J);if(M.after){M.after=M.after.replace(/\n*$/,"")}if(!M.after){M.selection=M.selection.replace(/\n*$/,"")}M.after+="\n\n"+G;return N};h.doLinkOrImage=function(F,G,I){F.trimWhitespace();F.findTags(/\s*!?\[/,/\][ ]?(?:\n[ ]*)?(\[.*?\])?/);if(F.endTag.length>1){F.startTag=F.startTag.replace(/!?\[/,"");F.endTag="";h.addLinkDef(F,null)}else{if(/\n\n/.test(F.selection)){h.addLinkDef(F,null);return}var H=function(L){if(L!==null){F.startTag=F.endTag="";var K=" [999]: "+L;var J=h.addLinkDef(F,K);F.startTag=I?"![":"[";F.endTag="]["+J+"]";if(!F.selection){if(I){F.selection="alt text"}else{F.selection="link text"}}}G()};if(I){a.prompt(B,b,H,1)}else{a.prompt(D,g,H)}return true}};a.makeAPI=function(){y.wmd={};y.wmd.editor=y.editor;y.wmd.previewManager=y.previewManager};a.startEditor=function(){if(y.wmd_env.autostart===false){a.makeAPI();return}var G;var F;var H=function(){y.panels=new y.PanelCollection();F=new y.previewManager();var I=F.refresh;G=new y.editor(I);F.refresh(true)};a.addEvent(top,"load",H)};y.previewManager=function(){var H=this;var V;var F;var N;var M;var S;var O;var I=3000;var P="delayed";var K=function(X,Y){a.addEvent(X,"input",Y);X.onpaste=Y;X.ondrop=Y;a.addEvent(X,"keypress",Y);a.addEvent(X,"keydown",Y);F=new y.inputPoller(Y,A)};var R=function(){var X=0;if(top.innerHeight){X=top.pageYOffset}else{if(E.documentElement&&E.documentElement.scrollTop){X=E.documentElement.scrollTop}else{if(E.body){X=E.body.scrollTop}}}return X};var L=function(){if(!y.panels.preview&&!y.panels.output){return}var Z=y.panels.input.value;if(Z&&Z==S){return}else{S=Z}var Y=new Date().getTime();if(!V&&y.showdown){V=new y.showdown.converter()}if(V){Z=V.makeHtml(Z)}var X=new Date().getTime();M=X-Y;G(Z);O=Z};var U=function(){if(N){top.clearTimeout(N);N=undefined}if(P!=="manual"){var X=0;if(P==="delayed"){X=M}if(X>I){X=I}N=top.setTimeout(L,X)}};var J=function(X){if(X.scrollHeight<=X.clientHeight){return 1}return X.scrollTop/(X.scrollHeight-X.clientHeight)};var W=function(){if(y.panels.preview){y.panels.preview.scrollTop=(y.panels.preview.scrollHeight-y.panels.preview.clientHeight)*J(y.panels.preview)}if(y.panels.output){y.panels.output.scrollTop=(y.panels.output.scrollHeight-y.panels.output.clientHeight)*J(y.panels.output)}};this.refresh=function(X){if(X){S="";L()}else{U()}};this.processingTime=function(){return M};this.output=function(){return O};this.setUpdateMode=function(X){P=X;H.refresh()};var Q=true;var G=function(aa){var X=C.getTop(y.panels.input)-R();if(y.panels.output){if(y.panels.output.value!==undefined){y.panels.output.value=aa;y.panels.output.readOnly=true}else{var Z=aa.replace(/&/g,"&");Z=Z.replace(/</g,"<");y.panels.output.innerHTML="<pre><code>"+Z+"</code></pre>"}}if(y.panels.preview){y.panels.preview.innerHTML=aa}W();if(Q){Q=false;return}var Y=C.getTop(y.panels.input)-R();if(v.isIE){top.setTimeout(function(){top.scrollBy(0,Y-X)},0)}else{top.scrollBy(0,Y-X)}};var T=function(){K(y.panels.input,U);L();if(y.panels.preview){y.panels.preview.scrollTop=0}if(y.panels.output){y.panels.output.scrollTop=0}};this.destroy=function(){if(F){F.destroy()}};T()};h.doAutoindent=function(F,G){F.before=F.before.replace(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]*\n$/,"\n\n");F.before=F.before.replace(/(\n|^)[ ]{0,3}>[ \t]*\n$/,"\n\n");F.before=F.before.replace(/(\n|^)[ \t]+\n$/,"\n\n");if(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]+.*\n$/.test(F.before)){if(h.doList){h.doList(F)}}if(/(\n|^)[ ]{0,3}>[ \t]+.*\n$/.test(F.before)){if(h.doBlockquote){h.doBlockquote(F)}}if(/(\n|^)(\t|[ ]{4,}).*\n$/.test(F.before)){if(h.doCode){h.doCode(F)}}};h.doBlockquote=function(F,G){F.selection=F.selection.replace(/^(\n*)([^\r]+?)(\n*)$/,function(L,K,J,I){F.before+=K;F.after=I+F.after;return J});F.before=F.before.replace(/(>[ \t]*)$/,function(J,I){F.selection=I+F.selection;return""});F.selection=F.selection.replace(/^(\s|>)+$/,"");F.selection=F.selection||"Blockquote";if(F.before){F.before=F.before.replace(/\n?$/,"\n")}if(F.after){F.after=F.after.replace(/^\n?/,"\n")}F.before=F.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/,function(I){F.startTag=I;return""});F.after=F.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/,function(I){F.endTag=I;return""});var H=function(J){var I=J?"> ":"";if(F.startTag){F.startTag=F.startTag.replace(/\n((>|\s)*)\n$/,function(L,K){return"\n"+K.replace(/^[ ]{0,3}>?[ \t]*$/gm,I)+"\n"})}if(F.endTag){F.endTag=F.endTag.replace(/^\n((>|\s)*)\n/,function(L,K){return"\n"+K.replace(/^[ ]{0,3}>?[ \t]*$/gm,I)+"\n"})}};if(/^(?![ ]{0,3}>)/m.test(F.selection)){h.wrap(F,y.wmd_env.lineLength-2);F.selection=F.selection.replace(/^/gm,"> ");H(true);F.skipLines()}else{F.selection=F.selection.replace(/^[ ]{0,3}> ?/gm,"");h.unwrap(F);H(false);if(!/^(\n|^)[ ]{0,3}>/.test(F.selection)&&F.startTag){F.startTag=F.startTag.replace(/\n{0,2}$/,"\n\n")}if(!/(\n|^)[ ]{0,3}>.*$/.test(F.selection)&&F.endTag){F.endTag=F.endTag.replace(/^\n{0,2}/,"\n\n")}}if(!/\n/.test(F.selection)){F.selection=F.selection.replace(/^(> *)/,function(I,J){F.startTag+=J;return""})}};h.doCode=function(F,G){var I=/\S[ ]*$/.test(F.before);var K=/^[ ]*\S/.test(F.after);if((!K&&!I)||/\n/.test(F.selection)){F.before=F.before.replace(/[ ]{4}$/,function(L){F.selection=L+F.selection;return""});var J=1;var H=1;if(/\n(\t|[ ]{4,}).*\n$/.test(F.before)){J=0}if(/^\n(\t|[ ]{4,})/.test(F.after)){H=0}F.skipLines(J,H);if(!F.selection){F.startTag=" ";F.selection="enter code here"}else{if(/^[ ]{0,3}\S/m.test(F.selection)){F.selection=F.selection.replace(/^/gm," ")}else{F.selection=F.selection.replace(/^[ ]{4}/gm,"")}}}else{F.trimWhitespace();F.findTags(/`/,/`/);if(!F.startTag&&!F.endTag){F.startTag=F.endTag="`";if(!F.selection){F.selection="enter code here"}}else{if(F.endTag&&!F.startTag){F.before+=F.endTag;F.endTag=""}else{F.startTag=F.endTag=""}}}};h.doList=function(Q,J,I){var S=/(\n|^)(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*$/;var R=/^\n*(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*/;var F="-";var N=1;var L=function(){var T;if(I){T=" "+N+". ";N++}else{T=" "+F+" "}return T};var M=function(T){if(I===undefined){I=/^\s*\d/.test(T)}T=T.replace(/^[ ]{0,3}([*+-]|\d+[.])\s/gm,function(U){return L()});return T};Q.findTags(/(\n|^)*[ ]{0,3}([*+-]|\d+[.])\s+/,null);if(Q.before&&!/\n$/.test(Q.before)&&!/^\n/.test(Q.startTag)){Q.before+=Q.startTag;Q.startTag=""}if(Q.startTag){var H=/\d+[.]/.test(Q.startTag);Q.startTag="";Q.selection=Q.selection.replace(/\n[ ]{4}/g,"\n");h.unwrap(Q);Q.skipLines();if(H){Q.after=Q.after.replace(R,M)}if(I==H){return}}var K=1;Q.before=Q.before.replace(S,function(T){if(/^\s*([*+-])/.test(T)){F=s.$1}K=/[^\n]\n\n[^\n]/.test(T)?1:0;return M(T)});if(!Q.selection){Q.selection="List item"}var O=L();var G=1;Q.after=Q.after.replace(R,function(T){G=/[^\n]\n\n[^\n]/.test(T)?1:0;return M(T)});Q.trimWhitespace(true);Q.skipLines(K,G,true);Q.startTag=O;var P=O.replace(/./g," ");h.wrap(Q,y.wmd_env.lineLength-P.length);Q.selection=Q.selection.replace(/\n/g,"\n"+P)};h.doHeading=function(H,I){H.selection=H.selection.replace(/\s+/g," ");H.selection=H.selection.replace(/(^\s+|\s+$)/g,"");if(!H.selection){H.startTag="## ";H.selection="Heading";H.endTag=" ##";return}var J=0;H.findTags(/#+[ ]*/,/[ ]*#+/);if(/#+/.test(H.startTag)){J=s.lastMatch.length}H.startTag=H.endTag="";H.findTags(null,/\s?(-+|=+)/);if(/=+/.test(H.endTag)){J=1}if(/-+/.test(H.endTag)){J=2}H.startTag=H.endTag="";H.skipLines(1,1);var K=J==0?2:J-1;if(K>0){var G=K>=2?"-":"=";var F=H.selection.length;if(F>y.wmd_env.lineLength){F=y.wmd_env.lineLength}H.endTag="\n";while(F--){H.endTag+=G}}};h.doHorizontalRule=function(F,G){F.startTag="----------\n";F.selection="";F.skipLines(2,1,true)}};Attacklab.wmd_env={};Attacklab.account_options={};Attacklab.wmd_defaults={version:1,output:"Markdown",lineLength:40,delayLoad:false};if(!Attacklab.wmd){Attacklab.wmd=function(){Attacklab.loadEnv=function(){var b=function(d){if(!d){return}for(var c in d){Attacklab.wmd_env[c]=d[c]}};b(Attacklab.wmd_defaults);b(Attacklab.account_options);b(top.wmd_options);Attacklab.full=true;var a="bold italic link blockquote code image ol ul heading hr";Attacklab.wmd_env.buttons=Attacklab.wmd_env.buttons||a};Attacklab.loadEnv()};Attacklab.wmd();Attacklab.wmdBase();Attacklab.Util.startEditor()};
\ No newline at end of file diff --git a/askbot/skins/old/media/js/wmd/wmd-test.html b/askbot/skins/old/media/js/wmd/wmd-test.html new file mode 100644 index 00000000..d748501a --- /dev/null +++ b/askbot/skins/old/media/js/wmd/wmd-test.html @@ -0,0 +1,158 @@ +<!DOCTYPE html> +<html> + + <head> + <title>Test WMD Page</title> + + <link rel="stylesheet" type="text/css" href="wmd.css" /> + + <meta http-equiv="pragma" content="no-cache"> + <meta http-equiv="cache-control" content="no-cache"> + <meta http-equiv="pragma-directive" content="no-cache"> + <meta http-equiv="cache-directive" content="no-cache"> + <meta http-equiv="expires" content="0"> + + <script type="text/javascript" src="jQuery/jquery-1.2.6.js"></script> + <script type="text/javascript" src="showdown.js"></script> + </head> + + <body> + <div id="wmd-button-bar" class="wmd-panel"></div> + <br/> + <textarea id="editor" class="wmd-panel"></textarea> + <br/> + <div id="previewer" class="wmd-panel"></div> + <br/> + <div id="wmd-output" class="wmd-panel"></div> + + <p>To test that page up/down and arrow keys work, copy this above the WMD + control.</p> + + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + Scroll Down!<br/> + + <script type="text/javascript" src="wmd.js"></script> + </body> +</html>
\ No newline at end of file diff --git a/askbot/skins/old/media/js/wmd/wmd.css b/askbot/skins/old/media/js/wmd/wmd.css new file mode 100644 index 00000000..f1091a35 --- /dev/null +++ b/askbot/skins/old/media/js/wmd/wmd.css @@ -0,0 +1,130 @@ +/*body +{ + background-color: White +} +*/ +.wmd-panel +{ +} + +#wmd-button-bar +{ + background-color: White; +} + +#wmd-input +{ + height: 500px; + background-color: Gainsboro; + border: 1px solid DarkGray; + margin-top: -20px; +} + +#wmd-preview +{ + background-color: LightSkyBlue; +} + +#wmd-output +{ + background-color: Pink; +} + +#wmd-button-row +{ + position: relative; + margin-left: 5px; + margin-right: 5px; + margin-bottom: 5px; + margin-top: 10px; + padding: 0px; + height: 20px; +} + +.wmd-spacer +{ + width: 1px; + height: 20px; + margin-left: 14px; + + position: absolute; + background-color: Silver; + display: inline-block; + list-style: none; +} + +.wmd-button +{ + width: 20px; + height: 20px; + margin-left: 5px; + margin-right: 5px; + + position: absolute; + background-image: url(images/wmd-buttons.png); + background-repeat: no-repeat; + background-position: 0px 0px; + display: inline-block; + list-style: none; +} + +.wmd-button > a +{ + width: 20px; + height: 20px; + margin-left: 5px; + margin-right: 5px; + + position: absolute; + display: inline-block; +} + + +/* sprite button slicing style information */ +#wmd-button-bar #wmd-bold-button {left: 0px; background-position: 0px 0;} +#wmd-button-bar #wmd-italic-button {left: 25px; background-position: -20px 0;} +#wmd-button-bar #wmd-spacer1 {left: 50px;} +#wmd-button-bar #wmd-link-button {left: 75px; background-position: -40px 0;} +#wmd-button-bar #wmd-quote-button {left: 100px; background-position: -60px 0;} +#wmd-button-bar #wmd-code-button {left: 125px; background-position: -80px 0;} +#wmd-button-bar #wmd-image-button {left: 150px; background-position: -100px 0;} +#wmd-button-bar #wmd-attachment-button {left: 175px; background-position: -120px 0;} +#wmd-button-bar #wmd-spacer2 {left: 200px;} +#wmd-button-bar #wmd-olist-button {left: 225px; background-position: -140px 0;} +#wmd-button-bar #wmd-ulist-button {left: 250px; background-position: -160px 0;} +#wmd-button-bar #wmd-heading-button {left: 275px; background-position: -180px 0;} +#wmd-button-bar #wmd-hr-button {left: 300px; background-position: -200px 0;} +#wmd-button-bar #wmd-spacer3 {left: 325px;} +#wmd-button-bar #wmd-undo-button {left: 350px; background-position: -220px 0;} +#wmd-button-bar #wmd-redo-button {left: 375px; background-position: -240px 0;} +#wmd-button-bar #wmd-help-button {right: 0px; background-position: -260px 0;} + + +.wmd-prompt-background +{ + background-color: Black; +} + +.wmd-prompt-dialog +{ + border: 1px solid #999999; + background-color: #F5F5F5; +} + +.wmd-prompt-dialog > div { + font-size: 1em; + font-family: arial, helvetica, sans-serif; +} + + +.wmd-prompt-dialog > form > input[type="text"] { + border: 1px solid #999999; + color: black; +} + +.wmd-prompt-dialog > form > input[type="button"]{ + border: 1px solid #888888; + font-family: trebuchet MS, helvetica, sans-serif; + font-size: 1em; + font-weight: bold; +} diff --git a/askbot/skins/old/media/js/wmd/wmd.js b/askbot/skins/old/media/js/wmd/wmd.js new file mode 100644 index 00000000..bc3b5a0c --- /dev/null +++ b/askbot/skins/old/media/js/wmd/wmd.js @@ -0,0 +1,2438 @@ +var Attacklab = Attacklab || {}; + +Attacklab.wmdBase = function(){ + + // A few handy aliases for readability. + var wmd = top.Attacklab; + var doc = top.document; + var re = top.RegExp; + var nav = top.navigator; + + // Some namespaces. + wmd.Util = {}; + wmd.Position = {}; + wmd.Command = {}; + wmd.Global = {}; + + var util = wmd.Util; + var position = wmd.Position; + var command = wmd.Command; + var global = wmd.Global; + + + // Used to work around some browser bugs where we can't use feature testing. + global.isIE = /msie/.test(nav.userAgent.toLowerCase()); + global.isIE_5or6 = /msie 6/.test(nav.userAgent.toLowerCase()) || /msie 5/.test(nav.userAgent.toLowerCase()); + global.isIE_7plus = global.isIE && !global.isIE_5or6; + global.isOpera = /opera/.test(nav.userAgent.toLowerCase()); + global.isKonqueror = /konqueror/.test(nav.userAgent.toLowerCase()); + + var toolbar_strong_label = $.i18n._('bold') + " <strong> Ctrl-B"; + var toolbar_emphasis_label = $.i18n._('italic') + " <em> Ctrl-I"; + var toolbar_hyperlink_label = $.i18n._('link') + " <a> Ctrl-L"; + var toolbar_blockquote_label = $.i18n._('quote') + " <blockquote> Ctrl-."; + var toolbar_code_label = $.i18n._('preformatted text') + " <pre><code> Ctrl-K"; + var toolbar_image_label = $.i18n._('image') + " <img> Ctrl-G"; + var toolbar_attachment_label = $.i18n._('attachment') + " Ctrl-F"; + var toolbar_numbered_label = $.i18n._('numbered list') + " <ol> Ctrl-O"; + var toolbar_bulleted_label = $.i18n._('bulleted list') + " <ul> Ctrl-U"; + var toolbar_heading_label = $.i18n._('heading') + " <h1>/<h2> Ctrl-H"; + var toolbar_horizontal_label = $.i18n._('horizontal bar') + " <hr> Ctrl-R"; + var toolbar_undo_label = $.i18n._('undo') + " Ctrl-Z"; + var toolbar_redo_label = $.i18n._('redo') + " Ctrl-Y"; + + // ------------------------------------------------------------------- + // YOUR CHANGES GO HERE + // + // I've tried to localize the things you are likely to change to + // this area. + // ------------------------------------------------------------------- + + // The text that appears on the upper part of the dialog box when + // entering links. + var imageDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter image url') + '</p>'; + var linkDialogText = "<p style='margin-top: 0px'>" + $.i18n._('enter url') + '</p>'; + var fileDialogText = "<p>" + $.i18n._('upload file attachment') + '</p>'; + // The default text that appears in the dialog input box when entering + // links. + var imageDefaultText = "http://"; + var linkDefaultText = "http://"; + + // The location of your button images relative to the base directory. + var imageDirectory = "images/"; + + // Some intervals in ms. These can be adjusted to reduce the control's load. + var previewPollInterval = 500; + var pastePollInterval = 100; + + // The link and title for the help button + var helpLink = "http://wmd-editor.com/"; + var helpHoverTitle = "WMD website"; + var helpTarget = "_blank"; + var localUploadFileName = null; + + // ------------------------------------------------------------------- + // END OF YOUR CHANGES + // ------------------------------------------------------------------- + + // A collection of the important regions on the page. + // Cached so we don't have to keep traversing the DOM. + wmd.PanelCollection = function(){ + this.buttonBar = doc.getElementById("wmd-button-bar"); + this.preview = doc.getElementById("previewer"); + this.output = doc.getElementById("wmd-output"); + this.input = doc.getElementById("editor"); + }; + + // This PanelCollection object can't be filled until after the page + // has loaded. + wmd.panels = undefined; + + // Internet explorer has problems with CSS sprite buttons that use HTML + // lists. When you click on the background image "button", IE will + // select the non-existent link text and discard the selection in the + // textarea. The solution to this is to cache the textarea selection + // on the button's mousedown event and set a flag. In the part of the + // code where we need to grab the selection, we check for the flag + // and, if it's set, use the cached area instead of querying the + // textarea. + // + // This ONLY affects Internet Explorer (tested on versions 6, 7 + // and 8) and ONLY on button clicks. Keyboard shortcuts work + // normally since the focus never leaves the textarea. + wmd.ieCachedRange = null; // cached textarea selection + wmd.ieRetardedClick = false; // flag + + // Returns true if the DOM element is visible, false if it's hidden. + // Checks if display is anything other than none. + util.isVisible = function (elem) { + + if (window.getComputedStyle) { + // Most browsers + return window.getComputedStyle(elem, null).getPropertyValue("display") !== "none"; + } + else if (elem.currentStyle) { + // IE + return elem.currentStyle.display !== "none"; + } + }; + + + // Adds a listener callback to a DOM element which is fired on a specified + // event. + util.addEvent = function(elem, event, listener){ + if (elem.attachEvent) { + // IE only. The "on" is mandatory. + elem.attachEvent("on" + event, listener); + } + else { + // Other browsers. + elem.addEventListener(event, listener, false); + } + }; + + + // Removes a listener callback from a DOM element which is fired on a specified + // event. + util.removeEvent = function(elem, event, listener){ + if (elem.detachEvent) { + // IE only. The "on" is mandatory. + elem.detachEvent("on" + event, listener); + } + else { + // Other browsers. + elem.removeEventListener(event, listener, false); + } + }; + + // Converts \r\n and \r to \n. + util.fixEolChars = function(text){ + text = text.replace(/\r\n/g, "\n"); + text = text.replace(/\r/g, "\n"); + return text; + }; + + // Extends a regular expression. Returns a new RegExp + // using pre + regex + post as the expression. + // Used in a few functions where we have a base + // expression and we want to pre- or append some + // conditions to it (e.g. adding "$" to the end). + // The flags are unchanged. + // + // regex is a RegExp, pre and post are strings. + util.extendRegExp = function(regex, pre, post){ + + if (pre === null || pre === undefined) + { + pre = ""; + } + if(post === null || post === undefined) + { + post = ""; + } + + var pattern = regex.toString(); + var flags; + + // Replace the flags with empty space and store them. + pattern = pattern.replace(/\/([gim]*)$/, ""); + flags = re.$1; + + // Remove the slash delimiters on the regular expression. + pattern = pattern.replace(/(^\/|\/$)/g, ""); + pattern = pre + pattern + post; + + return new re(pattern, flags); + }; + + + // Sets the image for a button passed to the WMD editor. + // Returns a new element with the image attached. + // Adds several style properties to the image. + util.createImage = function(img){ + + var imgPath = imageDirectory + img; + + var elem = doc.createElement("img"); + elem.className = "wmd-button"; + elem.src = imgPath; + + return elem; + }; + + +// This simulates a modal dialog box and asks for the URL when you +// click the hyperlink or image buttons. +// +// text: The html for the input box. +// defaultInputText: The default value that appears in the input box. +// makeLinkMarkdown: The function which is executed when the prompt is dismissed, either via OK or Cancel +util.prompt = function(text, defaultInputText, makeLinkMarkdown, dialogType){ + + // These variables need to be declared at this level since they are used + // in multiple functions. + var dialog;// The dialog box. + var background;// The background beind the dialog box. + var input;// The text box where you enter the hyperlink. + + if (defaultInputText === undefined) { + defaultInputText = ""; + } + + // Used as a keydown event handler. Esc dismisses the prompt. + // Key code 27 is ESC. + var checkEscape = function(key){ + var code = (key.charCode || key.keyCode); + if (code === 27) { + close(true); + } + }; + + // Dismisses the hyperlink input box. + // isCancel is true if we don't care about the input text. + // isCancel is false if we are going to keep the text. + var close = function(isCancel){ + util.removeEvent(doc.body, "keydown", checkEscape); + var text = input.value; + + if (isCancel){ + text = null; + } + else{ + // Fixes common pasting errors. + text = text.replace('http://http://', 'http://'); + text = text.replace('http://https://', 'https://'); + text = text.replace('http://ftp://', 'ftp://'); + + if (text.indexOf('http://') === -1 && text.indexOf('ftp://') === -1) { + if (dialogType == 'link'){ + //add http only to urls + text = 'http://' + text; + } + } + } + + dialog.parentNode.removeChild(dialog); + background.parentNode.removeChild(background); + makeLinkMarkdown(text); + return false; + }; + + // Creates the background behind the hyperlink text entry box. + // Most of this has been moved to CSS but the div creation and + // browser-specific hacks remain here. + var createBackground = function(){ + + background = doc.createElement("div"); + background.className = "wmd-prompt-background"; + style = background.style; + style.position = "absolute"; + style.top = "0"; + + style.zIndex = "1000"; + + // Some versions of Konqueror don't support transparent colors + // so we make the whole window transparent. + // + // Is this necessary on modern konqueror browsers? + if (global.isKonqueror){ + style.backgroundColor = "transparent"; + } + else if (global.isIE){ + style.filter = "alpha(opacity=50)"; + } + else { + style.opacity = "0.5"; + } + + var pageSize = position.getPageSize(); + style.height = pageSize[1] + "px"; + + if(global.isIE){ + style.left = doc.documentElement.scrollLeft; + style.width = doc.documentElement.clientWidth; + } + else { + style.left = "0"; + style.width = "100%"; + } + + doc.body.appendChild(background); + }; + + // Create the text input box form/window. + var createDialog = function(){ + + // The main dialog box. + dialog = doc.createElement("div"); + dialog.className = "wmd-prompt-dialog"; + dialog.style.padding = "10px;"; + dialog.style.position = "fixed"; + dialog.style.width = "400px"; + dialog.style.zIndex = "1001"; + + // The dialog text. + var question = doc.createElement("div"); + question.innerHTML = text; + question.style.padding = "5px"; + dialog.appendChild(question); + + // The web form container for the text box and buttons. + var form = doc.createElement("form"); + form.onsubmit = function(){ return close(false); }; + style = form.style; + style.padding = "0"; + style.margin = "0"; + style.cssFloat = "left"; + style.width = "100%"; + style.textAlign = "center"; + style.position = "relative"; + dialog.appendChild(form); + + // The input text box + input = doc.createElement("input"); + if(dialogType == 'image' || dialogType == 'file'){ + input.id = "image-url"; + } + input.type = "text"; + if (dialogType == 'file'){ + input.disabled = "disabled"; + }; + + input.value = defaultInputText; + style = input.style; + style.display = "block"; + style.width = "80%"; + style.marginLeft = style.marginRight = "auto"; + form.appendChild(input); + + // The upload file input + if(dialogType == 'image' || dialogType == 'file'){ + var upload_container = $('<div></div>'); + var upload_input = $('<input type="file" />'); + upload_input.attr('name', 'file-upload'); + upload_input.attr('id', 'file-upload'); + upload_input.attr('size', 26); + + var startUploadHandler = function(){ + localUploadFileName = $(this).val(); + return ajaxFileUpload($('#image-url'), startUploadHandler); + }; + + upload_input.change(startUploadHandler); + + upload_container.append(upload_input); + upload_container.append($('<br/>')); + + var spinner = $('<img />'); + spinner.attr('id', 'loading'); + spinner.attr('src', mediaUrl("media/images/indicator.gif")); + spinner.css('display', 'none'); + + upload_container.append(spinner); + upload_container.css('padding', '5px'); + $(form).append(upload_container); + } + + // The ok button + var okButton = doc.createElement("input"); + okButton.type = "button"; + okButton.onclick = function(){ + var isCancel = false; + if ($.trim($(input).val()) === ''){ + isCancel = true; + } + return close(isCancel); + }; + okButton.value = "OK"; + style = okButton.style; + style.margin = "10px"; + style.display = "inline"; + style.width = "7em"; + + // The cancel button + var cancelButton = doc.createElement("input"); + cancelButton.type = "button"; + cancelButton.onclick = function(){ return close(true); }; + cancelButton.value = "Cancel"; + style = cancelButton.style; + style.margin = "10px"; + style.display = "inline"; + style.width = "7em"; + + // The order of these buttons is different on macs. + if (/mac/.test(nav.platform.toLowerCase())) { + form.appendChild(cancelButton); + form.appendChild(okButton); + } + else { + form.appendChild(okButton); + form.appendChild(cancelButton); + } + + util.addEvent(doc.body, "keydown", checkEscape); + dialog.style.top = "50%"; + dialog.style.left = "50%"; + dialog.style.display = "block"; + if(global.isIE_5or6){ + dialog.style.position = "absolute"; + dialog.style.top = doc.documentElement.scrollTop + 200 + "px"; + dialog.style.left = "50%"; + } + doc.body.appendChild(dialog); + + // This has to be done AFTER adding the dialog to the form if you + // want it to be centered. + dialog.style.marginTop = -(position.getHeight(dialog) / 2) + "px"; + dialog.style.marginLeft = -(position.getWidth(dialog) / 2) + "px"; + + }; + + createBackground(); + + // Why is this in a zero-length timeout? + // Is it working around a browser bug? + top.setTimeout(function(){ + createDialog(); + var defTextLen = defaultInputText.length; + if (input.type == 'text' && input.selectionStart !== undefined) { + input.selectionStart = 0; + input.selectionEnd = defTextLen; + } + else if (input.createTextRange) { + var range = input.createTextRange(); + range.collapse(false); + range.moveStart("character", -defTextLen); + range.moveEnd("character", defTextLen); + range.select(); + } + + input.focus(); + }, 0); +}; + + + // UNFINISHED + // The assignment in the while loop makes jslint cranky. + // I'll change it to a better loop later. + position.getTop = function(elem, isInner){ + var result = elem.offsetTop; + if (!isInner) { + while (elem.offsetParent) { + elem = elem.offsetParent; + result += elem.offsetTop; + } + } + return result; + }; + + position.getHeight = function (elem) { + return elem.offsetHeight || elem.scrollHeight; + }; + + position.getWidth = function (elem) { + return elem.offsetWidth || elem.scrollWidth; + }; + + position.getPageSize = function(){ + + var scrollWidth, scrollHeight; + var innerWidth, innerHeight; + + // It's not very clear which blocks work with which browsers. + if(self.innerHeight && self.scrollMaxY){ + scrollWidth = doc.body.scrollWidth; + scrollHeight = self.innerHeight + self.scrollMaxY; + } + else if(doc.body.scrollHeight > doc.body.offsetHeight){ + scrollWidth = doc.body.scrollWidth; + scrollHeight = doc.body.scrollHeight; + } + else{ + scrollWidth = doc.body.offsetWidth; + scrollHeight = doc.body.offsetHeight; + } + + if(self.innerHeight){ + // Non-IE browser + innerWidth = self.innerWidth; + innerHeight = self.innerHeight; + } + else if(doc.documentElement && doc.documentElement.clientHeight){ + // Some versions of IE (IE 6 w/ a DOCTYPE declaration) + innerWidth = doc.documentElement.clientWidth; + innerHeight = doc.documentElement.clientHeight; + } + else if(doc.body){ + // Other versions of IE + innerWidth = doc.body.clientWidth; + innerHeight = doc.body.clientHeight; + } + + var maxWidth = Math.max(scrollWidth, innerWidth); + var maxHeight = Math.max(scrollHeight, innerHeight); + return [maxWidth, maxHeight, innerWidth, innerHeight]; + }; + + // Watches the input textarea, polling at an interval and runs + // a callback function if anything has changed. + wmd.inputPoller = function(callback, interval){ + + var pollerObj = this; + var inputArea = wmd.panels.input; + + // Stored start, end and text. Used to see if there are changes to the input. + var lastStart; + var lastEnd; + var markdown; + + var killHandle; // Used to cancel monitoring on destruction. + // Checks to see if anything has changed in the textarea. + // If so, it runs the callback. + this.tick = function(){ + + if (!util.isVisible(inputArea)) { + return; + } + + // Update the selection start and end, text. + if (inputArea.selectionStart || inputArea.selectionStart === 0) { + var start = inputArea.selectionStart; + var end = inputArea.selectionEnd; + if (start != lastStart || end != lastEnd) { + lastStart = start; + lastEnd = end; + + if (markdown != inputArea.value) { + markdown = inputArea.value; + return true; + } + } + } + return false; + }; + + + var doTickCallback = function(){ + + if (!util.isVisible(inputArea)) { + return; + } + + // If anything has changed, call the function. + if (pollerObj.tick()) { + callback(); + } + }; + + // Set how often we poll the textarea for changes. + var assignInterval = function(){ + // previewPollInterval is set at the top of the namespace. + killHandle = top.setInterval(doTickCallback, interval); + }; + + this.destroy = function(){ + top.clearInterval(killHandle); + }; + + assignInterval(); + }; + + // Handles pushing and popping TextareaStates for undo/redo commands. + // I should rename the stack variables to list. + wmd.undoManager = function(callback){ + + var undoObj = this; + var undoStack = []; // A stack of undo states + var stackPtr = 0; // The index of the current state + var mode = "none"; + var lastState; // The last state + var poller; + var timer; // The setTimeout handle for cancelling the timer + var inputStateObj; + + // Set the mode for later logic steps. + var setMode = function(newMode, noSave){ + + if (mode != newMode) { + mode = newMode; + if (!noSave) { + saveState(); + } + } + + if (!global.isIE || mode != "moving") { + timer = top.setTimeout(refreshState, 1); + } + else { + inputStateObj = null; + } + }; + + var refreshState = function(){ + inputStateObj = new wmd.TextareaState(); + poller.tick(); + timer = undefined; + }; + + this.setCommandMode = function(){ + mode = "command"; + saveState(); + timer = top.setTimeout(refreshState, 0); + }; + + this.canUndo = function(){ + return stackPtr > 1; + }; + + this.canRedo = function(){ + if (undoStack[stackPtr + 1]) { + return true; + } + return false; + }; + + // Removes the last state and restores it. + this.undo = function(){ + + if (undoObj.canUndo()) { + if (lastState) { + // What about setting state -1 to null or checking for undefined? + lastState.restore(); + lastState = null; + } + else { + undoStack[stackPtr] = new wmd.TextareaState(); + undoStack[--stackPtr].restore(); + + if (callback) { + callback(); + } + } + } + + mode = "none"; + wmd.panels.input.focus(); + refreshState(); + }; + + // Redo an action. + this.redo = function(){ + + if (undoObj.canRedo()) { + + undoStack[++stackPtr].restore(); + + if (callback) { + callback(); + } + } + + mode = "none"; + wmd.panels.input.focus(); + refreshState(); + }; + + // Push the input area state to the stack. + var saveState = function(){ + + var currState = inputStateObj || new wmd.TextareaState(); + + if (!currState) { + return false; + } + if (mode == "moving") { + if (!lastState) { + lastState = currState; + } + return; + } + if (lastState) { + if (undoStack[stackPtr - 1].text != lastState.text) { + undoStack[stackPtr++] = lastState; + } + lastState = null; + } + undoStack[stackPtr++] = currState; + undoStack[stackPtr + 1] = null; + if (callback) { + callback(); + } + }; + + var handleCtrlYZ = function(event){ + + var handled = false; + + if (event.ctrlKey || event.metaKey) { + + // IE and Opera do not support charCode. + var keyCode = event.charCode || event.keyCode; + var keyCodeChar = String.fromCharCode(keyCode); + + switch (keyCodeChar) { + + case "y": + undoObj.redo(); + handled = true; + break; + + case "z": + if (!event.shiftKey) { + undoObj.undo(); + } + else { + undoObj.redo(); + } + handled = true; + break; + } + } + + if (handled) { + if (event.preventDefault) { + event.preventDefault(); + } + if (top.event) { + top.event.returnValue = false; + } + return; + } + }; + + // Set the mode depending on what is going on in the input area. + var handleModeChange = function(event){ + + if (!event.ctrlKey && !event.metaKey) { + + var keyCode = event.keyCode; + + if ((keyCode >= 33 && keyCode <= 40) || (keyCode >= 63232 && keyCode <= 63235)) { + // 33 - 40: page up/dn and arrow keys + // 63232 - 63235: page up/dn and arrow keys on safari + setMode("moving"); + } + else if (keyCode == 8 || keyCode == 46 || keyCode == 127) { + // 8: backspace + // 46: delete + // 127: delete + setMode("deleting"); + } + else if (keyCode == 13) { + // 13: Enter + setMode("newlines"); + } + else if (keyCode == 27) { + // 27: escape + setMode("escape"); + } + else if ((keyCode < 16 || keyCode > 20) && keyCode != 91) { + // 16-20 are shift, etc. + // 91: left window key + // I think this might be a little messed up since there are + // a lot of nonprinting keys above 20. + setMode("typing"); + } + } + }; + + var setEventHandlers = function(){ + + util.addEvent(wmd.panels.input, "keypress", function(event){ + // keyCode 89: y + // keyCode 90: z + if ((event.ctrlKey || event.metaKey) && (event.keyCode == 89 || event.keyCode == 90)) { + event.preventDefault(); + } + }); + + var handlePaste = function(){ + if (global.isIE || (inputStateObj && inputStateObj.text != wmd.panels.input.value)) { + if (timer === undefined) { + mode = "paste"; + saveState(); + refreshState(); + } + } + }; + + // pastePollInterval is specified at the beginning of this namespace. + poller = new wmd.inputPoller(handlePaste, pastePollInterval); + + util.addEvent(wmd.panels.input, "keydown", handleCtrlYZ); + util.addEvent(wmd.panels.input, "keydown", handleModeChange); + + util.addEvent(wmd.panels.input, "mousedown", function(){ + setMode("moving"); + }); + wmd.panels.input.onpaste = handlePaste; + wmd.panels.input.ondrop = handlePaste; + }; + + var init = function(){ + setEventHandlers(); + refreshState(); + saveState(); + }; + + this.destroy = function(){ + if (poller) { + poller.destroy(); + } + }; + + init(); + }; + + // I think my understanding of how the buttons and callbacks are stored in the array is incomplete. + wmd.editor = function(previewRefreshCallback){ + + if (!previewRefreshCallback) { + previewRefreshCallback = function(){}; + } + + var inputBox = wmd.panels.input; + + var offsetHeight = 0; + + var editObj = this; + + var mainDiv; + var mainSpan; + + var div; // This name is pretty ambiguous. I should rename this. + + // Used to cancel recurring events from setInterval. + var creationHandle; + + var undoMgr; // The undo manager + + // Perform the button's action. + var doClick = function(button){ + + inputBox.focus(); + + if (button.textOp) { + + if (undoMgr) { + undoMgr.setCommandMode(); + } + + var state = new wmd.TextareaState(); + + if (!state) { + return; + } + + var chunks = state.getChunks(); + + // Some commands launch a "modal" prompt dialog. Javascript + // can't really make a modal dialog box and the WMD code + // will continue to execute while the dialog is displayed. + // This prevents the dialog pattern I'm used to and means + // I can't do something like this: + // + // var link = CreateLinkDialog(); + // makeMarkdownLink(link); + // + // Instead of this straightforward method of handling a + // dialog I have to pass any code which would execute + // after the dialog is dismissed (e.g. link creation) + // in a function parameter. + // + // Yes this is awkward and I think it sucks, but there's + // no real workaround. Only the image and link code + // create dialogs and require the function pointers. + var fixupInputArea = function(){ + + inputBox.focus(); + + if (chunks) { + state.setChunks(chunks); + } + + state.restore(); + previewRefreshCallback(); + }; + + var noCleanup = button.textOp(chunks, fixupInputArea); + + if(!noCleanup) { + fixupInputArea(); + } + + } + + if (button.execute) { + button.execute(editObj); + } + }; + + var setUndoRedoButtonStates = function(){ + if(undoMgr){ + setupButton(document.getElementById("wmd-undo-button"), undoMgr.canUndo()); + setupButton(document.getElementById("wmd-redo-button"), undoMgr.canRedo()); + } + }; + + var setupButton = function(button, isEnabled) { + + var normalYShift = "0px"; + var disabledYShift = "-20px"; + var highlightYShift = "-40px"; + + if(isEnabled) { + button.style.backgroundPosition = button.XShift + " " + normalYShift; + button.onmouseover = function(){ + this.style.backgroundPosition = this.XShift + " " + highlightYShift; + }; + + button.onmouseout = function(){ + this.style.backgroundPosition = this.XShift + " " + normalYShift; + }; + + // IE tries to select the background image "button" text (it's + // implemented in a list item) so we have to cache the selection + // on mousedown. + if(global.isIE) { + button.onmousedown = function() { + wmd.ieRetardedClick = true; + wmd.ieCachedRange = document.selection.createRange(); + }; + } + + if (!button.isHelp) + { + button.onclick = function() { + if (this.onmouseout) { + this.onmouseout(); + } + doClick(this); + return false; + }; + } + } + else { + button.style.backgroundPosition = button.XShift + " " + disabledYShift; + button.onmouseover = button.onmouseout = button.onclick = function(){}; + } + }; + + var makeSpritedButtonRow = function(){ + var buttonBar = document.getElementById("wmd-button-bar"); + var normalYShift = "0px"; + var disabledYShift = "-20px"; + var highlightYShift = "-40px"; + + var buttonRow = document.createElement("ul"); + buttonRow.id = "wmd-button-row"; + buttonRow = buttonBar.appendChild(buttonRow); + + + var boldButton = document.createElement("li"); + boldButton.className = "wmd-button"; + boldButton.id = "wmd-bold-button"; + boldButton.title = toolbar_strong_label; + boldButton.XShift = "0px"; + boldButton.textOp = command.doBold; + setupButton(boldButton, true); + buttonRow.appendChild(boldButton); + + var italicButton = document.createElement("li"); + italicButton.className = "wmd-button"; + italicButton.id = "wmd-italic-button"; + italicButton.title = toolbar_emphasis_label; + italicButton.XShift = "-20px"; + italicButton.textOp = command.doItalic; + setupButton(italicButton, true); + buttonRow.appendChild(italicButton); + + var spacer1 = document.createElement("li"); + spacer1.className = "wmd-spacer"; + spacer1.id = "wmd-spacer1"; + buttonRow.appendChild(spacer1); + + var linkButton = document.createElement("li"); + linkButton.className = "wmd-button"; + linkButton.id = "wmd-link-button"; + linkButton.title = toolbar_hyperlink_label; + linkButton.XShift = "-40px"; + linkButton.textOp = function(chunk, postProcessing){ + return command.doLinkOrImage(chunk, postProcessing, 'link'); + }; + setupButton(linkButton, true); + buttonRow.appendChild(linkButton); + + var quoteButton = document.createElement("li"); + quoteButton.className = "wmd-button"; + quoteButton.id = "wmd-quote-button"; + quoteButton.title = toolbar_blockquote_label; + quoteButton.XShift = "-60px"; + quoteButton.textOp = command.doBlockquote; + setupButton(quoteButton, true); + buttonRow.appendChild(quoteButton); + + var codeButton = document.createElement("li"); + codeButton.className = "wmd-button"; + codeButton.id = "wmd-code-button"; + codeButton.title = toolbar_code_label; + codeButton.XShift = "-80px"; + codeButton.textOp = command.doCode; + setupButton(codeButton, true); + buttonRow.appendChild(codeButton); + + var imageButton = document.createElement("li"); + imageButton.className = "wmd-button"; + imageButton.id = "wmd-image-button"; + imageButton.title = toolbar_image_label; + imageButton.XShift = "-100px"; + imageButton.textOp = function(chunk, postProcessing){ + return command.doLinkOrImage(chunk, postProcessing, 'image'); + }; + setupButton(imageButton, true); + buttonRow.appendChild(imageButton); + + var attachmentButton = document.createElement("li"); + attachmentButton.className = "wmd-button"; + attachmentButton.id = "wmd-attachment-button"; + attachmentButton.title = toolbar_attachment_label; + attachmentButton.XShift = "-120px"; + attachmentButton.textOp = function(chunk, postProcessing){ + return command.doLinkOrImage(chunk, postProcessing, 'file'); + }; + setupButton(attachmentButton, true); + buttonRow.appendChild(attachmentButton); + + var spacer2 = document.createElement("li"); + spacer2.className = "wmd-spacer"; + spacer2.id = "wmd-spacer2"; + buttonRow.appendChild(spacer2); + + var olistButton = document.createElement("li"); + olistButton.className = "wmd-button"; + olistButton.id = "wmd-olist-button"; + olistButton.title = toolbar_numbered_label; + olistButton.XShift = "-140px"; + olistButton.textOp = function(chunk, postProcessing){ + command.doList(chunk, postProcessing, true); + }; + setupButton(olistButton, true); + buttonRow.appendChild(olistButton); + + var ulistButton = document.createElement("li"); + ulistButton.className = "wmd-button"; + ulistButton.id = "wmd-ulist-button"; + ulistButton.title = toolbar_bulleted_label; + ulistButton.XShift = "-160px"; + ulistButton.textOp = function(chunk, postProcessing){ + command.doList(chunk, postProcessing, false); + }; + setupButton(ulistButton, true); + buttonRow.appendChild(ulistButton); + + var headingButton = document.createElement("li"); + headingButton.className = "wmd-button"; + headingButton.id = "wmd-heading-button"; + headingButton.title = toolbar_heading_label; + headingButton.XShift = "-180px"; + headingButton.textOp = command.doHeading; + setupButton(headingButton, true); + buttonRow.appendChild(headingButton); + + var hrButton = document.createElement("li"); + hrButton.className = "wmd-button"; + hrButton.id = "wmd-hr-button"; + hrButton.title = toolbar_horizontal_label; + hrButton.XShift = "-200px"; + hrButton.textOp = command.doHorizontalRule; + setupButton(hrButton, true); + buttonRow.appendChild(hrButton); + + var spacer3 = document.createElement("li"); + spacer3.className = "wmd-spacer"; + spacer3.id = "wmd-spacer3"; + buttonRow.appendChild(spacer3); + + var undoButton = document.createElement("li"); + undoButton.className = "wmd-button"; + undoButton.id = "wmd-undo-button"; + undoButton.title = toolbar_undo_label; + undoButton.XShift = "-220px"; + undoButton.execute = function(manager){ + manager.undo(); + }; + setupButton(undoButton, true); + buttonRow.appendChild(undoButton); + + var redoButton = document.createElement("li"); + redoButton.className = "wmd-button"; + redoButton.id = "wmd-redo-button"; + redoButton.title = toolbar_redo_label; + if (/win/.test(nav.platform.toLowerCase())) { + redoButton.title = toolbar_redo_label; + } + else { + // mac and other non-Windows platforms + redoButton.title = $.i18n._('redo') + " - Ctrl+Shift+Z"; + } + redoButton.XShift = "-240px"; + redoButton.execute = function(manager){ + manager.redo(); + }; + setupButton(redoButton, true); + buttonRow.appendChild(redoButton); + /* + var helpButton = document.createElement("li"); + helpButton.className = "wmd-button"; + helpButton.id = "wmd-help-button"; + helpButton.XShift = "-240px"; + helpButton.isHelp = true; + + var helpAnchor = document.createElement("a"); + helpAnchor.href = helpLink; + helpAnchor.target = helpTarget + helpAnchor.title = helpHoverTitle; + helpButton.appendChild(helpAnchor); + + setupButton(helpButton, true); + buttonRow.appendChild(helpButton); + */ + setUndoRedoButtonStates(); + }; + + var setupEditor = function(){ + + if (/\?noundo/.test(doc.location.href)) { + wmd.nativeUndo = true; + } + + if (!wmd.nativeUndo) { + undoMgr = new wmd.undoManager(function(){ + previewRefreshCallback(); + setUndoRedoButtonStates(); + }); + } + + makeSpritedButtonRow(); + + + var keyEvent = "keydown"; + if (global.isOpera) { + keyEvent = "keypress"; + } + + util.addEvent(inputBox, keyEvent, function(key){ + + // Check to see if we have a button key and, if so execute the callback. + if (key.ctrlKey || key.metaKey) { + + var keyCode = key.charCode || key.keyCode; + var keyCodeStr = String.fromCharCode(keyCode).toLowerCase(); + + // Bugfix for messed up DEL and . + if (keyCode === 46) { + keyCodeStr = ""; + } + if (keyCode === 190) { + keyCodeStr = "."; + } + + switch(keyCodeStr) { + case "b": + doClick(document.getElementById("wmd-bold-button")); + break; + case "i": + doClick(document.getElementById("wmd-italic-button")); + break; + case "l": + doClick(document.getElementById("wmd-link-button")); + break; + case ".": + doClick(document.getElementById("wmd-quote-button")); + break; + case "k": + doClick(document.getElementById("wmd-code-button")); + break; + case "g": + doClick(document.getElementById("wmd-image-button")); + break; + case "o": + doClick(document.getElementById("wmd-olist-button")); + break; + case "u": + doClick(document.getElementById("wmd-ulist-button")); + break; + case "h": + doClick(document.getElementById("wmd-heading-button")); + break; + case "r": + doClick(document.getElementById("wmd-hr-button")); + break; + case "y": + doClick(document.getElementById("wmd-redo-button")); + break; + case "z": + if(key.shiftKey) { + doClick(document.getElementById("wmd-redo-button")); + } + else { + doClick(document.getElementById("wmd-undo-button")); + } + break; + default: + return; + } + + + if (key.preventDefault) { + key.preventDefault(); + } + + if (top.event) { + top.event.returnValue = false; + } + } + }); + + // Auto-indent on shift-enter + util.addEvent(inputBox, "keyup", function(key){ + if (key.shiftKey && !key.ctrlKey && !key.metaKey) { + var keyCode = key.charCode || key.keyCode; + // Character 13 is Enter + if (keyCode === 13) { + fakeButton = {}; + fakeButton.textOp = command.doAutoindent; + doClick(fakeButton); + } + } + }); + + if (inputBox.form) { + var submitCallback = inputBox.form.onsubmit; + inputBox.form.onsubmit = function(){ + convertToHtml(); + if (submitCallback) { + return submitCallback.apply(this, arguments); + } + }; + } + }; + + // Convert the contents of the input textarea to HTML in the output/preview panels. + var convertToHtml = function(){ + + if (wmd.showdown) { + var markdownConverter = new wmd.showdown.converter(); + } + var text = inputBox.value; + + var callback = function(){ + inputBox.value = text; + //value is assigned here + }; + + if (!/markdown/.test(wmd.wmd_env.output.toLowerCase())) { + if (markdownConverter) { + inputBox.value = markdownConverter.makeHtml(text); + //value is assigned here + top.setTimeout(callback, 0); + } + } + return true; + }; + + + this.undo = function(){ + if (undoMgr) { + undoMgr.undo(); + } + }; + + this.redo = function(){ + if (undoMgr) { + undoMgr.redo(); + } + }; + + // This is pretty useless. The setupEditor function contents + // should just be copied here. + var init = function(){ + setupEditor(); + }; + + this.destroy = function(){ + if (undoMgr) { + undoMgr.destroy(); + } + if (div.parentNode) { + div.parentNode.removeChild(div); + } + if (inputBox) { + inputBox.style.marginTop = ""; + } + top.clearInterval(creationHandle); + }; + + init(); + }; + + // The input textarea state/contents. + // This is used to implement undo/redo by the undo manager. + wmd.TextareaState = function(){ + + // Aliases + var stateObj = this; + var inputArea = wmd.panels.input; + + this.init = function() { + + if (!util.isVisible(inputArea)) { + return; + } + + this.setInputAreaSelectionStartEnd(); + this.scrollTop = inputArea.scrollTop; + if (!this.text && inputArea.selectionStart || inputArea.selectionStart === 0) { + this.text = inputArea.value; + } + + }; + + // Sets the selected text in the input box after we've performed an + // operation. + this.setInputAreaSelection = function(){ + + if (!util.isVisible(inputArea)) { + return; + } + + if (inputArea.selectionStart !== undefined && !global.isOpera) { + + inputArea.focus(); + inputArea.selectionStart = stateObj.start; + inputArea.selectionEnd = stateObj.end; + inputArea.scrollTop = stateObj.scrollTop; + } + else if (doc.selection) { + + if (doc.activeElement && doc.activeElement !== inputArea) { + return; + } + + inputArea.focus(); + var range = inputArea.createTextRange(); + range.moveStart("character", -inputArea.value.length); + range.moveEnd("character", -inputArea.value.length); + range.moveEnd("character", stateObj.end); + range.moveStart("character", stateObj.start); + range.select(); + } + }; + + this.setInputAreaSelectionStartEnd = function(){ + + if (inputArea.selectionStart || inputArea.selectionStart === 0) { + + stateObj.start = inputArea.selectionStart; + stateObj.end = inputArea.selectionEnd; + } + else if (doc.selection) { + + stateObj.text = util.fixEolChars(inputArea.value); + + // IE loses the selection in the textarea when buttons are + // clicked. On IE we cache the selection and set a flag + // which we check for here. + var range; + if(wmd.ieRetardedClick && wmd.ieCachedRange) { + range = wmd.ieCachedRange; + wmd.ieRetardedClick = false; + } + else { + range = doc.selection.createRange(); + } + + var fixedRange = util.fixEolChars(range.text); + var marker = "\x07"; + var markedRange = marker + fixedRange + marker; + range.text = markedRange; + var inputText = util.fixEolChars(inputArea.value); + + range.moveStart("character", -markedRange.length); + range.text = fixedRange; + + stateObj.start = inputText.indexOf(marker); + stateObj.end = inputText.lastIndexOf(marker) - marker.length; + + var len = stateObj.text.length - util.fixEolChars(inputArea.value).length; + + if (len) { + range.moveStart("character", -fixedRange.length); + while (len--) { + fixedRange += "\n"; + stateObj.end += 1; + } + range.text = fixedRange; + } + + this.setInputAreaSelection(); + } + }; + + // Restore this state into the input area. + this.restore = function(){ + + if (stateObj.text !== undefined && stateObj.text != inputArea.value) { + inputArea.value = stateObj.text; + //value is assigned here + } + this.setInputAreaSelection(); + inputArea.scrollTop = stateObj.scrollTop; + }; + + // Gets a collection of HTML chunks from the inptut textarea. + this.getChunks = function(){ + + var chunk = new wmd.Chunks(); + + chunk.before = util.fixEolChars(stateObj.text.substring(0, stateObj.start)); + chunk.startTag = ""; + chunk.selection = util.fixEolChars(stateObj.text.substring(stateObj.start, stateObj.end)); + chunk.endTag = ""; + chunk.after = util.fixEolChars(stateObj.text.substring(stateObj.end)); + chunk.scrollTop = stateObj.scrollTop; + + return chunk; + }; + + // Sets the TextareaState properties given a chunk of markdown. + this.setChunks = function(chunk){ + + chunk.before = chunk.before + chunk.startTag; + chunk.after = chunk.endTag + chunk.after; + + if (global.isOpera) { + chunk.before = chunk.before.replace(/\n/g, "\r\n"); + chunk.selection = chunk.selection.replace(/\n/g, "\r\n"); + chunk.after = chunk.after.replace(/\n/g, "\r\n"); + } + + this.start = chunk.before.length; + this.end = chunk.before.length + chunk.selection.length; + this.text = chunk.before + chunk.selection + chunk.after; + this.scrollTop = chunk.scrollTop; + }; + + this.init(); + }; + + // before: contains all the text in the input box BEFORE the selection. + // after: contains all the text in the input box AFTER the selection. + wmd.Chunks = function(){ + }; + + // startRegex: a regular expression to find the start tag + // endRegex: a regular expresssion to find the end tag + wmd.Chunks.prototype.findTags = function(startRegex, endRegex){ + + var chunkObj = this; + var regex; + + if (startRegex) { + + regex = util.extendRegExp(startRegex, "", "$"); + + this.before = this.before.replace(regex, + function(match){ + chunkObj.startTag = chunkObj.startTag + match; + return ""; + }); + + regex = util.extendRegExp(startRegex, "^", ""); + + this.selection = this.selection.replace(regex, + function(match){ + chunkObj.startTag = chunkObj.startTag + match; + return ""; + }); + } + + if (endRegex) { + + regex = util.extendRegExp(endRegex, "", "$"); + + this.selection = this.selection.replace(regex, + function(match){ + chunkObj.endTag = match + chunkObj.endTag; + return ""; + }); + + regex = util.extendRegExp(endRegex, "^", ""); + + this.after = this.after.replace(regex, + function(match){ + chunkObj.endTag = match + chunkObj.endTag; + return ""; + }); + } + }; + + // If remove is false, the whitespace is transferred + // to the before/after regions. + // + // If remove is true, the whitespace disappears. + wmd.Chunks.prototype.trimWhitespace = function(remove){ + + this.selection = this.selection.replace(/^(\s*)/, ""); + + if (!remove) { + this.before += re.$1; + } + + this.selection = this.selection.replace(/(\s*)$/, ""); + + if (!remove) { + this.after = re.$1 + this.after; + } + }; + + + wmd.Chunks.prototype.skipLines = function(nLinesBefore, nLinesAfter, findExtraNewlines){ + + if (nLinesBefore === undefined) { + nLinesBefore = 1; + } + + if (nLinesAfter === undefined) { + nLinesAfter = 1; + } + + nLinesBefore++; + nLinesAfter++; + + var regexText; + var replacementText; + + this.selection = this.selection.replace(/(^\n*)/, ""); + this.startTag = this.startTag + re.$1; + this.selection = this.selection.replace(/(\n*$)/, ""); + this.endTag = this.endTag + re.$1; + this.startTag = this.startTag.replace(/(^\n*)/, ""); + this.before = this.before + re.$1; + this.endTag = this.endTag.replace(/(\n*$)/, ""); + this.after = this.after + re.$1; + + if (this.before) { + + regexText = replacementText = ""; + + while (nLinesBefore--) { + regexText += "\\n?"; + replacementText += "\n"; + } + + if (findExtraNewlines) { + regexText = "\\n*"; + } + this.before = this.before.replace(new re(regexText + "$", ""), replacementText); + } + + if (this.after) { + + regexText = replacementText = ""; + + while (nLinesAfter--) { + regexText += "\\n?"; + replacementText += "\n"; + } + if (findExtraNewlines) { + regexText = "\\n*"; + } + + this.after = this.after.replace(new re(regexText, ""), replacementText); + } + }; + + // The markdown symbols - 4 spaces = code, > = blockquote, etc. + command.prefixes = "(?:\\s{4,}|\\s*>|\\s*-\\s+|\\s*\\d+\\.|=|\\+|-|_|\\*|#|\\s*\\[[^\n]]+\\]:)"; + + // Remove markdown symbols from the chunk selection. + command.unwrap = function(chunk){ + var txt = new re("([^\\n])\\n(?!(\\n|" + command.prefixes + "))", "g"); + chunk.selection = chunk.selection.replace(txt, "$1 $2"); + }; + + command.wrap = function(chunk, len){ + command.unwrap(chunk); + var regex = new re("(.{1," + len + "})( +|$\\n?)", "gm"); + + chunk.selection = chunk.selection.replace(regex, function(line, marked){ + if (new re("^" + command.prefixes, "").test(line)) { + return line; + } + return marked + "\n"; + }); + + chunk.selection = chunk.selection.replace(/\s+$/, ""); + }; + + command.doBold = function(chunk, postProcessing){ + return command.doBorI(chunk, postProcessing, 2, "strong text"); + }; + + command.doItalic = function(chunk, postProcessing){ + return command.doBorI(chunk, postProcessing, 1, "emphasized text"); + }; + + // chunk: The selected region that will be enclosed with */** + // nStars: 1 for italics, 2 for bold + // insertText: If you just click the button without highlighting text, this gets inserted + command.doBorI = function(chunk, postProcessing, nStars, insertText){ + + // Get rid of whitespace and fixup newlines. + chunk.trimWhitespace(); + chunk.selection = chunk.selection.replace(/\n{2,}/g, "\n"); + + // Look for stars before and after. Is the chunk already marked up? + chunk.before.search(/(\**$)/); + var starsBefore = re.$1; + + chunk.after.search(/(^\**)/); + var starsAfter = re.$1; + + var prevStars = Math.min(starsBefore.length, starsAfter.length); + + // Remove stars if we have to since the button acts as a toggle. + if ((prevStars >= nStars) && (prevStars != 2 || nStars != 1)) { + chunk.before = chunk.before.replace(re("[*]{" + nStars + "}$", ""), ""); + chunk.after = chunk.after.replace(re("^[*]{" + nStars + "}", ""), ""); + } + else if (!chunk.selection && starsAfter) { + // It's not really clear why this code is necessary. It just moves + // some arbitrary stuff around. + chunk.after = chunk.after.replace(/^([*_]*)/, ""); + chunk.before = chunk.before.replace(/(\s?)$/, ""); + var whitespace = re.$1; + chunk.before = chunk.before + starsAfter + whitespace; + } + else { + + // In most cases, if you don't have any selected text and click the button + // you'll get a selected, marked up region with the default text inserted. + if (!chunk.selection && !starsAfter) { + chunk.selection = insertText; + } + + // Add the true markup. + var markup = nStars <= 1 ? "*" : "**"; // shouldn't the test be = ? + chunk.before = chunk.before + markup; + chunk.after = markup + chunk.after; + } + + return; + }; + + command.stripLinkDefs = function(text, defsToAdd){ + + text = text.replace(/^[ ]{0,3}\[(\d+)\]:[ \t]*\n?[ \t]*<?(\S+?)>?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|$)/gm, + function(totalMatch, id, link, newlines, title){ + defsToAdd[id] = totalMatch.replace(/\s*$/, ""); + if (newlines) { + // Strip the title and return that separately. + defsToAdd[id] = totalMatch.replace(/["(](.+?)[")]$/, ""); + return newlines + title; + } + return ""; + }); + + return text; + }; + + command.addLinkDef = function(chunk, linkDef){ + + var refNumber = 0; // The current reference number + var defsToAdd = {}; // + // Start with a clean slate by removing all previous link definitions. + chunk.before = command.stripLinkDefs(chunk.before, defsToAdd); + chunk.selection = command.stripLinkDefs(chunk.selection, defsToAdd); + chunk.after = command.stripLinkDefs(chunk.after, defsToAdd); + + var defs = ""; + var regex = /(\[(?:\[[^\]]*\]|[^\[\]])*\][ ]?(?:\n[ ]*)?\[)(\d+)(\])/g; + + var addDefNumber = function(def){ + refNumber++; + def = def.replace(/^[ ]{0,3}\[(\d+)\]:/, " [" + refNumber + "]:"); + defs += "\n" + def; + }; + + var getLink = function(wholeMatch, link, id, end){ + + if (defsToAdd[id]) { + addDefNumber(defsToAdd[id]); + return link + refNumber + end; + + } + return wholeMatch; + }; + + chunk.before = chunk.before.replace(regex, getLink); + + if (linkDef) { + addDefNumber(linkDef); + } + else { + chunk.selection = chunk.selection.replace(regex, getLink); + } + + var refOut = refNumber; + + chunk.after = chunk.after.replace(regex, getLink); + + if (chunk.after) { + chunk.after = chunk.after.replace(/\n*$/, ""); + } + if (!chunk.after) { + chunk.selection = chunk.selection.replace(/\n*$/, ""); + } + + chunk.after += "\n\n" + defs; + + return refOut; + }; + + command.doLinkOrImage = function(chunk, postProcessing, itemType){ + + chunk.trimWhitespace(); + chunk.findTags(/\s*!?\[/, /\][ ]?(?:\n[ ]*)?(\[.*?\])?/); + + if (chunk.endTag.length > 1) { + + chunk.startTag = chunk.startTag.replace(/!?\[/, ""); + chunk.endTag = ""; + command.addLinkDef(chunk, null); + + } + else { + + if (/\n\n/.test(chunk.selection)) { + command.addLinkDef(chunk, null); + return; + } + + // The function to be executed when you enter a link and press OK or Cancel. + // Marks up the link and adds the ref. + var makeLinkMarkdown = function(link){ + + if (link !== null) { + + chunk.startTag = chunk.endTag = ""; + //var linkDef = " [999]: " + link; + + //var num = command.addLinkDef(chunk, linkDef); + chunk.startTag = (itemType == 'image') ? "![" : "["; + chunk.endTag = "](" + link + ")"; + + if (!chunk.selection) { + if (itemType == 'image') { + chunk.selection = $.i18n._("image description"); + } + else if (itemType == 'file'){ + chunk.selection = localUploadFileName || $.i18n._("file name"); + localUploadFileName = null; + } + else { + chunk.selection = $.i18n._("link text"); + } + } + } + else { + if (itemType == 'image' || itemType == 'file'){ + return; + } + } + postProcessing(); + }; + + if (itemType == 'image') { + // add forth param to identify image window + util.prompt(imageDialogText, imageDefaultText, makeLinkMarkdown, 'image'); + } + else if (itemType == 'file'){ + util.prompt(fileDialogText, '', makeLinkMarkdown, 'file'); + } + else { + util.prompt(linkDialogText, linkDefaultText, makeLinkMarkdown, 'link'); + } + return true; + } +}; + + util.makeAPI = function(){ + wmd.wmd = {}; + wmd.wmd.editor = wmd.editor; + wmd.wmd.previewManager = wmd.previewManager; + }; + + util.startEditor = function(){ + + if (wmd.wmd_env.autostart === false) { + util.makeAPI(); + return; + } + + var edit; // The editor (buttons + input + outputs) - the main object. + var previewMgr; // The preview manager. + + // Fired after the page has fully loaded. + var loadListener = function(){ + + wmd.panels = new wmd.PanelCollection(); + + previewMgr = new wmd.previewManager(); + var previewRefreshCallback = previewMgr.refresh; + + edit = new wmd.editor(previewRefreshCallback); + + previewMgr.refresh(true); + + }; + + util.addEvent(top, "load", loadListener); + }; + + wmd.previewManager = function(){ + + var managerObj = this; + var converter; + var poller; + var timeout; + var elapsedTime; + var oldInputText; + var htmlOut; + var maxDelay = 3000; + var startType = "delayed"; // The other legal value is "manual" + + // Adds event listeners to elements and creates the input poller. + var setupEvents = function(inputElem, listener){ + + util.addEvent(inputElem, "input", listener); + inputElem.onpaste = listener; + inputElem.ondrop = listener; + + util.addEvent(inputElem, "keypress", listener); + util.addEvent(inputElem, "keydown", listener); + // previewPollInterval is set at the top of this file. + poller = new wmd.inputPoller(listener, previewPollInterval); + }; + + var getDocScrollTop = function(){ + + var result = 0; + + if (top.innerHeight) { + result = top.pageYOffset; + } + else + if (doc.documentElement && doc.documentElement.scrollTop) { + result = doc.documentElement.scrollTop; + } + else + if (doc.body) { + result = doc.body.scrollTop; + } + + return result; + }; + + var makePreviewHtml = function(){ + + // If there are no registered preview and output panels + // there is nothing to do. + if (!wmd.panels.preview && !wmd.panels.output) { + return; + } + + var text = wmd.panels.input.value; + if (text && text == oldInputText) { + return; // Input text hasn't changed. + } + else { + oldInputText = text; + } + + var prevTime = new Date().getTime(); + + if (!converter && wmd.showdown) { + converter = new wmd.showdown.converter(); + } + + if (converter) { + text = converter.makeHtml(text); + } + + // Calculate the processing time of the HTML creation. + // It's used as the delay time in the event listener. + var currTime = new Date().getTime(); + elapsedTime = currTime - prevTime; + + pushPreviewHtml(text); + htmlOut = text; + }; + + // setTimeout is already used. Used as an event listener. + var applyTimeout = function(){ + + if (timeout) { + top.clearTimeout(timeout); + timeout = undefined; + } + + if (startType !== "manual") { + + var delay = 0; + + if (startType === "delayed") { + delay = elapsedTime; + } + + if (delay > maxDelay) { + delay = maxDelay; + } + timeout = top.setTimeout(makePreviewHtml, delay); + } + }; + + var getScaleFactor = function(panel){ + if (panel.scrollHeight <= panel.clientHeight) { + return 1; + } + return panel.scrollTop / (panel.scrollHeight - panel.clientHeight); + }; + + var setPanelScrollTops = function(){ + + if (wmd.panels.preview) { + wmd.panels.preview.scrollTop = (wmd.panels.preview.scrollHeight - wmd.panels.preview.clientHeight) * getScaleFactor(wmd.panels.preview); + } + + if (wmd.panels.output) { + wmd.panels.output.scrollTop = (wmd.panels.output.scrollHeight - wmd.panels.output.clientHeight) * getScaleFactor(wmd.panels.output); + } + }; + + this.refresh = function(requiresRefresh){ + + if (requiresRefresh) { + oldInputText = ""; + makePreviewHtml(); + } + else { + applyTimeout(); + } + }; + + this.processingTime = function(){ + return elapsedTime; + }; + + // The output HTML + this.output = function(){ + return htmlOut; + }; + + // The mode can be "manual" or "delayed" + this.setUpdateMode = function(mode){ + startType = mode; + managerObj.refresh(); + }; + + var isFirstTimeFilled = true; + + var pushPreviewHtml = function(text){ + + var emptyTop = position.getTop(wmd.panels.input) - getDocScrollTop(); + + // Send the encoded HTML to the output textarea/div. + if (wmd.panels.output) { + // The value property is only defined if the output is a textarea. + if (wmd.panels.output.value !== undefined) { + wmd.panels.output.value = text; + //value is assigned here + wmd.panels.output.readOnly = true; + } + // Otherwise we are just replacing the text in a div. + // Send the HTML wrapped in <pre><code> + else { + var newText = text.replace(/&/g, "&"); + newText = newText.replace(/</g, "<"); + wmd.panels.output.innerHTML = "<pre><code>" + newText + "</code></pre>"; + } + } + + if (wmd.panels.preview) { + wmd.panels.preview.innerHTML = text; + } + + setPanelScrollTops(); + + if (isFirstTimeFilled) { + isFirstTimeFilled = false; + return; + } + + var fullTop = position.getTop(wmd.panels.input) - getDocScrollTop(); + + if (global.isIE) { + top.setTimeout(function(){ + top.scrollBy(0, fullTop - emptyTop); + }, 0); + } + else { + top.scrollBy(0, fullTop - emptyTop); + } + }; + + var init = function(){ + + setupEvents(wmd.panels.input, applyTimeout); + makePreviewHtml(); + + if (wmd.panels.preview) { + wmd.panels.preview.scrollTop = 0; + } + if (wmd.panels.output) { + wmd.panels.output.scrollTop = 0; + } + }; + + this.destroy = function(){ + if (poller) { + poller.destroy(); + } + }; + + init(); + }; + + // When making a list, hitting shift-enter will put your cursor on the next line + // at the current indent level. + command.doAutoindent = function(chunk, postProcessing){ + + chunk.before = chunk.before.replace(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]*\n$/, "\n\n"); + chunk.before = chunk.before.replace(/(\n|^)[ ]{0,3}>[ \t]*\n$/, "\n\n"); + chunk.before = chunk.before.replace(/(\n|^)[ \t]+\n$/, "\n\n"); + + if(/(\n|^)[ ]{0,3}([*+-]|\d+[.])[ \t]+.*\n$/.test(chunk.before)){ + if(command.doList){ + command.doList(chunk); + } + } + if(/(\n|^)[ ]{0,3}>[ \t]+.*\n$/.test(chunk.before)){ + if(command.doBlockquote){ + command.doBlockquote(chunk); + } + } + if(/(\n|^)(\t|[ ]{4,}).*\n$/.test(chunk.before)){ + if(command.doCode){ + command.doCode(chunk); + } + } + }; + + command.doBlockquote = function(chunk, postProcessing){ + + chunk.selection = chunk.selection.replace(/^(\n*)([^\r]+?)(\n*)$/, + function(totalMatch, newlinesBefore, text, newlinesAfter){ + chunk.before += newlinesBefore; + chunk.after = newlinesAfter + chunk.after; + return text; + }); + + chunk.before = chunk.before.replace(/(>[ \t]*)$/, + function(totalMatch, blankLine){ + chunk.selection = blankLine + chunk.selection; + return ""; + }); + + chunk.selection = chunk.selection.replace(/^(\s|>)+$/ ,""); + chunk.selection = chunk.selection || "Blockquote"; + + if(chunk.before){ + chunk.before = chunk.before.replace(/\n?$/,"\n"); + } + if(chunk.after){ + chunk.after = chunk.after.replace(/^\n?/,"\n"); + } + + chunk.before = chunk.before.replace(/(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*$)/, + function(totalMatch){ + chunk.startTag = totalMatch; + return ""; + }); + + chunk.after = chunk.after.replace(/^(((\n|^)(\n[ \t]*)*>(.+\n)*.*)+(\n[ \t]*)*)/, + function(totalMatch){ + chunk.endTag = totalMatch; + return ""; + }); + + var replaceBlanksInTags = function(useBracket){ + + var replacement = useBracket ? "> " : ""; + + if(chunk.startTag){ + chunk.startTag = chunk.startTag.replace(/\n((>|\s)*)\n$/, + function(totalMatch, markdown){ + return "\n" + markdown.replace(/^[ ]{0,3}>?[ \t]*$/gm, replacement) + "\n"; + }); + } + if(chunk.endTag){ + chunk.endTag = chunk.endTag.replace(/^\n((>|\s)*)\n/, + function(totalMatch, markdown){ + return "\n" + markdown.replace(/^[ ]{0,3}>?[ \t]*$/gm, replacement) + "\n"; + }); + } + }; + + if(/^(?![ ]{0,3}>)/m.test(chunk.selection)){ + command.wrap(chunk, wmd.wmd_env.lineLength - 2); + chunk.selection = chunk.selection.replace(/^/gm, "> "); + replaceBlanksInTags(true); + chunk.skipLines(); + } + else{ + chunk.selection = chunk.selection.replace(/^[ ]{0,3}> ?/gm, ""); + command.unwrap(chunk); + replaceBlanksInTags(false); + + if(!/^(\n|^)[ ]{0,3}>/.test(chunk.selection) && chunk.startTag){ + chunk.startTag = chunk.startTag.replace(/\n{0,2}$/, "\n\n"); + } + + if(!/(\n|^)[ ]{0,3}>.*$/.test(chunk.selection) && chunk.endTag){ + chunk.endTag=chunk.endTag.replace(/^\n{0,2}/, "\n\n"); + } + } + + if(!/\n/.test(chunk.selection)){ + chunk.selection = chunk.selection.replace(/^(> *)/, + function(wholeMatch, blanks){ + chunk.startTag += blanks; + return ""; + }); + } + }; + + command.doCode = function(chunk, postProcessing){ + + var hasTextBefore = /\S[ ]*$/.test(chunk.before); + var hasTextAfter = /^[ ]*\S/.test(chunk.after); + + // Use 'four space' markdown if the selection is on its own + // line or is multiline. + if((!hasTextAfter && !hasTextBefore) || /\n/.test(chunk.selection)){ + + chunk.before = chunk.before.replace(/[ ]{4}$/, + function(totalMatch){ + chunk.selection = totalMatch + chunk.selection; + return ""; + }); + + var nLinesBack = 1; + var nLinesForward = 1; + + if(/\n(\t|[ ]{4,}).*\n$/.test(chunk.before)){ + nLinesBack = 0; + } + if(/^\n(\t|[ ]{4,})/.test(chunk.after)){ + nLinesForward = 0; + } + + chunk.skipLines(nLinesBack, nLinesForward); + + if(!chunk.selection){ + chunk.startTag = " "; + chunk.selection = "enter code here"; + } + else { + if(/^[ ]{0,3}\S/m.test(chunk.selection)){ + chunk.selection = chunk.selection.replace(/^/gm, " "); + } + else{ + chunk.selection = chunk.selection.replace(/^[ ]{4}/gm, ""); + } + } + } + else{ + // Use backticks (`) to delimit the code block. + + chunk.trimWhitespace(); + chunk.findTags(/`/, /`/); + + if(!chunk.startTag && !chunk.endTag){ + chunk.startTag = chunk.endTag="`"; + if(!chunk.selection){ + chunk.selection = "enter code here"; + } + } + else if(chunk.endTag && !chunk.startTag){ + chunk.before += chunk.endTag; + chunk.endTag = ""; + } + else{ + chunk.startTag = chunk.endTag=""; + } + } + }; + + command.doList = function(chunk, postProcessing, isNumberedList){ + + // These are identical except at the very beginning and end. + // Should probably use the regex extension function to make this clearer. + var previousItemsRegex = /(\n|^)(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*$/; + var nextItemsRegex = /^\n*(([ ]{0,3}([*+-]|\d+[.])[ \t]+.*)(\n.+|\n{2,}([*+-].*|\d+[.])[ \t]+.*|\n{2,}[ \t]+\S.*)*)\n*/; + + // The default bullet is a dash but others are possible. + // This has nothing to do with the particular HTML bullet, + // it's just a markdown bullet. + var bullet = "-"; + + // The number in a numbered list. + var num = 1; + + // Get the item prefix - e.g. " 1. " for a numbered list, " - " for a bulleted list. + var getItemPrefix = function(){ + var prefix; + if(isNumberedList){ + prefix = " " + num + ". "; + num++; + } + else{ + prefix = " " + bullet + " "; + } + return prefix; + }; + + // Fixes the prefixes of the other list items. + var getPrefixedItem = function(itemText){ + + // The numbering flag is unset when called by autoindent. + if(isNumberedList === undefined){ + isNumberedList = /^\s*\d/.test(itemText); + } + + // Renumber/bullet the list element. + itemText = itemText.replace(/^[ ]{0,3}([*+-]|\d+[.])\s/gm, + function( _ ){ + return getItemPrefix(); + }); + + return itemText; + }; + + chunk.findTags(/(\n|^)*[ ]{0,3}([*+-]|\d+[.])\s+/, null); + + if(chunk.before && !/\n$/.test(chunk.before) && !/^\n/.test(chunk.startTag)){ + chunk.before += chunk.startTag; + chunk.startTag = ""; + } + + if(chunk.startTag){ + + var hasDigits = /\d+[.]/.test(chunk.startTag); + chunk.startTag = ""; + chunk.selection = chunk.selection.replace(/\n[ ]{4}/g, "\n"); + command.unwrap(chunk); + chunk.skipLines(); + + if(hasDigits){ + // Have to renumber the bullet points if this is a numbered list. + chunk.after = chunk.after.replace(nextItemsRegex, getPrefixedItem); + } + if(isNumberedList == hasDigits){ + return; + } + } + + var nLinesUp = 1; + + chunk.before = chunk.before.replace(previousItemsRegex, + function(itemText){ + if(/^\s*([*+-])/.test(itemText)){ + bullet = re.$1; + } + nLinesUp = /[^\n]\n\n[^\n]/.test(itemText) ? 1 : 0; + return getPrefixedItem(itemText); + }); + + if(!chunk.selection){ + chunk.selection = "List item"; + } + + var prefix = getItemPrefix(); + + var nLinesDown = 1; + + chunk.after = chunk.after.replace(nextItemsRegex, + function(itemText){ + nLinesDown = /[^\n]\n\n[^\n]/.test(itemText) ? 1 : 0; + return getPrefixedItem(itemText); + }); + + chunk.trimWhitespace(true); + chunk.skipLines(nLinesUp, nLinesDown, true); + chunk.startTag = prefix; + var spaces = prefix.replace(/./g, " "); + command.wrap(chunk, wmd.wmd_env.lineLength - spaces.length); + chunk.selection = chunk.selection.replace(/\n/g, "\n" + spaces); + + }; + + command.doHeading = function(chunk, postProcessing){ + + // Remove leading/trailing whitespace and reduce internal spaces to single spaces. + chunk.selection = chunk.selection.replace(/\s+/g, " "); + chunk.selection = chunk.selection.replace(/(^\s+|\s+$)/g, ""); + + // If we clicked the button with no selected text, we just + // make a level 2 hash header around some default text. + if(!chunk.selection){ + chunk.startTag = "## "; + chunk.selection = "Heading"; + chunk.endTag = " ##"; + return; + } + + var headerLevel = 0; // The existing header level of the selected text. + + // Remove any existing hash heading markdown and save the header level. + chunk.findTags(/#+[ ]*/, /[ ]*#+/); + if(/#+/.test(chunk.startTag)){ + headerLevel = re.lastMatch.length; + } + chunk.startTag = chunk.endTag = ""; + + // Try to get the current header level by looking for - and = in the line + // below the selection. + chunk.findTags(null, /\s?(-+|=+)/); + if(/=+/.test(chunk.endTag)){ + headerLevel = 1; + } + if(/-+/.test(chunk.endTag)){ + headerLevel = 2; + } + + // Skip to the next line so we can create the header markdown. + chunk.startTag = chunk.endTag = ""; + chunk.skipLines(1, 1); + + // We make a level 2 header if there is no current header. + // If there is a header level, we substract one from the header level. + // If it's already a level 1 header, it's removed. + var headerLevelToCreate = headerLevel == 0 ? 2 : headerLevel - 1; + + if(headerLevelToCreate > 0){ + + // The button only creates level 1 and 2 underline headers. + // Why not have it iterate over hash header levels? Wouldn't that be easier and cleaner? + var headerChar = headerLevelToCreate >= 2 ? "-" : "="; + var len = chunk.selection.length; + if(len > wmd.wmd_env.lineLength){ + len = wmd.wmd_env.lineLength; + } + chunk.endTag = "\n"; + while(len--){ + chunk.endTag += headerChar; + } + } + }; + + command.doHorizontalRule = function(chunk, postProcessing){ + chunk.startTag = "----------\n"; + chunk.selection = ""; + chunk.skipLines(2, 1, true); + } +}; + + +Attacklab.wmd_env = {}; +Attacklab.account_options = {}; +Attacklab.wmd_defaults = {version:1, output:"Markdown", lineLength:40, delayLoad:false}; + +if(!Attacklab.wmd) +{ + Attacklab.wmd = function() + { + Attacklab.loadEnv = function() + { + var mergeEnv = function(env) + { + if(!env) + { + return; + } + + for(var key in env) + { + Attacklab.wmd_env[key] = env[key]; + } + }; + + mergeEnv(Attacklab.wmd_defaults); + mergeEnv(Attacklab.account_options); + mergeEnv(top["wmd_options"]); + Attacklab.full = true; + + var defaultButtons = "bold italic link blockquote code image ol ul heading hr"; + Attacklab.wmd_env.buttons = Attacklab.wmd_env.buttons || defaultButtons; + }; + Attacklab.loadEnv(); + + }; + + Attacklab.wmd(); + Attacklab.wmdBase(); + Attacklab.Util.startEditor(); +}; + diff --git a/askbot/skins/old/media/style/auth.css b/askbot/skins/old/media/style/auth.css new file mode 100644 index 00000000..33702758 --- /dev/null +++ b/askbot/skins/old/media/style/auth.css @@ -0,0 +1,48 @@ +#bigicon_providers, #smallicon_providers { + display: block; + padding: 0px; + width:600px; + margin:0px 0px 5px 0px; +} + +.provider_logo { + display: inline-block; + padding: 4px; + border: 1px solid #DDD; + text-align: center; + vertical-align: middle; +} + +.provider_logo.big { + height: 40px; + width: 90px; +} + +.provider_logo.small { + height: 32px; + width: 32px; +} + +.provider_logo.selected { + outline: 2px solid #FFF8C6; +} + +.provider_logo .provider_url { + display: none; +} + +.signin_form input[type="text"], .signin_form input[type="password"], .signin_form input[type="submit"] { + height: 28px; + line-height: 22px; + font-size: 140%; + border: 1px solid #999; +} + +.signin_form .icon_input { + padding-left: 20px; +} + +.or_label { + margin-top: 20px; + margin-bottom: 10px; +}
\ No newline at end of file diff --git a/askbot/skins/old/media/style/jquery.autocomplete.css b/askbot/skins/old/media/style/jquery.autocomplete.css new file mode 100644 index 00000000..b3d7b759 --- /dev/null +++ b/askbot/skins/old/media/style/jquery.autocomplete.css @@ -0,0 +1,37 @@ +.acInput { + width: 200px; +} +.acResults { + padding: 0px; + border: 1px solid WindowFrame; + background-color: Window; + overflow: hidden; +} + +.acResults ul { + width: 100%; + list-style-position: outside; + list-style: none; + padding: 0; + margin: 0; +} + +.acResults li { + margin: 0px; + padding: 2px 5px; + cursor: pointer; + display: block; + width: 100%; + font: menu; + font-size: 12px; + overflow: hidden; +} + +.acLoading { + background : url('../images/indicator.gif') right center no-repeat; +} + +.acSelect { + background-color: Highlight; + color: HighlightText; +} diff --git a/askbot/skins/old/media/style/openid.css b/askbot/skins/old/media/style/openid.css new file mode 100644 index 00000000..0d201df2 --- /dev/null +++ b/askbot/skins/old/media/style/openid.css @@ -0,0 +1,45 @@ +#openid_form { + width: 470px; +} + #openid_form legend { + font-weight: bold; + } +#openid_choice { + display: none; +} +#openid_input_area { + clear: both; + padding: 10px; +} +#openid_btns, #openid_btns br { + clear: both; +} + #openid_highlight { + padding: 3px; + background-color: #FFFCC9; + float: left; + } + .openid_large_btn { + width: 100px; + height: 60px; + border: 1px solid #DDD; + margin: 3px; + float: left; + } + .openid_small_btn { + width: 24px; + height: 24px; + border: 1px solid #DDD; + margin: 3px; + float: left; + } + a.openid_large_btn:focus { + outline: none; + } + a.openid_large_btn:focus + { + -moz-outline-style: none; + } + .openid_selected { + border: 4px solid #DDD; + } diff --git a/askbot/skins/old/media/style/prettify.css b/askbot/skins/old/media/style/prettify.css new file mode 100644 index 00000000..10a37577 --- /dev/null +++ b/askbot/skins/old/media/style/prettify.css @@ -0,0 +1,27 @@ +/* Pretty printing styles. Used with prettify.js. */ + +.str { color: #080; } +.kwd { color: #008; } +.com { color: #800; } +.typ { color: #606; } +.lit { color: #066; } +.pun { color: #660; } +.pln { color: #000; } +.tag { color: #008; } +.atn { color: #606; } +.atv { color: #080; } +.dec { color: #606; } +pre.prettyprint { padding: 3px; border: 0px solid #888; } + +@media print { + .str { color: #060; } + .kwd { color: #006; font-weight: bold; } + .com { color: #600; font-style: italic; } + .typ { color: #404; font-weight: bold; } + .lit { color: #044; } + .pun { color: #440; } + .pln { color: #000; } + .tag { color: #006; font-weight: bold; } + .atn { color: #404; } + .atv { color: #060; } +} diff --git a/askbot/skins/old/media/style/style.css b/askbot/skins/old/media/style/style.css new file mode 100644 index 00000000..1431135f --- /dev/null +++ b/askbot/skins/old/media/style/style.css @@ -0,0 +1,2474 @@ +@import url(jquery.autocomplete.css); + +body { + background: #FFF; + font-size: 14px; + line-height: 150%; + margin: 0; + padding: 0; + color: #000; + font-family: sans-serif; +} + +div { + margin: 0 auto; + padding: 0; +} + +h1, h2, h3, h4, h5, h6, ul, li, dl, dt, dd, form, img, p { + margin: 0; + padding: 0; + border: none; +} + +label { + vertical-align: middle; +} + +hr { + border: none; + border-top: 1px dashed #ccccce; +} + +input, select { + vertical-align: middle; + font-family: Trebuchet MS, "segoe ui", Helvetica, "Microsoft YaHei", 宋 体, Tahoma, Verdana, MingLiu, PMingLiu, Arial, sans-serif; +} + +p { + font-size: 14px; + line-height: 140%; + margin-bottom: 6px; + padding-left: 5px; +} + +a { + color: #333333; + text-decoration: none; + cursor: pointer; +} + +/* http://pathfindersoftware.com/2007/09/developers-note-2/ */ +* html .clearfix, +* html .paginator { + height: 1; + overflow: visible; +} ++ html .clearfix, ++ html .paginator { + min-height: 1%; +} +.clearfix:after, +.paginator:after { + clear: both; + content:"."; + display:block; + height: 0; + visibility: hidden; +} + +.badges a { + color: #763333; + text-decoration: underline; +} + +a:hover { + text-decoration: underline; +} + +.badge-context-toggle.active { + cursor: pointer; + text-decoration: underline; +} + +h1 { + font-size: 160%; + padding: 10px 0 5px 5px; +} + +.users-page h1, .tags-page h1 { + float: left; +} + +.main-page h1 { + margin-right: 5px; +} + +h2 { + font-size: 140%; + padding: 3px 0 3px 5px; +} + +h3 { + font-size: 120%; + padding: 3px 0 3px 5px; +} + +ul { + list-style: disc; + margin-left: 20px; + padding-left: 0px; + margin-bottom: 1em; +} + +ol { + list-style: decimal; + margin-left: 30px; + margin-bottom: 1em; + padding-left: 0px; +} + +td ul { + vertical-align: middle; +} + +li input { + margin: 3px 3px 4px 3px; +} + +pre { + font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace; + font-size: 100%; + margin-bottom: 10px; + /*overflow: auto;*/ + background-color: #F5F5F5; + padding-left: 5px; + padding-top: 5px; + /*width: 671px;*/ + padding-bottom: 20px ! ie7; +} + +code { + font-family: Consolas, Monaco, Liberation Mono, Lucida Console, Monospace; + font-size: 100%; + +} + +blockquote { + margin-bottom: 10px; + margin-right: 15px; + padding: 10px 0px 1px 10px; + background-color: #F5F5F5; +} + +.content-wrapper {/* wrapper positioning class */ + width: 960px; + margin: auto; + position:relative; +} + +#ab-header { + margin-top: 0px; + background: #FFF; +} + +#ab-header .content-wrapper { + height: 90px;/* same as logo height */ +} + +#CALeft { + width: 710px; + float: left; + position: relative; + padding: 0 5px 10px 5px; +} + +#CARight { + width: 230px; + float: right; + padding: 0 5px 10px 5px; +} + +#CAFull { + float: left; + padding: 0 5px 10px 5px; + width: 950px; +} + +#ground { + width: 100%; + clear: both; + border-top: 1px solid #000; + padding: 6px 0 0 0; + text-align: center; + background: #777; +} + +#ground p { + margin-bottom:0; +} + +#ab-logo { + padding: 0px 0px 0px 10px; + position: absolute; + bottom: 0; + left: 0; + height: 90px; + width: 70px; +} + +img.license-logo { + margin: 6px 0 10px 0; +} + +#ab-meta-nav, +#ab-main-nav { + position: absolute; + left: 100px; +} + +#ab-meta-nav { + top: 0px; + height: 20px; + padding: 3px; + margin: 0; +} + +#ab-meta-nav a { + height: 35px; + text-align: right; + margin-left: 20px; + text-decoration: underline; + color: #555555; +} + +#ab-meta-nav a:first-child { + margin-left: 0; +} + +#ab-meta-nav a#ab-responses { + margin-left: 3px; +} +#ab-meta-nav a img { + vertical-align:middle; + margin-bottom:2px; +} + +#ab-meta-nav .user-info a { + margin: 0; + text-decoration: none; +} + +#ab-main-nav { + bottom: 0; +} + +#ab-main-nav a { + color: #333333; + background-color: #fff0e0; + border: 1px solid #888888; + border-bottom: none; + padding: 0px 12px 3px 12px; + height: 25px; + line-height: 30px; + margin-right: 10px; + font-size: 18px; + font-weight: 100; + text-decoration: none; + display: block; + float: left; +} + +#ab-main-nav a:hover { + text-decoration: underline; +} + +#ab-main-nav a.on { + height: 24px; + line-height: 28px; + border-bottom: 1px solid #a40000; + border-right: 1px solid #820000; + border-top: 1px solid #d40000; + border-left: 1px solid #d40000; /*background:#A31E39; */ + background: #b03a48; + color: #FFF; + font-weight: 800; + text-decoration: none +} + +#ab-main-nav a.special { + font-size: 18px; + color: #B02B2C; + font-weight: bold; + text-decoration: none; +} + +#ab-main-nav a.special:hover { + text-decoration: underline; +} + +#searchBar { + display:inline-block; + background-color: #cccccc;/*888a85; /*#e9b96e;*/ + width:700px; + border: 1px solid #aaaaaa; + padding: 4px 5px 4px 4px; +} + +#searchBar .searchInput, #searchBar .searchInputCancelable { + font-size: 24px; + line-height: 24px; + height: 31px; + margin: 0px 4px 0px 0px; + padding: 5px 0 0 5px; +} + +#searchBar .searchInput, #searchBar .searchInputCancelable { + width: 607px; +} + +#searchBar .searchInputCancelable { + width: 564px; +} + +#searchBar .searchBtn, #searchBar .cancelSearchBtn { + font-size: 20px; + color: #666; + background-color: #eee; + height: 40px; + border: 1px solid #aaa; + line-height: 22px; + text-align: center; + padding-bottom: 4px; +} + +#searchBar .searchBtn { + margin: 0px; + width: 78px; +} + +#searchBar .cancelSearchBtn { + width: 40px; + margin: 0px 3px 0px 0px; +} + +#askFormBar { + display:inline-block; + background-color: #e3e3e3;/*888a85; /*#e9b96e;*/ + border: 1px solid #aaaaaa; + padding: 4px 7px 5px 5px; +} +#askFormBar p { + width: 685px; + margin:0 0 5px 0; +} +#askFormBar .questionTitleInput { + font-size: 24px; + line-height: 24px; + height: 36px; + width: 680px; + margin: 0px; + padding: 5px 0 0 5px; +} + +#question-list { + float: left; + position: relative; + background-color: #FFF; + padding: 0; + width: 100%; +} + +.ask-page div#question-list { + float: none; + width: 706px; +} +.ask-page div#question-list h2 { + font-size: 14px; + padding-bottom: 0; +} +.ask-page div#question-list span { + padding: 3px 7px; + margin-right: 5px; + background: #ccc; +} + +/* tag formatting is also copy-pasted in template + because it must be the same in the emails + askbot/models/__init__.py:format_instant_notification_email() +*/ + +/* tag cloud */ + +.tag-size-1 { + font-size:12px; +} +.tag-size-2 { + font-size:13px; +} +.tag-size-3 { + font-size:14px; +} +.tag-size-4 { + font-size:15px; +} +.tag-size-5 { + font-size:16px; +} +.tag-size-6 { + font-size:17px; +} +.tag-size-7 { + font-size:18px; +} +.tag-size-8 { + font-size:19px; +} +.tag-size-9 { + font-size:20px; +} +.tag-size-10 { + font-size:21px; +} + +ul.tags, +.boxC ul.tags, +ul.tags.marked-tags, +ul#related-tags { + list-style: none; + margin: 0; + padding: 0; + line-height: 170%; + display: block; +} + +ul.tags li { + float:left; + display: block; + margin: 0 5px 0 0; + padding: 0; +} + +.wildcard-tags { + clear: both; +} + +ul.tags.marked-tags li, +.wildcard-tags ul.tags li { + margin-bottom: 5px; +} + +#tagSelector div.inputs { + clear: both; + float: none; +} + +.tags-page ul.tags li, +ul#ab-user-tags li { + width: 160px; +} + +ul#related-tags li { + margin: 0 5px 3px 0; + float: left; + clear: left; +} + +/* .tag-left and .tag-right are for the sliding doors decoration of tags */ +.tag-left { + background: url(../images/tag-right.png) no-repeat right center; + border: none; + cursor: pointer; + display: block; + float: left; + height: 18px; + margin: 0 5px 0 0; + overflow-x: hidden; + padding: 0; +} + +.tag-right { + background: url(../images/tag-left.png) no-repeat left center; + border: none; + display: block; + float: left; + height: 18px; + line-height: 20px; + font-weight: normal; + font-size: 11px; + padding: 0px 7px 0px 15px; + text-decoration: none; + text-align: center; + white-space: nowrap; + vertical-align: middle; +} + +.deletable-tag { + margin-right: 3px; + white-space: nowrap; +} + +.deletable-tag .tag-right { + padding-right: 0px; + float: left; +} +.deletable-tag.tag-left { + padding-right: 3px; +} + +.tags a.tag-right, +.tags span.tag-right { + color: #333; + text-decoration: none; +} + +span.delete-icon { + padding-left: 13px; + vertical-align: bottom; + background: url(../images/close-small-dark.png) no-repeat; + cursor: default; +} +span.delete-icon:hover { + background: url(../images/close-small-hover.png) no-repeat; +} + +.tags span.delete-icon { + float: left; + height: 15px; + margin: 2px 0 0 1px; + display: block; +} + +.tag-number { + font-weight: 700; + display: block; + float: left; + font-family: sans-serif; +} + +.badges .tag-number { + float: none; + display: inline; + padding-right: 15px; +} + +ul#search-tags { + padding-top: 3px; +} + +.short-summary { + position: relative; + filter: inherit; + padding: 5px 2px 5px 2px; + border-top: 1px dashed #ccccce; + overflow: hidden; + width: 702px; + float: left; +} + +.short-summary h2 { + font-size: 16px; + font-family: "Trebuchet MS", "segoe ui", arial, sans-serif; +} + +.short-summary .userinfo .relativetime, +.short-summary .userinfo a, +.short-summary span.anonymous { + font-size: 11px; + clear:both; + font-weight: normal; + color: #555; +} + + +.short-summary .userinfo { + text-align:center; + line-height:16px; +} + +.short-summary .counts { + float: right; + margin: 2px 0 0 5px; +} + +.short-summary .counts .item-count { + border:1px solid #cccccc; + -moz-border-radius:5px; + -webkit-border-radius:5px; + padding:0px 5px 0px 5px; + font-size: 17px; + font-weight: 800; +} + +.short-summary .counts .votes div, +.short-summary .counts .views div, +.short-summary .counts .answers div, +.short-summary .counts .favorites div +{ + font-size: 12px; + line-height:14px; + color: #555; +} + +.short-summary .tags { + margin-top: 0; +} + +.no-votes .item-count { + background: white; + color: gray; +} +.some-votes .item-count { + background: #a3d0ff; + color: #4a4a4a; +} +.no-answers .item-count { + background: #b63333; + color: yellow; +} +.no-favorites .item-count { + background: #b63333; + color: yellow; +} +.some-answers .item-count { + background: #ffed9c; + color: #a4a4a4; +} +.some-favorites .item-count { + background:#338333; + color:#d0f5a9; +} +.accepted .item-count { + background:#338333; + color:#d0f5a9; +} +.no-views .item-count { + background: gray; + color: white; +} +.some-views .item-count { + background: #ff8c8c; + color: #4a4a4a; +} + +.short-summary .votes, +.short-summary .answers, +.short-summary .favorites, +.short-summary .views { + text-align: center; + margin: 0 3px; + padding: 4px 2px 0px 2px; + width: 46px; + float: right; + -moz-border-radius: 5px; + -khtml-border-radius: 5px; + -webkit-border-radius: 5px; +} + +.short-summary .views { + width: 36px; + padding-right: 0; +} + +.short-summary h2 { + padding-left: 0; +} + +#question-table, +.answer-table { + margin: 2px 0 10px 0; + border-spacing: 0px; +} + +.answer-table { + border-bottom: 1px solid #bbb; + clear: both; +} + +.evenMore { + font-size: 14px; + font-weight: 800; +} + +.evenMore a { + text-decoration: underline; +} + +.boxC { + background: white /*#cacdc6; /*f9f7ed;*/ + padding: 10px 10px 10px 15px; + margin-bottom: 12px; +} + +.boxC p { + margin-bottom: 4px; +} + +.boxC p.info-box-follow-up-links { + text-align: right; + margin: 0; +} + +.boxC h2, +.boxC h3 { + padding-left: 0; +} + +.boxC label { + color: #333; +} + +.pager { + clear:both; + border-top: 1px solid #777; + margin-top: 10px; + margin-bottom: 16px; +} + +.pagesize { + margin-top: 10px; + margin-bottom: 16px; + float: right; +} + +/** PAGINATOR **/ +.paginator { + padding: 5px 0 10px 0; + font: normal 12px sans-serif; +} + +.paginator .prev a, .paginator .prev a:visited, +.paginator .next a, .paginator .next a:visited { + border: 1px solid #fff; + background-color: #fff; + color: #777; + padding: 2px 4px 3px 4px; + font: bold 100% sans-serif; +} + +.paginator .prev { + margin-right: .5em; +} + +.paginator .next { + margin-left: .5em; +} + +.paginator .page a, .paginator .page a:visited, .paginator .curr { + padding: .25em; + font: normal .875em verdana; + border: 1px solid #ccc; + background-color: #fff; + margin: 0em .25em; + color: #777; +} + +.paginator .curr { + background-color: #777; + color: #fff; + border: 1px solid #777; + font-weight: bold; +} + +.paginator .page a:hover, +.paginator .curr a:hover, +.paginator .prev a:hover, +.paginator .next a:hover { + color: #fff; + background-color: #777; + border: 1px solid #777; + text-decoration: none; +} + +.paginator .text { + color: #777; + padding: .3em; + font: bold 100% sans-serif; +} + +.paginator-container-left { + padding: 5px 0 10px 0; +} + +p.rss { + float: right; + font-size: 12px; + color: #666; + margin: 0 2px 0 0; +} + +p.rss a { + padding-left: 16px; + background: url(../images/feed-icon-small.png) no-repeat; +} + +/* badges */ +a.medal { + font-size: 14px; + line-height: 250%; + font-weight: 800; + color: #333; + text-decoration: none; + background: url(../images/medala.gif) no-repeat; + border-left: 1px solid #EEE; + border-top: 1px solid #EEE; + border-bottom: 1px solid #CCC; + border-right: 1px solid #CCC; + padding: 4px 12px 4px 6px; +} + +a:hover.medal { + color: #333; + text-decoration: none; + background: url(../images/medala_on.gif) no-repeat; + border-left: 1px solid #E7E296; + border-top: 1px solid #E7E296; + border-bottom: 1px solid #D1CA3D; + border-right: 1px solid #D1CA3D; +} + +/*Tabs*/ +.tabBar { + background-color: #FFF; + border-bottom: 1px solid white; + height: 30px; + width: 100%; + clear: both; + margin-bottom: 3px; + margin-top: 3px; +} + +.tabBar h2 { + float: left; +} + +.tabsA, .tabsC { + background-color: #FFF; + float: right; + position: relative; + display: block; + font-weight: bold; + height: 20px; +} + +/* tabsA - used for sorting */ +.tabsA { float: right; } +.tabsC { float: left; } + +.tabsA a.on, .tabsC a.on, .tabsA a:hover, .tabsC a:hover { + background: #fff; + color: #a40000; + border-top: 1px solid #babdb6; + border-left: 1px solid #babdb6; + border-right: 1px solid #888a85; + border-bottom: 1px solid #888a85; + height: 24px; + line-height: 26px; + margin-top: 3px; +} + +.tabsA a.rev.on, tabsA a.rev.on:hover { + padding: 0px 2px 0px 7px; +} + +.tabsA a, .tabsC a{ + background: #f9f7eb; + border-top: 1px solid #eeeeec; + border-left: 1px solid #eeeeec; + border-right: 1px solid #a9aca5; + border-bottom: 1px solid #888a85; + color: #888a85; + display: block; + float: left; + height: 20px; + line-height: 22px; + margin: 5px 0 0 4px; + padding: 0 2px; + text-decoration: none; +} + +.tabsA .label, .tabsC .label { + float: left; + font-weight: bold; + color: #777; + margin: 8px 0 0 0px; +} + +.tabsB a { + background: #eee; + border: 1px solid #eee; + color: #777; + display: block; + float: left; + height: 22px; + line-height: 28px; + margin: 5px 0px 0 4px; + padding: 0 11px 0 11px; + text-decoration: none; +} + +.questions-related { + font-weight: 700; + word-wrap: break-word; +} + +.questions-related p { + line-height: 20px; + margin-bottom: 10px; + font-size: 100%; +} + +.question-status { + margin-top: 10px; + padding: 20px; + background-color: #F5F5F5; + text-align: center; +} + +.question-status h3 { + font-size: 125%; +} +.question-body, .answer-body { + min-height: 39px; + line-height: 20px; + overflow: auto; + width: 660px; +} +.question-body IMG, .answer-body IMG { + max-width: 600px; +} + +.vote-buttons { + float: left; + text-align: center; + padding-top: 2px; +} + +.vote-buttons IMG { + cursor: pointer; +} + +.vote-buttons .button{ + -moz-border-radius: 10px; + margin-top: 20px; + border-radius: 10px; + height: 20px; + width: 80px; + border-style: solid; + border-width: 1px; + padding: 8px; + float:left; +} + +.vote-buttons .followed{ + font-color: #000; + font-style:normal; + background: #cccccc; +} + +.vote-buttons .followed div{ + font-weight: normal; +} + +.vote-buttons .followed div.unfollow{ + display:none; +} + +.vote-buttons .followed:hover{ + color: #fff; + background: #8b0000; +} + +.vote-buttons .followed:hover div{ + display:none; +} + +.vote-buttons .followed:hover div.unfollow{ + display:inline; + font-weight: bold; +} + +.vote-buttons .follow{ + background: #cccccc; +} + +.vote-buttons .follow:hover{ + background: #234f32; + color: #fff; + font-weight: bold; +} + +.vote-number { + font-family: Arial; + padding: 0px 0 3px 0; + font-size: 140%; + font-weight: bold; + color: #777; +} + +.vote-buttons .notify-sidebar { + text-align: left; +} +.vote-buttons .notify-sidebar label { + vertical-align: top; +} + +.question-img-upvote:hover { + background: url(../images/vote-arrow-up-on.png) +} + +.question-img-downvote:hover { + background: url(../images/vote-arrow-down-on.png) +} + +.question-img-favorite:hover { + background: url(../images/vote-favorite-on.png) +} + +.favorite-number { + padding: 5px 0 0 10px; + font-size: 100%; + font-family: Arial; + font-weight: bold; + color: #777; + text-align: left; +} + +.notify-me { + float: left; +} + +.offensive-flag a { + color: #777; + padding: 3px; + cursor: pointer; +} + +.offensive-flag a:hover { + background-color: #777; + text-decoration: none; + color: #fff; +} + +.linksopt a { + color: #777; + padding: 3px; + cursor: pointer; +} + +.linksopt a:hover { + background-color: #777; + text-decoration: none; + color: #fff; +} + +.post-controls a { + color: #777; + padding: 3px; + cursor: pointer; + border: none; + background: none; + text-decoration: none; +} + +.post-controls a:hover { + background-color: #777; + color: #fff; +} + +.post-controls .sep { + color: #ccc; +} + +.comments { + font-size: 12px; + width: 650px; + clear: both; +} + +.comments .comment { + border-top: 1px dotted #cccccc; + margin: 0; + overflow: auto; +} + +.comments .content { + margin-bottom: 7px; +} + +.comments div.comment { + min-height: 25px; +} + +.comments div.comment:hover { + background-color: #eee; +} + +div.comment .comment-votes { + float: left; + width: 37px; + line-height: 130%; + padding: 6px 5px 6px 3px; +} + +div.comment .comment-body { + line-height: 140%; + margin: 3px 26px 0 46px; + padding: 5px 3px; + color: #666; +} + +div.comment .comment-body p{ + font-size:inherit; + margin-bottom: 3px; + padding: 0; +} + +div.comment .comment-delete { + float: right; + width: 14px; + line-height: 130%; + padding: 8px 6px; +} + +div.comment .upvote { + margin: 0px; + padding-right: 17px; + padding-top: 2px; + text-align: right; + height: 20px; + font-size: 13px; + font-weight: bold; + color: #777; +} + +div.comment .upvote.upvoted { + color: #d64000; +} + +div.comment .upvote.hover { + background: url(../images/go-up-grey.png) no-repeat; + background-position: right 1px; +} + +div.comment .upvote:hover { + background: url(../images/go-up-orange.png) no-repeat; + background-position: right 1px; +} + +.comments div.controls { + clear: both; + background: url(../images/gray-up-arrow-h18px.png) no-repeat; + width: 100%; + padding-left: 12px; + margin: 3px 0 20px 5px; +} + +.comments form.post-comments { + width: 560px; + margin: 3px 30px 4px 45px; +} + +.comments textarea { + display: block; + height: 42px; + width: 572px; + margin: 6px 0 5px 1px; + font-family: sans-serif; + outline: none; + overflow:auto; + font-size: 12px; + line-height: 140%; + padding-left:2px; +} + +.comments input { + margin-left: 10px; + margin-top: 1px; + vertical-align: top; + width: 100px; +} + +.comments .counter { + display: inline-block; + width: 245px; + vertical-align: top; +} + +.comments .controls a { + color: #888888; + padding: 0 3px 2px; +} + +.comments .controls a:hover { + background-color: #777777; + color: white; + text-decoration: none; +} + +.comments .help-text{ + float: right; + text-align:right; + color: gray; + margin-bottom: 0px; + margin-top: 0px; + line-height: 50%; +} + +span.text-counter { + margin-right: 20px; +} + +span.form-error { + color: #990000; + font-weight: normal; + margin-left: 5px; +} + +p.form-item { + margin: 0px; +} + +div.comments { + padding: 0; +} + +.comments .button { + color: black; + font-size: 11px; + background: #eeeeee; + padding: 3px; + cursor: pointer; +} + +.comment a { + background-color: inherit; + color: blue; + padding: 0; +} + +.comment a.author, a.author:hover { + background-color: inherit; + color: blue; + padding: 0; +} + +.comment a.author:hover { + text-decoration: underline; +} + +.accepted-answer { + background-color: #EBFFE6; + border-bottom-color: #9BD59B; +} + +.accepted-answer .comments .button { + background-color: #CCFFBF; +} + +.accepted-answer .comments { + background-color: #CCFFBF; +} + +.answered { + background: #CCC; + color: #999; +} + +.answered-accepted { + background: #CCC; + color: #763333; +} + +.answered-by-owner { + background: #E9E9FF; +} + +.answered-by-owner .comments .button { + background-color: #E6ECFF; +} + +.answered-by-owner .comments { + background-color: #E6ECFF; +} + +.answered-accepted strong { + color: #E1E818; +} + +.answer-img-accept:hover { + background: url(../images/vote-accepted-on.png) +} + +.deleted { + background: #F4E7E7 none repeat scroll 0 0; +} + + +.boxC ul { + margin-left: 15px; +} + +.boxC li { + list-style-type: disc; + font-size: 13px; + line-height: 20px; + margin-bottom: 10px; +} + +/* openid styles */ +.form-row { + line-height: 25px; +} + +table.form-as-table { + margin-top: 5px; +} + +table.form-as-table ul { + list-style-type: none; + display: inline; +} + +table.form-as-table li { + display: inline; +} + +table.form-as-table td { + text-align: right; +} + +table.form-as-table th { + text-align: left; + font-weight: normal; +} + +table.ab-subscr-form { + width: 45em; +} + +table.ab-tag-filter-form { + width: 45em; +} + +.submit-row { + line-height: 30px; + padding-top: 10px; + display: block; + clear: both; +} + +.errors { + line-height: 20px; + color: red; +} + +.error { + color: darkred; + margin: 0; + font-size: 10px; +} + +label.retag-error { + color: darkred; + padding-left: 5px; + font-size: 10px; +} + +.fieldset { + border: none; + margin-top: 10px; + padding: 10px; +} + +.openid-input { + background: url(../images/openid.gif) no-repeat; + padding-left: 15px; + cursor: pointer; +} + +.openid-login-input { + background-position: center left; + background: url(../images/openid.gif) no-repeat 0% 50%; + padding: 5px 5px 5px 15px; + cursor: pointer; + font-family: Trebuchet MS; + font-weight: 300; + font-size: 150%; + width: 500px; +} + +.openid-login-submit { + height: 40px; + width: 80px; + line-height: 40px; + cursor: pointer; + border: 1px solid #777; + font-weight: bold; + font-size: 120%; +} + +span.form-error { + color: #990000; + font-size: 90%; + font-weight: normal; + margin-left: 5px; +} + +.title-desc { + color: #666666; + font-size: 90%; +} + +/*adjustment for editor preview*/ +#editor { + font-size: 100%; + min-height: 200px; + line-height: 18px; + width: 702px; + margin:0; +} + +#id_title { + width: 100%; +} + +.wmd-preview { + margin: 3px 0 5px 0; + padding: 6px; + width: 691px; + background-color: #F5F5F5; + min-height: 20px; + overflow: auto; +} + +.wmd-preview pre { + background-color: #E7F1F8; + +} + +.wmd-preview blockquote { + background-color: #eee; +} + +.wmd-preview IMG { + max-width: 600px; +} + +.preview-toggle { + width: 100%; + color: #666; /*letter-spacing:1px;*/ + text-align: left; +} + +.preview-toggle span:hover { + cursor: pointer; +} + +.after-editor { + margin-top: 10px; +} + +.checkbox { + margin-left:5px; + font-weight:normal; + cursor:help +} + +.question-options { + margin-top: 1px; + float: left; + color: #666; + line-height: 13px; +} +.question-options label { + vertical-align: text-bottom; +} + +.ask-page input.submit, +.edit-question-page input.submit { + float: left; +} + +.edit-content-html { + border-top: 1px dotted #D8D2A9; + border-bottom: 1px dotted #D8D2A9; + margin: 5px 0 5px 0; +} + +.revision { + margin: 10px 0 10px 0; + width: 100%; + font-size: 13px; +} + +.revision .header { + background-color: #eee; + padding: 5px; + cursor: pointer; +} + +.revision .author { + background-color: #E9E9FF; +} + +.revision .summary { + padding: 5px 0 10px 0; +} + +.revision .summary span { + background-color: yellow; + padding-left: 3px; + padding-right: 3px; + display: inline; +} + +.revision h1 { + font-size: 130%; + font-weight: 600; + padding: 15px 0 15px 0; +} + +.revision-mark { + width: 200px; + text-align: left; + display: inline-block; + font-size: 90%; + overflow: hidden; +} + +.revision-number { + font-size: 300%; + font-weight: bold; + font-family: sans-serif; +} + +.revision .answerbody { + padding: 10px 0 5px 10px; +} + +/* Revision pages */ +del { + color: #FF5F5F; +} + +del .post-tag { + color: #FF5F5F; +} + +ins { + background-color: #97ff97; +} + +ins p{ + background-color: #97ff97; +} + +ins .post-tag { + background-color: #97ff97; +} + +/*用户资料页é¢*/ +.count { + font-family: Arial; + font-size: 200%; + font-weight: 700; + color: #777 +} + +.scoreNumber { + font-family: Arial; + font-size: 35px; + font-weight: 800; + color: #777; + line-height: 40px; /*letter-spacing:0px*/ + margin-top: 3px; +} + +.user-details { + font-size: 13px; +} + +.user-about { + background-color: #EEEEEE; + height: 200px; + line-height: 20px; + overflow: auto; + padding: 10px; + width: 90%; +} + +/* +.favorites-count-off { + color: #919191; + float: left; + text-align: center; +} + +.favorites-count { + color: #D4A849; + float: left; + text-align: center; +} +*/ + +/* todo: get rid of this in html */ +.favorites-empty { + width: 32px; + height: 45px; + float: left; +} + +.user-info-table { + margin-bottom: 10px; + border-spacing: 0; +} + +/* todo: remove this hack? */ +.user-stats-table .narrow { + width: 660px; +} + +.narrow .summary h3 { + padding: 0px; + margin: 0px; +} + +.relativetime { + font-weight: bold; + text-decoration: none; +} + +.narrow .tags { + float: left; +} + +.answer-summary { + display: block; + clear: both; + padding: 3px; +} + +.answer-votes { + background-color: #EEEEEE; + color: #555555; + float: left; + font-family: Arial; + font-size: 110%; + font-weight: bold; + height: 15px; + padding: 4px 4px 5px; + text-align: center; + text-decoration: none; + width: 20px; + margin-right: 10px; +} + +.vote-count { + font-family: Arial; + font-size: 160%; + font-weight: 700; + color: #777; +} + +/* todo: make these more semantic */ +.user-action-1 { + font-weight: bold; + color: #333; +} + +.user-action-2 { + font-weight: bold; + color: #CCC; +} + +.user-action-3 { + color: #333; +} + +.user-action-4 { + color: #333; +} + +.user-action-5 { + color: darkred; +} + +.user-action-6 { + color: darkred; +} + +.user-action-7 { + color: #333; +} + +.user-action-8 { + padding: 3px; + font-weight: bold; + background-color: #CCC; + color: #763333; +} + +.revision-summary { + background-color: #FFFE9B; + padding: 2px; +} + +.question-title-link a { + font-weight: bold; + color: #0077CC; +} + +.answer-title-link a { + color: #333; +} + +/* todo: make these more semantic */ +.post-type-1 a { + font-weight: bold; + +} + +.post-type-3 a { + font-weight: bold; + +} + +.post-type-5 a { + font-weight: bold; +} + +.post-type-2 a { + color: #333; +} + +.post-type-4 a { + color: #333; +} + +.post-type-6 a { + color: #333; +} + +.post-type-8 a { + color: #333; +} + +.hilite { + background-color: #ff0; +} + +.hilite1 { + background-color: #ff0; +} + +.hilite2 { + background-color: #f0f; +} + +.hilite3 { + background-color: #0ff; +} + +.gold, .badge1 { + color: #FFCC00; +} + +.silver, .badge2 { + color: #CCCCCC; +} + +.bronze, .badge3 { + color: #CC9933; +} + +.score { + font-weight: 800; + color: #333; +} + +.footerLinks { + color: #EEE; + font-size: 13px; /* letter-spacing:1px;*/ +} + +.footerLinks a { + color: #FFF; + font-size: 13px; +} + +a.comment { + background: #EEE; + color: #993300; + padding: 5px; +} + +a.offensive { + color: #999; +} + +.user { + padding: 5px; + line-height: 140%; + width: 170px; +} + +.user ul { + margin: 0; + list-style-type: none; +} + +.user .thumb { + clear: both; + float: left; + margin-right: 4px; + display: inline; +} + +.message { + padding: 5px; + margin: 10px 0 10px 0; + background-color: #eee; + border: 1px solid #aaaaaa; +} + +.message h1 { + padding-top: 0px; + font-size: 15px; +} + +.message p { + margin-bottom: 0px; +} + +p.space-above { + margin-top: 10px; +} + +.warning { + color: red; +} + +.darkred { + color: darkred; +} + +button::-moz-focus-inner { + padding:0; + border:none; +} +.submit { + cursor: pointer; /*letter-spacing:1px;*/ + background-color: #D4D0C8; + height: 30px; + border: 1px solid #777777; /* width:100px; */ + font-weight: bold; + font-size: 120%; +} + +.submit:hover { + text-decoration: underline; +} + +.submit.small { + margin-right:5px; + height:20px; + font-weight:normal; + font-size:12px; + padding:1px 5px; +} +.submit.small:hover { + text-decoration:none; +} +.question-page a.submit { + display: -moz-inline-stack; + display: inline-block; + line-height: 30px; + padding: 0 5px; + *display: inline; +} + +.ask-body { + padding-right: 10px; +} + +.notify { + position: fixed; + top: 0px; + left: 0px; + width: 100%; + z-index: 100; + padding: 0; + text-align: center; + font-weight: Bold; + color: #444; + background-color: #F4A83D; +} + +.notify p { + margin-top: 5px; + margin-bottom: 5px; + font-size: 16px; +} + +#close-notify { + position: absolute; + right: 5px; + top: 5px; + padding: 0 3px 0 3px; + color: #735005; + text-decoration: none; + font-size: 14px; + line-height: 18px; + background-color: #FAD163; + border: 2px #735005 solid; + cursor: pointer; +} + +#close-notify:hover { + text-decoration: none; +} + +.noscript { + position: fixed; + top: 0px; + left: 0px; + width: 100%; + z-index: 100; + padding: 5px 0; + text-align: center; + font-family: sans-serif; + font-size: 120%; + font-weight: Bold; + color: #FFFFFF; + background-color: #AE0000; +} + +.big { + font-size: 15px; +} + +.strong { + font-weight: bold; +} + +.orange {/* used in django.po */ + color: #d64000; + font-weight: bold; +} + +.grey { + color: #808080; +} + +.about div { + padding: 10px 5px 10px 5px; + border-top: 1px dashed #aaaaaa; +} + +.highlight { + background-color: #FFF8C6; +} + +.nomargin { + margin: 0; +} + +.margin-bottom { + margin-bottom: 10px; +} + +.margin-top { + margin-top: 10px; +} + +.inline-block { + display: inline-block; +} + +.action-status { + margin: 0; + border: none; + text-align: center; + line-height: 10px; + font-size: 12px; + padding: 0; +} + +.action-status span { + padding: 3px 5px 3px 5px; + background-color: #fff380; /* nice yellow */ + font-weight: normal; + -moz-border-radius: 5px; + -khtml-border-radius: 5px; + -webkit-border-radius: 5px; +} + +.list-table td { + vertical-align: top; +} + +/* these need to go */ +table.form-as-table .errorlist { + display: block; + margin: 0; + padding: 0 0 0 5px; + text-align: left; + font-size: 10px; + color: darkred; +} + +table.form-as-table input { + display: inline; + margin-left: 4px; +} + +table.form-as-table th { + vertical-align: bottom; + padding-bottom: 4px; +} + +.form-row-vertical { + margin-top: 8px; + display: block; +} + +.form-row-vertical label { + margin-bottom: 3px; + display: block; +} + +/* above stuff needs to go */ +.text-align-right { + text-align: center; +} + +ul.form-horizontal-rows { + list-style: none; + margin: 0; +} + +ul.form-horizontal-rows li { + position: relative; + height: 40px; +} + +ul.form-horizontal-rows label { + display: inline-block; +} + +ul.form-horizontal-rows ul.errorlist { + list-style: none; + color: darkred; + font-size: 10px; + line-height: 10px; + position: absolute; + top: 2px; + left: 180px; + text-align: left; + margin: 0; +} + +ul.form-horizontal-rows ul.errorlist li { + height: 10px; +} + +ul.form-horizontal-rows label { + position: absolute; + left: 0px; + bottom: 6px; + margin: 0px; + line-height: 12px; + font-size: 12px; +} + +ul.form-horizontal-rows li input { + position: absolute; + bottom: 0px; + left: 180px; + margin: 0px; +} + +.narrow .summary { + float: left; +} + +.user-profile-tool-links { + font-weight: bold; + vertical-align: top; +} + +.post-controls, .post-tags { + font-size: 11px; + line-height: 12px; + min-width: 200px; + padding-left: 5px; + margin-bottom: 5px; +} + +.post-controls { + clear: left; + float: left; +} + +ul.post-tags { + margin-left: 7px; +} +ul.post-tags li { + margin-top: 4px; + margin-bottom: 3px; +} + +ul.post-retag { + margin-bottom:0px; + margin-left:5px; +} + +#question-controls .tags { + margin: 0 0 3px 0; +} + +.post-update-info-container { + float: right; + min-width: 85px; +} + +.post-update-info { + display: inline-block; + float: right; + font-size: 11px; + width: 190px; + margin-bottom: 5px; + line-height: 14px +} + +.post-update-info p { + line-height: 13px; + font-size: 11px; + margin: 0 0 2px 1px; + padding: 0; +} + +.post-update-info .gravatar { + float: left; + margin-right: 4px; +} + + +.post-update-info p.tip { + color: #444; +} + +#tagSelector { + padding-bottom: 2px; + margin-bottom: 0; +} + +#related-tags { + padding-left: 3px; +} + +#hideIgnoredTagsControl { + margin: 5px 0 0 0; +} + +#hideIgnoredTagsControl label { + font-size: 12px; + color: #666; +} + +#hideIgnoredTagsCb { + margin: 0 2px 0 1px; +} + +#recaptcha_widget_div { + width: 318px; + float: left; + clear: both; +} + +p.signup_p { + margin: 20px 0px 0px 0px; +} + +.simple-subscribe-options ul { + list-style: none; + list-style-position: outside; + margin: 0; +} + +/* a workaround to set link colors correctly */ +.answer-body a { + color:#0000ff; +} +.question-body a { + color:#0000ff; +} +.question-body li { + margin-bottom:0.7em; +} +.answer-body li {$ + margin-bottom:0.7em; +} +.wmd-preview a { + color:#0000ff; +} +.wmd-preview li { + margin-bottom:0.7em; +} + +.karma-summary { + padding:5px; + font-size:13px; +} + +.karma-summary h3 { + text-align: center; + font-weight: bold; + padding:5px; +} + +.karma-diagram { + width:377px; + height:300px; + float:left; + margin-right:10px; +} + +.karma-details { + float:right; + width:300px; + height:250px; + overflow-y:auto; + word-wrap:break-word; +} + +.karma-gained { + font-weight:bold; + background:#eee; + width:20px; + color:green; + padding:5px; +} + +.karma-lost { + font-weight:bold; + background:#eee; + width:20px; + color:red; + padding:5px; +} + +.search-result-summary { + font-weight: bold; + font-size:18px; + line-height:22px; + margin:0px 0px 0px 0px; + padding:2px 0 0 0; + float: left; +} +.search-tips { + font-size:12px; + line-height:12px; + color: #555; + margin:0 0 5px 0; + padding:0px; + clear:both; +} +.search-tips a { + text-decoration: underline; + color: #555; +} + +.faq-rep-item { + text-align:right; + padding-right:5px; +} + +img.gravatar { + margin:2px; +} +.user-info-table .gravatar { + margin:0; +} + +.vote-notification { + z-index: 1; + cursor: pointer; + display: none; + position: absolute; + padding: 15px; + color: white; + background-color: darkred; + text-align: center; +} + +.vote-notification a { + color: white; + text-decoration: underline; +} + +#responses { + clear:both; + line-height:18px; + margin-bottom:15px; +} + +#responses div.face { + float:left; + text-align: center; + width: 54px; + padding: 3px; + overflow:hidden; +} + +.response-parent { + margin-top: 18px; +} + +.response-parent strong{ + font-size: 20px; +} + +.re { + min-height: 57px; + clear: both; + margin-top: 10px; +} + +#responses input { + float:left; +} +#re_tools { + margin-bottom:10px; +} +#re_sections { + margin-bottom:6px; +} +#re_sections .on { + font-weight:bold; +} + +.avatar-page ul { + list-style: none; +} +.avatar-page li { + display: inline; +} +.user-profile-page .avatar p { + margin-bottom: 0px; +} +.user-profile-page .tabBar a#stats { + margin-left: 0; +} +.user-profile-page img.gravatar { + margin: 2px 0 3px 0; +} +.user-profile-page h3 { + padding: 0; + margin-top: -3px; +} +.userList { + font-size: 13px; +} + +img.flag { + border: 1px solid #eee; + vertical-align: text-top; +} + +.main-page img.flag { + vertical-align: text-bottom; +} + +.facebook-share.icon, .twitter-share.icon, .linkedin-share.icon, .identica-share.icon { + background: url(../images/sprite.png) no-repeat; + display:block; + text-indent:-100em; + height:25px; + width:25px; +} +.facebook-share.icon { + background-position: -25px 0px; +} +.identica-share.icon { + background-position: -85px 0px; +} +.twitter-share.icon { + margin-top:10px; + background-position: 0px 0px; +} +.linkedin-share.icon { + background-position: -55px 0px; +} +/* Pretty printing styles. Used with prettify.js. */ + +a.edit { + padding-left:3px; + color: #145bff; +} + +.str { color: #080; } +.kwd { color: #008; } +.com { color: #800; } +.typ { color: #606; } +.lit { color: #066; } +.pun { color: #660; } +.pln { color: #000; } +.tag { color: #008; }/* name conflict here */ +.atn { color: #606; } +.atv { color: #080; } +.dec { color: #606; } +pre.prettyprint { padding: 3px; border: 0px solid #888; } + +@media print { + .str { color: #060; } + .kwd { color: #006; font-weight: bold; } + .com { color: #600; font-style: italic; } + .typ { color: #404; font-weight: bold; } + .lit { color: #044; } + .pun { color: #440; } + .pln { color: #000; } + .tag { color: #006; font-weight: bold; } + .atn { color: #404; } + .atv { color: #060; } +} + +.follow-toggle { + border: 2px solid; + -moz-border-radius:5px; + -webkit-border-radius:5px; + border-radius: 5px; + height: auto; + width: 200px; + float:left; + padding: 0; + margin-right:100%; + margin-bottom: 10px; +} + +.follow-toggle .follow{ + font-color: #000; + font-style:normal; + background: #4cd46f; +} + +.follow-toggle .follow:hover{ + font-weight: bold; +} + +.follow-toggle .unfollow{ + background: #4cd46f; +} + +.follow-toggle .unfollow:hover{ + background: #d94849; +} + +.follow-toggle .unfollow div.unfollow-red{ + display:none; +} + +.follow-toggle .unfollow div.unfollow-green{ + background: #4cd46f; +} + +.follow-toggle .unfollow:hover div.unfollow-red{ + display:inline; + color:#fff; + font-weight:bold; +} + +.follow-toggle .unfollow:hover div.unfollow-green{ + display:none; +} diff --git a/askbot/skins/old/templates/404.html b/askbot/skins/old/templates/404.html new file mode 100644 index 00000000..158bfb94 --- /dev/null +++ b/askbot/skins/old/templates/404.html @@ -0,0 +1,5 @@ +{% load extra_tags %} +{% include_jinja "404.jinja.html" request %} +{% comment %} +this one has to be a django template because of use of default hander404 +{% endcomment %} diff --git a/askbot/skins/old/templates/404.jinja.html b/askbot/skins/old/templates/404.jinja.html new file mode 100644 index 00000000..2da99646 --- /dev/null +++ b/askbot/skins/old/templates/404.jinja.html @@ -0,0 +1,44 @@ +{% extends "one_column_body.html" %} +<!-- template 404.jinja.html --> +{% block title %}{% spaceless %}{% trans %}Page not found{% endtrans %}{% endspaceless %}{% endblock %} +{% block forestyle%} +<style type="text/css"> + form input { margin-right: 5px; } +</style> +{% endblock %} +{% block content %} +<h1>{% trans %}Page not found{% endtrans %}</h1> +<div id="main-body"> + <div style="padding:5px 0px 10px 0;line-height:25px;"> + <h2>{% trans %}Sorry, could not find the page you requested.{% endtrans %}</h2> + <div style="margin-top:5px"> + {% trans %}This might have happened for the following reasons:{% endtrans %}<br/> + <ul> + <li>{% trans %}this question or answer has been deleted;{% endtrans %}</li> + <li>{% trans %}url has error - please check it;{% endtrans %}</li> + <li>{% trans %}the page you tried to visit is protected or you don't have sufficient points, see{% endtrans %} <a href="{% url faq %}">{% trans %}faq{% endtrans %}</a>;</li> + <li>{% trans %}if you believe this error 404 should not have occured, please{% endtrans %} + <a href="{{feedback_site_url}}" target="_blank">{% trans %}report this problem{% endtrans %}</a></li> + </u> + </div> + <script type="text/javascript"> + var GOOG_FIXURL_LANG = '{{settings.LANGUAGE_CODE}}'; + var GOOG_FIXURL_SITE = '{{site_url}}'; + </script> + <script type="text/javascript" src="http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script> + <ul> + <li><a href="#" id="linkPrevious">{% trans %}back to previous page{% endtrans %} »</li> + <li><a href="{% url questions %}">{% trans %}see all questions{% endtrans %} »</a></li> + <li><a href="{% url tags %}">{% trans %}see all tags{% endtrans %} »</a></li> + </u> + </div> +</div> +{% endblock %} +{% block endjs %} + <script type="text/javascript"> + $().ready(function(){ + $("#linkPrevious").bind("click", back=function(){history.go(-1);}) + }); + </script> +{% endblock %} +<!-- end template 404.jinja.html --> diff --git a/askbot/skins/old/templates/500.html b/askbot/skins/old/templates/500.html new file mode 100644 index 00000000..8ec1bce4 --- /dev/null +++ b/askbot/skins/old/templates/500.html @@ -0,0 +1,5 @@ +{% load extra_tags %} +{% include_jinja "500.jinja.html" request %} +{% comment %}this template must be django +because of the use of default handler500 +{% endcomment %} diff --git a/askbot/skins/old/templates/500.jinja.html b/askbot/skins/old/templates/500.jinja.html new file mode 100644 index 00000000..297ae736 --- /dev/null +++ b/askbot/skins/old/templates/500.jinja.html @@ -0,0 +1,25 @@ +{% extends "two_column_body.html" %} +<!-- template 500.html --> +{% block title %}{% spaceless %}{% trans %}Internal server error{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans %}Internal server error{% endtrans %}</h1> +<div id="main-body"> + <div style="padding:5px 0px 10px 0;line-height:25px"> + {% trans %}system error log is recorded, error will be fixed as soon as possible{% endtrans %}<br/> + {% trans %}please report the error to the site administrators if you wish{% endtrans %} + <ul> + <li><a href="#" id="linkPrevious">{% trans %}back to previous page{% endtrans %}</li> + <li><a href="{% url questions %}">{% trans %}see latest questions{% endtrans %}</a></li> + <li><a href="{% url tags %}">{% trans %}see tags{% endtrans %}</a></li> + </u> + </div> +</div> +{% endblock %} +{% block endjs %} + <script type="text/javascript"> + $().ready(function(){ + $("#linkPrevious").bind("click", back=function(){history.go(-1);}) + }); + </script> +{% endblock %} +<!-- end template 500.html --> diff --git a/askbot/skins/old/templates/about.html b/askbot/skins/old/templates/about.html new file mode 100644 index 00000000..fce4223e --- /dev/null +++ b/askbot/skins/old/templates/about.html @@ -0,0 +1,10 @@ +{% extends "two_column_body.html" %} +<!-- template about.html --> +{% block title %}{% spaceless %}{% trans site_name=settings.APP_SHORT_NAME %}About {{site_name}}{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans site_name=settings.APP_SHORT_NAME %}About {{site_name}}{% endtrans %}</h1> +<div class="content"> + {{settings.FORUM_ABOUT}} +</div> +{% endblock %} +<!-- end template about.html --> diff --git a/askbot/skins/old/templates/answer_edit.html b/askbot/skins/old/templates/answer_edit.html new file mode 100644 index 00000000..e8cbc7ae --- /dev/null +++ b/askbot/skins/old/templates/answer_edit.html @@ -0,0 +1,80 @@ +{% extends "two_column_body.html" %} +{% import "macros.html" as macros %} +<!-- template answer_edit.html --> +{% block title %}{% spaceless %}{% trans %}Edit answer{% endtrans %}{% endspaceless %}{% endblock %} +{% block forestyle %} + <link rel="stylesheet" type="text/css" href="{{"/js/wmd/wmd.css"|media}}" /> +{% endblock %} +{% block content %} +<h1> + {% trans %}Edit answer{% endtrans %} [<a href="{{ answer.question.get_absolute_url() }}#{{ answer.id }}">{% trans %}back{% endtrans %}</a>] +</h1> +<div id="main-body" class="ask-body"> + <form id="fmedit" action="{% url edit_answer answer.id %}" method="post" >{% csrf_token %} + <label for="id_revision" ><strong>{% trans %}revision{% endtrans %}:</strong></label> <br/> + {% if revision_form.revision.errors %}{{ revision_form.revision.errors.as_ul() }}{% endif %} + <div style="vertical-align:middle"> + {{ revision_form.revision }} <input type="submit" style="display:none" id="select_revision" name="select_revision" value="{% trans %}select revision{% endtrans %}"> + </div> + {{ macros.edit_post(form) }} + <div class="after-editor"> + <input type="submit" value="{% trans %}Save edit{% endtrans %}" class="submit" /> + <input type="button" value="{% trans %}Cancel{% endtrans %}" class="submit" onclick="history.back(-1);" /> + </div> + {% if settings.WIKI_ON and answer.wiki == False %} + {{ macros.checkbox_in_div(form.wiki) }} + {% endif %} + </form> +</div> +{% endblock %} + +{% block sidebar %} + {% include "blocks/answer_edit_tips.html" %} +{% endblock %} + +{% block endjs %} + {% include "blocks/editor_data.html" %} + <script type='text/javascript' src='{{"/js/editor.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/jquery.validate.min.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/post.js"|media}}'></script> + <script type='text/javascript'> + {% if settings.ENABLE_MATHJAX or settings.MARKUP_CODE_FRIENDLY %} + var codeFriendlyMarkdown = true; + {% else %} + var codeFriendlyMarkdown = false; + {% endif %} + </script> + <script type='text/javascript' src='{{"/js/wmd/showdown.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/wmd/wmd.js"|media}}'></script> + <script type="text/javascript"> + $().ready(function(){ + $("#nav_questions").attr('className',"on"); + $('#editor').TextAreaResizer(); + + //highlight code synctax when editor has new text + $("#editor").typeWatch({highlight: false, wait: 3000, + captureLength: 5, callback: lanai.highlightSyntax}); + + //toggle preview of editor + var display = true; + var txt = "{% trans %}hide preview{% endtrans %}"; + $('#pre-collapse').text(txt); + $('#pre-collapse').bind('click', function(){ + txt = display ? "{% trans %}show preview{% endtrans %}" : "{% trans %}hide preview{% endtrans %}"; + display = !display; + $('#previewer').toggle(); + $('#pre-collapse').text(txt); + }); + + setupFormValidation($("#fmedit"), CPValidator.getQuestionFormRules(), CPValidator.getQuestionFormMessages()); + + $('#id_revision').unbind().change(function(){ + $("#select_revision").click(); + }); + + lanai.highlightSyntax(); + + }); + </script> +{% endblock %} +<!-- end template answer_edit.html --> diff --git a/askbot/skins/old/templates/ask.html b/askbot/skins/old/templates/ask.html new file mode 100644 index 00000000..9aaa7e8c --- /dev/null +++ b/askbot/skins/old/templates/ask.html @@ -0,0 +1,63 @@ +{% extends "two_column_body.html" %} +{% import "macros.html" as macros %} +<!-- template ask.html --> +{% block title %}{% spaceless %}{% trans %}Ask a question{% endtrans %}{% endspaceless %}{% endblock %} +{% block forestyle %} + <link rel="stylesheet" type="text/css" href="{{"/js/wmd/wmd.css"|media}}" /> +{% endblock %} +{# main contents of ask form is in the template input_bar #} +{% block sidebar %} +{% include "blocks/question_edit_tips.html" %} +{% endblock %} +{% block endjs %} + <script type='text/javascript' src='{{"/js/editor.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/jquery.validate.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/post.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/wmd/showdown.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/wmd/wmd.js"|media}}'></script> + <script type='text/javascript'> + var sortMethod = undefined;//need for live_search + var minSearchWordLength = {{settings.MIN_SEARCH_WORD_LENGTH}}; + </script> + <script type='text/javascript' src='{{"/js/live_search.js"|media}}'></script> + {% include "blocks/editor_data.html" %} + {% if mandatory_tags %} + {% include "blocks/mandatory_tags_js.html" %} + {% endif %} + <script type='text/javascript'> + askbot['urls']['api_get_questions'] = '{% url api_get_questions %}'; + {% if settings.ENABLE_MATHJAX or settings.MARKUP_CODE_FRIENDLY %} + var codeFriendlyMarkdown = true; + {% else %} + var codeFriendlyMarkdown = false; + {% endif %} + $().ready(function(){ + liveSearch().init('ask_page'); + //set current module button style + $('#editor').TextAreaResizer(); + + //highlight code synctax when editor has new text + $("#editor").typeWatch({highlight: false, wait: 3000, + captureLength: 5, callback: lanai.highlightSyntax}); + + //toggle preview of editor + //todo remove copy-paste + var display = true; + var txt = "[{% trans %}hide preview{% endtrans %}]"; + $('#pre-collapse').text(txt); + $('#pre-collapse').bind('click', function(){ + txt = display ? "[{% trans %}show preview{% endtrans %}]" : "[{% trans %}hide preview{% endtrans %}]"; + display = !display; + $('#previewer').toggle(); + $('#pre-collapse').text(txt); + }); + //Tags autocomplete + + {{ macros.tag_autocomplete_js(id = '#id_tags') }} + + setupFormValidation($("#fmask"), CPValidator.getQuestionFormRules(), CPValidator.getQuestionFormMessages()); + lanai.highlightSyntax(); + }); + </script> +{% endblock %} +<!-- end template ask.html --> diff --git a/askbot/skins/old/templates/authopenid/changeemail.html b/askbot/skins/old/templates/authopenid/changeemail.html new file mode 100644 index 00000000..1316a048 --- /dev/null +++ b/askbot/skins/old/templates/authopenid/changeemail.html @@ -0,0 +1,80 @@ +{% extends "one_column_body.html" %} +{% block title %}{% spaceless %}{% trans %}Change email{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<!-- changeemail.html action_type={{action_type}}--> +{% if action_type=="change" %} + <h1> + {% if user.email %} + {% trans %}Change email{% endtrans %} + {% else %} + {% trans %}Save your email address{% endtrans %} + {% endif %} + </h1> + <p class="message"> + {% if user.email %} + {% trans %}change {{email}} info{% endtrans %} + {% else %} + {% trans %}here is why email is required, see {{gravatar_faq_url}}{% endtrans %} + {% endif %} + </p> + {% if msg %} + <p class="error">{{ msg }}</p> + {% endif %} + <div class="aligned"> + <form action="." method="post" accept-charset="utf-8">{% csrf_token %} + {% if next %} + <input type="hidden" name="next" value="{{next}}"/> + {% endif %} + <div class="form-row-vertical"> + <label for="id_email">{% if user.email %}{% trans %}Your new Email{% endtrans %}{% else %}{% trans %}Your Email{% endtrans %}{% endif %}</label> + {% if form.email.errors %} + <p class="error">{{form.email.errors|join(", ")}}</p> + {% endif %} + {{ form.email }} + </div> + <div class="submit-row"> + <input class="submit" type="submit" name="change_email" value="{% if user.email %}{% trans %}Change email{% endtrans %}{% else %}{% trans %}Save Email{% endtrans %}{% endif %}"> + {% if user.email %} + <input class="submit" type="submit" name="cancel" value="{% trans %}Cancel{% endtrans %}"> + {% endif %} + </div> + </form> + </div> +{% elif action_type=="validate" %} + <div id="main-bar" class="headNormal"> + {% trans %}Validate email{% endtrans %} + </div> + <p class="message"> + {% trans %}validate {{email}} info or go to {{change_email_url}}{% endtrans %} + </p> +{% elif action_type=="keep" %} + <div id="main-bar" class="headNormal"> + {% trans %}Email not changed{% endtrans %} + </div> + <p class="message"> + {% trans %}old {{email}} kept, if you like go to {{change_email_url}}{% endtrans %} + </p> +{% elif action_type=="done_novalidate" %} + <div id="main-bar" class="headNormal"> + {% trans %}Email changed{% endtrans %} + </div> + <p class="message"> + {% trans %}your current {{email}} can be used for this{% endtrans %} + </p> +{% elif action_type=="validation_complete" %} + <div id="main-bar" class="headNormal"> + {% trans %}Email verified{% endtrans %} + </div> + <p class="message"> + {% trans %}thanks for verifying email{% endtrans %} + </p> +{% elif action_type=="key_not_sent" %} + <div id="main-bar" class="headNormal"> + {% trans %}email key not sent{% endtrans %} + </div> + <p class="message"> + {% trans %}email key not sent {{email}} change email here {{change_link}}{% endtrans %} + </p> +{% endif %} +{% endblock %} +<!-- end changeemail.html --> diff --git a/askbot/skins/old/templates/authopenid/complete.html b/askbot/skins/old/templates/authopenid/complete.html new file mode 100644 index 00000000..969a173f --- /dev/null +++ b/askbot/skins/old/templates/authopenid/complete.html @@ -0,0 +1,84 @@ +{% extends "one_column_body.html" %} +<!-- complete.html --> +{# +views calling this template: +* django_authopenid.views.register with login_type='openid' +* django_authopenid.views.signin - with login_type='legacy' + +purpose of this template is to allow user enter his/her name +email and sign up for email alerts at the initial registratio + +parameters: +* provider +* login_type openid|legacy +* username (same as screen name or username in the models, and nickname in openid sreg) +* openid_register_form +* openid_verify_form - not clear what this form is supposed to do, not used for legacy +* email_feeds_form forum.forms.SimpleEmailSubscribeForm +* openid_username_exists +#} +{% block head %}{% endblock %} +{% block title %}{% spaceless %}{% trans %}Registration{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} + <h1>{% trans %}Registration{% endtrans %}</h1> + <div id="completetxt" > + <div class="message"> + {% if login_type=='openid' %} + {% trans %}register new {{provider}} account info, see {{gravatar_faq_url}}{% endtrans %} + {% elif login_type=='legacy' %} + {% if external_login_name_is_taken %} + {% trans %}{{username}} already exists, choose another name for + {{provider}}. Email is required too, see {{gravatar_faq_url}} + {% endtrans %} + {% else %} + {% trans %}register new external {{provider}} account info, see {{gravatar_faq_url}}{% endtrans %} + {% endif %} + {% else %} + {% trans %}register new Facebook connect account info, see {{gravatar_faq_url}}{% endtrans %} + {% endif %} + </div> + <p style="display:none">{% trans %}This account already exists, please use another.{% endtrans %}</p> + </div> + {% if openid_register_form.errors %} + <ul class="errorlist"> + {% for error in openid_register_form.non_field_errors() %} + <li>{{error}}</li> + {% endfor %} + </ul> + {% endif %} + <div class="login"> + {% if login_type=='openid' %} + <form name="fregister" action="{% url user_register %}" method="POST">{% csrf_token %} + {% elif login_type=='facebook' %} + <form name="fregister" action="" method="POST">{% csrf_token %} + {% else %} + <form name="fregister" action="{{ settings.LOGIN_URL }}" method="POST">{% csrf_token %} + {% endif %} + {{ openid_register_form.next }} + <div class="form-row-vertical"> + <label for="id_username">{% trans %}Screen name label{% endtrans %}</label> + {% if openid_register_form.username.errors %} + <p class="error">{{ openid_register_form.username.errors|join(", ") }}</p> + {% endif %} + {{ openid_register_form.username }} + </div> + <div class="form-row-vertical margin-bottom"> + <label for="id_email">{% trans %}Email address label{% endtrans %}</label> + {% if openid_register_form.email.errors %} + <p class="error">{{ openid_register_form.email.errors|join(", ") }}</p> + {% endif %} + {{ openid_register_form.email }} + </div> + <p>{% trans %}receive updates motivational blurb{% endtrans %}</p> + <div class='simple-subscribe-options'> + {{email_feeds_form.subscribe}} + {% if email_feeds_form.errors %} + <p class="error">{% trans %}please select one of the options above{% endtrans %}</p> + {% endif %} + </div> + <p class='space-above'>{% trans %}Tag filter tool will be your right panel, once you log in.{% endtrans %}</p> + <div class="submit-row"><input type="submit" class="submit" name="bnewaccount" value="{% trans %}create account{% endtrans %}"/></div> + </form> + </div> +{% endblock %} +<!-- end complete.html --> diff --git a/askbot/skins/old/templates/authopenid/confirm_email.txt b/askbot/skins/old/templates/authopenid/confirm_email.txt new file mode 100644 index 00000000..1a0f4e63 --- /dev/null +++ b/askbot/skins/old/templates/authopenid/confirm_email.txt @@ -0,0 +1,12 @@ +{% trans %}Thank you for registering at our Q&A forum!{% endtrans %} + +{% trans %}Your account details are:{% endtrans %} + +{% trans %}Username:{% endtrans %} {{ username }} +{% trans %}Password:{% endtrans %} {{ password }} + +{% trans %}Please sign in here:{% endtrans %} +{{signup_url}} + +{% trans %}Sincerely, +Forum Administrator{% endtrans %} diff --git a/askbot/skins/old/templates/authopenid/email_validation.txt b/askbot/skins/old/templates/authopenid/email_validation.txt new file mode 100644 index 00000000..9c5baa8a --- /dev/null +++ b/askbot/skins/old/templates/authopenid/email_validation.txt @@ -0,0 +1,14 @@ +{% trans %}Greetings from the Q&A forum{% endtrans %}, + +{% trans %}To make use of the Forum, please follow the link below:{% endtrans %} + +{{validation_link}} + +{% trans %}Following the link above will help us verify your email address.{% endtrans %} + +{% trans %}If you beleive that this message was sent in mistake - +no further action is needed. Just ingore this email, we apologize +for any inconvenience{% endtrans %} + +{% trans %}Sincerely, +Forum Administrator{% endtrans %} diff --git a/askbot/skins/old/templates/authopenid/logout.html b/askbot/skins/old/templates/authopenid/logout.html new file mode 100644 index 00000000..a07b78d1 --- /dev/null +++ b/askbot/skins/old/templates/authopenid/logout.html @@ -0,0 +1,31 @@ +{% extends "one_column_body.html" %} +<!-- template logout.html --> +{% block title %}{% spaceless %}{% trans %}Logout{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans %}You have successfully logged out{% endtrans %}</h1> +{% if have_federated_login_methods %} + <p>{% trans %}However, you still may be logged in to your OpenID provider. Please logout of your provider if you wish to do so.{% endtrans %}</p> + {% if settings.FACEBOOK_KEY and settings.FACEBOOK_SECRET %} + <div id="fb-root"></div> + <script src="http://connect.facebook.net/en_US/all.js"></script> + <script> + FB.init({appId: '{{settings.FACEBOOK_KEY}}', status: true, cookie: true, xfbml: true}); + </script> + {% endif %} +{% endif %} +{% endblock %} +{% block endjs %} + <script type="text/javascript"> + $(document).ready(function(){ + //logout user from facebook + if (typeof FB != 'undefined'){ + FB.getLoginStatus(function(response){ + if (response.session){ + FB.logout(); + } + }); + } + }); + </script> +{% endblock %} +<!-- end logout.html --> diff --git a/askbot/skins/old/templates/authopenid/macros.html b/askbot/skins/old/templates/authopenid/macros.html new file mode 100644 index 00000000..477d277c --- /dev/null +++ b/askbot/skins/old/templates/authopenid/macros.html @@ -0,0 +1,58 @@ +{% macro login_provider_input(login_provider) %} + <input + name="{{login_provider.name}}" + type="image" + class="{{login_provider.type}}" + src="{{login_provider.icon_media_path|media}}" + alt="{{login_provider.tooltip_text}}" + title="{{login_provider.tooltip_text}}" + /> +{% endmacro %} + +{% macro provider_buttons( + login_form = None, + major_login_providers = None, + minor_login_providers = None, + hide_local_login = False, + settings = None, + logged_in = False + ) +%} + <div id="login-icons"> + <ul class="login-icons large"> + {% for login_provider in major_login_providers %} + {% if login_provider.name == 'local' and hide_local_login == True %} + {# do nothing here, left if statement this way for simplicity #} + {% else %} + {% if logged_in == True and login_provider.type == 'password' and login_provider.password_changeable == False %} + {% else %} + <li> + {{ login_provider_input(login_provider) }} + </li> + {% endif %} + {% endif %} + {% endfor %} + </ul> + <ul class="login-icons small"> + {% for login_provider in minor_login_providers %} + {% if logged_in == True and login_provider.type == 'password' and login_provider.password_changeable == False %} + {% else %} + <li> + {{ login_provider_input(login_provider) }} + </li> + {% endif %} + {% endfor %} + </ul> + </div> + <fieldset + id="openid-fs" + {% if not login_form.openid_login_token.errors %} + style="display:none;" + {% endif %} + > + <h2 id="openid-heading">{% trans %}Please enter your <span>user name</span>, then sign in{% endtrans %}</h2> + <p class="hint">{% trans %}(or select another login method above){% endtrans %}</p> + <input type="text" name="openid_login_token" /> + <input class="submit-b" type="submit" name="openid_login_with_extra_token" value="{% trans %}Sign in{% endtrans %}"/> + </fieldset> +{% endmacro %} diff --git a/askbot/skins/old/templates/authopenid/providers_javascript.html b/askbot/skins/old/templates/authopenid/providers_javascript.html new file mode 100644 index 00000000..0fe72eb3 --- /dev/null +++ b/askbot/skins/old/templates/authopenid/providers_javascript.html @@ -0,0 +1,55 @@ +<script type='text/javascript' src='{{"/js/jquery.validate.min.js"|media}}'></script> +<script type="text/javascript" src="{{"/jquery-openid/jquery.openid.js"|media}}"></script> +<script type="text/javascript"> + var extra_token_name = {}; + var create_pw_text = {}; + var change_pw_text = {}; + var authUrl = '/{% trans %}account/{% endtrans %}'; + var siteName = '{{settings.APP_SHORT_NAME}}'; + var provider_count = {{existing_login_methods|length}}; + {% for login_provider in major_login_providers %} + {%if settings['SIGNIN_' + login_provider.name.upper() + '_ENABLED'] == True %} + {% if login_provider.extra_token_name %} + extra_token_name['{{login_provider.name}}'] = '{{login_provider.extra_token_name}}'; + {% endif %} + {% if login_provider.type == 'password' %} + create_pw_text['{{login_provider.name}}'] = '{{login_provider.create_password_prompt}}'; + change_pw_text['{{login_provider.name}}'] = '{{login_provider.change_password_prompt}}'; + {% endif %} + {% endif %} + {% endfor %} + {% for login_provider in minor_login_providers %} + {% if settings['SIGNIN_' + login_provider.name.upper() + '_ENABLED'] == True %} + {% if login_provider.extra_token_name %} + extra_token_name['{{login_provider.name}}'] = '{{login_provider.extra_token_name}}'; + {% endif %} + {% if login_provider.type == 'password' %} + create_pw_text['{{login_provider.name}}'] = '{{login_provider.create_password_prompt}}'; + change_pw_text['{{login_provider.name}}'] = '{{login_provider.change_password_prompt}}'; + {% endif %} + {% endif %} + {% endfor %} + {% if user.is_authenticated() %} + var userIsAuthenticated = true; + {% else %} + var userIsAuthenticated = false; + {% endif %} + askbot['settings']['signin_always_show_local_login'] = {% if settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN %}true{% else %}false{% endif %}; + $("body").authenticator(); +</script> +{% if settings.FACEBOOK_KEY and settings.FACEBOOK_SECRET %} +<div id="fb-root"></div> +<script src="http://connect.facebook.net/en_US/all.js"></script> +<script> + $(document).ready(function(){ + if (typeof FB != 'undefined'){ + var ret = FB.init({appId: '{{settings.FACEBOOK_KEY}}', status: true, cookie: true, xfbml: true}); + FB.Event.subscribe('auth.sessionChange', function(response){ + if (response.session) { + $('#signin-form').submit(); + } + }); + }; + }); +</script> +{% endif %} diff --git a/askbot/skins/old/templates/authopenid/signin.html b/askbot/skins/old/templates/authopenid/signin.html new file mode 100644 index 00000000..49c447a1 --- /dev/null +++ b/askbot/skins/old/templates/authopenid/signin.html @@ -0,0 +1,241 @@ +{% extends "two_column_body.html" %}
+{% import "authopenid/macros.html" as login_macros %}
+<!-- signin.html -->
+{% block title %}{% spaceless %}{% trans %}User login{% endtrans %}{% endspaceless %}{% endblock %}
+{% block forestyle %}
+ <link rel="stylesheet" type="text/css" media="screen" href="{{"/jquery-openid/openid.css"|media}}"/>
+{% endblock %}
+{% block content %}
+{% if have_buttons or view_subtype == 'email_sent' %}
+ <h1>{{page_title}}</h1>
+{% endif %}
+ {% if answer %}
+ <div class="message">
+ {% trans title=answer.question.title, summary=answer.summary %}
+ Your answer to {{title}} {{summary}} will be posted once you log in
+ {% endtrans %}
+ </div>
+ {% endif %}
+ {% if question %}
+ <div class="message">
+ {% trans title=question.title, summary=question.summary %}Your question
+ {{title}} {{summary}} will be posted once you log in
+ {% endtrans %}
+ </div>
+ {% endif %}
+ <p id='login-intro'>
+ {% if view_subtype == 'default' and have_buttons %}
+ {% trans %}Take a pick of your favorite service below to sign in using secure OpenID or similar technology. Your external service password always stays confidential and you don't have to rememeber or create another one.{% endtrans %}
+ {% elif view_subtype == 'add_openid' and have_buttons %}
+ {% if existing_login_methods %}
+ {% trans %}It's a good idea to make sure that your existing login methods still work, or add a new one. Please click any of the icons below to check/change or add new login methods.{% endtrans %}
+ {% else %}
+ {% trans %}Please add a more permanent login method by clicking one of the icons below, to avoid logging in via email each time.{% endtrans %}
+ {% endif %}
+ {% elif view_subtype == 'change_openid' and have_buttons %}
+ {% if existing_login_methods %}
+ {% trans %}Click on one of the icons below to add a new login method or re-validate an existing one.{% endtrans %}
+ {% else %}
+ {% trans %}You don't have a method to log in right now, please add one or more by clicking any of the icons below.{% endtrans %}
+ {% endif %}
+ {% elif view_subtype == 'email_sent' %}
+ {% trans %}Please check your email and visit the enclosed link to re-connect to your account{% endtrans %}
+ {% endif %}
+ </p>
+ {% if openid_error_message %}
+ <p class="warning">{{ openid_error_message }}</p>
+ {% endif %}
+ {% if view_subtype != 'email_sent' and view_subtype != 'bad_key' %}
+ <form id="signin-form" method="post" action="{{ settings.LOGIN_URL }}">{% csrf_token %}
+ {# in this branch - the real signin view we display the login icons
+ here we hide the local login button only if admin
+ wants to always show the password login form - then
+ the button is useless.
+ #}
+ {{ login_form.login_provider_name }}
+ {{ login_form.next }}
+ {{
+ login_macros.provider_buttons(
+ login_form = login_form,
+ major_login_providers = major_login_providers,
+ minor_login_providers = minor_login_providers,
+ hide_local_login = settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN,
+ settings = settings,
+ logged_in = user.is_authenticated()
+ )
+ }}
+ {% if use_password_login == True %}
+ <fieldset
+ id="password-fs"
+ {% if user.is_anonymous() %}
+ {% if not login_form.username.errors and not login_form.password_login_failed %}
+ {% if not settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN %}
+ style="display:none;"
+ {%endif%}
+ {% endif %}
+ {% else %}
+ {% if not login_form.new_password.errors and not login_form.new_password_retyped.errors %}
+ {% if not settings.SIGNIN_ALWAYS_SHOW_LOCAL_LOGIN %}
+ style="display:none;"
+ {% endif%}
+ {% endif %}
+ {% endif %}
+ >
+ {{login_form.password_action}}
+ {% if user.is_anonymous() %}
+ <h2 id="password-heading">
+ {% trans %}Please enter your <span>user name and password</span>, then sign in{% endtrans %}
+ </h2>
+ {% if have_buttons %}
+ <p class="hint">{% trans %}(or select another login method above){% endtrans %}</p>
+ {% endif %}
+ {% if login_form.password_login_failed %}
+ <p class="error">{% trans %}Login failed, please try again{% endtrans %}</p>
+ {% endif %}
+ <table class="login">
+ <tr>
+ <td><label for="id_username">{% trans %}Login or email{% endtrans %}</label></td>
+ <td>{{login_form.username}}</td>
+ </tr>
+ <tr>
+ <td><label for="id_password">{% trans %}Password{% endtrans %}</label></td>
+ <td>{{login_form.password}}</td>
+ </tr>
+ </table>
+ <p id="local_login_buttons">
+ <input class="submit-b" name="login_with_password" type="submit" value="{% trans %}Login{% endtrans %}" />
+ {% if settings.USE_LDAP_FOR_PASSWORD_LOGIN == False %}
+ <a class="create-password-account" style="vertical-align:middle" href="{% url user_signup_with_password %}?login_provider=local">{% trans %}Create a password-protected account{% endtrans %}</a>
+ {% endif %}
+ </p>
+ {% elif settings.USE_LDAP_FOR_PASSWORD_LOGIN == False %}
+ <h2 id="password-heading">
+ {% trans %}To change your password - please enter the new one twice, then submit{% endtrans %}
+ </h2>
+ <table class="login">
+ <tr>
+ <td><label for="id_new_password">{% trans %}New password{% endtrans %}</label></td>
+ <td>
+ {{login_form.new_password}}
+ <span class="error">{{login_form.new_password.errors[0]}}</span>
+ </td>
+ </tr>
+ <tr>
+ <td><label for="id_new_password_retyped">{% trans %}Please, retype{% endtrans %}</label></td>
+ <td>
+ {{login_form.new_password_retyped}}
+ <span class="error">{{login_form.new_password_retyped.errors[0]}}</span>
+ </td>
+ </tr>
+ </table>
+ <p id="local_login_buttons">
+ <input class="submit-b" name="change_password" type="submit" value="{% trans %}Change password{% endtrans %}" />
+ </p>
+ {% endif %}
+ </fieldset>
+ {% endif %}
+ </form>
+ {% if user.is_authenticated() and existing_login_methods and settings.ALLOW_ADD_REMOVE_LOGIN_METHODS %}
+ <div
+ id='existing-login-methods'
+ {% if login_form.password_change_failed %}
+ style="display:none";
+ {% endif %}
+ >
+ <h2 id='ab-show-login-methods'>
+ {% trans %}Here are your current login methods{% endtrans %}
+ </h2>
+ <table id='ab-existing-login-methods'>
+ <tr>
+ <th>{% trans %}provider{% endtrans %}</th>
+ <th>{% trans %}last used{% endtrans %}</th>
+ <th>{% trans %}delete, if you like{% endtrans %}</th>
+ </tr>
+ {% for login_method in existing_login_methods %}
+ <tr class="ab-provider-row">
+ <td class="ab-provider-name">
+ {{login_method.provider_name}}
+ </td>
+ <td>
+ {% if login_method.last_used_timestamp %}
+ {{login_method.last_used_timestamp|diff_date}}
+ {% endif %}
+ </td>
+ <td>
+ {% if login_method.is_deletable %}
+ <button>{% trans %}delete{% endtrans %}</button>
+ {% else %}
+ {% trans %}cannot be deleted{% endtrans %}
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ </table>
+ </div>
+ {% endif %}
+ {% endif %}
+ {% if view_subtype != 'email_sent' or view_subtype == 'bad_key' %}
+ {% if user.is_anonymous() and settings.ALLOW_ACCOUNT_RECOVERY_BY_EMAIL %}
+ <form id="account-recovery-form" action="{% url user_account_recover %}" method="post">{% csrf_token %}
+ {% if view_subtype != 'bad_key' %}
+ <h2 id='account-recovery-heading'>{% trans %}Still have trouble signing in?{% endtrans %}</h2>
+ {% endif %}
+ <p class="hint">
+ <span class="text">
+ {% if view_subtype == 'bad_key' %}
+ {% trans %}Please, enter your email address below and obtain a new key{% endtrans %}
+ {% else %}
+ {% trans %}Please, enter your email address below to recover your account{% endtrans %}
+ {% endif %}
+ </span>
+ <span style="display:none" class="link"> - <a href="#">{% trans %}recover your account via email{% endtrans %}</a></span>
+ </p>
+ <fieldset id='email-input-fs'>
+ {% if account_recovery_form.email.errors %}
+ <p class="error">{{account_recovery_form.email.errors[0]}}</p>
+ {% endif %}
+ {{ account_recovery_form.email }}
+ <input
+ class="submit-b"
+ type="submit"
+ {% if view_subtype == 'bad_key' %}
+ value="{% trans %}Send a new recovery key{% endtrans %}"
+ {% else %}
+ value="{% trans %}Recover your account via email{% endtrans %}"
+ {% endif %}
+ />
+ </fieldset>
+ </form>
+ {% endif %}
+ {% endif %}
+{% endblock %}
+
+{% block sidebar %}
+ {% if have_buttons %}
+ <div class="boxC">
+ <h2>{% trans %}Why use OpenID?{% endtrans %}</h2>
+ <ul>
+ <li>
+ {% trans %}with openid it is easier{% endtrans %}
+ </li>
+ <li>
+ {% trans %}reuse openid{% endtrans %}
+ </li>
+ <li>
+ {% trans %}openid is widely adopted{% endtrans %}
+ </li>
+ <li>
+ {% trans %}openid is supported open standard{% endtrans %}
+ </li>
+ </ul>
+ <p class="info-box-follow-up-links">
+ <a href="http://openid.net/what/" target="_blank">{% trans %}Find out more{% endtrans %} »</a><br/>
+ <a href="http://openid.net/get/" target="_blank">{% trans %}Get OpenID{% endtrans %} »</a>
+ </p>
+ </div>
+ {% endif %}
+{% endblock%}
+{%block endjs%}
+{%include "authopenid/providers_javascript.html" %}
+{%endblock%}
+<!-- end signin.html -->
diff --git a/askbot/skins/old/templates/authopenid/signup_with_password.html b/askbot/skins/old/templates/authopenid/signup_with_password.html new file mode 100644 index 00000000..047ff076 --- /dev/null +++ b/askbot/skins/old/templates/authopenid/signup_with_password.html @@ -0,0 +1,58 @@ +{% extends "one_column_body.html" %} +{% import "authopenid/macros.html" as login_macros %} +<!--signup.html--> +{% block title %}{% spaceless %}{% trans %}Signup{% endtrans %}{% endspaceless %}{% endblock %} +{% block forestyle %} + <link rel="stylesheet" type="text/css" media="screen" href="{{"/jquery-openid/openid.css"|media}}"/> +{% endblock %} +{% block content %} +{% if settings.PASSWORD_REGISTER_SHOW_PROVIDER_BUTTONS == True %} + <h1>{% trans %}Please register by clicking on any of the icons below{% endtrans %}</h1> + <form id="signin-form" method="post" action="{{ settings.LOGIN_URL }}">{% csrf_token %} + {# hide_local_login == True because it is password reg form #} + {{ + login_macros.provider_buttons( + login_form = login_form, + major_login_providers = major_login_providers, + minor_login_providers = minor_login_providers, + hide_local_login = True, + settings = settings + ) + }} + </form> + <h2>{% trans %}or create a new user name and password here{% endtrans %}</h2> +{% else %} + <h1>{% trans %}Create login name and password{% endtrans %}</h1> + <p class="message">{% trans %}Traditional signup info{% endtrans %}</p> +{%endif%} +<form action="{% url user_signup_with_password %}" method="post" accept-charset="utf-8">{% csrf_token %} + {{form.login_provider}} + <ul class="form-horizontal-rows"> + <li><label for="usename_id">{{form.username.label}}</label>{{form.username}}{{form.username.errors}}</li> + <li><label for="email_id">{{form.email.label}}</label>{{form.email}}{{form.email.errors}}</li> + <li><label for="password1_id">{{form.password1.label}}</label>{{form.password1}}{{form.password1.errors}}</li> + <li><label for="password2_id">{{form.password2.label}}</label>{{form.password2}}{{form.password2.errors}}</li> + </ul> + <p style="margin-top: 10px">{% trans %}receive updates motivational blurb{% endtrans %}</p> + <div class='simple-subscribe-options'> + {{email_feeds_form.subscribe}} + {% if email_feeds_form.errors %} + <p class="error">{% trans %}please select one of the options above{% endtrans %}</p> + {% endif %} + </div> + {% if settings.USE_RECAPTCHA %} + <p class="signup_p">{% trans %}Please read and type in the two words below to help us prevent automated account creation.{% endtrans %}</p> + {{form.recaptcha}} + {% endif %} + <div class="submit-row"><input type="submit" class="submit" value="{% trans %}Create Account{% endtrans %}" /> + {% if settings.PASSWORD_REGISTER_SHOW_PROVIDER_BUTTONS == False %} + <strong>{% trans %}or{% endtrans %} + <a href="{{ settings.LOGIN_URL }}">{% trans %}return to OpenID login{% endtrans %}</a></strong> + {% endif %} + </div> +</form> +{% endblock %} +{%block endjs%} +{%include "authopenid/providers_javascript.html" %} +{%endblock%} +<!--end signup.html--> diff --git a/askbot/skins/old/templates/avatar/add.html b/askbot/skins/old/templates/avatar/add.html new file mode 100644 index 00000000..68a188ef --- /dev/null +++ b/askbot/skins/old/templates/avatar/add.html @@ -0,0 +1,15 @@ +{% extends "user_profile/user.html" %} +{% import "macros.html" as macros %} +{% block profilesection %}{% trans %}add avatar{% endtrans %}{% endblock %} +{% block usercontent %} + <h2>{% trans %}Change avatar{% endtrans %} + <p>{% trans %}Your current avatar: {% endtrans %}</p> + {{ macros.gravatar(user, 128) }} + {% if not avatars %} + <p>{% trans %}You haven't uploaded an avatar yet. Please upload one now.{% endtrans %}</p> + {% endif %} + <form enctype="multipart/form-data" method="POST" action="{% url avatar_add %}">{% csrf_token %} + {{ upload_avatar_form.as_p() }} + <p><input type="submit" value="{% trans %}Upload New Image{% endtrans %}" /></p> + </form> +{% endblock %} diff --git a/askbot/skins/old/templates/avatar/change.html b/askbot/skins/old/templates/avatar/change.html new file mode 100644 index 00000000..7921a662 --- /dev/null +++ b/askbot/skins/old/templates/avatar/change.html @@ -0,0 +1,24 @@ +{% extends "user_profile/user.html" %} +{% import "macros.html" as macros %} +{% block profilesection %} + {% trans %}change avatar{% endtrans %} +{% endblock %} +{% block usercontent %} + <p>{% trans %}Your current avatar: {% endtrans %}<br/> + {{ macros.gravatar(user, 128) }} + </p> + {% if not avatars %} + <p>{% trans %}You haven't uploaded an avatar yet. Please upload one now.{% endtrans %}</p> + {% else %} + <form method="POST" action="{% url avatar_change %}">{% csrf_token %} + <ul> + {{ primary_avatar_form.as_ul() }} + </ul> + <p><input type="submit" value="{% trans %}Choose new Default{% endtrans %}" /></p> + </form> + {% endif %} + <form enctype="multipart/form-data" method="POST" action="{% url avatar_add %}">{% csrf_token %} + {{ upload_avatar_form.as_p() }} + <p><input type="submit" value="{% trans %}Upload{% endtrans %}" /></p> + </form> +{% endblock %} diff --git a/askbot/skins/old/templates/avatar/confirm_delete.html b/askbot/skins/old/templates/avatar/confirm_delete.html new file mode 100644 index 00000000..282d72fa --- /dev/null +++ b/askbot/skins/old/templates/avatar/confirm_delete.html @@ -0,0 +1,16 @@ +{% extends "user_profile/user.html" %} +{% import "macros.html" as macros %} +{% block profilesection %}{% trans %}delete avatar{% endtrans %}{% endblock %} +{% block usercontent %} + <p>{% trans %}Please select the avatars that you would like to delete.{% endtrans %}</p> + {% if not avatars %} + <p>{% trans avatar_change_url="avatar_change"|url %}You have no avatars to delete. Please <a href="{{ avatar_change_url }}">upload one</a> now.{% endtrans %}</p> + {% else %} + <form method="POST" action="{% url avatar_delete %}">{% csrf_token %} + <ul> + {{ delete_avatar_form.as_ul() }} + </ul> + <p><input type="submit" value="{% trans %}Delete These{% endtrans %}" /></p> + </form> + {% endif %} +{% endblock %} diff --git a/askbot/skins/old/templates/badge.html b/askbot/skins/old/templates/badge.html new file mode 100644 index 00000000..ee7f5360 --- /dev/null +++ b/askbot/skins/old/templates/badge.html @@ -0,0 +1,24 @@ +{% extends "two_column_body.html" %} +{% import "macros.html" as macros %} +<!-- template badge.html --> +{% block title %}{% spaceless %}{% trans name=badge.name %}{{name}}{% endtrans %} - {% trans %}Badge{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans name=badge.name %}Badge "{{name}}"{% endtrans %}</h1> + <p> + <a href="{{badge.get_absolute_url()}}" title="{{ badge.get_type_display() }} : {% trans description=badge.description %}{{description}}{% endtrans %}" class="medal"><span class="{{ badge.css_class }}">●</span> {% trans name=badge.name%}{{name}}{% endtrans %}</a> {% trans description=badge.description %}{{description}}{% endtrans %} + </p> + <div> + {% if badge.awarded_count %} + <p style="float:left"><span class="count">{{ badge_recipients|length|intcomma }}</span> + <strong>{% trans num_awardees=badge_recipients|length %}user received this badge:{% pluralize %}users received this badge:{% endtrans %}</strong></p> + {% endif %} + </div> + <div id="award-list" style="clear:both;margin-left:20px;line-height:25px;"> + {% for recipient in badge_recipients %} + <p style="width:180px;float:left"><a href="{{ recipient.get_absolute_url() }}">{{ recipient.username }}</a> + {{ macros.user_score_and_badge_summary(recipient) }} + </p> + {% endfor %} + </div> +{% endblock %} +<!-- end template badge.html --> diff --git a/askbot/skins/old/templates/badges.html b/askbot/skins/old/templates/badges.html new file mode 100644 index 00000000..bbd09951 --- /dev/null +++ b/askbot/skins/old/templates/badges.html @@ -0,0 +1,60 @@ +{% extends "two_column_body.html" %} +<!-- template badges.html --> +{% block title %}{% spaceless %}{% trans %}Badges summary{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans %}Badges{% endtrans %}</h1> +<p> +{% trans %}Community gives you awards for your questions, answers and votes.{% endtrans %}<br/> +{% trans %}Below is the list of available badges and number +of times each type of badge has been awarded. Give us feedback at {{feedback_faq_url}}. +{% endtrans %} +</p> +<div id="medalList"> + {% for badge in badges %} + <div style="clear:both;line-height:30px"> + <div style="float:left;min-width:30px;text-align:right;height:30px"> + {% for a in mybadges %} + {% if a.badge_id == badge.id %} + <span style="font-size:175%; padding-right:5px; color:#5B9058;">✔</span> + {% endif %} + {% endfor %} + </div> + <div style="float:left;width:230px;"> + <a href="{{badge.get_absolute_url()}}" + title="{{badge.get_type_display()}} : {{badge.description}}" + class="medal"><span class="{{ badge.css_class }}">●</span> {{badge.name}}</a><strong> + × {{ badge.awarded_count|intcomma }}</strong> + </div> + <p style="float:left;margin-top:8px;">{{badge.description}}</p> + </div> + {% endfor %} +</div> +{% endblock %} +{% block sidebar %} +<div class="boxC"> + <h2>{% trans %}Community badges{% endtrans %}</h2> + <p> + <a style="cursor:default;" title="{% trans %}gold badge: the highest honor and is very rare{% endtrans %}" class="medal"><span class="badge1">●</span> {% trans %}gold{% endtrans %}</a> + </p> + <p> + {% trans %}gold badge description{% endtrans %} + </p> + <p> + <a + style="cursor:default;" + title="{% trans %}silver badge: occasionally awarded for the very high quality contributions{% endtrans %}" + class="medal"><span class="badge2">●</span> {% trans %}silver{% endtrans %}</a> + </p> + <p> + {% trans %}silver badge description{% endtrans %} + </p> + <p> + <a style="cursor:default;" title="{% trans %}bronze badge: often given as a special honor{% endtrans %}" class="medal"> + <span class="badge3">●</span> {% trans %}bronze{% endtrans %}</a> + </p> + <p> + {% trans %}bronze badge description{% endtrans %} + </p> +</div> +{% endblock %} +<!-- end template badges.html --> diff --git a/askbot/skins/old/templates/base.html b/askbot/skins/old/templates/base.html new file mode 100644 index 00000000..9f779945 --- /dev/null +++ b/askbot/skins/old/templates/base.html @@ -0,0 +1,70 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<!-- template base.html --> +<html xmlns="http://www.w3.org/1999/xhtml"> + {% spaceless %} + <head> + <title>{% block title %}{% endblock %} - {{ settings.APP_TITLE|escape }}</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + {% block meta_description %} + <meta name="description" content="{{settings.APP_DESCRIPTION|escape}}" /> + {% endblock %} + <meta name="keywords" content="{%block keywords%}{%endblock%},{{settings.APP_KEYWORDS|escape}}" /> + {% if settings.GOOGLE_SITEMAP_CODE %} + <meta name="google-site-verification" content="{{settings.GOOGLE_SITEMAP_CODE}}" /> + {% endif %} + <link rel="shortcut icon" href="{{ settings.SITE_FAVICON|media }}" /> + <link href="{{"/style/style.css"|media }}" rel="stylesheet" type="text/css" /> + {{ skin.get_extra_css_link() }} + {% if settings.USE_CUSTOM_CSS %} + <link + href="{% url "custom_css" %}?v={{settings.MEDIA_RESOURCE_REVISION}}" + rel="stylesheet" + type="text/css" + /> + {% endif %} + {% block forestyle %}{% endblock %} + {% if user_messages %} + <style type="text/css"> + body { margin-top:2.4em; } + </style> + {% endif %} + {% if settings.USE_CUSTOM_HTML_HEAD %} + {{ settings.CUSTOM_HTML_HEAD }} + {% endif %} + <script type="text/javascript"> + var askbot = {}; + askbot['data'] = {}; + askbot['urls'] = {}; + askbot['settings'] = {}; + askbot['messages'] = {}; + </script> + {% block forejs %} + {% endblock %} + {# avoid adding javascript here so that pages load faster #} + </head> + {% endspaceless %} + <body class="{% block body_class %}{% endblock %}{% if page_class %} {{page_class}}{% endif %}"> + {% include "blocks/system_messages.html" %} + {% include "custom_header.html" ignore missing %} + {% include "blocks/header.html" %} + <div class="content-wrapper"> + {% block body %} + {% endblock %} + </div> + {% if settings.FOOTER_MODE == 'default' %} + {% include "blocks/footer.html" %} + {% elif settings.FOOTER_MODE == 'customize' %} + {{ settings.CUSTOM_FOOTER }} + {% endif %} + {% include "custom_footer.html" ignore missing %} + {% include "blocks/bottom_scripts.html" %} + {% block endjs %} + {% endblock %} + <script type="text/javascript"> + for (url_name in askbot['urls']){ + askbot['urls'][url_name] = cleanUrl(askbot['urls'][url_name]); + } + </script> + </body> +</html> +<!-- end template base.html --> diff --git a/askbot/skins/old/templates/blocks/README b/askbot/skins/old/templates/blocks/README new file mode 100644 index 00000000..88537d0a --- /dev/null +++ b/askbot/skins/old/templates/blocks/README @@ -0,0 +1,2 @@ +this directory should contain block templates that +are included within other templates diff --git a/askbot/skins/old/templates/blocks/answer_edit_tips.html b/askbot/skins/old/templates/blocks/answer_edit_tips.html new file mode 100644 index 00000000..23e4df53 --- /dev/null +++ b/askbot/skins/old/templates/blocks/answer_edit_tips.html @@ -0,0 +1,63 @@ +<!-- template answer_edit_tips.html --> +<div class="boxC"> + <h2>{% trans %}answer tips{% endtrans %}</h2> + <div> + <ul> + <li> <b>{% trans %}please make your answer relevant to this community{% endtrans %}</b> + </li> + <li> + {% trans %}try to give an answer, rather than engage into a discussion{% endtrans %} + </li> + <li> + {% trans %}please try to provide details{% endtrans %} + </li> + <li> + {% trans %}be clear and concise{% endtrans %} + </li> + </ul> + <p class='info-box-follow-up-links'> + <a href="{% url faq %}" target="_blank" title="{% trans %}see frequently asked questions{% endtrans %}">faq »</a> + </p> + </div> +</div> + +<div class="boxC"> + <h2>{% trans %}Markdown tips{% endtrans %}</h2> + <ul> + {% if settings.MARKUP_CODE_FRIENDLY or settings.ENABLE_MATHJAX %} + <li> + {% trans %}*italic*{% endtrans %} + </li> + <li> + {% trans %}**bold**{% endtrans %} + </li> + {% else %} + <li> + {% trans %}*italic* or _italic_{% endtrans %} + </li> + <li> + {% trans %}**bold** or __bold__{% endtrans %} + </li> + {% endif %} + <li> + <b>{% trans %}link{% endtrans %}</b>:[{% trans %}text{% endtrans %}](http://url.com/ "{% trans %}title{% endtrans %}") + + </li> + <li> + <b>{% trans %}image{% endtrans %}</b>:![alt {% trans %}text{% endtrans %}](/path/img.jpg "{% trans %}title{% endtrans %}") + + </li> + <li> + {% trans %}numbered list:{% endtrans %} + 1. Foo + 2. Bar + </li> + <li> + {% trans %}basic HTML tags are also supported{% endtrans %} + </li> + </ul> + <p class='info-box-follow-up-links'> + <a href="http://en.wikipedia.org/wiki/Markdown" target="_blank">{% trans %}learn more about Markdown{% endtrans %} »</a> + </p> +</div> +<!-- end template answer_edit_tips.html --> diff --git a/askbot/skins/old/templates/blocks/ask_form.html b/askbot/skins/old/templates/blocks/ask_form.html new file mode 100644 index 00000000..606aef78 --- /dev/null +++ b/askbot/skins/old/templates/blocks/ask_form.html @@ -0,0 +1,46 @@ +{% import "macros.html" as macros %} +<form id="fmask" action="" method="post" >{% csrf_token %} + <div class="form-item"> + <div id="askFormBar"> + {% if not request.user.is_authenticated() %} + <p>{% trans %}login to post question info{% endtrans %}</p> + {% else %} + {% if settings.EMAIL_VALIDATION %} + {% if not request.user.email_isvalid %} + {% trans email=request.user.email %}must have valid {{email}} to post, + see {{email_validation_faq_url}} + {% endtrans %} + {% endif %} + {% endif %} + {% endif %} + <input id="id_title" class="questionTitleInput" name="title" autocomplete="off" + value="{% if form.initial.title %}{{form.initial.title}}{% endif %}"/> + <span class="form-error">{{ form.title.errors }}</span> + </div> + <div class="title-desc"> + {{ form.title.help_text }} + </div> + </div> + <div id='question-list'></div> + {{ + macros.edit_post( + form, + post_type = 'question', + edit_title = False, + mandatory_tags = mandatory_tags + ) + }} + {% if not request.user.is_authenticated() %} + <input type="submit" name="post_anon" value="{% trans %}Login/signup to post your question{% endtrans %}" class="submit" /> + {% else %} + <input type="submit" name="post" value="{% trans %}Ask your question{% endtrans %}" class="submit" /> + {% endif %} + <div class="question-options"> + {% if settings.WIKI_ON %} + {{ macros.checkbox_in_div(form.wiki) }} + {% endif %} + {% if settings.ALLOW_ASK_ANONYMOUSLY %} + {{ macros.checkbox_in_div(form.ask_anonymously) }} + {% endif %} + </div> +</form> diff --git a/askbot/skins/old/templates/blocks/bottom_scripts.html b/askbot/skins/old/templates/blocks/bottom_scripts.html new file mode 100644 index 00000000..771c13a4 --- /dev/null +++ b/askbot/skins/old/templates/blocks/bottom_scripts.html @@ -0,0 +1,95 @@ +{# most, if not all javascripts should go here + this template is included at the very bottow of the + main template "base.html" +#} +<div id="no-javascript"> + <noscript class="noscript"> + {% trans app_name = settings.APP_SHORT_NAME %}Please note: {{app_name}} requires javascript to work properly, please enable javascript in your browser, <a href="{{noscript_url}}">here is how</a>{% endtrans %} + </noscript> +</div> +<script type="text/javascript"> + var i18nLang = '{{settings.LANGUAGE_CODE}}'; + var scriptUrl = '/{{settings.ASKBOT_URL}}' + var askbotSkin = '{{settings.ASKBOT_DEFAULT_SKIN}}'; + var enableMathJax = {% if settings.ENABLE_MATHJAX %}true{% else %}false{% endif %}; + {% if request.user.is_authenticated() %} + askbot['data']['userIsAuthenticated'] = true; + askbot['data']['userId'] = {{request.user.id}}; + askbot['data']['userIsAdminOrMod'] = {% if + request.user.is_administrator() + or request.user.is_moderator() + %}true{% else %}false{% endif %}; + {% else %} + askbot['data']['userIsAuthenticated'] = false; + {% endif %} + askbot['urls']['mark_read_message'] = '{% url "read_message" %}'; + askbot['urls']['get_tags_by_wildcard'] = '{% url "get_tags_by_wildcard" %}'; + askbot['urls']['get_tag_list'] = '{% url "get_tag_list" %}'; + askbot['urls']['follow_user'] = scriptUrl + 'followit/follow/user/{{'{{'}}userId{{'}}'}}/'; + askbot['urls']['unfollow_user'] = scriptUrl + 'followit/unfollow/user/{{'{{'}}userId{{'}}'}}/'; + askbot['urls']['user_signin'] = '{{ settings.LOGIN_URL }}'; +</script> +<script + type="text/javascript" + {% if settings.DEBUG %} + src="{{"/js/jquery-1.4.3.js"|media}}" + {% else %} + src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js" + {% endif %} +></script> +<script type='text/javascript' src="{{"/js/i18n.js"|media }}"></script> +<script type='text/javascript' src="{{"/js/jquery.i18n.js"|media }}"></script> +<script type='text/javascript' src="{% url "askbot_jsi18n" %}"></script> +<script type='text/javascript' src="{{"/js/utils.js"|media }}"></script> +{% if settings.ENABLE_MATHJAX %} + <script type='text/javascript' src="{{settings.MATHJAX_BASE_URL}}/MathJax.js"> + MathJax.Hub.Config({ + extensions: ["tex2jax.js"], + jax: ["input/TeX","output/HTML-CSS"], + tex2jax: {inlineMath: [["$","$"],["\\(","\\)"]]} + }); + </script> +{% endif %} +<script type="text/javascript"> +{% if active_tab != "tags" and active_tab != "users" %} +{# start asking question with title from search query #} + $(document).ready(function(){ + $('#nav_ask').click( + function(){ + var starting_title = $('#keywords').attr('value'); + var new_url = $(this).attr('href') + '?title=' + encodeURIComponent(starting_title); + window.location.href = new_url; + return false; + } + ); + //{# focus input on the search bar endcomment #} + {% if active_tab != "ask" %} + $('#keywords').focus(); + {% else %} + $('#id_title').focus(); + {% endif %} + }); +{% endif %} +{% if user_messages %} + $('#validate_email_alert').click(function(){notify.close(true)}) + notify.show(); +{% endif %} +</script> +{% if settings.USE_CUSTOM_JS %} +<script + src="{% url "custom_js"%}?{{ settings.MEDIA_RESOURCE_REVISION }}" + type="text/javascript" +></script> +{% endif %} +{% if settings.GOOGLE_ANALYTICS_KEY %} +<script type="text/javascript"> + var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); + document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); + </script> + <script type="text/javascript"> + try { + var pageTracker = _gat._getTracker('{{ settings.GOOGLE_ANALYTICS_KEY }}'); + pageTracker._trackPageview(); + } catch(err) {} +</script> +{% endif %} diff --git a/askbot/skins/old/templates/blocks/editor_data.html b/askbot/skins/old/templates/blocks/editor_data.html new file mode 100644 index 00000000..79ed96fb --- /dev/null +++ b/askbot/skins/old/templates/blocks/editor_data.html @@ -0,0 +1,10 @@ +<script type="text/javascript"> + {# data necessary for the post editor, goes into endjs block #} + askbot['settings']['maxTagLength'] = {{settings.MAX_TAG_LENGTH}}; + 'each tag must be shorter than %(max_chars)d characters', + askbot['messages']['maxTagLength'] = '{% trans max_chars = settings.MAX_TAG_LENGTH %}each tag must be shorter that {{max_chars}} character{% pluralize %}each tag must be shorter than {{max_chars}} characters{% endtrans %}'; + askbot['settings']['maxTagsPerPost'] = {{settings.MAX_TAGS_PER_POST}}; + askbot['messages']['maxTagsPerPost'] = '{% trans tag_count = settings.MAX_TAGS_PER_POST %}please use {{tag_count}} tag{% pluralize %}please use {{tag_count}} tags or less{% endtrans %}'; + askbot['messages']['tagLimits'] = '{% trans tag_count=settings.MAX_TAGS_PER_POST, max_chars=settings.MAX_TAG_LENGTH %}please use up to {{tag_count}} tags, less than {{max_chars}} characters each{% endtrans %}'; + askbot['urls']['upload'] = '{% url "upload" %}'; +</script> diff --git a/askbot/skins/old/templates/blocks/footer.html b/askbot/skins/old/templates/blocks/footer.html new file mode 100644 index 00000000..94c409ef --- /dev/null +++ b/askbot/skins/old/templates/blocks/footer.html @@ -0,0 +1,53 @@ +<!-- template footer.html --> +<div id="ground"> + <p class="footerLinks" > + <a href="{% url about %}">{% trans %}about{% endtrans %}</a><span class="link-separator"> |</span> + <a href="{% url faq %}">{% trans %}faq{% endtrans %}</a><span class="link-separator"> |</span> + <a href="{% url privacy %}">{% trans %}privacy policy{% endtrans %}</a><span class="link-separator"> |</span> + {% spaceless %} + <a href= + {% if settings.FEEDBACK_SITE_URL %} + "{{settings.FEEDBACK_SITE_URL}}" + target="_blank"> + {% else %} + "{% url feedback %}?next={{request.path}}"> + {% endif %} + {% trans %}give feedback{% endtrans %} + </a> + {% endspaceless %} + </p> + <p> + <a href="http://askbot.org" target="_blank"> + Powered by Askbot version {{settings.ASKBOT_VERSION}} + </a> + </p> + {% if settings.USE_LICENSE %}{# could be factored out into separate template #} + {% if settings.LICENSE_USE_URL %} + <p>{{settings.APP_COPYRIGHT}} {% trans + license_title=settings.LICENSE_TITLE, + license_url=settings.LICENSE_URL + %}Content on this site is licensed under a <a href="{{license_url}}">{{license_title}}</a> license.{% endtrans %}</p> + {% if settings.LICENSE_USE_LOGO %} + <a href="{{ settings.LICENSE_URL}}"> + <img + class="license-logo" + src="{{settings.LICENSE_LOGO_URL|media }}" + title="{{settings.LICENSE_ACRONYM}}" + alt="{{settings.LICENSE_ACRONYM}}" + /> + </a> + {% endif %} + {% else %} + <p>{{settings.APP_COPYRIGHT}} {% trans license=settings.LICENSE_TITLE %}Content on this site is licensed under a {{license}}{% endtrans %}</p> + {% if settings.LICENSE_USE_LOGO %} + <img + class="license-logo" + src="{{settings.LICENSE_LOGO_URL|media }}" + title="{{settings.LICENSE_ACRONYM}}" + alt="{{settings.LICENSE_ACRONYM}}" + /> + {% endif %} + {% endif %} + {% endif %} +</div> +<!-- end template footer.html --> diff --git a/askbot/skins/old/templates/blocks/forum_body.html b/askbot/skins/old/templates/blocks/forum_body.html new file mode 100644 index 00000000..c36b48cd --- /dev/null +++ b/askbot/skins/old/templates/blocks/forum_body.html @@ -0,0 +1,14 @@ +<div class="notify" style="display:none"> + {% if user_messages %} + {% for message in user_messages %} + <p class="darkred">{{ message }}</p> + {% endfor %} + {% endif %} + <a id="close-notify" onclick="notify.close(true)">×</a> +</div> +{% include "header.html" %} +{% block body %} +{% endblock %} +{% if settings.SHOW_FOOTER %} + {% include "footer.html" %} +{% endif %} diff --git a/askbot/skins/old/templates/blocks/header.html b/askbot/skins/old/templates/blocks/header.html new file mode 100644 index 00000000..d7359007 --- /dev/null +++ b/askbot/skins/old/templates/blocks/header.html @@ -0,0 +1,44 @@ +<!-- template header.html --> +{% import "macros.html" as macros %} +<div id="ab-header"> + <div class="content-wrapper"> + {% if settings.SHOW_LOGO %} + <a id="ab-logo" href="{% url questions %}?start_over=true"><img + src="{{ settings.SITE_LOGO_URL|media }}" + title="{% trans %}back to home page{% endtrans %}" + alt="{% trans site=settings.APP_SHORT_NAME %}{{site}} logo{% endtrans %}"/></a> + {% endif %} + <div id="ab-meta-nav"> + {% include "blocks/header_meta_links.html" %} + {{settings.CUSTOM_HEADER}} + </div> + <div id="ab-main-nav"> + <a + id="nav_questions" + href="{% url questions %}" + {% if active_tab == 'questions' %}class="on"{% endif %} + >{% trans %}questions{% endtrans %}</a> + <a + id="nav_tags" + href="{% url tags %}" + {% if active_tab == 'tags' %}class="on"{% endif %} + >{% trans %}tags{% endtrans %}</a> + <a + id="nav_users" + href="{% url users %}" + {% if active_tab == 'users' %}class="on"{% endif %} + >{% trans %}users{% endtrans %}</a> + <a + id="nav_badges" + href="{% url badges %}" + {% if active_tab == 'badges' %}class="on"{% endif %} + >{% trans %}badges{% endtrans %}</a> + <a + id="nav_ask" + href="{% url ask %}" + class="{% if active_tab == 'ask' %}on{% else %}special{% endif %}" + >{% trans %}ask a question{% endtrans %}</a> + </div> + </div> +</div> +<!-- end template header.html --> diff --git a/askbot/skins/default/templates/blocks/header_meta_links.html b/askbot/skins/old/templates/blocks/header_meta_links.html index 83a5ed55..83a5ed55 100644 --- a/askbot/skins/default/templates/blocks/header_meta_links.html +++ b/askbot/skins/old/templates/blocks/header_meta_links.html diff --git a/askbot/skins/old/templates/blocks/input_bar.html b/askbot/skins/old/templates/blocks/input_bar.html new file mode 100644 index 00000000..bed97eb4 --- /dev/null +++ b/askbot/skins/old/templates/blocks/input_bar.html @@ -0,0 +1,47 @@ +{% if active_tab != "ask" %} +{% spaceless %} +<div id="searchBar"> + {# url action depends on which tab is active #} + <form + {% if active_tab == "tags" %} + action="{% url tags %}" + {% elif active_tab == "users" %} + action="{% url users %}" + {% else %} + action="{% url questions %}" + {% endif %} + method="get"> + {# class was searchInput #} + <input + {% if query %} + class="searchInputCancelable" + {% else %} + class="searchInput" + {% endif %} + type="text" + autocomplete="off" + value="{{ query|default_if_none('') }}" + name="query" + id="keywords"/> + {% if query %}{# query is only defined by questions view #} + <input type="button" + value="x" + name="reset_query" + {# todo - make sure it works on Enter keypress #} + onclick="window.location.href='{% url questions %}?reset_query=true'" + class="cancelSearchBtn"/> + {% endif %} + <input type="submit" value="{% trans %}search{% endtrans %}" name="search" class="searchBtn" /> + {% if active_tab == "tags" %} + <input type="hidden" name="t" value="tag"/> + {% else %} + {% if active_tab == "users" %} + <input type="hidden" name="t" value="user"/> + {% endif %} + {% endif %} + </form> +</div> +{% endspaceless %} +{% else %} + {% include "blocks/ask_form.html" %} +{% endif %} diff --git a/askbot/skins/old/templates/blocks/mandatory_tags_js.html b/askbot/skins/old/templates/blocks/mandatory_tags_js.html new file mode 100644 index 00000000..f04a6345 --- /dev/null +++ b/askbot/skins/old/templates/blocks/mandatory_tags_js.html @@ -0,0 +1,25 @@ +<script type="text/javascript"> + $(document).ready(function(){ + var fake_tag = new Tag(); + $('ul.tags .tag').each(function(idx, elem){ + var tag_input = $('input#id_tags'); + var callback = function(){ + var new_tag = fake_tag.decodeTagName($(elem).html()); + if (/\*$/.test(new_tag)){//strip the asterisk + new_tag = new_tag.substring(0, new_tag.length - 1); + } + if ($.trim(tag_input.val()) !== ''){ + var entered_tags = tag_input.val().split(/\s+/); + } else { + var entered_tags = []; + } + if ($.inArray(new_tag, entered_tags) === -1){ + entered_tags.push(new_tag); + tag_input.val(entered_tags.join(' ')); + tag_input.focus(); + } + }; + setupButtonEventHandlers($(elem), callback); + }); + }); +</script> diff --git a/askbot/skins/old/templates/blocks/paginator.html b/askbot/skins/old/templates/blocks/paginator.html new file mode 100644 index 00000000..9782407f --- /dev/null +++ b/askbot/skins/old/templates/blocks/paginator.html @@ -0,0 +1,4 @@ +<!-- paginator.html --> +{% import "macros.html" as macros %} +{{ macros.paginator(paginator_context)}} +<!-- end paginator.html --> diff --git a/askbot/skins/old/templates/blocks/question_edit_tips.html b/askbot/skins/old/templates/blocks/question_edit_tips.html new file mode 100644 index 00000000..83c36840 --- /dev/null +++ b/askbot/skins/old/templates/blocks/question_edit_tips.html @@ -0,0 +1,59 @@ +<!-- question_edit_tips.html --> +<div class="boxC"> + <h2>{% trans %}question tips{% endtrans %}</h2> + <ul> + <li> <b>{% trans %}please ask a relevant question{% endtrans %}</b> + </li> + <li> + {% trans %}please try provide enough details{% endtrans %} + </li> + <li> + {% trans %}be clear and concise{% endtrans %} + </li> + </ul> + <p class='info-box-follow-up-links'> + <a href="{% url faq %}" target="_blank" title="{% trans %}see frequently asked questions{% endtrans %}">{% trans %}faq{% endtrans %} »</a> + </p> +</div> + +<div class="boxC"> + <h2>{% trans %}Markdown tips{% endtrans %}</h2> + <ul> + {% if settings.MARKDUP_CODE_FRIENDLY or settings.ENABLE_MATHJAX %} + <li> + {% trans %}*italic*{% endtrans %} + </li> + <li> + {% trans %}**bold**{% endtrans %} + </li> + {% else %} + <li> + {% trans %}*italic* or _italic_{% endtrans %} + </li> + <li> + {% trans %}**bold** or __bold__{% endtrans %} + </li> + {% endif %} + <li> + <b>{% trans %}link{% endtrans %}</b>:[{% trans %}text{% endtrans %}](http://url.com/ "{% trans %}title{% endtrans %}") + + </li> + + <li> + <b>{% trans %}image{% endtrans %}</b>:![alt {% trans %}text{% endtrans %}](/path/img.jpg "{% trans %}title{% endtrans %}") + + </li> + <li> + {% trans %}numbered list:{% endtrans %} + 1. Foo + 2. Bar + </li> + <li> + {% trans %}basic HTML tags are also supported{% endtrans %} + </li> + </ul> + <p class='info-box-follow-up-links'> + <a href="http://en.wikipedia.org/wiki/Markdown" target="_blank">{% trans %}learn more about Markdown{% endtrans %} »</a> + </p> +</div> +<!-- end question_edit_tips.html --> diff --git a/askbot/skins/old/templates/blocks/system_messages.html b/askbot/skins/old/templates/blocks/system_messages.html new file mode 100644 index 00000000..18ba03d7 --- /dev/null +++ b/askbot/skins/old/templates/blocks/system_messages.html @@ -0,0 +1,8 @@ +<div class="notify" style="display:none"> + {% if user_messages %} + {% for message in user_messages %} + <p class="darkred">{{ message }}</p> + {% endfor %} + {% endif %} + <a id="close-notify" onclick="notify.close(true)">×</a> +</div> diff --git a/askbot/skins/old/templates/blocks/tag_selector.html b/askbot/skins/old/templates/blocks/tag_selector.html new file mode 100644 index 00000000..c3626be9 --- /dev/null +++ b/askbot/skins/old/templates/blocks/tag_selector.html @@ -0,0 +1,46 @@ +{# todo - maybe disable navigation from ignored tags here when "hide" is on - with js? #} +{% import "macros.html" as macros %} +<div id="tagSelector" class="boxC"> + <h2>{% trans %}Interesting tags{% endtrans %}</h2> + {{ + macros.tag_list_widget( + interesting_tag_names, + deletable = True, + css_class = 'interesting marked-tags' + ) + }} + {# todo - add this via js + "remove '%(tag_name)s' from the list of interesting tags"| + format(tag_name = tag_name) + #} + <div class="inputs"> + <input id="interestingTagInput" autocomplete="off" type="text"/> + <input id="interestingTagAdd" type="submit" value="{% trans %}Add{% endtrans %}"/> + </div> + <h2>{% trans %}Ignored tags{% endtrans %}</h2> + {{ + macros.tag_list_widget( + ignored_tag_names, + deletable = True, + css_class = 'ignored marked-tags' + ) + }} + {# todo: add this via javascript + "remove '%(tag_name)s' from the list of ignored tags"| + format(tag_name = tag_name) + #} + <div class="inputs"> + <input id="ignoredTagInput" autocomplete="off" type="text"/> + <input id="ignoredTagAdd" type="submit" value="{% trans %}Add{% endtrans%}"/> + </div> + <h3>{% trans %}Display tag filter{% endtrans%}</h3> + <div id="displayTagFilterControl"> + {{ + macros.radio_select( + name = "display_tag_filter_strategy", + value = request.user.display_tag_filter_strategy, + choices = tag_filter_strategy_choices + ) + }} + </div> +</div> diff --git a/askbot/skins/old/templates/close.html b/askbot/skins/old/templates/close.html new file mode 100644 index 00000000..d8160865 --- /dev/null +++ b/askbot/skins/old/templates/close.html @@ -0,0 +1,27 @@ +{% extends "one_column_body.html" %} +<!-- template close.html --> +{% block title %}{% spaceless %}{% trans %}Close question{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans %}Close question{% endtrans %}</h1> + <p>{% trans %}Close the question{% endtrans %}: <a href="{{ question.get_absolute_url() }}"> + <strong>{{ question.get_question_title() }}</strong></a> + </p> + <form id="fmclose" action="{% url close question.id %}" method="post" >{% csrf_token %} + <p> + <strong>{% trans %}Reasons{% endtrans %}:</strong> + {{ form.reason }} + </p> + <p> + <input type="submit" value="{% trans %}OK to close{% endtrans %}" class="submit" /> + <input id="btBack" type="button" class="submit" value="{% trans %}Cancel{% endtrans %}" /> + </p> + </form> +{% endblock %} +{% block endjs %} + <script type="text/javascript"> + $().ready(function(){ + $('#btBack').bind('click', function(){ history.back(); }); + }); + </script> +{% endblock %} +<!-- end template close.html --> diff --git a/askbot/skins/old/templates/faq.html b/askbot/skins/old/templates/faq.html new file mode 100644 index 00000000..be25d2ee --- /dev/null +++ b/askbot/skins/old/templates/faq.html @@ -0,0 +1,9 @@ +{% extends "two_column_body.html" %} +<!-- template faq.html --> +{% block title %}{% spaceless %}{% trans %}FAQ{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<div class="content"> + {{forum_faq}} +</div> +{% endblock %} +<!-- end template faq.html --> diff --git a/askbot/skins/old/templates/faq_static.html b/askbot/skins/old/templates/faq_static.html new file mode 100644 index 00000000..f1d34141 --- /dev/null +++ b/askbot/skins/old/templates/faq_static.html @@ -0,0 +1,99 @@ +{% extends "two_column_body.html" %} +<!-- template faq.html --> +{% block title %}{% spaceless %}{% trans %}FAQ{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans %}Frequently Asked Questions {% endtrans %}({% trans %}FAQ{% endtrans %})</h1> +<h2 class="first">{% trans %}What kinds of questions can I ask here?{% endtrans %}</h2> +<p>{% trans %}Most importanly - questions should be <strong>relevant</strong> to this community.{% endtrans %} +{% trans %}Before asking the question - please make sure to use search to see whether your question has alredy been answered.{% endtrans %} +</p> +<h2>{% trans %}What questions should I avoid asking?{% endtrans %}</h2> +<p>{% trans %}Please avoid asking questions that are not relevant to this community, too subjective and argumentative.{% endtrans %} +</p> +<h2>{% trans %}What should I avoid in my answers?{% endtrans %}</h2> +<p>{{ settings.APP_TITLE }} {% trans %}is a Q&A site, not a discussion group. Therefore - please avoid having discussions in your answers, comment facility allows some space for brief discussions.{% endtrans %}</p> +<h2>{% trans %}Who moderates this community?{% endtrans %}</h2> +<p>{% trans %}The short answer is: <strong>you</strong>.{% endtrans %} +{% trans %}This website is moderated by the users.{% endtrans %} +{% trans %}The reputation system allows users earn the authorization to perform a variety of moderation tasks.{% endtrans %} +</p> +<h2>{% trans %}How does reputation system work?{% endtrans %}</h2> +<p>{% trans %}Rep system summary{% endtrans %}</p> +<p>{% trans MAX_REP_GAIN_PER_USER_PER_DAY=settings.MAX_REP_GAIN_PER_USER_PER_DAY, REP_GAIN_FOR_RECEIVING_UPVOTE=settings.REP_GAIN_FOR_RECEIVING_UPVOTE, REP_LOSS_FOR_RECEIVING_DOWNVOTE=settings.REP_LOSS_FOR_RECEIVING_DOWNVOTE|absolute_value %}For example, if you ask an interesting question or give a helpful answer, your input will be upvoted. On the other hand if the answer is misleading - it will be downvoted. Each vote in favor will generate <strong>{{REP_GAIN_FOR_RECEIVING_UPVOTE}}</strong> points, each vote against will subtract <strong>{{REP_LOSS_FOR_RECEIVING_DOWNVOTE}}</strong> points. There is a limit of <strong>{{MAX_REP_GAIN_PER_USER_PER_DAY}}</strong> points that can be accumulated for a question or answer per day. The table below explains reputation point requirements for each type of moderation task.{% endtrans %} +</p> + +<table cellspacing="3" cellpadding="3"> + <tr> + <th width="40px" style="text-align:right"></th> + <th width="300px"></th> + </tr> + <tr> + <td class="faq-rep-item"><strong>{{settings.MIN_REP_TO_VOTE_UP}}</strong></td> + <td>{% trans %}upvote{% endtrans %}</td> + </tr> + <!-- + <tr> + <td class="faq-rep-item"><strong>15</strong></td> + <td>{% trans %}use tags{% endtrans %}</td> + </tr> + --> + <tr> + <td class="faq-rep-item"><strong>{{settings.MIN_REP_TO_LEAVE_COMMENTS}}</strong></td> + <td>{% trans %}add comments{% endtrans %}</td> + </tr> + <tr> + <td class="faq-rep-item"><strong>{{settings.MIN_REP_TO_VOTE_DOWN}}</strong></td> + <td>{% trans %}downvote{% endtrans %}</td> + </tr><tr> + <td class="faq-rep-item"><strong>{{settings.MIN_REP_TO_ACCEPT_OWN_ANSWER}}</strong></td> + <td>{% trans %} accept own answer to own questions{% endtrans %}</td> + </tr> + </tr><tr> + <td class="faq-rep-item"><strong>{{settings.MIN_REP_TO_CLOSE_OWN_QUESTIONS}}</strong></td> + <td>{% trans %}open and close own questions{% endtrans %}</td> + </tr> + <tr> + <td class="faq-rep-item"><strong>{{settings.MIN_REP_TO_RETAG_OTHERS_QUESTIONS}}</strong></td> + <td>{% trans %}retag other's questions{% endtrans %}</td> + </tr> + {% if settings.WIKI_ON %} + <tr> + <td class="faq-rep-item"><strong>{{settings.MIN_REP_TO_EDIT_WIKI}}</strong></td> + <td>{% trans %}edit community wiki questions{% endtrans %}</td> + </tr> + {% endif %} + <tr> + <td class="faq-rep-item"><strong>{{settings.MIN_REP_TO_EDIT_OTHERS_POSTS}}</strong></td> + <td>{% trans %}"edit any answer{% endtrans %}</td> + </tr> + <tr> + <td class="faq-rep-item"><strong>{{settings.MIN_REP_TO_DELETE_OTHERS_COMMENTS}}</strong></td> + <td>{% trans %}"delete any comment{% endtrans %}</td> + </tr> +</table> +<a id='gravatar'></a><h2>{% trans %}what is gravatar{% endtrans %}</h2> +{% trans %}gravatar faq info{% endtrans %} +<h2>{% trans %}To register, do I need to create new password?{% endtrans %}</h2> +<p>{% trans %}No, you don't have to. You can login through any service that supports OpenID, e.g. Google, Yahoo, AOL, etc."{% endtrans %} +<strong><a href="{{ settings.LOGIN_URL }}">{% trans %}"Login now!"{% endtrans %}</a> »</strong> +</p> +<h2>{% trans %}Why other people can edit my questions/answers?{% endtrans %}</h2> +<p> {% trans %}Goal of this site is...{% endtrans %} {% trans %}So questions and answers can be edited like wiki pages by experienced users of this site and this improves the overall quality of the knowledge base content.{% endtrans %} +{% trans %}If this approach is not for you, we respect your choice.{% endtrans %} +</p> +<h2>{% trans %}Still have questions?{% endtrans %}</h2> +<p>{% trans %}Please ask your question at {{ask_question_url}}, help make our community better!{% endtrans %} +</p> +</div> +<script type="text/javascript"> + //highlihts section if url has matching #anchor_name + $(document).ready(function (){ + var hash = window.location.hash; + if (hash.length > 1){ + $(hash).parent().addClass('highlight'); + window.location.hash = hash; + } + }) +</script> +{% endblock %} +<!-- end template faq.html --> diff --git a/askbot/skins/old/templates/feedback.html b/askbot/skins/old/templates/feedback.html new file mode 100644 index 00000000..d5e8b3a7 --- /dev/null +++ b/askbot/skins/old/templates/feedback.html @@ -0,0 +1,46 @@ +{% extends "two_column_body.html" %} +<!-- template feedback.html --> +{% block title %}{% spaceless %}{% trans %}Feedback{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans %}Give us your feedback!{% endtrans %}</h1> +<form method="post" action="{% url feedback %}" accept-charset="utf-8">{% csrf_token %} + {% if user.is_authenticated() %} + <p class="message"> + {% trans user_name=user.username %} + <span class='big strong'>Dear {{user_name}}</span>, we look forward to hearing your feedback. + Please type and send us your message below. + {% endtrans %} + <p> + {% else %} + <p class="message"> + {% trans %} + <span class='big strong'>Dear visitor</span>, we look forward to hearing your feedback. + Please type and send us your message below. + {% endtrans %} + </p> + <div class="form-row"><label>{{form.name.label}}</label><br/>{{form.name}}</div> + <div class="form-row"> + <label>{{form.email.label}} + {% if form.errors.email %} + <span class='error'>{% trans %}(please enter a valid email){% endtrans %}</span> + {% endif %} + </label><br/>{{form.email}} + </div> + {% endif %} + <div class="form-row"> + <label>{{form.message.label}} + {% if form.errors.message %} + <span class="error">{% trans %}(this field is required){% endtrans %}</span> + </label> + {% endif %} + <br/> + {{form.message}} + </div> + {{form.next}} + <div class="submit-row"> + <input type="submit" class="submit" value="{% trans %}Send Feedback{% endtrans %}"/> + <input type="submit" class="submit" name="cancel" value="{% trans %}Cancel{% endtrans %}"/> + </div> +</form> +{% endblock %} +<!-- end template feedback.html --> diff --git a/askbot/skins/old/templates/feedback_email.txt b/askbot/skins/old/templates/feedback_email.txt new file mode 100644 index 00000000..a729066a --- /dev/null +++ b/askbot/skins/old/templates/feedback_email.txt @@ -0,0 +1,13 @@ +{% spaceless %} +{% trans site_title = settings.APP_SHORT_NAME|safe %} +Hello, this is a {{site_title}} forum feedback message. +{% endtrans %} +{% endspaceless %} +{% if user.is_authenticated() -%} + {{user.username|safe}} ({{user.email|safe}}, ip:{{request.META.REMOTE_ADDR}}) +{%- else %} + {%- if name %}{{name|safe}} {% else %}{% trans %}Anonymous{% endtrans %} {% endif -%} + ({%- if email %}, {% endif -%}ip:{{request.META.REMOTE_ADDR}}) +{%- endif %} wrote: + +{{message|safe}} diff --git a/askbot/skins/old/templates/import_data.html b/askbot/skins/old/templates/import_data.html new file mode 100644 index 00000000..affeaa73 --- /dev/null +++ b/askbot/skins/old/templates/import_data.html @@ -0,0 +1,31 @@ +{% extends "two_column_body.html" %} +{% block title %}{% trans %}Import StackExchange data{% endtrans %}{% endblock %} +{% block content %} + <h1>{% trans %}Import StackExchange data{% endtrans %}</h1> + {% if need_configuration %} + <p><em>Note:</em> to import stackexchange data, first add + <code>'askbot.importers.stackexchange',</code> + to the <code>INSTALLED_APPS</code> setting in your <code>settings.py</code> + file, then run <code>python manage.py syncdb</code>, and restart the application. + After that, pleale return to here and try again. + </p> + {% else %} + <p class="message">{% trans %}<em>Warning:</em> if your database is not empty, please back it up + before attempting this operation.{% endtrans %} + </p> + <p>{% trans %}Upload your stackexchange dump .zip file, then wait until + the data import completes. This process may take several minutes. + Please note that feedback will be printed in plain text. + {% endtrans %} + </p> + <form id="load-dump-form" method="post" enctype="multipart/form-data">{% csrf_token %} + <table> + {{dump_upload_form.as_table()}} + </table> + <input type="submit" value="{% trans %}Import data{% endtrans %}" /> + </form> + <p>{% trans %}In the case you experience any difficulties in using this import tool, + please try importing your data via command line: <code>python manage.py load_stackexchange path/to/your-data.zip</code>{% endtrans %} + </p> + {% endif %} +{% endblock %} diff --git a/askbot/skins/old/templates/instant_notification.html b/askbot/skins/old/templates/instant_notification.html new file mode 100644 index 00000000..92799a96 --- /dev/null +++ b/askbot/skins/old/templates/instant_notification.html @@ -0,0 +1,42 @@ +{% trans %}<p>Dear {{receiving_user_name}},</p>{% endtrans %} + {% if update_type == 'question_comment' %} +{% trans %} +<p>{{update_author_name}} left a <a href="{{post_url}}">new comment</a>:</p> +{% endtrans %} + {% endif %} + {% if update_type == 'answer_comment' %} +{% trans %} +<p>{{update_author_name}} left a <a href="{{post_url}}">new comment</a></p> +{% endtrans %} + {% endif %} + {% if update_type == 'new_answer' %} +{% trans %} +<p>{{update_author_name}} answered a question +<a href="{{post_url}}">{{origin_post_title}}</a></p> +{% endtrans %} + {% endif %} + {% if update_type == 'new_question' %} +{% trans %} +<p>{{update_author_name}} posted a new question +<a href="{{post_url}}">{{origin_post_title}}</a></p> +{% endtrans %} + {% endif %} + {%if update_type == 'answer_update' %} +{% trans %} +<p>{{update_author_name}} updated an answer to the question +<a href="{{post_url}}">{{origin_post_title}}</a></p> +{% endtrans %} + {% endif %} + {% if update_type == 'question_update' %} +{% trans %} +<p>{{update_author_name}} updated a question +<a href="{{post_url}}">{{origin_post_title}}</a></p> +{% endtrans %} + {% endif %} +<p></p> +{% trans %} +<div>{{content_preview}}</div> +<p>Please note - you can easily <a href="{{user_subscriptions_url}}">change</a> +how often you receive these notifications or unsubscribe. Thank you for your interest in our forum!</p> +{% endtrans %} +{% trans %}<p>Sincerely,<br/>Forum Administrator</p>{% endtrans %} diff --git a/askbot/skins/old/templates/macros.html b/askbot/skins/old/templates/macros.html new file mode 100644 index 00000000..afa7b264 --- /dev/null +++ b/askbot/skins/old/templates/macros.html @@ -0,0 +1,757 @@ +{%- macro user_score_and_badge_summary(user) -%} + <span class="reputation-score" + title="{{user.get_karma_summary}}" + >{{user.reputation}}</span> + {% if user.gold or user.silver or user.bronze %} + <span title="{{user.get_badge_summary}}"> + {% if user.gold %} + <span class='badge1'>●</span> + <span class="badgecount">{{user.gold}}</span> + {% endif %} + {% if user.silver %} + <span class='badge2'>●</span> + <span class="badgecount">{{user.silver}}</span> + {% endif %} + {% if user.bronze %} + <span class='badge3'>●</span> + <span class="badgecount">{{user.bronze}}</span> + {% endif %} + </span> + {% endif %} +{%- endmacro -%} + +{%- macro share(site = None, site_label = None, icon = False) -%} + <a class="{{ site }}-share{% if icon == True %} icon{% endif %}" + title="{% trans %}Share this question on {{site}}{% endtrans %}" + >{% if icon == False %}{% if site_label %}{{ site_label }}{% else %}{{ site }}{% endif %}{% endif %}</a> +{%- endmacro -%} + +{%- macro follow_toggle(follow, name, alias, id) -%} + {# follow - boolean; name - object type name; alias - e.g. users name; id - object id #} + <div + class="follow-toggle" + id="follow-{{ name }}-{{ id }}" + > + {% if follow %} + <div class="follow">{% trans %}follow {{alias}}{% endtrans %}</div> + {% else %} + <div class="unfollow"> + <div class="unfollow-red">{% trans %}unfollow {{alias}}{% endtrans %}</div> + <div class="unfollow-green">{% trans %}following {{alias}}{% endtrans %}</div> + </div> + {% endif %} + </div> +{%- endmacro -%} + +{%- macro follow_user_toggle(visitor = None, subject = None) -%} + {% if visitor.is_anonymous() %} + {{ follow_toggle(True, 'user', subject.username, subject.id) }} + {% else %} + {% if visitor != subject %} + {% if visitor.is_following(subject) %} + {{ follow_toggle(False, 'user', subject.username, subject.id) }} + {% else %} + {{ follow_toggle(True, 'user', subject.username, subject.id) }} + {% endif %} + {% endif %} + {% endif %} +{%- endmacro -%} + +{%- macro user_long_score_and_badge_summary(user) -%} + <a class="user-micro-info" + href="{{user.get_absolute_url()}}?sort=reputation" + >{% trans %}karma:{% endtrans %} {{user.reputation}}</a> + {%- if user.gold or user.silver or user.bronze %} + <a class="user-micro-info" + href="{{user.get_absolute_url()}}#badges" + ><span title="{{user.get_badge_summary}}">{% trans %}badges:{% endtrans %} + {% if user.gold %} + <span class='badge1'>●</span> + <span class="badgecount">{{user.gold}}</span> + {% endif %} + {% if user.silver %} + <span class='badge2'>●</span> + <span class="badgecount">{{user.silver}}</span> + {% endif %} + {% if user.bronze %} + <span class='badge3'>●</span> + <span class="badgecount">{{user.bronze}}</span> + {%- endif -%} + </span></a> + {%- endif -%} +{%- endmacro -%} + +{%- macro user_country_flag(user) -%} + {% if user.country and user.show_country %} + <img class="flag" + src="{{ ('/images/flags/' ~ user.country.code|lower ~ '.gif')|media }}" + alt="{% trans + country=user.country.name + %}flag of {{country}}{% + endtrans %}" + title="{% trans + country=user.country.name, + person=user.username %}{{person}} is from {{country}}{% + endtrans %}" + /> + {% endif %} +{%- endmacro -%} + +{%- macro user_country_name_and_flag(user) -%} + {% if user.country and user.show_country %} + {{ user.country.name }} + {{ user_country_flag(user) }} + {% endif %} +{%- endmacro -%} + +{%- macro user_full_location(user) -%} + {% if user.location %} + {{ user.location }}, + {% endif %} + {{ user_country_name_and_flag(user) }} +{%- endmacro -%} + +{%- macro user_list(users, profile_section = None) -%} +<div class="userList"> + <table class="list-table"> + <tr> + <td class="list-td"> + {% for user in users %} + <div class="user"> + <ul> + <li class="thumb">{{ gravatar(user, 32) }}</li> + <li><a href="{% url user_profile user.id, user.username|slugify %}{% if profile_section %}?sort={{profile_section}}{% endif %}">{{user.username}}</a>{{ user_country_flag(user) }}</li> + <li>{{ user_score_and_badge_summary(user) }}</li> + </ul> + </div> + {% if loop.index is divisibleby 7 %} + </td> + <td> + {% endif %} + {% endfor %} + </td> + </tr> + </table> +</div> +{%- endmacro -%} + +{%- macro paginator(p, position='left') -%}{# p is paginator context dictionary #} +{% spaceless %} + {% if p.is_paginated %} + <div class="paginator" style="float:{{position}}"> + {% if p.has_previous %} + <span class="prev"><a href="{{p.base_url}}page={{ p.previous }}{{ p.extend_url }}" title="{% trans %}previous{% endtrans %}"> + « {% trans %}previous{% endtrans %}</a></span> + {% endif %} + {% if not p.in_leading_range %} + {% for num in p.pages_outside_trailing_range %} + <span class="page"><a href="{{p.base_url}}page={{ num }}{{ p.extend_url }}" >{{ num }}</a></span> + {% endfor %} + ... + {% endif %} + + {% for num in p.page_numbers %} + {% if num == p.page and p.pages != 1%} + <span class="curr" title="{% trans %}current page{% endtrans %}">{{ num }}</span> + {% else %} + <span class="page"><a href="{{p.base_url}}page={{ num }}{{ p.extend_url }}" title="{% trans %}page number {{num}}{% endtrans %}">{{ num }}</a></span> + {% endif %} + {% endfor %} + + {% if not p.in_trailing_range %} + ... + {% for num in p.pages_outside_leading_range|reverse %} + <span class="page"><a href="{{p.base_url}}page={{ num }}{{ p.extend_url }}" title="{% trans %}page number {{ num }}{% endtrans %}">{{ num }}</a></span> + {% endfor %} + {% endif %} + {% if p.has_next %} + <span class="next"><a href="{{p.base_url}}page={{ p.next }}{{ p.extend_url }}" title="{% trans %}next page{% endtrans %}">{% trans %}next page{% endtrans %} »</a></span> + {% endif %} + </div> + {% endif %} +{% endspaceless %} +{%- endmacro -%} + +{%- macro pagesize_switch(p, position='left') -%}{# p is paginator context #} +{% spaceless %} +{% if p.is_paginated %} + <div class="paginator" style="float:{{position}}"> + <span class="text">{% trans %}posts per page{% endtrans %}</span> + {% if p.page_size == 10 %} + <span class="curr">10</span> + {% else %} + <span class="page"><a href="{{p.base_url}}page_size=10">10</a></span> + {% endif %} + + {% if p.page_size == 30 %} + <span class="curr">30</span> + {% else %} + <span class="page"><a href="{{p.base_url}}page_size=30">30</a></span> + {% endif %} + + {% if p.page_size == 50 %} + <span class="curr">50</span> + {% else %} + <span class="page"><a href="{{p.base_url}}page_size=50">50</a></span> + {% endif %} + </div> +{% endif %} +{% endspaceless %} +{%- endmacro -%} + +{#todo: rename this to avatar #} +{%- macro gravatar(user, size) -%} +{% spaceless %} +<a style="text-decoration:none" + href="{{ user.get_absolute_url() }}" +><img class="gravatar" + width="{{size}}" height="{{size}}" + src="{{ user.get_avatar_url(size) }}" + title="{{user.username}}" + alt="{% trans username=user.username %}{{username}} gravatar image{% endtrans %}" +/></a> +{% endspaceless %} +{%- endmacro -%} + +{%- macro user_website_link(user, max_display_length=25) -%} + {% if user.website %} + <a + href="{{user.website}}" + title="{% trans username=user.username|escape, url=user.website %}{{username}}'s website is {{url}}{% endtrans %}" + {% if user.can_have_strong_url() == False %} + rel="nofollow" + {% endif %} + > + {{user.website|truncate(length=max_display_length, killwords=True, end='...')}} + </a> + {% endif %} +{%- endmacro -%} + +{%- macro post_contributor_avatar_and_credentials(post, user) -%} + {% if post.is_anonymous %} + <img alt="{% trans %}anonymous user{% endtrans %}" src="{{ '/images/anon.png'|media }} " class="gravatar" width="32" height="32" /> + <p>{{ user.get_anonymous_name() }}</p> + {% else %} + {{ gravatar(user, 32) }} + {{ user.get_profile_link()}}{{ user_country_flag(user) }}<br/> + {{ user_score_and_badge_summary(user) }}<br/> + {{ user_website_link(user) }} + {% endif %} +{%- endmacro -%} + +{%- macro post_contributor_info(post, contributor_type, is_wiki, wiki_min_rep) -%} +{# there is a whole bunch of trickery here, probably indicative of +poor design of the data or methods on data objects #} +{% if contributor_type=="original_author" %} + <div class='post-update-info'> + {% if is_wiki %} + <p> + {%- if post.post_type == 'question' -%} + {%- trans %}asked{% endtrans %} + {% elif post.post_type == 'answer' %} + {%- trans %}answered{% endtrans %} + {% else %} + {%- trans %}posted{% endtrans %} + {% endif %} + <strong>{{post.added_at|diff_date}}</strong> + </p> + <img + src="{{'/images/wiki.png'|media}}" + alt="{% trans %}this post is marked as community wiki{% endtrans %}" + style="float:left" + /> + <p class="tip">{% trans %}This post is a wiki. + Anyone with karma >{{wiki_min_rep}} is welcome to improve it.{% endtrans %}</p> + {% else %} + <p style="line-height:12px;"> + {# todo: access to class names needs to be removed here #} + {% if post.post_type == 'question' %} + {% trans %}asked{% endtrans %} + {% elif post.post_type == 'answer' %} + {% trans %}answered{% endtrans %} + {% else %} + {% trans %}posted{% endtrans %} + {% endif %} + {% if post.__class__.__name__ in ('QuestionRevision', 'AnswerRevision') %} + <strong>{{post.revised_at|diff_date}}</strong> + {% else %} + <strong>{{post.added_at|diff_date}}</strong> + {% endif %} + </p> + {{ post_contributor_avatar_and_credentials(post, post.author) }} + {% endif %} + </div> +{% elif contributor_type=="last_updater" %} + {% if post.post_type in ('Question', 'Answer') %} + {% set last_edited_at = post.last_edited_at %} + {% set original_author = post.author %} + {% set update_author = post.last_edited_by %} + {% elif post.post_type in ('QuestionRevision', 'AnswerRevision') %} + {% set last_edited_at = post.revised_at %} + {% set original_author = None %}{# fake value to force display widget in the revision views #} + {% set update_author = post.author %} + {% endif %} + {% if last_edited_at %} + <div class='post-update-info'> + <p style="line-height:12px;"> + <a + {% if post.post_type == 'Question' %} + href="{% url question_revisions post.id %}" + {% else %} + href="{% url answer_revisions post.id %}" + {% endif %} + >{% trans %}updated{% endtrans %} <strong>{{ last_edited_at|diff_date }}</strong></a> + </p> + {% if original_author != update_author or is_wiki %} + {{ post_contributor_avatar_and_credentials(post, update_author) }} + {% endif %} + </div> + {% endif %} +{% endif %} +{%- endmacro -%} + +{%- macro if_else(condition, if_true, if_false) -%} + {%- if condition == True -%} + {{if_true}} + {%- else -%} + {{if_false}} + {%- endif -%} +{%- endmacro -%} + +{%- macro tag_cloud(tags = None, font_sizes = None) -%} + {% for tag in tags %} + <span class="tag-size-{{ font_sizes[tag.name] }}"> + <a class="link-typeA" title="Number of entries: {{ tag.used_count }}" href="{% url questions %}?tags={{ tag.name }}">{{ tag.name }}</a> + </span> + {% endfor %} +{%- endmacro -%} + +{%- macro tag_list_widget( + tags, + id = None, + deletable = False, + make_links = True, + url_params = None, + css_class = None + ) +-%} +<ul {% if id %}id="{{ id }}"{% endif %} + class="tags{% if css_class %} {{css_class}}{% endif %}" +> + {% if tags %} + {% for tag in tags %} + {{ tag_widget( + tag, + deletable = deletable, + is_link = make_links, + url_params = url_params, + html_tag = 'li' + )}} + {% endfor %} + {% endif %} +</ul> +{%- endmacro -%} + +{# todo: remove the extra content argument to make its usage more explicit #} +{%- macro tag_widget( + tag, + deletable = False, + is_link = True, + delete_link_title = None, + css_class = None, + url_params = None, + html_tag = 'div', + extra_content = '' + ) +-%} + {% spaceless %} + <{{ html_tag }} class="tag-left{% if deletable %} deletable-tag{% endif %}"> + <{% if not is_link or tag[-1] == '*' %}span{% else %}a{% endif %} + class="tag tag-right{% if css_class %} {{ css_class }}{% endif %}" + {% if is_link %} + href="{% url questions %}?tags={{tag|urlencode}}{{ + if_else( + url_params != None, + '&' ~ url_params, + '' + )|escape + }}" + title="{% trans %}see questions tagged '{{ tag }}'{% endtrans %}" + {% endif %} + rel="tag" + >{{ tag|replace('*', '✽') }}</{% if not is_link or tag[-1] == '*' %}span{% else %}a{% endif %}> + {% if deletable %} + <span class="delete-icon" + {% if delete_link_title %} + title="{{ delete_link_title }}" + {% endif %} + ></span> + {% endif %} + </{{ html_tag }}> + {{ extra_content }} + {% endspaceless %} +{%- endmacro -%} + +{%- macro radio_select(name = None, value = None, choices = None) -%} + {% for choice in choices %} + <p class="choice"> + {% set id = "id_" ~ name ~ "_" ~ choice[0] %} + <input + id="{{ id }}" + name="{{ name }}" + value="{{ choice[0] }}" + type="radio" + {% if value == choice[0] %} + checked="checked" + {% endif %} + /> + <label for="{{ id }}">{{ choice[1] }}</label> + </p> + {% endfor %} +{%- endmacro -%} + +{%- macro question_summary(question, extra_class=None) -%} + <div class="short-summary{% if extra_class %} {{extra_class}}{% endif %}"> + <div class="counts"> + <div class="views + {% if question.view_count == 0 -%} + no-views + {% else -%} + some-views + {%- endif -%}"> + <span class="item-count">{{question.view_count|humanize_counter}}</span> + <div> + {% trans cnt=question.view_count %}view{% pluralize %}views{% endtrans %} + </div> + </div> + <div class="answers + {% if question.answer_count == 0 -%} + no-answers + {% else -%} + {%- if question.answer_accepted -%} + accepted + {%- else -%} + some-answers + {%- endif -%} + {%- endif -%}"> + <span + class="item-count" + >{{question.answer_count|humanize_counter}}{% if question.answer_accepted%}✓{% endif %}</span> + <div> + {% trans cnt=question.answer_count %}answer{% pluralize %}answers{% endtrans %} + </div> + </div> + <div class="votes + {% if question.score == 0 -%} + no-votes + {% else -%} + some-votes + {%- endif -%}"> + <span class="item-count">{{question.score|humanize_counter}}</span> + <div> + {% trans cnt=question.score %}vote{% pluralize %}votes{% endtrans %} + </div> + </div> + + <div style="clear:both"></div> + <div class="userinfo"> + <span class="relativetime" title="{{question.last_activity_at}}">{{ question.last_activity_at|diff_date }}</span> + {% if question.is_anonymous %} + <span class="anonymous">{{ question.last_activity_by.get_anonymous_name() }}</span> + {% else %} + <a href="{% url user_profile question.last_activity_by.id, question.last_activity_by.username|slugify %}">{{question.last_activity_by.username}}</a>{{ user_country_flag(question.last_activity_by) }} + {#{user_score_and_badge_summary(question.last_activity_by)}#} + {% endif %} + </div> + </div> + <h2><a title="{{question.summary|escape}}" href="{{ question.get_absolute_url() }}">{{question.get_question_title()|escape}}</a></h2> + {{ tag_list_widget(question.get_tag_names()) }} + </div> +{%- endmacro -%} + +{%- macro comment_votes(comment = None) -%} + <div class="comment-votes"> + {% if comment.score > 0 %} + <div class="upvote{% if comment.upvoted_by_user %} upvoted{% endif %}">{{comment.score}}</div> + {% else %} + <div class="upvote"></div> + {% endif %} + </div> +{%- endmacro -%} + +{# Warning! Any changes to the comment markup here must be duplicated in post.js +for the purposes of the AJAX comment editor #} + +{%- macro comment_list(comments = None, user = None) -%} + {% for comment in comments %} + <div class="comment" id="comment-{{comment.id}}"> + {{ comment_votes(comment = comment) }} + <div class="comment-delete"> + {% if user|can_delete_comment(comment) %} + <span class="delete-icon" title="{% trans %}delete this comment{% endtrans %}"></span> + {% endif %} + </div> + <div class="comment-body"> + {{comment.html}} + <a + class="author" + href="{{comment.user.get_profile_url()}}" + >{{comment.user.username}}</a> + <span class="age"> ({{comment.added_at|diff_date}})</span> + {% if user|can_edit_comment(comment) %} + <a class="edit">{% trans %}edit{% endtrans %}</a> + {% endif %} + </div> + </div> + {% endfor %} +{%- endmacro -%} + +{%- macro add_or_show_comments_button(post = None, can_post = None, max_comments = None, widget_id = None) -%} + <script type="text/javascript"> + askbot['data']['{{widget_id}}'] = { + can_post: {% if can_post %}true{% else %}false{% endif %}, + truncated: {% if post.comment_count > max_comments %}true{% else %}false{% endif %} + }; + </script> + {% if post.comment_count > max_comments %} + {% set remaining_comments = post.comment_count - max_comments %} + <a class="button"> + {% if can_post %} + {% trans %}add comment{% endtrans %} / + {% trans counter=remaining_comments %}see <strong>{{counter}}</strong> more{% pluralize %}see <strong>{{counter}}</strong> more{% endtrans %} + {% else %} + {% trans counter=remaining_comments %}see <strong>{{counter}}</strong> more comment{% pluralize %}see <strong>{{counter}}</strong> more comments + {% endtrans %} + {% endif %} + </a> + {% elif can_post %} + <a class="button">{% trans %}add comment{% endtrans %}</a> + {% endif %} +{%- endmacro -%} + +{%- macro post_comments_widget(post=None, show_post = None, show_comment = None, comment_order_number = None, user=None, max_comments=None) -%} + {% spaceless %} + {% set widget_id = 'comments-for-' + post.post_type + '-' + post.id|string %} + <div class="comments" id="{{widget_id}}"> + <div class="content"> + {% if show_post == post and show_comment %} + {% if comment_order_number > max_comments %} + {% set comments = post.get_comments(visitor = user)[:comment_order_number] %} + {{ comment_list(comments = comments, user = user) }} + {% else %} + {% set comments = post.get_comments(visitor = user)[:max_comments] %} + {{ comment_list(comments = comments, user = user) }} + {% endif %} + {% else %} + {% set comments = post.get_comments(visitor = user)[:max_comments] %} + {{ comment_list(comments = comments, user = user) }} + {% endif %} + </div> + <div class="controls"> + {% set can_post = user|can_post_comment(post) %} + {% if show_post == post and show_comment %} + {% if comment_order_number > max_comments %} + {{ + add_or_show_comments_button( + post = post, + can_post = can_post, + max_comments = comment_order_number, + widget_id = widget_id + ) + }} + {% else %} + {{ + add_or_show_comments_button( + post = post, + can_post = can_post, + max_comments = max_comments, + widget_id = widget_id + ) + }} + {% endif %} + {% else %} + {{ + add_or_show_comments_button( + post = post, + can_post = can_post, + max_comments = max_comments, + widget_id = widget_id + ) + }} + {% endif %} + </div> + </div> + {% endspaceless %} +{%- endmacro -%} + +{%- macro reversible_sort_button(button_sort_criterium=None, asc_tooltip=None, + desc_tooltip=None, label=None, current_sort_method=None) -%} +{# + sort button where descending sort is default + and the search method is togglable between ascending and descending + buttons are rendered as links with id constructed as + "by_" + button_sort_criterium + class "on" is added when current_sort_method is one of + button_sort_criterium + "asc" or "desc" +#} + {% set key_name = button_sort_criterium %} + {% set sort = current_sort_method %} + {% if sort == key_name + "-asc" %}{# "worst" first #} + <a id="by_{{key_name}}" + href="?sort={{key_name}}-desc" + class="rev on" + title="{{desc_tooltip}}"><span>{{label}} ▲</span></a> + {% elif sort == key_name + "-desc" %}{# "best first" #} + <a id="by_{{key_name}}" + href="?sort={{key_name}}-asc" + class="rev on" + title="{{asc_tooltip}}"><span>{{label}} ▼</span></a> + {% else %}{# default, when other button is active #} + <a id="by_{{key_name}}" + href="?sort={{key_name}}-desc" + class="off" + title="{{desc_tooltip}}"><span>{{label}}</span></a> + {% endif %} + <script type="text/javascript">{# need to pass on text translations to js #} + var sortButtonData = sortButtonData || {}; + sortButtonData["{{key_name}}"] = { + label: "{{label}}", + asc_tooltip: "{{asc_tooltip}}", + desc_tooltip: "{{desc_tooltip}}" + }; + </script> +{%- endmacro %} + +{%- macro checkbox_in_div(checkbox_field, class = 'checkbox') -%} + <div{% if class %} class="{{class}}"{% endif %} + title="{{checkbox_field.help_text}}"> + {{ checkbox_field }} + {{ checkbox_field.label_tag() }} + {{ checkbox_field.errors }} + </div> +{%- endmacro -%} + +{%- macro edit_post( + post_form, + post_type = None, + mandatory_tags = None, + edit_title = False + ) +-%} + {% if edit_title %} + <div class="form-item"> + <label for="id_title" ><strong>{{ post_form.title.label_tag() }}:</strong></label> <span class="form-error"></span><br/> + {{ post_form.title }} {{ post_form.title.errors }} + <div class="title-desc"> + {{ post_form.title.help_text }} + </div> + </div> + {% endif %} + <div id="wmd-button-bar" class="wmd-panel"></div> + <div class="form-item"> + {{ post_form.text }}{# this element is resizable and will be wrapped by js #} + <label for="editor" class="form-error">{{ post_form.text.errors }}</label> + </div> + {# need label element for resizable input, b/c form validation won't find span #} + {% if post_type == 'question' %} + <div class="form-item"> + {% if mandatory_tags %} + <label for="id_tags"> + <strong>{% trans %}tags{% endtrans %},</strong> + {% trans %}one of these is required{% endtrans %} + </label> + {{ + tag_list_widget( + mandatory_tags, + make_links = False, + css_class = 'clearfix' + ) + }} + {% else %} + <label for="id_tags"> + <strong>{% trans %}tags{% endtrans %}:</strong> + {% trans %}(required){% endtrans %} + </label> + {% endif %} + <span class="form-error">{{ post_form.tags.errors }}</span><br/> + {{ post_form.tags }} + <div class="title-desc"> + {{ post_form.tags.help_text }} + </div> + </div> + {% endif %} + {% if 'summary' in post_form['fields'] %} + <div class="form-item"> + <strong>{{ post_form.summary.label_tag() }}</strong> <br/> + {{ post_form.summary }} + <div class="title-desc"> + {{ post_form.summary.help_text }} + </div> + <div class="form-error" >{{ post_form.summary.errors }}</div> + </div> + {% endif %} + <div class="preview-toggle"> + <span + id="pre-collapse" + title="{% trans %}Toggle the real time Markdown editor preview{% endtrans %}" + > + [{% trans %}hide preview{% endtrans %}] + </span> + </div> + <div id="previewer" class="wmd-preview"></div> +{%- endmacro -%} + +{%- macro inbox_link(user) -%} + {% if user.new_response_count > 0 or user.seen_response_count > 0 %} + <a id='ab-responses' href="{{user.get_absolute_url()}}?sort=inbox§ion=forum"> + <img + alt="{% trans username=user.username %}responses for {{username}}{% endtrans %}" + {% if user.new_response_count > 0 %} + src="{{ "/images/mail-envelope-full.png"|media }}" + title="{% trans response_count=user.new_response_count %}you have a new response{% pluralize %}you have {{response_count}} new responses{% endtrans %}" + {% elif user.seen_response_count > 0 %} + src="{{ "/images/mail-envelope-empty.png"|media }}" + title="{% trans %}no new responses yet{% endtrans %}" + {% endif %} + /> + </a> + {% endif %} +{%- endmacro -%} + +{%- macro moderation_items_link(user, moderation_items) -%} + {% if moderation_items %} + <a id="ab-responses" + href="{{user.get_absolute_url()}}?sort=inbox§ion=flags" + > + {% if moderation_items['new_count'] > 0 %} + <img src="{{'/images/dialog-warning.png'|media}}" + {% if moderation_items['seen_count'] > 0 %} + alt="{% trans new=moderation_items['new_count'], seen=moderation_items['seen_count']%}{{new}} new flagged posts and {{seen}} previous{% endtrans %}" + title="{% trans new=moderation_items['new_count'], seen=moderation_items['seen_count']%}{{new}} new flagged posts and {{seen}} previous{% endtrans %}" + {% else %} + alt="{% trans new=moderation_items['new_count'] %}{{new}} new flagged posts{% endtrans %}" + title="{% trans new=moderation_items['new_count'] %}{{new}} new flagged posts{% endtrans %}" + {% endif %} + /> + {% elif moderation_items['seen_count'] > 0 %} + <img src={{'/images/dialog-warning-off.png'|media}} + alt="{% trans seen=moderation_items['seen_count'] %}{{seen}} flagged posts{% endtrans %}" + title="{% trans seen=moderation_items['seen_count'] %}{{seen}} flagged posts{% endtrans %}" + /> + {% endif %} + </a> + {% endif %} +{%- endmacro -%} + +{%- macro tag_autocomplete_js(id = '#id_tags') -%} + var tagAc = new AutoCompleter({ + url: '{% url "get_tag_list" %}', + preloadData: true, + minChars: 1, + useCache: true, + matchInside: true, + maxCacheLength: 100, + delay: 10 + }); + tagAc.decorate($("{{ id }}")); +{%- endmacro -%} diff --git a/askbot/skins/old/templates/main_page.html b/askbot/skins/old/templates/main_page.html new file mode 100644 index 00000000..d0cddc68 --- /dev/null +++ b/askbot/skins/old/templates/main_page.html @@ -0,0 +1,24 @@ +{% extends "two_column_body.html" %} +{# + this template is split into several + blocks that are included here + the blocks are within directory templates/main_page + relative to the skin directory + + there is no html markup in this file +#} +<!-- questions.html --> +{% block title %}{% spaceless %}{% trans %}Questions{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} + {% include "main_page/tab_bar.html" %} + {% include "main_page/headline.html" %} + {% include "main_page/content.html" %} + {% include "main_page/paginator.html" %} +{% endblock %} +{% block sidebar %} + {% include "main_page/sidebar.html" %} +{% endblock %} +{% block endjs %} + {% include "main_page/javascript.html" %} +{% endblock %} +<!-- end questions.html --> diff --git a/askbot/skins/old/templates/main_page/content.html b/askbot/skins/old/templates/main_page/content.html new file mode 100644 index 00000000..72128cdc --- /dev/null +++ b/askbot/skins/old/templates/main_page/content.html @@ -0,0 +1,17 @@ +{% import "macros.html" as macros %} +<div id="question-list"> +{% cache 0 "questions" questions search_tags scope sort query context.page context.page_size language_code %} + {% for question in questions.object_list %} + {{macros.question_summary(question)}} + {% endfor %} +{% endcache %} +{# comment todo: fix css here #} +{% if questions_count == 0 %} + {% include "main_page/nothing_found.html" %} +{% else %} + <p class="evenMore" style="padding-left:9px"> + {% trans %}Did not find what you were looking for?{% endtrans %} + <a href="{% url ask %}">{% trans %}Please, post your question!{% endtrans %}</a> + </p> +{% endif %} +</div> diff --git a/askbot/skins/old/templates/main_page/headline.html b/askbot/skins/old/templates/main_page/headline.html new file mode 100644 index 00000000..130a9bd9 --- /dev/null +++ b/askbot/skins/old/templates/main_page/headline.html @@ -0,0 +1,48 @@ +{% import "macros.html" as macros %} +{% if questions_count > 0 %} + <div style="clear:both"> + <p class="rss"> + (<a + href="{{settings.APP_URL}}/feeds/rss/" + title="{% trans %}subscribe to the questions feed{% endtrans %}" + >{% trans %}rss feed{% endtrans %}</a>) + </p> + <h1 id="question-count" class="search-result-summary"> + {% if search_tags %} + {% trans cnt=questions_count, q_num=questions_count|intcomma %}{{q_num}} question, tagged{% pluralize %}{{q_num}} questions, tagged{% endtrans %} + {% else %} + {% trans cnt=questions_count, q_num=questions_count|intcomma %}{{q_num}} question{% pluralize %}{{q_num}} questions{% endtrans %} + {% endif %} + {% if author_name %} + {% trans %}with {{author_name}}'s contributions{% endtrans %} + {% endif %} + </h1> + {{ macros.tag_list_widget( + search_tags, + id = 'search-tags', + deletable = True, + make_links = False + ) + }} + {% if author_name or search_tags or query %} + <p class="search-tips">{% trans %}Search tips:{% endtrans %} + {% if reset_method_count > 1 %} + {% if author_name %} + <a href="{% url questions %}?reset_author=true">{% trans %}reset author{% endtrans %}</a> + {% endif %} + {% if search_tags %}{% if author_name and query %}, {% elif author_name %}{% trans %} or {% endtrans %}{% endif %} + <a href="{% url questions %}?reset_tags=true">{% trans %}reset tags{% endtrans %}</a> + {% endif %} + {% if query %}{% trans %} or {% endtrans %} + <a href="{% url questions %}?start_over=true">{% trans %}start over{% endtrans %}</a> + {% endif %} + {% else %} + <a href="{% url questions %}?start_over=true">{% trans %}start over{% endtrans %}</a> + {% endif %} + {% trans %} - to expand, or dig in by adding more tags and revising the query.{% endtrans %} + </p> + {% else %} + <p class="search-tips">{% trans %}Search tip:{% endtrans %} {% trans %}add tags and a query to focus your search{% endtrans %}</p> + {% endif %} + </div> +{% endif %} diff --git a/askbot/skins/old/templates/main_page/javascript.html b/askbot/skins/old/templates/main_page/javascript.html new file mode 100644 index 00000000..14dfe3cd --- /dev/null +++ b/askbot/skins/old/templates/main_page/javascript.html @@ -0,0 +1,30 @@ +<script type="text/javascript"> + var sortMethod = '{{sort}}'; + var showSortByRelevance = {% if show_sort_by_relevance %}true{% else %}false{% endif %}; + var minSearchWordLength = {{settings.MIN_SEARCH_WORD_LENGTH}}; + $(document).ready(function(){ + /*var on_tab = '#nav_questions'; + $(on_tab).attr('className','on');*/ + liveSearch().init('main_page'); + Hilite.exact = false; + Hilite.elementid = "question-list"; + Hilite.debug_referrer = location.href; + {% if update_avatar_data == True %} + var today = new Date();{#add timestamp to prevent browser caching #} + $.getJSON('{% url user_update_has_custom_avatar %}?t=' + today.getTime()); + {% endif %} + }); + askbot['urls']['mark_interesting_tag'] = scriptUrl + '{% url mark_interesting_tag %}'; + askbot['urls']['mark_ignored_tag'] = scriptUrl + '{% url mark_ignored_tag %}'; + askbot['urls']['unmark_tag'] = scriptUrl + '{% url unmark_tag %}'; + askbot['urls']['set_tag_filter_strategy'] = '{% url "set_tag_filter_strategy" %}'; + askbot['urls']['questions'] = '{% url "questions" %}'; + askbot['urls']['question_url_template'] = scriptUrl + '{% trans %}question/{% endtrans %}{{ "{{QuestionID}}/" }}'; + askbot['urls']['user_url_template'] = scriptUrl + '{% trans %}users/{% endtrans %}{{ "{{user_id}}" }}/{{ "{{slug}}" }}/'; + askbot['messages']['name_of_anonymous_user'] = '{{ name_of_anonymous_user }}'; +</script> +<script type='text/javascript' src='{{"/js/editor.js"|media}}'></script> +{% if request.user.is_authenticated() %} +<script type='text/javascript' src='{{"/js/tag_selector.js"|media}}'></script> +{% endif %} +<script type="text/javascript" src="{{"/js/live_search.js"|media}}"></script> diff --git a/askbot/skins/old/templates/main_page/nothing_found.html b/askbot/skins/old/templates/main_page/nothing_found.html new file mode 100644 index 00000000..50f2f340 --- /dev/null +++ b/askbot/skins/old/templates/main_page/nothing_found.html @@ -0,0 +1,31 @@ +{# todo: add tips to widen selection #} +<p class="evenMore" style="padding-top:30px;text-align:center;"> +{% if scope == "unanswered" %} + {% trans %}There are no unanswered questions here{% endtrans %} +{% endif %} +{% if scope == "favorite" %} + {% trans %}No questions here. {% endtrans %} + {% trans %}Please star (bookmark) some questions or follow some users.{% endtrans %} +{% endif %} +</p> +{% if query or search_tags or author_name %} +<p class="evenMore" style="text-align:center"> + {% trans %}You can expand your search by {% endtrans %} + {% if reset_method_count > 1 %} + {% if author_name %} + <a href="{% url questions %}?reset_author=true">{% trans %}resetting author{% endtrans %}</a> + {% endif %} + {% if search_tags %}{% if author_name and query %}, {% elif author_name %}{% trans %} or {% endtrans %}{% endif %} + <a href="{% url questions %}?reset_tags=true">{% trans %}resetting tags{% endtrans %}</a> + {% endif %} + {% if query %}{% trans %} or {% endtrans %} + <a href="{% url questions %}?start_over=true">{% trans %}starting over{% endtrans %}</a> + {% endif %} + {% else %} + <a href="{% url questions %}?start_over=true">{% trans %}starting over{% endtrans %}</a> + {% endif %} +</p> +{% endif %} +<p class="evenMore" style="text-align:center"> +<a href="{% url ask %}">{% trans %}Please always feel free to ask your question!{% endtrans %}</a> +</p> diff --git a/askbot/skins/old/templates/main_page/paginator.html b/askbot/skins/old/templates/main_page/paginator.html new file mode 100644 index 00000000..4a77060f --- /dev/null +++ b/askbot/skins/old/templates/main_page/paginator.html @@ -0,0 +1,7 @@ +{% import "macros.html" as macros %} +{% if questions_count > 10 %}{# todo: remove magic number #} + <div id="pager" class="pager"> + {{ macros.paginator(context|setup_paginator, position='left') }} + {{ macros.pagesize_switch(context, position='right') }} + </div> +{% endif %} diff --git a/askbot/skins/old/templates/main_page/sidebar.html b/askbot/skins/old/templates/main_page/sidebar.html new file mode 100644 index 00000000..6abc0492 --- /dev/null +++ b/askbot/skins/old/templates/main_page/sidebar.html @@ -0,0 +1,46 @@ +{% import "macros.html" as macros %} + +{{ settings.SIDEBAR_MAIN_HEADER }} + +{% if contributors and settings.SIDEBAR_MAIN_SHOW_AVATARS %} + {% cache 600 "contributors" contributors search_tags scope sort query context.page context.page_size language_code %} + <div id="contrib-users" class="boxC"> + <h2>{% trans %}Contributors{% endtrans %}</h2> + {% spaceless %} + {% for person in contributors %} + {{ macros.gravatar(person,48) }} + {% endfor %} + {% endspaceless %} + </div> + {% endcache %} +{% endif %} + +{% if request.user.is_authenticated() and settings.SIDEBAR_MAIN_SHOW_TAG_SELECTOR %} + {% include "blocks/tag_selector.html" %} +{% endif %} + +{% if tags and settings.SIDEBAR_MAIN_SHOW_TAGS %} + {% cache 0 "tags" tags search_tags scope sort query context.page context.page_size language_code %} + <div class="boxC"> + <h2>{% trans %}Related tags{% endtrans %}</h2> + {% if tag_list_type == 'list' %} + <ul id="related-tags" class="tags"> + {% for tag in tags %} + <li> + {{ macros.tag_widget( + tag.name, + html_tag = 'div', + extra_content = '<span class="tag-number">× ' ~ + tag.local_used_count|intcomma ~ '</span>' + )}} + </li> + {% endfor %} + </ul> + {% else %} + {{ macros.tag_cloud(tags = tags, font_sizes = font_size) }} + {% endif %} + </div> + {% endcache %} +{% endif %} + +{{ settings.SIDEBAR_MAIN_FOOTER }} diff --git a/askbot/skins/old/templates/main_page/tab_bar.html b/askbot/skins/old/templates/main_page/tab_bar.html new file mode 100644 index 00000000..1b27ab3a --- /dev/null +++ b/askbot/skins/old/templates/main_page/tab_bar.html @@ -0,0 +1,86 @@ +{% import "macros.html" as macros %} +{% cache 600 "scope_sort_tabs" search_tags request.user scope sort query context.page context.page_size language_code %} +<div class="tabBar"> + <div class="tabsC"> + <span class="label">{% trans %}In:{% endtrans %}</span> + <a id="all" + class="{% if scope == 'all' %}on{% else %}off{% endif %}" + href="?scope=all" + title="{% trans %}see all questions{% endtrans %}" + ><span>{% trans %}all{% endtrans %}</span></a> + <a id="unanswered" + class="{% if scope == 'unanswered' %}on{% else %}off{% endif %}" + href="?scope=unanswered&sort=answers-asc" + title="{% trans %}see unanswered questions{% endtrans %}" + ><span>{% trans %}unanswered{% endtrans %}</span></a> + {% if request.user.is_authenticated() %} + <a id="favorite" + class="{% if scope == 'favorite' %}on{% else %}off{% endif %}" + href="?scope=favorite" + title="{% trans %}see your followed questions{% endtrans %}" + ><span>{% trans %}followed{% endtrans %}</span></a> + {% endif %} + </div> + <div id="sort_tabs" class="tabsA"> + <span class="label">{% trans %}Sort by:{% endtrans %}</span> + {% if show_sort_by_relevance %} + {% set asc_relevance_tooltip = gettext('most relevant questions') %} + {% set desc_relevance_tooltip = gettext('click to see most relevant questions') %} + {% set relevance_label = gettext('relevance') %} + {% if query %} + <a id="by_relevance" + {% if sort == "relevance-desc" %} + href="?sort=relevance-desc" + class="on" + title="{{asc_relevance_tooltip}}"><span>{{relevance_label}} ▼</span> + {% else %} + href="?sort=relevance-desc" + class="off" + title="{{desc_relevance_tooltip}}"><span>{{relevance_label}}</span> + {% endif %} + </a> + {% endif %} + <script type="text/javascript"> + var sortButtonData = sortButtonData || {}; + sortButtonData['relevance'] = { + asc_tooltip: "{{asc_relevance_tooltip}}", + desc_tooltip: "{{desc_relevance_tooltip}}", + label: "{{relevance_label}}" + }; + </script> + {% endif %} + {{macros.reversible_sort_button( + button_sort_criterium = 'age', + label = gettext('by date'), + asc_tooltip = gettext('click to see the oldest questions'), + desc_tooltip = gettext('click to see the newest questions'), + current_sort_method = sort + ) + }} + {{macros.reversible_sort_button( + button_sort_criterium = 'activity', + label = gettext('by activity'), + asc_tooltip = gettext('click to see the least recently updated questions'), + desc_tooltip = gettext('click to see the most recently updated questions'), + current_sort_method = sort + ) + }} + {{macros.reversible_sort_button( + button_sort_criterium = 'answers', + label = gettext('by answers'), + asc_tooltip = gettext('click to see the least answered questions'), + desc_tooltip = gettext('click to see the most answered questions'), + current_sort_method = sort + ) + }} + {{macros.reversible_sort_button( + button_sort_criterium = 'votes', + label = gettext('by votes'), + asc_tooltip = gettext('click to see least voted questions'), + desc_tooltip = gettext('click to see most voted questions'), + current_sort_method = sort + ) + }} + </div> +</div> +{% endcache %} diff --git a/askbot/skins/old/templates/one_column_body.html b/askbot/skins/old/templates/one_column_body.html new file mode 100644 index 00000000..e97de505 --- /dev/null +++ b/askbot/skins/old/templates/one_column_body.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} +{% block body_class %}one-col{% endblock %} +{% block body %} +<div id="CAFull"> + {% include "blocks/input_bar.html" %} + {% block content%} + {% endblock%} +</div> +{% endblock %} diff --git a/askbot/skins/old/templates/privacy.html b/askbot/skins/old/templates/privacy.html new file mode 100644 index 00000000..61f4d945 --- /dev/null +++ b/askbot/skins/old/templates/privacy.html @@ -0,0 +1,8 @@ +{% extends "one_column_body.html" %} +<!-- privacy.html --> +{% block title %}{% spaceless %}{% trans %}Privacy policy{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans %}Privacy policy{% endtrans %}</h1> +{{settings.FORUM_PRIVACY}} +{% endblock %} +<!-- end privacy.html --> diff --git a/askbot/skins/old/templates/question.html b/askbot/skins/old/templates/question.html new file mode 100644 index 00000000..06cd1332 --- /dev/null +++ b/askbot/skins/old/templates/question.html @@ -0,0 +1,553 @@ +{% extends "two_column_body.html" %} +{% import "macros.html" as macros %} +<!-- question.html --> +{% block title %}{% spaceless %}{{ question.get_question_title() }}{% endspaceless %}{% endblock %} +{% block meta_description %} + <meta name="description" content="{{question.summary|striptags|escape}}" /> +{% endblock %} +{% block keywords %}{{question.tagname_meta_generator()}}{% endblock %} +{% block forestyle %} + <link rel="canonical" href="{{settings.APP_URL}}{{question.get_absolute_url()}}" /> + <link rel="stylesheet" type="text/css" href="{{'/js/wmd/wmd.css'|media}}" /> +{% endblock %} +{% block content %} +<h1><a href="{{ question.get_absolute_url() }}">{{ question.get_question_title() }}</a></h1> +<table style="width:100%;" id="question-table" {% if question.deleted %}class="deleted"{%endif%}> + <tr> + <td style="width:30px;vertical-align:top"> + <div class="vote-buttons"> + {% if question_vote %} + <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote" + {% if question_vote.is_upvote() %} + src="{{'/images/vote-arrow-up-on.png'|media}}" + {% else %} + src="{{'/images/vote-arrow-up.png'|media}}" + {% endif %} + alt="{% trans %}i like this post (click again to cancel){% endtrans %}" + title="{% trans %}i like this post (click again to cancel){% endtrans %}" /> + <div id="question-vote-number-{{ question.id }}" class="vote-number" + title="{% trans %}current number of votes{% endtrans %}"> + {{ question.score }} + </div> + <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote" + {% if question_vote.is_downvote() %} + src="{{'/images/vote-arrow-down-on.png'|media}}" + {% else %} + src="{{'/images/vote-arrow-down.png'|media}}" + {% endif %} + alt="{% trans %}i dont like this post (click again to cancel){% endtrans %}" + title="{% trans %}i dont like this post (click again to cancel){% endtrans %}" /> + {% else %} + <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote" + alt="{% trans %}i like this post (click again to cancel){% endtrans %}" + src="{{'/images/vote-arrow-up.png'|media}}" + title="{% trans %}i like this post (click again to cancel){% endtrans %}" /> + <div id="question-vote-number-{{ question.id }}" class="vote-number" + title="{% trans %}current number of votes{% endtrans %}"> + {{ question.score }} + </div> + <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote" + src="{{'/images/vote-arrow-down.png'|media}}" + alt="{% trans %}i dont like this post (click again to cancel){% endtrans %}" + title="{% trans %}i dont like this post (click again to cancel){% endtrans %}" /> + {% endif %} + + {% if settings.ENABLE_SHARING_TWITTER %}{{ macros.share(site = 'twitter', icon = True) }}{% endif %} + {% if settings.ENABLE_SHARING_FACEBOOK %}{{ macros.share(site = 'facebook', icon = True) }}{% endif %} + {% if settings.ENABLE_SHARING_LINKEDIN %}{{ macros.share(site = 'linkedin', icon = True) }}{% endif %} + {% if settings.ENABLE_SHARING_IDENTICA %}{{ macros.share(site = 'identica', icon = True) }}{% endif %} + {% if settings.ENABLE_SHARING_GOOGLE %}<g:plusone size="small" count="false"></g:plusone>{% endif %} + </div> + </td> + <td> + <div class="question-body"> + {{question.html}} + </div> + <ul id="question-tags" class="post-tags tags"> + {% for tag in question.get_tag_names() %} + {{ macros.tag_widget( + tag, + css_class = 'post-tag', + html_tag = 'li' + ) + }} + {% endfor %} + </ul> + <div id="question-controls" class="post-controls"> + {% set pipe=joiner('<span class="sep">|</span>') %} + {% if request.user|can_edit_post(question) %}{{ pipe() }} + <a href="{% url edit_question question.id %}">{% trans %}edit{% endtrans %}</a> + {% endif %} + {% if request.user|can_retag_question(question) %}{{ pipe() }} + <a id="retag" href="{% url retag_question question.id %}">{% trans %}retag{% endtrans %}</a> + <script type="text/javascript"> + var retagUrl = "{% url retag_question question.id %}"; + </script> + {% endif %} + {% if question.closed %} + {% if request.user|can_reopen_question(question) %}{{ pipe() }} + <a href="{% url reopen question.id %}">{% trans %}reopen{% endtrans %}</a> + {% endif %} + {% else %} + {% if request.user|can_close_question(question) %}{{ pipe() }} + <a href="{% url close question.id %}">{% trans %}close{% endtrans %}</a> + {% endif %} + {% endif %} + {% if request.user|can_flag_offensive(question) %}{{ pipe() }} + <span id="question-offensive-flag-{{ question.id }}" class="offensive-flag" + title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"> + <a>{% trans %}flag offensive{% endtrans %}</a> + {% if request.user|can_see_offensive_flags(question) %} + <span class="darkred">{% if question.offensive_flag_count > 0 %}({{ question.offensive_flag_count }}){% endif %}</span> + {% endif %} + </span> + {% endif %} + {% if request.user|can_delete_post(question) %}{{ pipe() }} + <a id="question-delete-link-{{question.id}}">{% if question.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %}</a> + {% endif %} + </div> + <div class="post-update-info-container"> + {{ + macros.post_contributor_info( + question, + "original_author", + question.wiki, + settings.MIN_REP_TO_EDIT_WIKI + ) + }} + {{ + macros.post_contributor_info( + question, + "last_updater", + question.wiki, + settings.MIN_REP_TO_EDIT_WIKI, + ) + }} + </div> + {{ + macros.post_comments_widget( + post = question, + show_post = show_post, + show_comment = show_comment, + comment_order_number = comment_order_number, + user = request.user, + max_comments = settings.MAX_COMMENTS_TO_SHOW + ) + }} + <!--/div--> + </td> + </tr> +</table> +{% if question.closed %} +<div class="question-status" style="margin-bottom:15px"> +<h3>{% trans close_reason=question.get_close_reason_display() %}The question has been closed for the following reason "{{ close_reason }}" by{% endtrans %} +<a href="{{ question.closed_by.get_profile_url() }}">{{ question.closed_by.username }}</a> +{% trans closed_at=question.closed_at %}close date {{closed_at}}{% endtrans %}</h3> +</div> +{% endif %} +{% if answers %} + <div class="tabBar"> + <h2 id="sort-top"> + {% trans counter=answers|length %} + {{counter}} Answer: + {% pluralize %} + {{counter}} Answers: + {% endtrans %} + </h2> + <div class="tabsA"> + <a id="oldest" href="{{ question.get_absolute_url() }}?sort=oldest#sort-top" + title="{% trans %}oldest answers will be shown first{% endtrans %}" + ><span>{% trans %}oldest answers{% endtrans %}</span></a> + <a id="latest" href="{{ question.get_absolute_url() }}?sort=latest#sort-top" + title="{% trans %}newest answers will be shown first{% endtrans %}" + ><span>{% trans %}newest answers{% endtrans %}</span></a> + <a id="votes" href="{{ question.get_absolute_url() }}?sort=votes#sort-top" + title="{% trans %}most voted answers will be shown first{% endtrans %}" + ><span>{% trans %}popular answers{% endtrans %}</span></a> + </div> + </div> + {{ macros.paginator(paginator_context) }} + + {% for answer in answers %} + <a name="{{ answer.id }}"></a> + <div id="answer-container-{{ answer.id }}" class="answer {% if answer.accepted %}accepted-answer{% endif %} {% if answer.author_id==question.author_id %} answered-by-owner{% endif %} {% if answer.deleted %}deleted{% endif %}"> + <table style="width:100%;" class="answer-table"> + <tr> + <td style="width:30px;vertical-align:top"> + <div class="vote-buttons"> + <img id="answer-img-upvote-{{ answer.id }}" class="answer-img-upvote" + {% if user_answer_votes[answer.id] == 1 %} + src="{{'/images/vote-arrow-up-on.png'|media}}" + {% else %} + src="{{'/images/vote-arrow-up.png'|media}}" + {% endif %} + alt="{% trans %}i like this answer (click again to cancel){% endtrans %}" + title="{% trans %}i like this answer (click again to cancel){% endtrans %}"/> + <div id="answer-vote-number-{{ answer.id }}" class="vote-number" title="{% trans %}current number of votes{% endtrans %}"> + {{ answer.score }} + </div> + <img id="answer-img-downvote-{{ answer.id }}" class="answer-img-downvote" + {% if user_answer_votes[answer.id] == -1 %} + src="{{'/images/vote-arrow-down-on.png'|media}}" + {% else %} + src="{{'/images/vote-arrow-down.png'|media}}" + {% endif %} + alt="{% trans %}i dont like this answer (click again to cancel){% endtrans %}" + title="{% trans %}i dont like this answer (click again to cancel){% endtrans %}" /> + {% if request.user == question.author %} + <img id="answer-img-accept-{{ answer.id }}" class="answer-img-accept" + {% if answer.accepted %} + src="{{'/images/vote-accepted-on.png'|media}}" + {% else %} + src="{{'/images/vote-accepted.png'|media}}" + {% endif %} + alt="{% trans %}mark this answer as favorite (click again to undo){% endtrans %}" + title="{% trans %}mark this answer as favorite (click again to undo){% endtrans %}" /> + {% else %} + {% if answer.accepted %} + <img id="answer-img-accept-{{ answer.id }}" class="answer-img-accept" + {% if answer.accepted %} + src="{{'/images/vote-accepted-on.png'|media}}" + {% else %} + src="{{'/images/vote-accepted.png'|media}}" + {% endif %} + alt="{% trans question_author=question.author.username %}{{question_author}} has selected this answer as correct{% endtrans %}" + title="{% trans questsion_author=question.author.username%}{{question_author}} has selected this answer as correct{% endtrans %}" + {% endif %} + {% endif %} + </div> + </td> + <td> + <div class="item-right"> + <div class="answer-body"> + {{ answer.html }} + </div> + <div class="answer-controls post-controls"> + {% set pipe=joiner('<span class="sep">|</span>') %} + <span class="linksopt">{{ pipe() }} + <a + href="{{ answer.get_absolute_url() }}" + title="{% trans %}answer permanent link{% endtrans %}"> + {% trans %}permanent link{% endtrans %} + </a> + </span> + {% if request.user|can_edit_post(answer) %}{{ pipe() }} + <span class="action-link"><a href="{% url edit_answer answer.id %}">{% trans %}edit{% endtrans %}</a></span> + {% endif %} + {% if request.user|can_flag_offensive(answer) %}{{ pipe() }} + <span id="answer-offensive-flag-{{ answer.id }}" class="offensive-flag" + title="{% trans %}report as offensive (i.e containing spam, advertising, malicious text, etc.){% endtrans %}"> + <a>{% trans %}flag offensive{% endtrans %}</a> + {% if request.user|can_see_offensive_flags(answer) %} + <span class="darkred">{% if answer.offensive_flag_count > 0 %}({{ answer.offensive_flag_count }}){% endif %}</span> + {% endif %} + </span> + {% endif %} + {% if request.user|can_delete_post(answer) %}{{ pipe() }} + {% spaceless %} + <span class="action-link"> + <a id="answer-delete-link-{{answer.id}}"> + {% if answer.deleted %}{% trans %}undelete{% endtrans %}{% else %}{% trans %}delete{% endtrans %}{% endif %}</a> + </span> + {% endspaceless %} + {% endif %} + {% if settings.ALLOW_SWAPPING_QUESTION_WITH_ANSWER and request.user.is_authenticated() and request.user.is_administrator_or_moderator() %}{{ pipe() }} + <span class="action-link"> + <a id="swap-question-with-answer-{{answer.id}}">{% trans %}swap with question{% endtrans %}</a> + </span> + {% endif %} + </div> + <div class="post-update-info-container"> + {{ + macros.post_contributor_info( + answer, + "original_author", + answer.wiki, + settings.MIN_REP_TO_EDIT_WIKI + ) + }} + {{ + macros.post_contributor_info( + answer, + "last_updater", + answer.wiki, + settings.MIN_REP_TO_EDIT_WIKI + ) + }} + </div> + {{ + macros.post_comments_widget( + post = answer, + show_post = show_post, + show_comment = show_comment, + comment_order_number = comment_order_number, + user = request.user, + max_comments = settings.MAX_COMMENTS_TO_SHOW + ) + }} + </div> + </td> + </tr> + </table> + </div> + {% endfor %} + {{ macros.paginator(paginator_context) }} +{% else %} + {% set question_url=settings.APP_URL+question.get_absolute_url()|urlencode %} + <h2 class="share-question">{% trans %}Know someone who can answer? Share a <a href="{{ question_url }}">link</a> to this question via{% endtrans %} + {% if settings.ENABLE_SHARING_TWITTER %}{{ macros.share(site = 'twitter', site_label = 'Twitter') }},{% endif %} + {% if settings.ENABLE_SHARING_FACEBOOK %}{{ macros.share(site = 'facebook', site_label = 'Facebook') }},{% endif %} + {% if settings.ENABLE_SHARING_LINKEDIN %}{{ macros.share(site = 'linkedin', site_label = 'LinkedIn') }},{% endif %} + {% if settings.ENABLE_SHARING_IDENTICA %}{{ macros.share(site = 'identica', site_label = 'Identi.ca') }},{% endif %} + {%- if settings.ENABLE_SHARING_TWITTER or settings.ENABLE_SHARING_FACEBOOK or settings.ENABLE_SHARING_LINKEDIN or settings.ENABLE_SHARING_IDENTICA -%} + {% trans %} or{% endtrans %} + {% endif %} + <a href="mailto:?subject={{ settings.APP_SHORT_NAME|urlencode }}&body={{ question_url }}">{% trans %}email{% endtrans %}</a>. + </h2> +{% endif %} +<form id="fmanswer" action="{% url answer question.id %}" method="post">{% csrf_token %} + {% if request.user.is_authenticated() %} + <p style="padding-left:3px"> + {{ answer.email_notify }} + <label for="question-subscribe-updates"> + {% set email_feed_frequency = request.user.get_followed_question_alert_frequency() %} + {% if email_feed_frequency =='n' %} + {% trans %}Notify me once a day when there are any new answers{% endtrans %} + {% elif email_feed_frequency =='d' %} + {% trans %}Notify me once a day when there are any new answers{% endtrans %} + {% elif email_feed_frequency =='w' %} + {% trans %}Notify me weekly when there are any new answers{% endtrans %} + {% elif email_feed_frequency =='i' %} + {% trans %}Notify me immediately when there are any new answers{% endtrans %} + {% endif %} + </label> + {% trans profile_url=request.user.get_profile_url() %}You can always adjust frequency of email updates from your {{profile_url}}{% endtrans %} + </p> + {% else %} + <p style="padding-left:3px"> + {{ answer.email_notify }} + <label>{% trans %}once you sign in you will be able to subscribe for any updates here{% endtrans %}</label> + </p> + {% endif %} + <div style="clear:both"> + </div> + {% if request.user.is_anonymous() and settings.ALLOW_POSTING_BEFORE_LOGGING_IN == False %} + {% if not question.closed %} + <a + class="submit" + href="{{settings.LOGIN_URL}}?next={% url question question.id %}" + >{% trans %}Login/Signup to Answer{% endtrans %}</a> + {% endif %} + {% else %} + {% if not question.closed %} + <div style="padding:10px 0 0 0;"> + {% spaceless %} + <h2> + {% if answers %} + {% trans %}Your answer{% endtrans %} + {% else %} + {% trans %}Be the first one to answer this question!{% endtrans %} + {% endif %} + </h2> + {% endspaceless %} + </div> + {% if request.user.is_anonymous() %} + <div class="message">{% trans %}you can answer anonymously and then login{% endtrans %}</div> + {% else %} + <p class="message"> + {% if request.user==question.author %} + {% trans %}answer your own question only to give an answer{% endtrans %} + {% else %} + {% trans %}please only give an answer, no discussions{% endtrans %} + {% endif %} + </p> + {% endif %} + {{ macros.edit_post(answer) }} + <input type="submit" + {% if user.is_anonymous() %} + value="{% trans %}Login/Signup to Post Your Answer{% endtrans %}" + {% else %} + {% if user == question.author %} + value="{% trans %}Answer Your Own Question{% endtrans %}" + {% else %} + value="{% trans %}Answer the question{% endtrans %}" + {% endif %} + {% endif %} + class="submit after-editor" style="float:left"/> + {% if settings.WIKI_ON %} + {{ macros.checkbox_in_div(answer.wiki) }} + {% endif %} + {% endif %} + {% endif %} + </form> +{% endblock %} + +{% block sidebar %} + +{{ settings.SIDEBAR_QUESTION_HEADER }} +<div class="boxC vote-buttons"> + <h2 style="font-size: 22px;margin-top: 11px; text-align: left;">{% trans %}Question tools{% endtrans %}</h2> + {% if favorited %} + <a class="button followed" + alt="{% trans %}click to unfollow this question{% endtrans %}"> + <div>{% trans %}Following{% endtrans %}</div> + <div class='unfollow'>{% trans %}Unfollow{% endtrans %}</div> + </a> + {% else %} + <a class="button follow" + alt="{% trans %}click to follow this question{% endtrans %}"> + {%trans %}Follow{%endtrans%} + </a> + {% endif %} + <div class="clearfix"></div> + <div id="favorite-number" class="favorite-number{% if favorited %} my-favorite-number{% endif %}"> + {% set follower_count = question.favourite_count %} + {% if follower_count > 0 %} + {% trans count=follower_count %}{{count}} follower{% pluralize %}{{count}} followers{% endtrans %} + {% endif %} + </div> +<div class="notify-sidebar"> + {%if request.user.is_authenticated() %} + <input type="checkbox" id="question-subscribe-sidebar"/> + <label for="question-subscribe-sidebar">{% trans %}email the updates{% endtrans %}</label> + {%else%} + <input type="checkbox" id="question-subscribe-sidebar"/> + <label for="question-subscribe-sidebar">{% trans %}<strong>Here</strong> (once you log in) you will be able to sign up for the periodic email updates about this question.{% endtrans %}</label> + {%endif%} + </div> +</div> +{% cache 0 "questions_tags" questions_tags question.id language_code %} +{% if settings.SIDEBAR_QUESTION_SHOW_TAGS %} + <div class="boxC"> + <div class="clearfix"></div> + <h2> + {% trans %}Question tags{% endtrans %}: + </h2> + <ul id="related-tags" class="tags"> + {% for tag in tags %} + <li> + {{ macros.tag_widget( + tag, + html_tag = 'div', + url_params = 'start_over=true', + extra_content = '<span class="tag-number">× ' ~ + tag.used_count|intcomma ~ '</span>' + ) + }} + </li> + {% endfor %} + </ul> + </div> +{% endif %} + +{% if settings.SIDEBAR_QUESTION_SHOW_META %} +<div class="boxC"> + <div class="clearfix"></div> + <h2>{% trans %}Stats:{% endtrans %}</h2> + <p> + {% trans %}question asked{% endtrans %}: <strong title="{{ question.added_at }}">{{question.added_at|diff_date}}</strong> + </p> + <p> + {% trans %}question was seen{% endtrans %}: <strong>{{ question.view_count|intcomma }} {% trans %}times{% endtrans %}</strong> + </p> + <p> + {% trans %}last updated{% endtrans %}: <strong title="{{ question.last_activity_at }}">{{question.last_activity_at|diff_date}}</strong> + </p> +</div> +{% endif %} +{% endcache %} + +{% if similar_questions.data and settings.SIDEBAR_QUESTION_SHOW_RELATED %} + {#% cache 1800 "related_questions" related_questions question.id language_code %#} + <div class="boxC"> + <h2>{% trans %}Related questions{% endtrans %}</h2> + <div class="questions-related"> + {% for question in similar_questions.data() %} + <p> + <a href="{{ question.get_absolute_url() }}">{{ question.get_question_title() }}</a> + </p> + {% endfor %} + </div> + </div> + {#% endcache %#} +{% endif %} + +{{ settings.SIDEBAR_QUESTION_FOOTER }} + +{% endblock %} +{% block endjs %} + {% if not question.closed %} + <script type='text/javascript' src='{{"/js/editor.js"|media}}'></script> + <script type='text/javascript'> + {% if settings.ENABLE_MATHJAX or settings.MARKUP_CODE_FRIENDLY %} + var codeFriendlyMarkdown = true; + {% else %} + var codeFriendlyMarkdown = false; + {% endif %} + var maxCommentLength = {{settings.MAX_COMMENT_LENGTH}}; + askbot['urls']['postComments'] = '{% url post_comments %}'; + askbot['urls']['editComment'] = '{% url edit_comment %}'; + askbot['urls']['deleteComment'] = '{% url delete_comment %}'; + askbot['urls']['getComment'] = '{% url get_comment %}'; + askbot['urls']['question_url_template'] = scriptUrl + '{% trans %}question/{% endtrans %}{{ "{{QuestionID}}/{{questionSlug}}" }}';{# yes it needs to be that whacky #} + askbot['urls']['user_signin'] = '{{ settings.LOGIN_URL }}'; + askbot['urls']['vote_url_template'] = scriptUrl + '{% trans %}questions/{% endtrans %}{{ "{{QuestionID}}/" }}{% trans %}vote/{% endtrans %}'; + askbot['urls']['swap_question_with_answer'] = '{% url swap_question_with_answer %}'; + askbot['urls']['upvote_comment'] = '{% url upvote_comment %}'; + askbot['messages']['addComment'] = '{% trans %}add comment{% endtrans %}'; + {% if settings.SAVE_COMMENT_ON_ENTER %} + askbot['settings']['saveCommentOnEnter'] = true; + {% else %} + askbot['settings']['saveCommentOnEnter'] = false; + {% endif %} + </script> + <script type='text/javascript' src='{{"/js/wmd/showdown.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/wmd/wmd.js"|media}}'></script> + {% endif %} + <script type='text/javascript' src='{{"/js/jquery.validate.min.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/post.js"|media}}'></script> + <script type="text/javascript"> + // define reputation needs for comments + var repNeededForComments = 50; + $().ready(function(){ + {% if request.user.is_authenticated() %} + if ($('#question-subscribe-updates')[0].checked){ + $('#question-subscribe-sidebar').attr({'checked': 'checked'}); + } + {%endif%} + $("#nav_questions").attr('className',"on"); + var answer_sort_tab = "{{ tab_id }}"; + $("#" + answer_sort_tab).attr('className',"on"); + + Vote.init({{ question.id }}, '{{ question.title|slugify }}', '{{ question.author.id }}','{{ request.user.id }}'); + + {% if not question.closed and request.user.is_authenticated %}initEditor();{% endif %} + + lanai.highlightSyntax(); + $('#btLogin').bind('click', function(){window.location.href='{{ settings.LOGIN_URL }}'; } ) + if (window.location.hash === 'fmanswer'){ + $('#fmanswer textarea').focus(); + } + {% if settings.ENABLE_SHARING_GOOGLE %}$.getScript("http://apis.google.com/js/plusone.js"){% endif %} + }); + + function initEditor(){ + $('#editor').TextAreaResizer(); + //highlight code synctax when editor has new text + $("#editor").typeWatch({highlight: false, wait: 3000, + captureLength: 5, callback: lanai.highlightSyntax}); + + var display = true; + var txt = "[{% trans %}hide preview{% endtrans %}]"; + $('#pre-collapse').text(txt); + $('#pre-collapse').bind('click', function(){ + txt = display ? "[{% trans %}show preview{% endtrans %}]" : "[{% trans %}hide preview{% endtrans %}]"; + display = !display; + $('#previewer').toggle(); + $('#pre-collapse').text(txt); + }); + setupFormValidation($("#fmanswer"), CPValidator.getQuestionFormRules(), CPValidator.getQuestionFormMessages()); + } + </script> + {% include "blocks/editor_data.html" %} +{% endblock %} diff --git a/askbot/skins/old/templates/question_edit.html b/askbot/skins/old/templates/question_edit.html new file mode 100644 index 00000000..feee2521 --- /dev/null +++ b/askbot/skins/old/templates/question_edit.html @@ -0,0 +1,97 @@ +{% extends "two_column_body.html" %} +{% import "macros.html" as macros %} +<!-- question_edit.html --> +{% block title %}{% spaceless %}{% trans %}Edit question{% endtrans %}{% endspaceless %}{% endblock %} +{% block forestyle %} + <link rel="stylesheet" type="text/css" href="{{"/js/wmd/wmd.css"|media}}" /> +{% endblock %} +{% block content %} +<h1>{% trans %}Edit question{% endtrans %} [<a href="{{ question.get_absolute_url() }}">{% trans %}back{% endtrans %}</a>]</h1> +<form id="fmedit" action="{% url edit_question question.id %}" method="post" >{% csrf_token %} + + {% if revision_form.revision.errors %}{{ revision_form.revision.errors.as_ul() }}{% endif %} + <div style="vertical-align:middle"> + {{ revision_form.revision }} <input type="submit" style="display:none" + id="select_revision" name="select_revision" + value="{% trans %}select revision{% endtrans %}"> + </div> + {{ + macros.edit_post( + form, + post_type='question', + edit_title=True, + mandatory_tags = mandatory_tags + ) + }} + <div class="after-editor"> + <input type="submit" value="{% trans %}Save edit{% endtrans %}" class="submit" /> + <input type="button" value="{% trans %}Cancel{% endtrans %}" class="submit" onclick="history.back(-1);" /> + <div class="question-options"> + {% if settings.WIKI_ON and question.wiki == False %} + {{ macros.checkbox_in_div(form.wiki) }} + {% endif %} + {% if form.can_stay_anonymous() %} + {{ macros.checkbox_in_div(form.reveal_identity) }} + {% endif %} + </div> + </div> +</form> +{% endblock %} + +{% block sidebar %} +{% include "blocks/question_edit_tips.html" %} +{% endblock %} + +{% block endjs %} + {% include "blocks/editor_data.html" %} + <script type='text/javascript' src='{{"/js/editor.js"|media }}'></script> + {% if mandatory_tags %} + {% include "blocks/mandatory_tags_js.html" %} + {% endif %} + <script type='text/javascript' src='{{"/js/jquery.validate.min.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/post.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/wmd/showdown.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/wmd/wmd.js"|media}}'></script> + <script type="text/javascript"> + {% if settings.ENABLE_MATHJAX or settings.MARKUP_CODE_FRIENDLY %} + var codeFriendlyMarkdown = true; + {% else %} + var codeFriendlyMarkdown = false; + {% endif %} + //todo move javascript out + $().ready(function(){ + $("#nav_questions").attr('className',"on"); + $('#editor').TextAreaResizer(); + + //highlight code synctax when editor has new text + $("#editor").typeWatch({highlight: false, wait: 3000, + captureLength: 5, callback: lanai.highlightSyntax}); + + //toggle preview of editor + var display = true; + var txt = "[{% trans %}hide preview{% endtrans %}]"; + $('#pre-collapse').text(txt); + $('#pre-collapse').bind('click', function(){ + txt = display ? "[{% trans %}show preview{% endtrans %}]" : "[{% trans %}hide preview{% endtrans %}]"; + display = !display; + $('#previewer').toggle(); + $('#pre-collapse').text(txt); + }); + + {{ macros.tag_autocomplete_js(id = '#id_tags') }} + + setupFormValidation( + $("#fmedit"), + CPValidator.getQuestionFormRules(), + CPValidator.getQuestionFormMessages() + ); + + $('#id_revision').unbind().change(function(){ + $("#select_revision").click(); + }); + lanai.highlightSyntax(); + + }); + </script> +{% endblock %} +<!-- end question_edit.html --> diff --git a/askbot/skins/old/templates/question_retag.html b/askbot/skins/old/templates/question_retag.html new file mode 100644 index 00000000..883dc3aa --- /dev/null +++ b/askbot/skins/old/templates/question_retag.html @@ -0,0 +1,68 @@ +{% extends "two_column_body.html" %} +<!-- question_retag.html --> +{% block title %}{% spaceless %}{% trans %}Change tags{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans %}Change tags{% endtrans %} [<a href="{{ question.get_absolute_url() }}">{% trans %}back{% endtrans %}</a>]</h1> +<form id="fmretag" action="{% url retag_question question.id %}" method="post" >{% csrf_token %} + <h2> + {{ question.get_question_title() }} + </h2> + <div id="description" class="edit-content-html"> + {{ question.html }} + </div> + <div class="form-item"> + <strong>{{ form.tags.label_tag() }}:</strong> <span class="form-error"></span><br/> + {{ form.tags }} {{ form.tags.errors }} + <div class="title-desc"> + {{ form.tags.help_text }} + </div> + </div> + <div class="error" ></div> + <input type="submit" value="{% trans %}Retag{% endtrans %}" class="submit" /> + <input type="button" value="{% trans %}Cancel{% endtrans %}" class="submit" onclick="history.back(-1);" /> +</form> +{% endblock %} + +{% block sidebar %} +<div class="boxC"> + <h2>{% trans %}Why use and modify tags?{% endtrans %}</h2> + <ul> + <li>{% trans %}Tags help to keep the content better organized and searchable{% endtrans %}</li> + <li> + {% trans %}tag editors receive special awards from the community{% endtrans %} + </li> + </ul> + <p class='info-box-follow-up-links'> + <a href="{% url faq %}">faq »</a> + </p> +</div> +{% endblock %} +{% block endjs %} + <script type='text/javascript' src='{{"/js/editor.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/post.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/jquery.validate.min.js"|media}}'></script> + <script type="text/javascript"> + $().ready(function(){ + $("#nav_questions").attr('className',"on"); + {% import "macros.html" as macros %} + {{ macros.tag_autocomplete_js(id = '#id_tags') }} + $("#fmretag").validate({ + rules: { + tags: { + required: true, + maxength: 105 + } + }, + messages: { + tags: { + required: "{% trans %}tags are required{% endtrans %}", + maxlength: "{% trans %}up to 5 tags, less than 20 characters each{% endtrans %}" + } + } + + }); + lanai.highlightSyntax(); + }); + </script> +{% endblock %} +<!-- end question_retag.html --> diff --git a/askbot/skins/old/templates/reopen.html b/askbot/skins/old/templates/reopen.html new file mode 100644 index 00000000..d68e8bdc --- /dev/null +++ b/askbot/skins/old/templates/reopen.html @@ -0,0 +1,38 @@ +{% extends "two_column_body.html" %} +<!-- reopen.html --> +{% block title %}{% spaceless %}{% trans %}Reopen question{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1>{% trans %}Reopen question{% endtrans %}</h1> +<p>{% trans %}Title{% endtrans %}: + <a href="{{ question.get_absolute_url() }}"> + <span class="big">{{ question.get_question_title() }}</span> + </a> +</p> +<p>{% trans %}This question has been closed by + <a href="{{closed_by_profile_url}}">{{closed_by_username}}</a> +{% endtrans %} +</p> +<p> + {% trans %}Close reason:{% endtrans %} "<strong>{{question.get_close_reason_display()}}</strong>". +</p> +<p> + {% trans %}When:{% endtrans %} {{question.closed_at|diff_date}} +</p> +<p> + {% trans %}Reopen this question?{% endtrans %} +</p> +<form id="fmclose" action="{% url reopen question.id %}" method="post" >{% csrf_token %} + <div id="" style="padding:20px 0 20px 0"> + <input type="submit" value="{% trans %}Reopen this question{% endtrans %}" class="submit" /> + <input id="btBack" type="button" value="{% trans %}Cancel{% endtrans %}" class="submit" /> + </div> +</form> +{% endblock %} +{% block endjs %} + <script type="text/javascript"> + $().ready(function(){ + $('#btBack').bind('click', function(){ history.back(); }); + }); + </script> +{% endblock %} +<!-- end reopen.html --> diff --git a/askbot/skins/old/templates/revisions.html b/askbot/skins/old/templates/revisions.html new file mode 100644 index 00000000..0c10e6d4 --- /dev/null +++ b/askbot/skins/old/templates/revisions.html @@ -0,0 +1,97 @@ +{% extends "two_column_body.html" %} +{% import "macros.html" as macros %} +<!-- revisions.html --> +{% block title %}{% spaceless %}{% trans %}Revision history{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1> + {% trans %}Revision history{% endtrans %} [<a href="{{ post.get_absolute_url() }}">{% trans %}back{% endtrans %}</a>] +</h1> +<div id="revisions"> +{% for revision in revisions %} + <div class="revision"> + <div + id="rev-header-{{ revision.revision }}" + class="header {% if post.author_id == revision.author_id %}author{% endif %}" + > + <div class="header-controls"> + <table width="100%"> + <tr> + <td width="20" style="vertical-align:middle"> + <img + id="rev-arrow-{{ revision.revision }}" + src="{{"/images/expander-arrow-show.gif"|media}}" + alt="{% trans %}click to hide/show revision{% endtrans %}" + /> + </td> + <td width="30px" style="vertical-align:middle"> + <span + class="revision-number" + title="{% trans number=revision.revision %}revision {{number}}{% endtrans %}">{{ revision.revision }}</span></td> + <td width="200px" style="vertical-align:middle"> + {% if revision.summary %} + <div class="summary"> + <span>{{ revision.summary }}</span> + </div> + {% endif %} + {% if request.user|can_edit_post(post) %} + <a href="{% url edit_answer post.id %}?revision={{ revision.revision }}">{% trans %}edit{% endtrans %}</a> + {% endif %} + </td> + <td align="right"> + <div class="revision-mark" > + {% if revision.revision == 1 %} + {% set contributor_type = "original_author" %} + {% else %} + {% set contributor_type = "last_updater" %} + {% endif %} + {{ macros.post_contributor_info( + revision, + contributor_type, + False, + 0 + ) + }} + </div> + </td> + </tr> + </table> + </div> + </div> + <div id="rev-body-{{ revision.revision }}" class="answerbody"> + {{ revision.diff }} + </div> + </div> +{% endfor %} +</div> +{% endblock %} + +{% block endjs %} + <script type='text/javascript' src='{{"/js/editor.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/post.js"|media}}'></script> + <script type="text/javascript"> + //todo - take this out into .js file + $(document).ready(function(){ + $("#nav_questions").attr('className',"on"); + $('div.revision div[id^=rev-header-]').bind('click', function(){ + var revId = this.id.substr(11); + toggleRev(revId); + + }); + lanai.highlightSyntax(); + }); + + function toggleRev(id) { + var arrow = $("#rev-arrow-" + id); + var visible = arrow.attr("src").indexOf("hide") > -1; + var path = mediaUrl( + "media/images/expander-arrow-" + + (visible ? "show" : "hide") + + ".gif" + + "?v={{settings.MEDIA_RESOURCE_REVISION}}" + ); + arrow.attr("src", path); + $("#rev-body-" + id).slideToggle("fast"); + } +</script> +{% endblock %} +<!-- end revisions.html --> diff --git a/askbot/skins/old/templates/subscribe_for_tags.html b/askbot/skins/old/templates/subscribe_for_tags.html new file mode 100644 index 00000000..b436fb84 --- /dev/null +++ b/askbot/skins/old/templates/subscribe_for_tags.html @@ -0,0 +1,19 @@ +{% extends "two_column_body.html" %} +{% import "macros.html" as macros %} +{% block title %}{% trans %}Subscribe for tags{% endtrans %}{% endblock %} +{% block content %} +<h1>{% trans %}Subscribe for tags{% endtrans %}</h1> +<p>{% trans %}Please, subscribe for the following tags:{% endtrans %}</p> +<ul class="tags" style="margin-left: 4px"> + {% for tag in tags %} + {{ macros.tag_widget(tag, html_tag = 'li', is_link = False) }} + {% endfor %} +</ul> +<div style="clear:both;padding-top: 5px"> + <form method="post" action="{% url subscribe_for_tags %}">{% csrf_token %} + <input type="hidden" name="tags" value="{{tags|join(' ')|escape}}" /> + <input type="submit" name="ok" value="{% trans %}Subscribe{% endtrans %}" /> + <input type="submit" name="nope" value="{% trans %}Cancel{% endtrans %}" /> + </form> +</div> +{% endblock %} diff --git a/askbot/skins/old/templates/tags.html b/askbot/skins/old/templates/tags.html new file mode 100644 index 00000000..7d9026af --- /dev/null +++ b/askbot/skins/old/templates/tags.html @@ -0,0 +1,75 @@ +{% extends "two_column_body.html" %} +{% import "macros.html" as macros %} +<!-- tags.html --> +{% block title %}{% spaceless %}{% trans %}Tag list{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<!-- Tabs --> +<div class="tabBar"> + {% if stag %} + <h1>{% trans %}Tags, matching "{{ stag }}"{% endtrans %}</h1> + {% else %} + <h1>{% trans %}Tag list{% endtrans %}</h1> + {% endif %} + + <div class="tabsA"> + <a + id="sort_name" + href="{% url tags %}?sort=name" + {% if tab_id == 'name' %}class="on"{% endif %} + title="{% trans %}sorted alphabetically{% endtrans %}" + ><span>{% trans %}by name{% endtrans %}</span></a> + <a + id="sort_used" + href="{% url tags %}?sort=used" + {% if tab_id == 'used' %}class="on"{% endif %} + title="{% trans %}sorted by frequency of tag use{% endtrans %}" + ><span>{% trans %}by popularity{% endtrans %}</span></a> + </div> +</div> +{% if tag_list_type == 'list' %} + {% if not tags.object_list %} + <span>{% trans %}Nothing found{% endtrans %}</span> + {% endif %} + {% if tags.object_list %} + <div class='clearfix'></div> + <ul class='tags'> + {% for tag in tags.object_list %} + <li> + {{ macros.tag_widget( + tag = tag.name, + url_params = 'start_over=true', + html_tag = 'div', + extra_content = '<span class="tag-number">× ' ~ + tag.used_count|intcomma ~ '</span>' + ) + }} + </li> + {% endfor %} + </ul> + <div class="pager"> + {{macros.paginator(paginator_context)}} + </div> + {% endif %} +{% else %} + <div class="clearfix"></div> + {% if not tags %} + <span>{% trans %}Nothing found{% endtrans %}</span> + {% endif %} + {{ macros.tag_cloud(tags = tags, font_sizes = font_size) }} +{% endif %} + +{% endblock %} +{% block endjs %} + <script type="text/javascript"> + /*<![CDATA[*/ + $().ready(function(){ + $("#ipSearchTag").focus(); + $("#type-tag").attr('checked',true); + Hilite.exact = false; + Hilite.elementid = "searchtags"; + Hilite.debug_referrer = location.href; + }); + /*]]>*/ + </script> +{% endblock %} +<!-- end tags.html --> diff --git a/askbot/skins/old/templates/two_column_body.html b/askbot/skins/old/templates/two_column_body.html new file mode 100644 index 00000000..a284744e --- /dev/null +++ b/askbot/skins/old/templates/two_column_body.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} +{% block body_class %}two-col{% endblock %} +{% block body %} +<div id="CALeft"> + {% include "blocks/input_bar.html" %} + {% block content%} + {% endblock%} +</div> +<div id="CARight"> + {% block sidebar%} + {% endblock%} +</div> +{% endblock %} diff --git a/askbot/skins/old/templates/user_profile/user.html b/askbot/skins/old/templates/user_profile/user.html new file mode 100644 index 00000000..ad3d564b --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user.html @@ -0,0 +1,42 @@ +{% extends "two_column_body.html" %} +<!-- user.html --> +{% block title %}{% spaceless %}{{ page_title }}{% endspaceless %}{% endblock %} +{% block forestyle%} +<style type="text/css"> + .history-table td { padding: 5px; } +</style> +{% endblock %} +{% block content %} + <h1> + {% spaceless %} + <a href="{% url user_profile view_user.id, view_user.username|slugify %}"> + {% trans username=view_user.username %}{{username}}'s profile{% endtrans %} - {% block profilesection %}{% endblock %} + </a> + {% endspaceless %} + </h1> + <div style="margin-left: 5px;"> + {% include "user_profile/user_tabs.html" %} + {% block usercontent %} + {% endblock %} + </div> +{% endblock %}<!-- end user.html --> +{% block endjs %} + <script type="text/javascript"> + var viewUserID = {{view_user.id}}; + askbot['data']['viewUserName'] = '{{ view_user.username }}'; + </script> + {% if request.user|can_moderate_user(view_user) %} + <script type='text/javascript' src='{{"/js/jquery.form.js"|media}}'></script> + {% endif %} + <script type="text/javascript" src='{{"/js/user.js"|media}}'></script> + {% block userjs %} + {% endblock %} +{% endblock %} +{% block sidebar %} + +{{ settings.SIDEBAR_PROFILE_HEADER }} + +{{ settings.SIDEBAR_PROFILE_FOOTER }} + +{% endblock %} +<!-- end of user.html --> diff --git a/askbot/skins/old/templates/user_profile/user_edit.html b/askbot/skins/old/templates/user_profile/user_edit.html new file mode 100644 index 00000000..1e2fa2d6 --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_edit.html @@ -0,0 +1,100 @@ +{% extends "one_column_body.html" %} +{% import "macros.html" as macros %} +<!-- user_edit.html --> +{% block title %}{% spaceless %}{% trans %}Edit user profile{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<h1> + {{ request.user.username }} - {% trans %}edit profile{% endtrans %} +</h1> +<div id="main-body" style="width:100%;padding-top:10px"> + <form name="" action="{% url edit_user request.user.id %}" method="post">{% csrf_token %} + <div id="left" style="float:left;width:180px"> + {% if request.user.email %} + {{ macros.gravatar(request.user, 128) }} + {% else %} + <img src="{{"/images/nophoto.png"|media}}"> + {% endif %} + <h1><a href="{% url faq %}#gravatar">{% trans %}change picture{% endtrans %}</a><h1> + </div> + <div style="float:right;width:750px;text-align:left;"> + <h2>{% trans %}Registered user{% endtrans %}</h2> + <table class="user-details"> + <tr> + <th width="100px"></th> + <th></th> + </tr> + <tr> + <td>{% trans %}Screen Name{% endtrans %}:</td> + <td> + {% if settings.EDITABLE_SCREEN_NAME %} + {{ form.username }} + <span class="form-error"></span> {{ form.username.errors }} </td> + {% else %} + {{ request.user.username }} + {% endif %} + </td> + </tr> + <tr> + <td>{{ form.email.label_tag() }}:</td> + <td>{{ form.email }} <span class="form-error"></span> {{ form.email.errors }} </td> + </tr> + <tr> + <td></td> + <td class="title-desc">{{ form.email.help_text }}</td> + </tr> + <tr> + <td>{{ form.realname.label_tag() }}:</td> + <td>{{ form.realname }} <span class="form-error"></span> {{ form.realname.errors }} </td> + </tr> + <tr> + <td>{{ form.website.label_tag() }}:</td> + <td>{{ form.website }} <span class="form-error"></span> {{ form.website.errors }} </td> + </tr> + <tr> + <td>{{ form.city.label_tag() }}:</td> + <td>{{ form.city }} <span class="form-error"></span> {{ form.city.errors }} </td> + </tr> + <tr> + <td>{{ form.country.label_tag() }}:</td> + <td>{{ form.country }} <span class="form-error"></span> {{ form.country.errors }} </td> + </tr> + <tr> + <td>{{ form.show_country.label_tag() }}:</td> + <td>{{ form.show_country }} <span class="form-error"></span> {{ form.show_country.errors }} </td> + </tr> + <tr> + <td>{{ form.birthday.label_tag() }}:</td> + <td>{{ form.birthday }} <span class="form-error"></span> {{ form.birthday.errors }} </td> + </tr> + <tr> + <td></td> + <td class="title-desc">{{ form.birthday.help_text }}</td> + </tr> + <tr style="height:10px"> + <td colspan="2"> + </td> + </tr> + <tr> + <td style="vertical-align:top">{{ form.about.label_tag() }}:</td> + <td>{{ form.about }} <span class="form-error"></span> {{ form.about.errors }} </td> + </tr> + </table> + <div style="margin:30px 0 60px 0"> + <input type="submit" value="{% trans %}Update{% endtrans %}" class="submit" > + <input id="cancel" type="button" value="{% trans %}Cancel{% endtrans %}" class="submit" > + </div> + </div> + </form> +</div> +{% endblock %} +{% block endjs %} + <script type="text/javascript"> + $().ready(function(){ + $("#nav_profile").attr('className',"on"); + $("#cancel").bind('click', function(){history.go(-1);}) + }); + </script> + {% block userjs %} + {% endblock %} +{% endblock %} +<!-- end user_edit.html --> diff --git a/askbot/skins/old/templates/user_profile/user_email_subscriptions.html b/askbot/skins/old/templates/user_profile/user_email_subscriptions.html new file mode 100644 index 00000000..e6a18dd3 --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_email_subscriptions.html @@ -0,0 +1,27 @@ +{% extends "user_profile/user.html" %} +<!-- user_email_subscriptions.html --> +{% block profilesection %} + {% trans %}subscriptions{% endtrans %} +{% endblock %} +{% block usercontent %} + <h2>{% trans %}Email subscription settings{% endtrans %}</h2> + <p class="message">{% trans %}email subscription settings info{% endtrans %}</p> + <div> + {% if action_status %} + <p class="action-status"><span>{{action_status}}</span></p> + {% endif %} + <form method="post" action="">{% csrf_token %} + <table class='form-as-table ab-subscr-form'> + {{email_feeds_form.as_table()}} + </table> + <table class='form-as-table ab-tag-filter-form'> + {{tag_filter_selection_form}} + </table> + <div class="submit-row text-align-right"> + <input type="submit" class="submit" name="save" value="{% trans %}Update{% endtrans %}"/> + <input type="submit" class="submit" name="stop_email" value="{% trans %}Stop sending email{% endtrans %}"/> + </div> + </form> + </div> +{% endblock %} +<!-- end user_email_subscriptions.html --> diff --git a/askbot/skins/old/templates/user_profile/user_favorites.html b/askbot/skins/old/templates/user_profile/user_favorites.html new file mode 100644 index 00000000..bb019c90 --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_favorites.html @@ -0,0 +1,9 @@ +{% extends "user_profile/user.html" %} +<!-- user_favorites.html --> +{% block profilesection %} + {% trans %}followed questions{% endtrans %} +{% endblock %} +{% block usercontent %} +{% include "user_profile/users_questions.html" %} +{% endblock %} +<!-- end user_favorites.html --> diff --git a/askbot/skins/old/templates/user_profile/user_inbox.html b/askbot/skins/old/templates/user_profile/user_inbox.html new file mode 100644 index 00000000..e7e3dbfe --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_inbox.html @@ -0,0 +1,106 @@ +{% extends "user_profile/user.html" %} +{% import "macros.html" as macros %} +<!-- user_responses.html --> +{# +This template accepts a list of response list +they are a generalized form of any response and + +The following properties of response object are used: +timestamp - when it happened +user - user who gave response (database object) +response_type - type of response +response_url - link to the question +response_title - title of the question +response_snippet - abbreviated content of the response +inbox_section - forum|flags +#} +{% block profilesection %} + {% trans %}inbox{% endtrans %} +{% endblock %} +{% block usercontent %} + <div style="padding-top:5px;font-size:13px;"> + {% set re_count = request.user.new_response_count + + request.user.seen_response_count + %} + {% if moderation_items %} + {% set flag_count = moderation_items['new_count'] + + moderation_items['seen_count'] + %} + {% else %} + {% set flag_count = 0 %} + {% endif %} + {% if re_count > 0 and flag_count > 0 %} + <div id="re_sections"> + {% trans %}Sections:{% endtrans %} + <a href="{{request.user.get_absolute_url()}}?sort=inbox§ion=forum" + {% if inbox_section == 'forum' %}class="on"{% endif %} + > + {% trans %}forum responses ({{re_count}}){% endtrans -%} + </a> | + <a href="{{request.user.get_absolute_url()}}?sort=inbox§ion=flags" + {% if inbox_section == 'flags' %}class="on"{% endif %} + > + {% trans %}flagged items ({{flag_count}}){% endtrans %} + </a> + </div> + {% endif %} + {% if inbox_section == 'forum' %} + <div id="re_tools"> + <strong>{% trans %}select:{% endtrans %}</strong> + <a id="sel_all">{% trans %}all{% endtrans %}</a> | + <a id="sel_seen">{% trans %}seen{% endtrans %}</a> | + <a id="sel_new">{% trans %}new{% endtrans %}</a> | + <a id="sel_none">{% trans %}none{% endtrans %}</a><br /> + <button id="re_mark_seen">{% trans %}mark as seen{% endtrans %}</button> + <button id="re_mark_new">{% trans %}mark as new{% endtrans %}</button> + <button id="re_dismiss">{% trans %}dismiss{% endtrans %}</button> + </div> + {% endif %} + <div id="responses"> + {% for response in responses %} + <div class="response-parent"> + <p class="headline"> + <strong>"{{ response.response_title.strip()|escape}}"</strong> + </p> + <div id="re_{{response.id}}" class="re{% if response.is_new %} new highlight{% else %} seen{% endif %}"> + {% if inbox_section == 'forum' %}<input type="checkbox" />{% endif %} + <div class="face"> + {{ macros.gravatar(response.user, 48) }} + </div> + <a style="font-size:12px" href="{{ response.user.get_absolute_url() }}">{{ response.user.username }}</a> + <a style="text-decoration:none;" href="{{ response.response_url }}"> + {{ response.response_type }} + ({{ response.timestamp|diff_date(True) }}):<br/> + {{ response.response_snippet}} + </a> + </div> + {% if response.nested_responses %} + {%for nested_response in response.nested_responses %} + <div id="re_{{nested_response.id}}" class="re{% if nested_response.is_new %} new highlight{% else %} seen{% endif %}"> + {% if inbox_section == 'forum' %}<input type="checkbox" />{% endif %} + <div class="face"> + {{ macros.gravatar(nested_response.user, 48) }} + </div> + <a style="font-size:12px" href="{{ nested_response.user.get_absolute_url() }}">{{ nested_response.user.username }}</a> + <a style="text-decoration:none;" href="{{ nested_response.response_url }}"> + {{ nested_response.response_type }} + ({{ nested_response.timestamp|diff_date(True) }}):<br/> + {{ nested_response.response_snippet}} + </a> + </div> + {%endfor%} + {%endif%} + </div> + {% endfor %} + </div> + </div> +{% endblock %} +{% block userjs %} + <script type="text/javascript" src="{{'/js/user.js'|media}}"></script> + <script type="text/javascript"> + var askbot = askbot || {}; + askbot['urls'] = askbot['urls'] || {}; + askbot['urls']['manageInbox'] = '{% url manage_inbox %}'; + </script> +<!-- end user_responses.html --> +{% endblock %} diff --git a/askbot/skins/old/templates/user_profile/user_info.html b/askbot/skins/old/templates/user_profile/user_info.html new file mode 100644 index 00000000..36b782e5 --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_info.html @@ -0,0 +1,107 @@ +<!-- user_info.html --> +{% import "macros.html" as macros %} +<table class="user-info-table"> + <tr> + <td style="vertical-align:top;text-align:center;"> + <div class='avatar'> + {{ macros.gravatar(view_user, 128) }} + {% if request.user == view_user %} + <p><a + {% if support_custom_avatars %} + href="{% url avatar_change %}" + {% else %} + href="{% url faq %}#gravatar" + {% endif %} + >{% trans %}change picture{% endtrans %}</a></p> + {% if support_custom_avatars %} + <p><a + href="{% url avatar_delete %}" + >{% trans %}remove{% endtrans %}</a> + </p> + {% endif %} + {% endif %} + </div> + <div class="scoreNumber">{{view_user.reputation|intcomma}}</div> + <p><b style="color:#777;">{% trans %}reputation{% endtrans %}</b></p> + {% if user_follow_feature_on %} + {{ macros.follow_user_toggle(visitor = request.user, subject = view_user) }} + {% endif %} + </td> + <td width="360" style="padding-left:5px;vertical-align: top;"> + <table class="user-details"> + {% if request.user == view_user %} + <tr> + <td class="user-profile-tool-links" align="left" colspan="2"> + <a href="{% url edit_user view_user.id %}"> + {% trans %}update profile{% endtrans %} + </a> + {% if request.user == view_user and settings.ALLOW_ADD_REMOVE_LOGIN_METHODS %} + | <a href="{{ settings.LOGIN_URL }}?next={{ settings.LOGIN_URL }}"> + {% trans %}manage login methods{% endtrans %} + </a> + {% endif %} + </td> + </tr> + {% endif %} + <tr> + <th colspan="2" align="left"> + <h3>{{user_status_for_display}}</h3> + </th> + </tr> + {% if view_user.real_name %} + <tr> + <td>{% trans %}real name{% endtrans %}</td> + <td><b>{{view_user.real_name}}</b></td> + </tr> + {% endif %} + <tr> + <td>{% trans %}member for{% endtrans %}</td> + <td><strong>{{ view_user.date_joined|diff_date }}</strong></td> + </tr> + {% if view_user.last_seen %} + <tr> + <td>{% trans %}last seen{% endtrans %}</td> + <td><strong title="{{ view_user.last_seen }}">{{view_user.last_seen|diff_date}}</strong></td> + </tr> + {% endif %} + {% if view_user.website %} + <tr> + <td>{% trans %}user website{% endtrans %}</td> + <td>{{ macros.user_website_link(view_user, max_display_length = 30) }}</td> + </tr> + {% endif %} + {% if view_user.location or view_user.country %} + <tr> + <td>{% trans %}location{% endtrans %}</td> + <td>{{ macros.user_full_location(view_user) }}</td> + </tr> + {% endif %} + {% if view_user.date_of_birth%} + <tr> + <!--todo - redo this with whole sentence translation --> + <td>{% trans %}age{% endtrans %}</td> + <td>{{view_user.date_of_birth|get_age}} {% trans %}age unit{% endtrans %}</td> + </tr> + {% endif %} + {# + <!-- + {% if votes_today_left %} + <tr> + <td>{% trans "todays unused votes" %}</td> + <td><strong class="darkred">{{ votes_today_left }}</strong> {% trans "votes left" %}</td> + </tr> + {% endif %} + --> + #} + </table> + </td> + <td width="380"> + <div class="user-about"> + {% if view_user.about %} + {{view_user.about|linebreaks}} + {% endif %} + </div> + </td> + </tr> +</table> +<!-- end user_info.html --> diff --git a/askbot/skins/old/templates/user_profile/user_moderate.html b/askbot/skins/old/templates/user_profile/user_moderate.html new file mode 100644 index 00000000..b2f350df --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_moderate.html @@ -0,0 +1,94 @@ +{% extends "user_profile/user.html" %} +<!-- user_moderate.html --> +{% block profilesection %} + {% trans %}moderation{% endtrans %} +{% endblock %} +{% block usercontent %} +{% if request.user != view_user %} + <h3>{% trans username=view_user.username, status=view_user.get_status_display() %}{{username}}'s current status is "{{status}}"{% endtrans %} + </h3> + {% if user_status_changed %} + <p class="action-status"><span>{% trans %}User status changed{% endtrans %}</span></p> + {% endif %} + <form method="post">{% csrf_token %} + <input type="hidden" name="sort" value="moderate"/> + <table class="form-as-table"> + {{ change_user_status_form.as_table() }} + </table> + <p id="id_user_status_info"> + </p> + <input type="submit" class="submit" name="change_status" value="{% trans %}Save{% endtrans %}" /> + </form> +{% endif %} +<hr/> +<h3> +{% if request.user == view_user %} + {% trans reputation=view_user.reputation %}Your current reputation is {{reputation}} points{% endtrans %} +{% else %} + {% trans reputation=view_user.reputation %}User's current reputation is {{reputation}} points{% endtrans %} +{% endif %} +</h3> +{% if user_rep_changed %} + <p class="action-status"><span>{% trans %}User reputation changed{% endtrans %}</span></p> +{% endif %} +<form method="post">{% csrf_token %} + <input type="hidden" name="sort" value="moderate"/> + <table class="form-as-table"> + {{ change_user_reputation_form.as_table() }} + </table> + <input type="submit" class="submit" name="subtract_reputation" value="{% trans %}Subtract{% endtrans %}" /> + <input type="submit" class="submit" name="add_reputation" value="{% trans %}Add{% endtrans %}" /> +</form> +{% if request.user != view_user %} +<hr/> +<h3>{% trans username=view_user.username %}Send message to {{username}}{% endtrans %}</h3> +<p>{% trans %}An email will be sent to the user with 'reply-to' field set to your email address. Please make sure that your address is entered correctly.{% endtrans %}</p> + {% if message_sent %} + <p class="action-status"><span>{% trans %}Message sent{% endtrans %}</span></p> + {% endif %} +<form method="post">{% csrf_token %} + <input type="hidden" name="sort" value="moderate"/> + <div class="form-row-vertical"> + <label for="id_subject_line">{{ send_message_form.subject_line.label}}</label> + {% if send_message_form.subject_line.errors %} + <p class="error">{{send_message_form.subject_line.errors|join(', ')}}</p> + {% endif %} + {{ send_message_form.subject_line}} + </div> + <div class="form-row-vertical"> + <label for="id_body_text">{{ send_message_form.body_text.label}}</label> + {% if send_message_form.body_text.errors %} + <p class="error">{{send_message_form.body_text.errors|join(', ')}}</p> + {% endif %} + {{ send_message_form.body_text}} + </div> + <input type="submit" class="submit" name="send_message" value="{% trans %}Send message{% endtrans %}" /> +</form> +{% endif %} +{% endblock %} +{% block endjs %} + <script type="text/javascript" > + $("#id_user_status_info").hide(); + $("#id_user_status").change(function () { + var optionValue = $(this).attr('value'); + if (optionValue == "d") { + $('#id_user_status_info').html("{% trans %}Administrators have privileges of normal users, but in addition they can assign/revoke any status to any user, and are exempt from the reputation limits.{% endtrans %}"); + $('#id_user_status_info').show('slow'); + } else if (optionValue == "m"){ + $('#id_user_status_info').html("{% trans %}Moderators have the same privileges as administrators, but cannot add or remove user status of 'moderator' or 'administrator'.{% endtrans %}"); + $('#id_user_status_info').show('slow'); + } else if (optionValue == "a"){ + $('#id_user_status_info').html("{% trans %}'Approved' status means the same as regular user.{% endtrans %}"); + $('#id_user_status_info').show('slow'); + } else if (optionValue == "s"){ + $('#id_user_status_info').html("{% trans %}Suspended users can only edit or delete their own posts.{% endtrans %}"); + $('#id_user_status_info').show('slow'); + } else if (optionValue == "b"){ + $('#id_user_status_info').html("{% trans %}Blocked users can only login and send feedback to the site administrators.{% endtrans %}"); + $('#id_user_status_info').show('slow'); + } else { + $('#id_user_status_info').hide('slow'); + } + }) + </script> +{% endblock %} diff --git a/askbot/skins/old/templates/user_profile/user_network.html b/askbot/skins/old/templates/user_profile/user_network.html new file mode 100644 index 00000000..1fd2e06a --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_network.html @@ -0,0 +1,25 @@ +{% extends "user_profile/user.html" %} +{% import "macros.html" as macros %} +<!-- user_network.html --> +{% block profileseciton %} + {% trans %}network{% endtrans %} +{% endblock %} +{% block usercontent %} + {% if followed_users or followers %} + {% if followers %} + <h2>{% trans count=followers|length %}Followed by {{count}} person{% pluralize count %}Followed by {{count}} people{% endtrans %}</h2> + {{ macros.user_list(followers, profile_section = 'network') }} + {% endif %} + {% if followed_users %} + <h2>{% trans count=followed_users|length %}Following {{count}} person{% pluralize count %}Following {{count}} people{% endtrans %}</h2> + {{ macros.user_list(followed_users, profile_section = 'network') }} + {% endif %} + {% else %} + {% if request.user == view_user %} + <p>{% trans %}Your network is empty. Would you like to follow someone? - Just visit their profiles and click "follow"{% endtrans %}</p> + {% else %} + <p>{% trans username = view_user.username %}{{username}}'s network is empty{% endtrans %}</p> + {% endif %} + {% endif %} +{% endblock %} +<!-- end user_network.html --> diff --git a/askbot/skins/old/templates/user_profile/user_recent.html b/askbot/skins/old/templates/user_profile/user_recent.html new file mode 100644 index 00000000..cbd59202 --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_recent.html @@ -0,0 +1,42 @@ +{% extends "user_profile/user.html" %} +<!-- user_recent.html --> +{% block profilesection %} + {% trans %}activity{% endtrans %} +{% endblock %} +{% block usercontent %} + <div style="padding-top:5px;font-size:13px;"> + {% for act in activities %} + <div style="clear:both;line-height:20px" > + <div style="width:180px;float:left">{{ act.time|diff_date(True) }}</div> + <div style="width:150px;float:left"> + <span class="user-action-{{ act.type_id }}">{{ act.type }}</span> + </div> + <div style="float:left;overflow:hidden;"> + {% if act.is_badge %} + <a href="{{act.badge.get_absolute_url()}}" title="{{ act.badge.get_type_display() }} : {% trans description=act.badge.description %}{{description}}{% endtrans %}" class="medal"><span class="{{ act.badge.css_class }}">●</span> {% trans name=act.badge.name %}{{name}}{% endtrans %}</a> + {% if act.related_object_type == 'question' %}{# question #} + {% for question in questions %}{# could also create a new dict #} + {% if question.question_id == act.obj %} + (<a title="{{question.summary|collapse}}" + href="{% url question question.question_id %}{{question.title|slugify}}">{% trans %}source{% endtrans %}</a>) + {% endif %} + {% endfor %} + {% elif act.related_object_type == 'answer' %}{# answer #} + {% for answer in answers %}{# could also create a new dict #} + {% if answer.answer_id == act.obj %} + (<a title="{{answer.text|collapse}}" + href="{% url question answer.question_id %}{{answer.question_title|slugify}}#{{answer.answer_id}}">{% trans %}source{% endtrans %}</a>) + {% endif %} + {% endfor %} + {% endif %} + {% else %} + <span class="post-type-{{ act.type_id }}"><a href="{{ act.title_link }}">{{ act.title|escape }}</a></span> + {% if act.summary %}<span class="revision-summary">{{ act.summary|escape }}</span>{% endif %} + {% endif %} + <div style="height:5px"></div> + </div> + </div> + {% endfor %} + </div> +{% endblock %} +<!-- end user_recent.html --> diff --git a/askbot/skins/old/templates/user_profile/user_reputation.html b/askbot/skins/old/templates/user_profile/user_reputation.html new file mode 100644 index 00000000..99b304d2 --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_reputation.html @@ -0,0 +1,40 @@ +{% extends "user_profile/user.html" %} +<!-- user_reputation.html --> +{% block profilesection %} + {% trans %}karma{% endtrans %} +{% endblock %} +{% block usercontent %} + <div class="karma-summary"> + <div id="diagram" class="karma-diagram"></div> + <div class="karma-details"> + {% if view_user.id == user.id %} + <h3>{% trans %}Your karma change log.{% endtrans %}</h3> + {% else %} + <h3>{% trans user_name=view_user.username %}{{user_name}}'s karma change log{% endtrans %}</h3> + {% endif %} + {% for rep in reputation %} + <p> + <span class="karma-gained">{{ rep.positive }}</span> + <span class="karma-lost">{{ rep.negative }}</span> + {{ rep.get_explanation_snippet() }} + <span class="small">({{rep.reputed_at|diff_date}})</span> + </p> + {% endfor %} + </div> + </div> +{% endblock %} +{% block userjs %} + <script type='text/javascript' src='{{"/js/excanvas.min.js"|media}}'></script> + <script type='text/javascript' src='{{"/js/jquery.flot.min.js"|media}}'></script> + <script type="text/javascript"> + $().ready(function(){ + var d = {{ reps }}; + var placeholder = $("#diagram"); + var plot = $.plot(placeholder, [d], { + xaxis: { mode: "time" }, + points: { show: true }, + lines: { show: true } + }); + }); + </script> +{% endblock %}<!-- end user_reputation.html --> diff --git a/askbot/skins/old/templates/user_profile/user_stats.html b/askbot/skins/old/templates/user_profile/user_stats.html new file mode 100644 index 00000000..d9002d30 --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_stats.html @@ -0,0 +1,159 @@ +{% extends "user_profile/user.html" %} +{% import "macros.html" as macros %} +<!-- user_stats.html --> +{% block profilesection %} + {% trans %}overview{% endtrans %} +{% endblock %} + {% block usercontent %} + {% include "user_profile/user_info.html" %} + <a name="questions"></a> + {% spaceless %} + <h2>{% trans counter=questions|length %}<span class="count">{{counter}}</span> Question{% pluralize %}<span class="count">{{counter}}</span> Questions{% endtrans %}</h2> + {% endspaceless %} + {% include "user_profile/users_questions.html" %} + <a name="answers"></a> + {% spaceless %} + <h2 style="clear:both;">{% trans counter=answered_questions|length %}<span class="count">{{counter}}</span> Answer{% pluralize %}<span class="count">{{counter}}</span> Answers{% endtrans %}</h2> + {% endspaceless %} + <div class="user-stats-table"> + {% for answered_question in answered_questions %} + <div class="answer-summary"> + <a title="{{answered_question.summary|collapse}}" + href="{% url question answered_question.id %}{{answered_question.title|slugify}}#{{answered_question.answer_id}}"> + <span class="answer-votes {% if answered_question.accepted %}answered-accepted{% endif %}" + title="{% trans answer_score=answered_question.answer_score %}the answer has been voted for {{ answer_score }} times{% endtrans %} {% if answered_question.accepted %}{% trans %}this answer has been selected as correct{% endtrans %}{%endif%}"> + {{ answered_question.answer_score }} + </span> + </a> + <div class="answer-link"> + {% spaceless %} + <a href="{% url question answered_question.id %}{{answered_question.title|slugify}}#{{answered_question.answer_id}}">{{answered_question.title}}</a> + {% endspaceless %} + {% if answered_question.comment_count %} + <span> + {% trans comment_count=answered_question.comment_count %}({{comment_count}} comment){% pluralize %}the answer has been commented {{comment_count}} times{% endtrans %} + </span> + {% endif %} + </div> + </div> + {% endfor %} + </div> + <br/> + <a name="votes"></a> + {% spaceless %} + <h2>{% trans cnt=total_votes %}<span class="count">{{cnt}}</span> Vote{% pluralize %}<span class="count">{{cnt}}</span> Votes {% endtrans %}</h2> + {% endspaceless %} + <div class="user-stats-table"> + <table> + <tr> + <td width="60"> + <img style="cursor: default;" src="{{"/images/vote-arrow-up-on.png"|media}}" alt="{% trans %}thumb up{% endtrans %}" /> + <span title="{% trans %}user has voted up this many times{% endtrans %}" class="vote-count">{{up_votes}}</span> + </td> + <td width="60"> + <img style="cursor: default;" src="{{"/images/vote-arrow-down-on.png"|media}}" alt="{% trans %}thumb down{% endtrans %}" /> + <span title="{% trans %}user voted down this many times{% endtrans %}" class="vote-count">{{down_votes}}</span> + + </td> + </tr> + </table> + </div> + <a name="tags"></a> + {% spaceless %} + <h2>{% trans counter=user_tags|length %}<span class="count">{{counter}}</span> Tag{% pluralize %}<span class="count">{{counter}}</span> Tags{% endtrans %}</h2> + {% endspaceless %} + <div class="user-stats-table"> + <table class="tags"> + <tr> + <td valign="top"> + <ul id="ab-user-tags" class="tags"> + {% for tag in user_tags %} + <li> + {{ macros.tag_widget( + tag.name, + html_tag = 'div', + url_params = + "author=" ~ view_user.id ~ + "&start_over=true", + extra_content = + '<span class="tag-number">× ' ~ + tag.user_tag_usage_count|intcomma ~ + '</span>' + ) + }} + </li> + {# + {% if loop.index is divisibleby 10 %} + </td> + <td width="180" valign="top"> + {% endif %} + #} + {% endfor %} + </ul> + </td> + </tr> + </table> + </div> + <a name="badges"></a> + {% spaceless %} + <h2>{% trans counter=total_awards %}<span class="count">{{counter}}</span> Badge{% pluralize %}<span class="count">{{counter}}</span> Badges{% endtrans %}</h2> + {% endspaceless %} + <div class="user-stats-table badges"> + <table> + <tr> + <td style="line-height:35px"> + {% for badge in badges %}{# todo: translate badge name properly #} + <a + href="{{badge.get_absolute_url()}}" + title="{% trans description=badge.description %}{{description}}{% endtrans %}" + class="medal" + ><span class="{{ badge.css_class }}">●</span> {% trans name=badge.name %}{{name}}{% endtrans %} + </a> + <span class="tag-number">× + <span class="badge-context-toggle">{{ badge.award_badge.count()|intcomma }}</span> + </span> + <ul id="badge-context-{{ badge.id }}" class="badge-context-list" style="display:none"> + {% for award in badge.award_badge.filter(user = view_user) %} + {% if award.content_type in (question_type, answer_type) %} + <li> + <a + title="{{ award.content_object.get_snippet()|collapse }}" + href="{{ award.content_object.get_absolute_url() }}" + >{% if award.content_type == answer_type %}{% trans %}Answer to:{% endtrans %}{% endif %} {{ award.content_object.get_origin_post().title }}</a> + </li> + {% endif %} + {% endfor %} + </ul> + {% if loop.index is divisibleby 3 %} + </td></tr> + <tr><td style="line-height:35px"> + {% endif %} + {% endfor %} + </td> + </tr> + </table> + </div> +{% endblock %} +{% block endjs %} + {{ super() }} + <script type="text/javascript"> + $(document).ready(function(){ + $('.badge-context-toggle').each(function(idx, elem){ + var context_list = $(elem).parent().next('ul'); + if (context_list.children().length > 0){ + $(elem).addClass('active'); + var toggle_display = function(){ + if (context_list.css('display') == 'none'){ + $('.badge-context-list').hide();{# hide all context lists #} + context_list.show(); + } else { + context_list.hide(); + } + }; + $(elem).click(toggle_display); + } + }); + }); + </script> +{% endblock %} +<!-- end user_stats.html --> diff --git a/askbot/skins/old/templates/user_profile/user_tabs.html b/askbot/skins/old/templates/user_profile/user_tabs.html new file mode 100644 index 00000000..ad24a303 --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_tabs.html @@ -0,0 +1,52 @@ +<!-- user_tabs.html --> +<div class="tabBar"> + <div class="tabsC"> + <a id="stats" {% if tab_name=="stats" %}class="on"{% endif %} + title="{% trans %}User profile{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=stats" + ><span>{% trans %}overview{% endtrans %}</span></a> + {% if request.user == view_user or request.user|can_moderate_user(view_user) %} + <a id="inbox" {% if tab_name=="inbox" %}class="on"{% endif %} + title="{% trans %}comments and answers to others questions{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=inbox" + ><span>{% trans %}inbox{% endtrans %}</span></a> + {% endif %} + {% if user_follow_feature_on %} + <a id="network" {% if tab_name=="network" %}class="on"{% endif %} + title="{% trans %}followers and followed users{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=network" + ><span>{% trans %}network{% endtrans %}</span></a> + {% endif %} + <a id="reputation" {% if tab_name=="reputation" %}class="on"{% endif %} + title="{% trans %}graph of user reputation{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=reputation" + ><span>{% trans %}reputation history{% endtrans %}</span></a> + <a id="favorites" {% if tab_name=="favorites" %}class="on"{% endif %} + title="{% trans %}questions that user is following{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=favorites" + ><span>{% trans %}followed questions{% endtrans %}</span></a> + <a id="recent" {% if tab_name=="recent" %}class="on"{% endif %} + title="{% trans %}recent activity{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=recent" + ><span>{% trans %}activity{% endtrans %}</span></a> + {% if request.user == view_user or request.user|can_moderate_user(view_user) %} + <a id="votes" {% if tab_name=="votes" %}class="on"{% endif %} + title="{% trans %}user vote record{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=votes" + ><span>{% trans %}casted votes{% endtrans %}</span></a> + {% endif %} + {% if request.user == view_user or request.user|can_moderate_user(view_user) %} + <a id="email_subscriptions" {% if tab_name=="email_subscriptions" %}class="on"{% endif %} + title="{% trans %}email subscription settings{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=email_subscriptions" + ><span>{% trans %}subscriptions{% endtrans %}</span></a> + {% endif %} + {% if request.user|can_moderate_user(view_user) %} + <a id="moderation" {% if tab_name=="moderation" %}class="on"{% endif %} + title="{% trans %}moderate this user{% endtrans %}" + href="{% url user_profile view_user.id, view_user.username|slugify %}?sort=moderation" + ><span>{% trans %}moderation{% endtrans %}</span></a> + {% endif %} + </div> +</div> +<!-- end user_tabs.html --> diff --git a/askbot/skins/old/templates/user_profile/user_votes.html b/askbot/skins/old/templates/user_profile/user_votes.html new file mode 100644 index 00000000..d5e469ae --- /dev/null +++ b/askbot/skins/old/templates/user_profile/user_votes.html @@ -0,0 +1,30 @@ +{% extends "user_profile/user.html" %} +<!-- user_votes.html --> +{% block profilesection %} + {% trans %}votes{% endtrans %} +{% endblock %} +{% block usercontent %} + <div style="padding-top:5px;font-size:13px;"> + {% for vote in votes %} + <div style="clear:both;line-height:20px" > + <div style="width:150px;float:left">{{vote.voted_at|diff_date(True)}}</div> + <div style="width:30px;float:left"> + {% if vote.vote==1 %} + <img src="{{"/images/vote-arrow-up-on.png"|media}}" title="{% trans %}upvote{% endtrans %}"> + {% else %} + <img src="{{"/images/vote-arrow-down-on.png"|media}}" title="{% trans %}downvote{% endtrans %}"> + {% endif %} + </div> + <div style="float:left;overflow:hidden;width:750px"> + {% if vote.answer_id==0 %} + <span class="question-title-link"><a href="{% url question vote.question_id %}{{ vote.title|slugify }}">{{ vote.title|escape }}</a></span> + {% else %} + <span class="answer-title-link" ><a href="{% url question vote.question_id %}{{ vote.title|slugify }}#{{ vote.answer_id }}">{{ vote.title|escape}}</a></span> + {% endif %} + <div style="height:5px"></div> + </div> + </div> + {% endfor %} + </div> +{% endblock %} +<!-- end user_votes.html --> diff --git a/askbot/skins/old/templates/user_profile/users_questions.html b/askbot/skins/old/templates/user_profile/users_questions.html new file mode 100644 index 00000000..41809a62 --- /dev/null +++ b/askbot/skins/old/templates/user_profile/users_questions.html @@ -0,0 +1,8 @@ +<!-- users_questions.html --> +{% import "macros.html" as macros %} +<div class="user-stats-table"> + {% for question in questions %} + {{macros.question_summary(question, extra_class='narrow')}} + {% endfor %} +</div> +<!-- end users_questions.html --> diff --git a/askbot/skins/old/templates/users.html b/askbot/skins/old/templates/users.html new file mode 100644 index 00000000..750b3abb --- /dev/null +++ b/askbot/skins/old/templates/users.html @@ -0,0 +1,58 @@ +{% extends "two_column_body.html" %} +{% import "macros.html" as macros %} +<!-- users.html --> +{% block title %}{% spaceless %}{% trans %}Users{% endtrans %}{% endspaceless %}{% endblock %} +{% block content %} +<div class="tabBar"> + <h1>{% trans %}Users{% endtrans %}</h1> + <div class="tabsA"> + <a + id="sort_reputation" + href="{% url users %}?sort=reputation" + {% if tab_id == 'reputation' %}class="on"{% endif %} + title="{% trans %}reputation{% endtrans %}" + ><span>{% trans %}reputation{% endtrans %}</span></a> + <a + id="sort_newest" + href="{% url users %}?sort=newest" + {% if tab_id == 'newest' %}class="on"{% endif %} + class="off" title="{% trans %}recent{% endtrans %}" + ><span>{% trans %}recent{% endtrans %}</span></a> + <a + id="sort_last" + href="{% url users %}?sort=last" + {% if tab_id == 'last' %}class="on"{% endif %} + class="off" title="{% trans %}oldest{% endtrans %}" + ><span>{% trans %}oldest{% endtrans %}<span></a> + <a + id="sort_user" + href="{% url users %}?sort=user" + {% if tab_id == 'user' %}class="on"{% endif %} + title="{% trans %}by username{% endtrans %}" + ><span>{% trans %}by username{% endtrans %}</span></a> + </div> +</div> +<p> + {% if suser %} + {% trans %}users matching query {{suser}}:{% endtrans %} + {% endif %} + {% if not users.object_list %} + <span>{% trans %}Nothing found.{% endtrans %}</span> + {% endif %} +</p> +{{ macros.user_list(users.object_list) }} +<div class="pager"> + {{ macros.paginator(paginator_context) }} +</div> +{% endblock %} +{% block endjs %} + <script type="text/javascript"> + //todo move javascript out + $().ready(function(){ + Hilite.exact = false; + Hilite.elementid = "main-body"; + Hilite.debug_referrer = location.href; + }); + </script> +{% endblock %} +<!-- end users.html --> diff --git a/askbot/skins/utils.py b/askbot/skins/utils.py index e7997f7a..da3a8a06 100644 --- a/askbot/skins/utils.py +++ b/askbot/skins/utils.py @@ -42,20 +42,21 @@ def get_available_skins(selected=None): stock_dir = os.path.normpath(os.path.dirname(__file__)) stock_skins = get_skins_from_dir(stock_dir) default_dir = stock_skins.pop('default') + common_dir = stock_skins.pop('common') skins.update(stock_skins) - if selected: if selected in skins: selected_dir = skins[selected] skins.clear() skins[selected] = selected_dir else: - assert(selected == 'default') + assert(selected == 'default' or selected == 'common') skins = SortedDict() #re-insert default as a last item skins['default'] = default_dir + skins['common'] = common_dir return skins |